How to use gpio_isr_register?
- martinayotte
- Posts: 141
- Joined: Fri Nov 13, 2015 4:27 pm
Re: How to use gpio_isr_register?
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.
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.
Re: How to use gpio_isr_register?
yes you are right martinmartinayotte 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.
http://esp32.com/viewtopic.php?f=13&t=3 ... t=10#p1594
if you enable only one gpio, then we can mask, or cases or do with you mentioned example too in the isr.(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
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
..
btw, how you would handle it ?
best wishes
rudi
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
- martinayotte
- Posts: 141
- Joined: Fri Nov 13, 2015 4:27 pm
Re: How to use gpio_isr_register?
What is the question exactly ?
Because all states are present in gpio_intr_status, you simply needs to verify each bits as needed.
Because all states are present in gpio_intr_status, you simply needs to verify each bits as needed.
Re: How to use gpio_isr_register?
the q was , how you handle bounce to debounce.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.
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.
-------------------------------------
問候飛出去的朋友遍全球魯迪
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
Re: How to use gpio_isr_register?
Hi,rudi ;-) wrote:where is the code?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.
@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
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); }
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);
}
Please let me know your opinion or input on this ASAP
Regards,
Ritesh Prajapati
Ritesh Prajapati
Re: How to use gpio_isr_register?
Not sure - cause I am unfortunately no clairvoyantRitesh 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?
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.
-------------------------------------
問候飛出去的朋友遍全球魯迪
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪
Re: How to use gpio_isr_register?
Hi,rudi ;-) wrote:Not sure - cause I am unfortunately no clairvoyantRitesh 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?
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
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
Ritesh Prajapati
Re: How to use gpio_isr_register?
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
Re: How to use gpio_isr_register?
I am having trouble with the interrupt signatures. In this thread and all the documentation, the signature is:
But when I cmd+click the function name, it takes me to a header with the following signature:
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
Code: Select all
esp_err_t gpio_isr_register( uint32_t gpioIntr, void (*fn)(void *), void *arg)
Code: Select all
esp_err_t gpio_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, gpio_isr_handle_t *handle);
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
-
- Posts: 9764
- Joined: Thu Nov 26, 2015 4:08 am
Re: How to use gpio_isr_register?
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: Majestic-12 [Bot], Sang_Huynh and 107 guests