Open okhsunrog opened 1 year ago
It's a bit difficult to tell what the issue is without seeing the source code of your gpio_isr_handler
function.
Perhaps your gpio_isr_handler
doesn't clear the GPIO interrupt status register? This would lead to the interrupt triggering again and again, until the system is reset by the interrupt watchdog timer.
Oh, so I should clear it manually? in this example https://github.com/espressif/esp-idf/tree/release/v5.1/examples/peripherals/gpio/generic_gpio it's just like this:
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
that's the full code I was testing with
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/gpio_filter.h"
#define GPIO_OUTPUT_IO_0 CONFIG_GPIO_OUTPUT_0
#define GPIO_OUTPUT_IO_1 CONFIG_GPIO_OUTPUT_1
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
#define GPIO_INPUT_IO_0 CONFIG_GPIO_INPUT_0
#define GPIO_INPUT_IO_1 CONFIG_GPIO_INPUT_1
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0
static QueueHandle_t gpio_evt_queue = NULL;
static void IRAM_ATTR gpio_isr_handler(void* arg)
{
uint32_t gpio_num = (uint32_t) arg;
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
static void gpio_task_example(void* arg)
{
uint32_t io_num;
for(;;) {
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
}
}
}
void app_main(void)
{
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
io_conf.intr_type = GPIO_INTR_POSEDGE;
io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
gpio_isr_register(gpio_isr_handler, (void*) GPIO_INPUT_IO_1, ESP_INTR_FLAG_DEFAULT, NULL);
int cnt = 0;
while(1) {
printf("cnt: %d\n", cnt++);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
}
}
Oh, so I should clear it manually? in this example https://github.com/espressif/esp-idf/tree/release/v5.1/examples/peripherals/gpio/generic_gpio it's just like this:
The example uses per-GPIO handlers, via gpio_install_isr_service and gpio_isr_handler_add.
gpio_install_isr_service
already implements things such as clearing interrupt status, therefore the handler code in the application is simpler.
If you implement the whole ISR yourself, then you have write this code yourself.
Thanks! Now I see where is the problem. I'd be really grateful if you show me a working example of an ISR for gpio_isr_register
.
Hi @okhsunrog, may I ask your reason why you want to use gpio_isr_register
, instead of calling gpio_install_isr_service
, which helps to clear the interrupt status bits internally inside the default ISR?
I have seen the difficulty in using gpio_isr_register
, since the driver doesn't provide public functions to get and clear the GPIO interrupt status in the first place (and probably not a good idea to public these two functions). A bit hacky way is to make use of the HAL functions to get and clear the GPIO interrupt status directly in your application.
Answers checklist.
IDF version.
5.1 release
Operating System used.
Linux
How did you build your project?
VS Code IDE
If you are using Windows, please specify command line type.
None
Development Kit.
ESP32-C3 luat os dev board
Power Supply used.
USB
What is the expected behavior?
gpio_isr_register registers an ISR which works as expected
What is the actual behavior?
The app crashed
Steps to reproduce.
with
Debug Logs.
More Information.
I found the issue a day before with my project, using esp-idf installed manually, from cli. Today I removed esp-idf and installed fresh one in VS Code, tested with an official gpio example. Interrrupts work fine with gpio_isr_handler_add but everithing breaks with gpio_isr_register. Maybe I'm not using it the right way? There aren't any examples for this function