How to use gpio_isr_register?

User avatar
martinayotte
Posts: 113
Joined: Fri Nov 13, 2015 4:27 pm

Re: How to use gpio_isr_register?

Postby martinayotte » Thu Oct 27, 2016 3:42 pm

BTW, folks and @rudi, using "switch/case" with numeric values for each interrupt is not a good practice.
If both interrupts come at the same time, your code won't handle any, since gpio_intr_status will be set to 393216.

You should use bitmask as "if (gpio_intr_status & 0x02000) {}" and "if (gpio_intr_status & 0x04000) {}" for GPIO17/GPIO18 respectively.

User avatar
rudi ;-)
Posts: 1209
Joined: Fri Nov 13, 2015 3:25 pm

Re: How to use gpio_isr_register?

Postby rudi ;-) » Thu Oct 27, 2016 4:52 pm

martinayotte wrote:BTW, folks and @rudi, using "switch/case" with numeric values for each interrupt is not a good practice.
If both interrupts come at the same time, your code won't handle any, since gpio_intr_status will be set to 393216.

You should use bitmask as "if (gpio_intr_status & 0x02000) {}" and "if (gpio_intr_status & 0x04000) {}" for GPIO17/GPIO18 respectively.


yes you are right martin

viewtopic.php?f=13&t=345&start=10#p1594
(if we not enable isr on gpio17 but pushes one time)
if i push gpio17 i get no fired isr,

( usr only on gpio18 )
but if i push gpio18,
i get gpio_intr_status
393216
means
1100000000000000000
gpio18 + gpio17


if you enable only one gpio, then we can mask, or cases or do with you mentioned example too in the isr.
i think - but if we enable more, then we can only handle on same time only one fired INTR ?!
the default case in enable two ( 17, 18 ) was for probe the things, does it (fast) bounce or not "in the isr" in the meantime in "fire" moment.
if we want handle a second without isr fire we can example look up for the value on the pin after fired and in the isr every time
( see the preview example with disabled gpio17 isr )
( btw similar example fire on SDA pin..and a lookup for the value of an other pin(scl) in the isr meantime after sda fired )

Code: Select all


 scl=GPIO_INPUT_GET(GPIO_ID_PIN(I2C_SLAVE_SDL_GPIO));
 sda=GPIO_INPUT_GET(GPIO_ID_PIN(I2C_SLAVE_SDA_GPIO));
   
 if(( (gpio_status>>I2C_SLAVE_SDA_GPIO)& BIT0)&&scl) //SDA trigger and sdl high   
{
           if( sda )// sda posedge , stop
..
..
          else //sda negedge,start
..


this was only a "example" because bounce was theme.
btw, how you would handle it ?

best wishes
rudi ;-)
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

User avatar
martinayotte
Posts: 113
Joined: Fri Nov 13, 2015 4:27 pm

Re: How to use gpio_isr_register?

Postby martinayotte » Fri Oct 28, 2016 1:58 pm

What is the question exactly ?
Because all states are present in gpio_intr_status, you simply needs to verify each bits as needed.

User avatar
rudi ;-)
Posts: 1209
Joined: Fri Nov 13, 2015 3:25 pm

Re: How to use gpio_isr_register?

Postby rudi ;-) » Fri Oct 28, 2016 3:10 pm

martinayotte wrote:What is the question exactly ?
Because all states are present in gpio_intr_status, you simply needs to verify each bits as needed.


the q was , how you handle bounce to debounce.
i handle it simply by tags or a small mask or lookup in the mask.

yes i know martin, the case "default" was create to look is there an other active in the pin mask near fired pin.
for me the theme is cleared.

thanks
rudi
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

Ritesh
Posts: 608
Joined: Tue Sep 06, 2016 9:37 am
Location: India
Contact:

Re: How to use gpio_isr_register?

Postby Ritesh » Sun Dec 11, 2016 12:36 pm

rudi ;-) wrote:
WiFive wrote:
I tried the example in gpio.h with gpio0 and get the interrupt messages over uart when the button on devkitc is pressed.


where is the code?

:roll:

:ugeek:


@Neil

example you connect a PIR to the GPIO17
you build an alarm

https://www.mpja.com/download/31227sc.pdf

The PIR i linked has 3.3 / 0 TTL
with 5 V supply

because Nano32 has 5.0 V output too,
i connect 5 V to Power
ground to ground
TTL to GPIO 17
( bevore i test with push button )


here is a example with PIR and the Nano32 form MakerAsia & GravitechThai

IMG_5453.JPG




an here the code for you.
if you use in your book
please named it

credit: MakerAsia

thank you


Code: Select all



#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/gpio.h"


//
#define INPUT_GPIO 17

// #define INPUT_GPIO_DOORBUTTON 18
// #define INPUT_GPIO_ALARMBUTTON 19

#define TAG 3


void gpioCallback (void* arg);


/******************************************************************************
 * FunctionName : hello_task
 * Description  :
 * Parameters   : void* pvParameter
 * Returns      :
*******************************************************************************/
void hello_task(void* pvParameter)
{
  /* Calc */
  printf("Hello, how are you?!\n");
      for (int i = 10; i >= 0; i--) {
          printf("Restarting in %d seconds...\n", i);
          vTaskDelay(1000 / portTICK_RATE_MS);
      }
      printf("Restarting now.\n");
      fflush(stdout);
      system_restart();
}

/******************************************************************************
 * FunctionName : main_task
 * Description  :
 * Parameters   : void* pvParameter
 * Returns      : void
*******************************************************************************/
void main_task(void* pvParameter)
{
  /* Calc */
  /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
         muxed to GPIO on reset already, but some default to other
         functions and need to be switched to GPIO. Consult the
         Technical Reference for a list of pads and their default
         functions.)
      */
     
      gpio_pad_select_gpio(INPUT_GPIO);
     
     /* Set the GPIO as a input */
      gpio_set_direction(INPUT_GPIO, GPIO_MODE_INPUT);
     
     /* Set the GPIO pull */
      gpio_set_pull_mode(INPUT_GPIO, GPIO_PULLUP_ONLY);
 
      // gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_NEGEDGE);
      // gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_ANYEDGE);
     gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_ANYEDGE);
 
      gpio_intr_enable(INPUT_GPIO);
 
      // Intterrupt number see below
      gpio_isr_register(INPUT_GPIO, gpioCallback, (void *)TAG); // 17
 
 
      while(1) {
        // if you need..
        // printf( "Loop...\n" );
        // vTaskDelay(1000 / portTICK_RATE_MS);
  }
}

/******************************************************************************
 * FunctionName : gpioCallback
 * Description  :
 * Parameters   : void* arg
 * Returns      : 
*******************************************************************************/
void gpioCallback(void* arg)
{
  /* Calc */
  uint32_t gpio_num = 0;
    uint32_t gpio_intr_status = READ_PERI_REG(GPIO_STATUS_REG);   //read status to get interrupt status for GPIO0-31
    uint32_t gpio_intr_status_h = READ_PERI_REG(GPIO_STATUS1_REG);//read status1 to get interrupt status for GPIO32-39
    SET_PERI_REG_MASK(GPIO_STATUS_W1TC_REG, gpio_intr_status);    //Clear intr for gpio0-gpio31
    SET_PERI_REG_MASK(GPIO_STATUS1_W1TC_REG, gpio_intr_status_h); //Clear intr for gpio32-39
    do {
      if(gpio_num < 32) {
       
                  
        if(gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
      ets_printf("1 Intr GPIO%d ,val: %d\n",gpio_num,gpio_get_level(gpio_num));
           //This is an isr handler, you should post an event to process it in RTOS queue.
         
         / * test your self......
         switch (gpio_intr_status & BIT(gpio_num)) {
            
            case 17: ets_print("GPIO 17 request\n"); break;
            
            case 18: ets_print("GPIO 18 request : task2 call\n");
                  xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL);
                  break;
                  
         }
         * /
         
        }
      // }
      } else {
        if(gpio_intr_status_h & BIT(gpio_num - 32)) {
          ets_printf("2 Intr GPIO%d, val : %d\n",gpio_num,gpio_get_level(gpio_num));
          //This is an isr handler, you should post an event to process it in RTOS queue.
        }
      }
  } while(++gpio_num < GPIO_PIN_COUNT);
 
  /* push_status = ; */
 }

/******************************************************************************
 * * * * * * * *: main of ESP32
 * FunctionName : app_main
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void app_main() 
{
  /* Calc */
  nvs_flash_init();
  system_init();
     
  // xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL);
  xTaskCreate(&main_task, "main_task", 2048, NULL, 5, NULL);
}



output.jpg


:mrgreen:


Hi,

As I have one requirement to implement button based Interrupt to reset ESP32 based on button event and for that I have looked your code and it seems like it may work for my requirement.

Code: Select all

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/gpio.h"


//
#define INPUT_GPIO 17

// #define INPUT_GPIO_DOORBUTTON 18
// #define INPUT_GPIO_ALARMBUTTON 19

#define TAG 3


void gpioCallback (void* arg);


/******************************************************************************
 * FunctionName : hello_task
 * Description  :
 * Parameters   : void* pvParameter
 * Returns      :
*******************************************************************************/
void hello_task(void* pvParameter)
{
  /* Calc */
  printf("Hello, how are you?!\n");
      for (int i = 10; i >= 0; i--) {
          printf("Restarting in %d seconds...\n", i);
          vTaskDelay(1000 / portTICK_RATE_MS);
      }
      printf("Restarting now.\n");
      fflush(stdout);
      system_restart();
}

/******************************************************************************
 * FunctionName : main_task
 * Description  :
 * Parameters   : void* pvParameter
 * Returns      : void
*******************************************************************************/
void main_task(void* pvParameter)
{
  /* Calc */
  /* Configure the IOMUX register for pad BLINK_GPIO (some pads are
         muxed to GPIO on reset already, but some default to other
         functions and need to be switched to GPIO. Consult the
         Technical Reference for a list of pads and their default
         functions.)
      */
     
      gpio_pad_select_gpio(INPUT_GPIO);
     
     /* Set the GPIO as a input */
      gpio_set_direction(INPUT_GPIO, GPIO_MODE_INPUT);
     
     /* Set the GPIO pull */
      gpio_set_pull_mode(INPUT_GPIO, GPIO_PULLUP_ONLY);
 
      // gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_NEGEDGE);
      // gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_ANYEDGE);
     gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_ANYEDGE);
 
      gpio_intr_enable(INPUT_GPIO);
 
      // Intterrupt number see below
      gpio_isr_register(INPUT_GPIO, gpioCallback, (void *)TAG); // 17
 
 
      while(1) {
        // if you need..
        // printf( "Loop...\n" );
        // vTaskDelay(1000 / portTICK_RATE_MS);
  }
}

/******************************************************************************
 * FunctionName : gpioCallback
 * Description  :
 * Parameters   : void* arg
 * Returns      : 
*******************************************************************************/
void gpioCallback(void* arg)
{
  /* Calc */
  uint32_t gpio_num = 0;
    uint32_t gpio_intr_status = READ_PERI_REG(GPIO_STATUS_REG);   //read status to get interrupt status for GPIO0-31
    uint32_t gpio_intr_status_h = READ_PERI_REG(GPIO_STATUS1_REG);//read status1 to get interrupt status for GPIO32-39
    SET_PERI_REG_MASK(GPIO_STATUS_W1TC_REG, gpio_intr_status);    //Clear intr for gpio0-gpio31
    SET_PERI_REG_MASK(GPIO_STATUS1_W1TC_REG, gpio_intr_status_h); //Clear intr for gpio32-39
    do {
      if(gpio_num < 32) {
       
                   
        if(gpio_intr_status & BIT(gpio_num)) { //gpio0-gpio31
      ets_printf("1 Intr GPIO%d ,val: %d\n",gpio_num,gpio_get_level(gpio_num));
           //This is an isr handler, you should post an event to process it in RTOS queue.
         
         / * test your self......
         switch (gpio_intr_status & BIT(gpio_num)) {
           
            case 17: ets_print("GPIO 17 request\n"); break;
           
            case 18: ets_print("GPIO 18 request : task2 call\n");
                  xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL);
                  break;
                 
         }
         * /
         
        }
      // }
      } else {
        if(gpio_intr_status_h & BIT(gpio_num - 32)) {
          ets_printf("2 Intr GPIO%d, val : %d\n",gpio_num,gpio_get_level(gpio_num));
          //This is an isr handler, you should post an event to process it in RTOS queue.
        }
      }
  } while(++gpio_num < GPIO_PIN_COUNT);
 
  /* push_status = ; */
 }

/******************************************************************************
 * * * * * * * *: main of ESP32
 * FunctionName : app_main
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void app_main() 
{
  /* Calc */
  nvs_flash_init();
  system_init();
     
  // xTaskCreate(&hello_task, "hello_task", 2048, NULL, 5, NULL);
  xTaskCreate(&main_task, "main_task", 2048, NULL, 5, NULL);
}

So, I have connected one GPIO from ESP32 to button in my product which is based on ESP32 as Master. So, Does you code will be worked for that or do I need to update or change it?

Please let me know your opinion or input on this ASAP
Regards,
Ritesh Prajapati

User avatar
rudi ;-)
Posts: 1209
Joined: Fri Nov 13, 2015 3:25 pm

Re: How to use gpio_isr_register?

Postby rudi ;-) » Mon Dec 12, 2016 12:35 am

Ritesh wrote:
.. So, I have connected one GPIO ...
..So, Does you code will be worked for that or do I need to update or change it?



Not sure - cause I am unfortunately no clairvoyant :mrgreen:
Which Gpio did you choose for it, Is it suitable as input?
If your GPIO is different to the code, yes you must then update or change it.

best wishes
rudi ;-)
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

Ritesh
Posts: 608
Joined: Tue Sep 06, 2016 9:37 am
Location: India
Contact:

Re: How to use gpio_isr_register?

Postby Ritesh » Mon Dec 12, 2016 1:13 am

rudi ;-) wrote:
Ritesh wrote:
.. So, I have connected one GPIO ...
..So, Does you code will be worked for that or do I need to update or change it?



Not sure - cause I am unfortunately no clairvoyant :mrgreen:
Which Gpio did you choose for it, Is it suitable as input?
If your GPIO is different to the code, yes you must then update or change it.

best wishes
rudi ;-)


Hi,

Yes. The GPIO which I have selected is suitable into INPUT mode and I have manually checked it's functionality in polling mode in which it's working fine as INPUT mode by checking it's value on external input source.

So, will it be worked if my GPIO is working fine into INPUT mode?
Regards,
Ritesh Prajapati

jimbob
Posts: 29
Joined: Fri Aug 05, 2016 10:47 pm

Re: How to use gpio_isr_register?

Postby jimbob » Mon Dec 12, 2016 9:20 am

Just as a reminder as to what I said before in this thread -- there's more detail there, but in summary, notice about gpio_isr_register

Code: Select all


//Use this for each pin you want as input, interrupt
      gpio_pad_select_gpio(INPUT_GPIO);
     
     /* Set the GPIO as a input */
      gpio_set_direction(INPUT_GPIO, GPIO_MODE_INPUT);
     
     /* Set the GPIO pull */
      gpio_set_pull_mode(INPUT_GPIO, GPIO_PULLUP_ONLY);
 
      // gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_NEGEDGE);
      // gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_ANYEDGE);
     gpio_set_intr_type(INPUT_GPIO, GPIO_INTR_ANYEDGE);
 
      gpio_intr_enable(INPUT_GPIO);


// Use this once to allow the interrupt handler to work. Also, you can't just pick any number for INTERRUPT_NUMBER

      gpio_isr_register(INTERRUPT_NUMBER, gpioCallback, (void *)TAG); // 17
     
 

phando
Posts: 17
Joined: Wed Dec 14, 2016 5:30 am

Re: How to use gpio_isr_register?

Postby phando » Mon Dec 19, 2016 11:42 pm

I am having trouble with the interrupt signatures. In this thread and all the documentation, the signature is:

Code: Select all

esp_err_t gpio_isr_register( uint32_t gpioIntr, void (*fn)(void *), void *arg)


But when I cmd+click the function name, it takes me to a header with the following signature:

Code: Select all

esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle);


Do I have an older or newer version of the SDK? Does anyone have a simple working example of an interrupt and a callback?

EDIT (but not a solution):
I was able to find the same signature on the docs here:
https://esp-idf.readthedocs.io/en/latest/api/gpio.html

ESP_Sprite
Posts: 1935
Joined: Thu Nov 26, 2015 4:08 am

Re: How to use gpio_isr_register?

Postby ESP_Sprite » Tue Dec 20, 2016 1:03 am

The function signature changed, indeed, because it now uses the dynamic interrupt allocation code to get an interrupt. Basically, instead of hardcoding an interrupt number, you now hand the function a bunch of flags indicating the type of interrupt you want. If needed, you can get an interrupt handle back which you can then use to disable/enable the interrupt. More info at http://esp-idf.readthedocs.io/en/latest ... alloc.html .

Who is online

Users browsing this forum: No registered users and 18 guests