Critical attention to GPIO interrupts

aml_tech
Posts: 4
Joined: Tue Jul 16, 2019 6:38 am

Critical attention to GPIO interrupts

Postby aml_tech » Tue Jul 16, 2019 10:19 am

I'm using ESP32 for develop a producto where I need to attend the interrupts without any delays. But when I transmit by Wifi interface the attention of interrupts is delayed some microseconds (50 - 100us).

I tried to execute wifi task only in the core 0 and the manage of signal only in the core 1. But although this the interrupts still delayed when wifi have activity.

I tried too using IRAM_ATTR in the interrupts functions, for store this code in RAM. But the result don't change.

My doubt after this probes is: Is possible to config the interrupt GPIO with a priority or other option for take a critical attention of this interrupts with uninterrupted execution of the code into the isr callbacks isr? Or this little delay is inevitable?

My code for do this is:
----------------------------------------------------

Code: Select all

void app_main(void)
{
esp_chip_info_t chip_info;
    
    esp_chip_info(&chip_info);

    printf("********************************\n");

    printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
            chip_info.cores,
            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("silicon revision %d, ", chip_info.revision);

    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    printf("********************************\n");
    fflush(stdout);

    xTaskCreatePinnedToCore(TaskWifi, "wireless_task", 5120, NULL, 5, NULL, 0);
    xTaskCreatePinnedToCore(TaskInterrupt, "Interrupt_task", 2048, NULL, 5, NULL, 1);
}
Configuration task of Wifi:

Code: Select all

xTaskCreatePinnedToCore(TaskWifi, "wireless_task", 5120, NULL, 5, NULL, 0)
The 'TaskWifi' is a function where the Wifi is configured and started. And send a message MQTT each 3 seconds.

Configuration task for interrupts:

Code: Select all

xTaskCreatePinnedToCore(TaskInterrupt, "Interrupt_task", 2048, NULL, 5, NULL, 1)
The 'TaskInterrupt' is a function where the GPIO is configured:

Code: Select all

void TaskInterrupt(void * xParams)
{
gpio_config_t xConf;

    xConf.intr_type = GPIO_INTR_DISABLE;
    xConf.pin_bit_mask = (1ULL << 33);
    xConf.mode = GPIO_MODE_INPUT;
    xConf.pull_up_en = GPIO_PULLUP_DISABLE;
    xConf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    gpio_config(&xConf);

    gpio_set_intr_type(33, GPIO_INTR_ANYEDGE);
    gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
    gpio_isr_handler_add(33, pIsrHandle, NULL);
}
The 'pIsrHandle' is the callback to attend the interrupt:

Code: Select all

void IRAM_ATTR pIsrHandle(void * arg)
{
timer_config_t xConfig;

    gpio_set_level(13, 1);
    xConfig.divider = 16;                          
    xConfig.counter_dir = TIMER_COUNT_UP;
    xConfig.counter_en = TIMER_PAUSE;
    xConfig.alarm_en = TIMER_ALARM_EN;
    xConfig.intr_type = TIMER_INTR_LEVEL;
    xConfig.auto_reload = false;
    
    timer_init(0, 0, &xConfig);
    timer_set_counter_value(0, 0, 0x00000000ULL);
    timer_set_alarm_value(0, 0, 500*5);          // 500us of time
    timer_enable_intr(0, 0);
    timer_isr_register(0, 0, pIsrTimerHandle, NULL, ESP_INTR_FLAG_IRAM, NULL);
    timer_start(0, 0);

    gpio_set_level(14, 1);
}
The 'pIsrTimerHandle' is the callback function for attend the Timer 0 of group 0 interrupt.

Code: Select all

void IRAM_ATTR pIsrTimerHandle(void * xParams)
{
    gpio_set_level(14, 0);
    gpio_set_level(13, 0);

    TIMERG0.hw_timer[0].update = 1;
    TIMERG0.int_clr_timers.t0 = 1;
    TIMERG0.hw_timer[0].alarm_high = 0;
    TIMERG0.hw_timer[0].alarm_low = 0;
    TIMERG0.hw_timer[0].config.alarm_en = TIMER_ALARM_DIS;
}
-------------------------------

With this code, watching pins '14' and '13' with a oscilloscope, I detect that the execution of interrupt is delayed about 50us aprox. when the ESP32 is transmitting by Wifi, when wifi transmission is idle it is high stable.
The effect is as if during the execution of the interruption it is stopped by another most priority task.
But I don't have other tasks and those are pinned to differents cores, I think this should be enough so that the two tasks do not affect each others.


ESP_Angus
Posts: 2344
Joined: Sun May 08, 2016 4:11 am

Re: Critical attention to GPIO interrupts

Postby ESP_Angus » Wed Jul 17, 2019 1:28 am

With this code, watching pins '14' and '13' with a oscilloscope, I detect that the execution of interrupt is delayed about 50us aprox. when the ESP32 is transmitting by Wifi, when wifi transmission is idle it is high stable.
What do you see if you watch pins 33 and 13 on the oscilloscope? This is a simpler measurement of a single interrupt latency, rather than two interrupts plus timer latency.

Try changing the setting of GPIOs to use direct register writes, ie (

Code: Select all

GPIO.out_w1ts.data = 1 << 13; // high
GPIO.out_w1tc.data = 1 << 13; // low
The reason for this is that the gpio_set_level() function is not in IRAM and might cause a flash cache miss when it's executed (causing a delay). This may be happening when WiFi is active because WiFi code is also being loaded into the cache.

Similarly, all of the timer config functions are not in IRAM. If possible, do as much of this configuration work outside the ISR as possible (should only need to configure most parameters once) and then use register writes to enable the timer inside the ISR.

Finally, by default the LWIP task is allowed to run on either core, and will sometimes take a spinlock which requires disabling interrupts. Try pinning this task to CPU 0, only:
https://docs.espressif.com/projects/esp ... k-affinity

aml_tech
Posts: 4
Joined: Tue Jul 16, 2019 6:38 am

Re: Critical attention to GPIO interrupts

Postby aml_tech » Wed Jul 17, 2019 12:53 pm

The signal on the pin 33 is a periodic square signal of 10ms. This is only a test code to validate the viability.

I configured on menuconfig->component-Wifi that only work on Core 0 and in the app_main() I pinned the Wifi task to the core 0. I hope this is enough to ensure that only the core 0 execute code of wifi.

Thanks for the response, following your recommendation and directly writing registers for enable the timer and manage the GPIO the delay was reduce a lot. Now the delay is about 5 or 10us.

Is a good way to continue working.

aml_tech
Posts: 4
Joined: Tue Jul 16, 2019 6:38 am

Re: Critical attention to GPIO interrupts

Postby aml_tech » Fri Jul 26, 2019 8:40 am

I'm detecting another delay related with the GPIO interrupts from ESP32.

The GPIO and interrupt configuration is:

Code: Select all

gpio_config_t xConf;

    xConf.intr_type = GPIO_INTR_DISABLE;
    xConf.pin_bit_mask = (1ULL << 33);
    xConf.mode = GPIO_MODE_INPUT;
    xConf.pull_up_en = GPIO_PULLUP_DISABLE;
    xConf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    gpio_config(&xConf);

    gpio_set_intr_type(33, GPIO_INTR_ANYEDGE);
    gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
    gpio_isr_handler_add(33, pIsrHandle, NULL);
When the Wifi is working the edge detection and the callback function execution is delayed. I explain it better, physically the edge of the signal and the callback execution has a delay of 200us between them. When the wifi is idle this delay don't occurs.

Can I use different configuration for solve it (different priority service, using other functions, etc..)? Why this delay occurs?
The wifi task is pinned in the core '0' and the task to configuration of the GPIO interrupt is pinned in the core '1'. I suppose this GPIO interrupt is being attended only by the core '1'

aml_tech
Posts: 4
Joined: Tue Jul 16, 2019 6:38 am

Re: Critical attention to GPIO interrupts

Postby aml_tech » Mon Jul 29, 2019 7:04 am

I have been able to test more this issue and I discard the direct relation of the wifi with this delay.

I have 2 interrupt pins configured using the same process (the same code lines) but in differents tasks (the pin 33 in a task pinned to core '1' and the pin 19 in a task pinned to the core '0').

I have been able to test that this delay occurs when both pins interrupts are configured, if I comment the pin 19 configuration and only have one interrupt configured don't have a delay in the callback execution.
Instead if I have the two interrupts working the callback is sometimes delayed. (The two interrupts are working, but sometimes the detection is delayed with the real edge event)
The most extrange is that the delay occurs even when the signal on the pin 19 is still and don't have any edge (is a pushbutton and I don't press it).

I'm thinking that it is a problem with the gpio_isr_service...
¿What is the right flag for the gpio_install_isr_service when I have some differents interrupts pins configured in differents tasks and differents cores?

Who is online

Users browsing this forum: No registered users and 91 guests