Page 1 of 1

High frequency GPIO Interrupt

Posted: Sat Feb 09, 2019 5:03 am
by dragondgold
I'm having a problem with "high-frequency" GPIO interrupt. I have a signal coming from another microcontroller that generates a 50us low pulse every 12ms and I capture this pulse using a falling-edge interrupt to send a task notification to a task with the highest priority in all my program.

The GPIO ISR service is placed in IRAM using:

Code: Select all

gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
The interrupt type is GPIO_INTR_NEGEDGE and the ISR handler looks like this:

Code: Select all

static void IRAM_ATTR scl_isr_handler(void* arg)
{
    static BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if(!gpio_get_level(PIC16_PIN))
    {
        vTaskNotifyGiveFromISR(task_handle, &xHigherPriorityTaskWoken);

        if(xHigherPriorityTaskWoken)
        {
            portYIELD_FROM_ISR();
        }
    }
}
The problem is, this works for around 250 ms after ESP32 boot and then the interrupt stops being fired (I'm checking everything with a logic analyzer and logs). However, if I increase the time to generate a 50us low pulse every 100ms instead of 12ms, it works as expected. How can I diagnose this problem? Can't the ESP32 handle an interrupt every 12ms? Even the RTOS tick rate is faster than that.

Re: High frequency GPIO Interrupt

Posted: Sat Feb 09, 2019 10:32 am
by ESP_Sprite
It should indeed have no issue handling that. What ESP-IDF version are you using? Do you happen to have the full code for this available somewhere?

Re: High frequency GPIO Interrupt

Posted: Sat Feb 09, 2019 5:14 pm
by dragondgold
Hi, thank you for your response! I'm using the latest release/v3.1 branch. Here is some more code:

main.c: https://pastebin.com/iG74a6wi
power_monitor.c: https://pastebin.com/vc52Yqnj
sdkconfig: https://pastebin.com/E6C7h5GG

The ESP32 is communicating with a PIC16 microcontroller through an I2C bus. There isn't any other device on the bus so when the PIC16 has new data available it generates a 50us low pulse on the SCL line, the ESP32 detects this pulse and starts reading data. At first, I thought the I2C was hanging in the ESP32 but I can see that the problem is indeed that the interrupt is not firing because I inserted an ets_printf() in it to check.

Here is a capture from the logic analyzer:

Image

The red circles are the pulses generated by the PIC16. As you can see the ESP32 works as expected in the beginning but after 50ms it simply stops.

Re: High frequency GPIO Interrupt

Posted: Sat Dec 21, 2019 4:08 am
by HelWeb
My measurements:
From external interrupt to interrupt routine; 1.7 µs
From external interrupt to RTOS task via interrupt routine like you do: 7.6 µs

So there should be no problem.

May you want to look at:
https://github.com/MacLeod-D/ESp32-Fast-external-IRQs

Re: High frequency GPIO Interrupt

Posted: Sat Dec 21, 2019 5:52 pm
by PeterR
Agree with above. Then you need to add task latency and I2C setup (say another 7uS).

You mention I2C. Did you know that the ESP will use the full transaction timeout on I2C bus error? I posted recently on this subject. One would hope that ACK fail would abort but on ESP-IDF 4.0 it seems not. I see this when on an EVB which I have not wired all my peripherals to. In this scenario my LED view update (I2C LED driver) hangs for my timeout. Annoying as the ESP timeout is for both a kind of software bus grant and hardware device response.
Maybe you have an I2C problem, this then causes your task to be waiting for your 20mS timeout but attempting to drive the bus, etc? EDIT: Doesn't even need to be driving bus, your task will just hang and not respond for 20mS.

Other thoughts are pull up strengths and pull detail implied by switching GPIO mode. You are loading the bus with capacitors err I mean probes.