Critical attention to GPIO interrupts
Posted: 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:
----------------------------------------------------
Configuration task of Wifi:
The 'TaskWifi' is a function where the Wifi is configured and started. And send a message MQTT each 3 seconds.
Configuration task for interrupts:
The 'TaskInterrupt' is a function where the GPIO is configured:
The 'pIsrHandle' is the callback to attend the interrupt:
The 'pIsrTimerHandle' is the callback function for attend the Timer 0 of group 0 interrupt.
-------------------------------
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.
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);
}
Code: Select all
xTaskCreatePinnedToCore(TaskWifi, "wireless_task", 5120, NULL, 5, NULL, 0)
Configuration task for interrupts:
Code: Select all
xTaskCreatePinnedToCore(TaskInterrupt, "Interrupt_task", 2048, NULL, 5, NULL, 1)
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);
}
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);
}
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.