Handling Interrupt via gpio_isr_register

linuxpaul
Posts: 27
Joined: Thu Jul 20, 2017 6:10 pm

Handling Interrupt via gpio_isr_register

Postby linuxpaul » Sun Sep 24, 2017 12:30 pm

Hello Forum,

I'd like handle Interrupts of two IOs (4 & 5) within a sinle callback,
so I tried the following by using gpio_isr_register:

Code: Select all

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "sdkconfig.h"

#define GPIO_INT_T   5
#define GPIO_INT_B   4
#define ESP_INTR_FLAG_DEFAULT 0

/* Can run 'make menuconfig' to choose the GPIO to blink,
   or you can edit the following line and set a number here.
*/
#define BLINK_GPIO CONFIG_BLINK_GPIO

static xQueueHandle gpio_evt_queue = NULL;
static gpio_isr_handle_t isr_handle;

static void IRAM_ATTR gpio_int_handler(void* arg)
{
    uint32_t gpio_num = READ_PERI_REG(GPIO_STATUS_REG);
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

static void gpio_task_example(void* arg) /*queue listener task*/
{
    uint32_t io_num;
    uint32_t port;
    for(;;) {
       printf("Waiting on Queue ....\n");
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
           if(io_num == 16) {port = 4;} else {port = 5;}
            printf("GPIO[%d]\n", port);
        }
    }
}

void blink_task(void *pvParameter)
{
    gpio_pad_select_gpio(BLINK_GPIO);
    gpio_pad_select_gpio(GPIO_INT_T);
    gpio_pad_select_gpio(GPIO_INT_B);

    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);

    gpio_set_direction(GPIO_INT_T, GPIO_MODE_INPUT);
    gpio_set_pull_mode(GPIO_INT_T, GPIO_PULLUP_ONLY);
    gpio_intr_enable(GPIO_INT_T);
    gpio_set_intr_type(GPIO_INT_T, GPIO_INTR_NEGEDGE);

    gpio_set_direction(GPIO_INT_B, GPIO_MODE_INPUT);
    gpio_set_pull_mode(GPIO_INT_B, GPIO_PULLUP_ONLY);
    gpio_intr_enable(GPIO_INT_B);
    gpio_set_intr_type(GPIO_INT_B, GPIO_INTR_NEGEDGE);

    gpio_isr_register(gpio_int_handler, NULL, ESP_INTR_FLAG_DEFAULT, &isr_handle);

    while(1) {
        gpio_set_level(BLINK_GPIO, 0);
        vTaskDelay(100 / portTICK_PERIOD_MS);
        gpio_set_level(BLINK_GPIO, 1);
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}

void app_main()
{

    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); /*create queue*/
    xTaskCreate(&gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL); /*start queue listener*/
    xTaskCreate(&blink_task, "blink_task", 512, NULL, 5, NULL);
}


The result is, by pressing Button on IO5 for example, a repeatly call of "IRAM_ATTR gpio_int_handler(void* arg)"
until an automatic reboot after ca 2 sec.

Output:

Code: Select all

I (807) cpu_start: Pro cpu start user code
I (865) cpu_start: Starting scheduler on PRO CPU.
I (187) cpu_start: Starting scheduler on APP CPU.
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIO[5]
Waiting on Queue ....
GPIOets Jun  8 2016 00:22:57

rst:0x8 (TG1WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
ets Jun  8 2016 00:22:57

rst:0x7 (TG0WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0010,len:4
load:0x3fff0014,len:5072
ho 0 tail 12 room 4
load:0x40078000,len:0
load:0x40078000,len:12652
entry 0x40078f44
W (95) boot: PRO CPU has been reset by WDT.
W (95) boot: WDT reset info: PRO CPU PC=0x400803c0
0x400803c0: _DoubleExceptionVector at ??:?

W (95) boot: WDT reset info: APP CPU PC=0x400836cf
0x400836cf: uart_tx_char at D:/Source/esp/esp-idf/components/vfs/vfs_uart.c:43 (discriminator 1)

I (114) boot: ESP-IDF v3.0-dev-168-gd515eeac 2nd stage bootloader
I (135) boot: compile time 22:10:27


Are there any suggestions to this behavoir? Why I don't get a singe call of the callback?

:)
linuxpaul


linuxpaul
Posts: 27
Joined: Thu Jul 20, 2017 6:10 pm

Re: Handling Interrupt via gpio_isr_register

Postby linuxpaul » Mon Sep 25, 2017 6:53 pm

OK,
Sorry, I think I didn't get this hint :oops:
Should I use the Var instead of the function?

Changing "uint32_t gpio_num = READ_PERI_REG(GPIO_STATUS_REG);"
to "uint32_t gpio_num = GPIO.status_w1tc;" within the callback,
just results in the same behavior.

WiFive
Posts: 1100
Joined: Tue Dec 01, 2015 7:35 am

Re: Handling Interrupt via gpio_isr_register

Postby WiFive » Mon Sep 25, 2017 7:24 pm

You need to clear the interrupt when you service it.

linuxpaul
Posts: 27
Joined: Thu Jul 20, 2017 6:10 pm

Re: Handling Interrupt via gpio_isr_register

Postby linuxpaul » Mon Sep 25, 2017 7:55 pm

Pretty simple,
Thank you WiFive

:)
linuxpaul

Who is online

Users browsing this forum: Baidu [Spider] and 13 guests