nrf_drv_gpiote_in_event_enable causes event

Hey,

When I call fn nrf_drv_gpiote_in_event_enable, the event handler is immediately called.  Note that at the beginning of the fn I even read the pin to verify it's high.  I also know it's high because I'm scoping it.   Also, this code does work properly when the line transitions to low.

Is there a way to stop this erroneous event from happening when enabled???

    ret_code_t err_code;

    nrf_gpio_cfg_input(gp_board_config->irq, NRF_GPIO_PIN_PULLUP);

    {
        volatile uint32_t read = nrf_gpio_pin_read(gp_board_config->irq);

        // Setting break point here verifies this line is high.
        read++;
    }

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    /**
     * Sam will set the interrupt aka wakeup line low until nrf responds with Ack.
     */

    nrf_drv_gpiote_in_config_t irq_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
    err_code = nrf_drv_gpiote_in_init(gp_board_config->irq, &irq_config, m_gpiote_evt_handler);
    APP_ERROR_CHECK(err_code);

    CRITICAL_REGION_ENTER();
    nrf_drv_gpiote_in_event_enable(gp_board_config->irq, true);

    {

        nrf_gpiote_events_t event   = nrfx_gpiote_in_event_addr_get(gp_board_config->irq);

        nrf_gpiote_event_clear(event);

        NVIC_ClearPendingIRQ(GPIOTE_IRQn);
    }

    CRITICAL_REGION_EXIT();

Note I even tried disabling ints, and then clearing the event and the interrupt - no success.

Parents
  • Hi,

    Which GPIO pin are you using? Have you tried other pins?

    Since you have passed "false" to the hi_accu argument of NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(), the pin will use the GPIOTE PORT event and not a dedicated IN event. Have you tried setting this to "true"?

    When you say that the event handler is called immediately, is this your application defined event handler? (m_gpiote_evt_handler) What are the pin and action variables set to?

    The code you have included in your post is not correct to clear events:

    nrf_gpiote_events_t event   = nrfx_gpiote_in_event_addr_get(gp_board_config->irq);
    nrf_gpiote_event_clear(event);

    nrfx_gpiote_in_event_addr_get() will return the address of the event register, while nrf_gpiote_event_clear() expects a nrf_gpiote_events_t enum value.

    Since you have set the hi_accu parameter to false, you can try passing the NRF_GPIOTE_EVENTS_PORT option to nrf_gpiote_event_clear().

    Best regards,
    Jørgen

  • Hi,

    I tested a simple version of your code in the pin_change_interrupt example in nRF5 SDK v17.1.0. I'm not able to reproduce the issue with interrupt triggering at start of application, or see any problems with the interrupt not triggering.

    Can you try this simple code on your board?

    #include <stdbool.h>
    #include "nrf.h"
    #include "nrf_drv_gpiote.h"
    #include "app_error.h"
    #include "boards.h"
    
    #define GPIO_BUTTON 25
    #define GPIO_LED    16
    
    
    void m_gpiote_evt_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        nrf_gpio_pin_toggle(GPIO_LED);
    }
    
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        ret_code_t err_code;
    
        nrf_gpio_cfg_input(GPIO_BUTTON, NRF_GPIO_PIN_PULLUP);
        nrf_gpio_cfg_output(GPIO_LED);
        nrf_gpio_pin_set(GPIO_LED);
    
        {
            volatile uint32_t read = nrf_gpio_pin_read(GPIO_BUTTON);
    
            // Setting break point here verifies this line is high.
            read++;
        }
    
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
    
        /**
         * Sam will set the interrupt aka wakeup line low until nrf responds with Ack.
         */
    
        nrf_drv_gpiote_in_config_t irq_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
        err_code = nrf_drv_gpiote_in_init(GPIO_BUTTON, &irq_config, m_gpiote_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        //CRITICAL_REGION_ENTER();
        nrf_drv_gpiote_in_event_enable(GPIO_BUTTON, true);
    
        //{
        //    nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
        //    NVIC_ClearPendingIRQ(GPIOTE_IRQn);
        //}
    
        //CRITICAL_REGION_EXIT();
    
        while (true)
        {
            __WFE();
            // Do nothing.
        }
    }

    On the nRF52840 DK, this will toggle LED4 in the interrrupt handler when BUTTON4 is pressed. Before the button is pressed, the LED will not light up.

    Namklak said:
    The goal is the get an interrupt when the GPIO line transitions from high to low - should I be using another technique other than nrf_drv_gpiote_in_init?

    The approach you have used is the best method to configure the interrupt using the PORT event. 

    Best regards,
    Jørgen

  • I tried your example of reading the pin after setting pin to an input - if I put a breakpoint on my code's equivalent of your line 32, I do NOT get the false event.  If I run the code without the breakpoint, I do get the false event after nrf_drv_gpiote_in_event_enable.

    Also, before this code runs, the dfu bootloader is running - I wonder if that is causing some uh initial conflict.

  • Namklak said:
    Also, before this code runs, the dfu bootloader is running - I wonder if that is causing some uh initial conflict.

    That is definitely a possibility, as I'm not able to reproduce it on my board that does not contain a bootloader.

    Which pin are you using? Are you seeing the "false event" on any pins configured as input?

    Have you read out the NRF_GPIOTE->EVENTS_PORT register to see if it is set before you enable the GPIOTE driver?

  • Crap.  Never mind, I found it, thanks for your help.  Not an 840 nor sdk issue, it is a system level issue.

Reply Children
No Data
Related