interrupt still triggered after interrupt service has been disabled

adherent
Posts: 19
Joined: Mon Jan 15, 2018 9:24 pm

interrupt still triggered after interrupt service has been disabled

Postby adherent » Mon Jan 15, 2018 9:36 pm

Hi all,

I use GPIO pin to receive interrupts. Rising and falling edge are both enabled. As soon as one interrupt has been triggered, I first send the pin number to a task.

Inside the task I disabled the interrupt for that pin using gpio_intr_disable, then do some gpio level manipulation which could trigger new interrupt. And at the end of the task I enable the interrupt for that pin again.

But now I can see a bunch of interrupts are generated, gpio_isr_handler is called several times even when the interrupt is disabled for that pin!

I am totally running out of idea. Please help! Thanks!

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

Re: interrupt still triggered after interrupt service has been disabled

Postby ESP_Sprite » Tue Jan 16, 2018 2:56 am

Can you post a representative sample for the code that does that?

adherent
Posts: 19
Joined: Mon Jan 15, 2018 9:24 pm

Re: interrupt still triggered after interrupt service has been disabled

Postby adherent » Tue Jan 16, 2018 9:50 am

Thanks for the quick reply.

Sure I can put some codes here. For the sake of readability the pasted code is simplified.

First a brief description of the configuration.

GPIO26 used as INPUT, rising edge and falling edge are enabled for receiving interrupt. Internal pull-up enabled, I add one external 10k pull-up resistor as well.

GPIO18 used as OUTPUT, initial output = 0.

GPIO26 is connected to GPIO18 using a button. When the button is pressed, GPIO26 changes to low(falling edge), button released, GPIO changes to high(rising edge).

Macro definition:

Code: Select all


#define GPIO_IN_KEY_ROW_0  GPIO_NUM_26
#define GPIO_IN_KEY_ROW_1  GPIO_NUM_34
#define GPIO_IN_KEY_ROW_2  GPIO_NUM_35
#define GPIO_IN_KEY_ROW_3  GPIO_NUM_36
#define GPIO_IN_KEY_ROW_4  GPIO_NUM_39
#define GPIO_IN_PIN_SEL  (((uint64_t)1<<GPIO_IN_KEY_ROW_0) | ((uint64_t)1<<GPIO_IN_KEY_ROW_1) | \
						  ((uint64_t)1<<GPIO_IN_KEY_ROW_2) | ((uint64_t)1<<GPIO_IN_KEY_ROW_3) | \
						  ((uint64_t)1<<GPIO_IN_KEY_ROW_4))

#define GPIO_OUT_KEY_COL_0  GPIO_NUM_18
#define GPIO_OUT_KEY_COL_1  GPIO_NUM_19
#define GPIO_OUT_KEY_COL_2  GPIO_NUM_21
#define GPIO_OUT_KEY_COL_3  GPIO_NUM_22
#define GPIO_OUT_PIN_SEL   (((uint64_t)1<<GPIO_OUT_KEY_COL_0) | ((uint64_t)1<<GPIO_OUT_KEY_COL_1) | \
							((uint64_t)1<<GPIO_OUT_KEY_COL_2) | ((uint64_t)1<<GPIO_OUT_KEY_COL_3))


appMain:

Code: Select all

void app_main()
{
    gpio_config_t io_conf_out, io_conf_in;
    //disable interrupt
    io_conf_out.intr_type = GPIO_PIN_INTR_DISABLE;
    //set as output mode
    io_conf_out.mode = GPIO_MODE_OUTPUT;
    //bit mask of the pins that you want to set,e.g.GPIO18/19
    io_conf_out.pin_bit_mask = GPIO_OUT_PIN_SEL;
    //disable pull-down mode
    io_conf_out.pull_down_en = 0;
    //disable pull-up mode
    io_conf_out.pull_up_en = 0;
    //configure GPIO with the given settings
    gpio_config(&io_conf_out);

    //interrupt of rising and falling edge
    io_conf_in.intr_type = GPIO_INTR_ANYEDGE;
    //bit mask of the pins
    io_conf_in.pin_bit_mask = GPIO_IN_PIN_SEL;
    //set as input mode    
    io_conf_in.mode = GPIO_MODE_INPUT;
    //disable pull-down mode
    io_conf_in.pull_down_en = 0;
    //enable pull-up mode
    io_conf_in.pull_up_en = 1;
    gpio_config(&io_conf_in);


    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //start gpio task
    xTaskCreate(gpio_task, "gpio_task", 2048, NULL, 10, NULL);

    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);

    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(GPIO_IN_KEY_ROW_0, gpio_isr_handler, (void*) GPIO_IN_KEY_ROW_0);
    gpio_isr_handler_add(GPIO_IN_KEY_ROW_1, gpio_isr_handler, (void*) GPIO_IN_KEY_ROW_1);
    gpio_isr_handler_add(GPIO_IN_KEY_ROW_2, gpio_isr_handler, (void*) GPIO_IN_KEY_ROW_2);
    gpio_isr_handler_add(GPIO_IN_KEY_ROW_3, gpio_isr_handler, (void*) GPIO_IN_KEY_ROW_3);
    gpio_isr_handler_add(GPIO_IN_KEY_ROW_4, gpio_isr_handler, (void*) GPIO_IN_KEY_ROW_4);

    //init button COL GPIO pins to low
    gpio_set_level(GPIO_OUT_KEY_COL_0, 0);
    gpio_set_level(GPIO_OUT_KEY_COL_1, 0);
    gpio_set_level(GPIO_OUT_KEY_COL_2, 0);
    gpio_set_level(GPIO_OUT_KEY_COL_3, 0);


    int cnt = 0;
    while(1) {
        printf("cnt: %d\n", cnt++);
        vTaskDelay(1000 / portTICK_RATE_MS);

        printf("row 0 level = %d\n", gpio_get_level(GPIO_IN_KEY_ROW_0));
        printf("row 1 level = %d\n", gpio_get_level(GPIO_IN_KEY_ROW_1));
        printf("row 2 level = %d\n", gpio_get_level(GPIO_IN_KEY_ROW_2));
        printf("row 3 level = %d\n", gpio_get_level(GPIO_IN_KEY_ROW_3));
        printf("row 4 level = %d\n", gpio_get_level(GPIO_IN_KEY_ROW_4));

    }
}


ISR code:

Code: Select all

static void gpio_isr_handler(void* arg)
{
	static uint32_t isr_counter = 0;
    uint32_t gpio_num = (uint32_t) arg;

    gpio_intr_disable(26);

    gpio_num += ((isr_counter++)<<24);
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}
task code:

Code: Select all

static void gpio_task(void* arg)
{
    uint32_t row = 0;
    uint32_t col = 0;

    uint32_t gpio_num = 0;

    uint32_t isr_counter = 0;

    char *button_pressed = "pressed";
    char *button_released = "released";

    for(;;)
    {
        if(xQueueReceive(gpio_evt_queue, &gpio_num, portMAX_DELAY))
        {
            //in case of falling edge
            if(gpio_get_level(row) == 0)
            {
//            	col = find_pressed_buttons_col(row);

            	gpio_set_level(18, 1);

            	vTaskDelay(200 / portTICK_RATE_MS);

            	gpio_set_level(18, 0);
            }
            //in case of rising edge
            else
            {
            	col = find_released_buttons_col(row);
            }

        	isr_counter = gpio_num >> 24;

            printf(" ISR counter %d \n", isr_counter);

            gpio_intr_enable(26);

        }
    }
}
I made some simple modification to the GPIO example. So hopefully it is still readable.

The weird behavior is that when I pressed the button, and kept it pressed. I saw ISR counter kept incrementing, although interrupt of GPIO26 has been disabled.

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

Re: interrupt still triggered after interrupt service has been disabled

Postby ESP_Sprite » Wed Jan 17, 2018 3:45 am

Just wondering: Are you sure those interrupts stem from GPIO26? If for whatever reason, any of the other GPIO pins are pulled low, you'd also see this behaviour.

Asking because I just took a look at the GPIO int code, and it seems simple enough that I couldn't spot any obvious bugs that could generate this.

User avatar
Gfast2
Posts: 182
Joined: Fri Aug 11, 2017 1:52 am

Re: interrupt still triggered after interrupt service has been disabled

Postby Gfast2 » Wed Jan 17, 2018 4:12 am

The weird behavior is that when I pressed the button, and kept it pressed. I saw ISR counter kept incrementing, although interrupt of GPIO26 has been disabled.
Hi adherent,

I don't have the time to mock up a test. But what I woundered is: Keeping on pressed down that button won't trigger any kind of "falling" / "rising" event on theory, which will trigger the ISR routine. So would it be helpful to probe GPIO 26 with a Scope or just a digital analyser to see what actually it does?

(Just got my ESD protection workshop yesterday & get shocked by how easy to produced a hardware damage. And those half-killed chips are the worst dream ever for Software developer... :cry: )

Cheers

Gfast2

adherent
Posts: 19
Joined: Mon Jan 15, 2018 9:24 pm

Re: interrupt still triggered after interrupt service has been disabled

Postby adherent » Wed Jan 17, 2018 10:24 am

ESP_Sprite wrote:Just wondering: Are you sure those interrupts stem from GPIO26? If for whatever reason, any of the other GPIO pins are pulled low, you'd also see this behaviour.

Asking because I just took a look at the GPIO int code, and it seems simple enough that I couldn't spot any obvious bugs that could generate this.
Even if other GPIO pins are pulled low, it cannot explain the behavior here, as the interrupts keep coming endless. Seems like someone keeps pushing another button and released it, pushed again then release again ....

adherent
Posts: 19
Joined: Mon Jan 15, 2018 9:24 pm

Re: interrupt still triggered after interrupt service has been disabled

Postby adherent » Wed Jan 17, 2018 10:28 am

Gfast2 wrote:
The weird behavior is that when I pressed the button, and kept it pressed. I saw ISR counter kept incrementing, although interrupt of GPIO26 has been disabled.
Hi adherent,

I don't have the time to mock up a test. But what I woundered is: Keeping on pressed down that button won't trigger any kind of "falling" / "rising" event on theory, which will trigger the ISR routine. So would it be helpful to probe GPIO 26 with a Scope or just a digital analyser to see what actually it does?

(Just got my ESD protection workshop yesterday & get shocked by how easy to produced a hardware damage. And those half-killed chips are the worst dream ever for Software developer... :cry: )

Cheers

Gfast2
yea, I could check what happens exactly to GPIO26 using a probe. However whatever I will see, it does not matter actually, because I disabled the interrupt of that pin. No matter how it changes, ISR should not be called. :cry:

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: interrupt still triggered after interrupt service has been disabled

Postby chegewara » Wed Jan 17, 2018 6:49 pm

Remember you have queue size 10, so you can have up to 10 readings after you turn off interrupts.

adherent
Posts: 19
Joined: Mon Jan 15, 2018 9:24 pm

Re: interrupt still triggered after interrupt service has been disabled

Postby adherent » Fri Jan 19, 2018 9:53 am

Solved, after reading this post: https://esp32.com/viewtopic.php?f=2&t=1836

The problem here is during the time while one GPIO's interrupt is disabled, the newly generated interrupts are somehow "registered" internally, and as soon as the interrupt is enabled again ISR will be called.

Who is online

Users browsing this forum: No registered users and 123 guests