This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Migration from app_gpiote to nrf_drv_gpiote

With the new nrf_drv_gpiote, how can I know if the handler has been trigged by event "low to high" or "high to low"?

Please, could you provide a configuration exemple? I tried this without success because the init for one pin is done twice:

nrf_drv_gpiote_in_config_t config_low_to_high = GPIOTE_CONFIG_IN_SENSE_LOTOHI(false);		
	err_code = nrf_drv_gpiote_in_init(WATCH_BUTTON_1_PIN_NO, &config_low_to_high, gpiote_event_watch_button_1_low_to_high);
APP_ERROR_CHECK(err_code);

nrf_drv_gpiote_in_config_t config_high_to_low = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);		
	err_code = nrf_drv_gpiote_in_init(WATCH_BUTTON_1_PIN_NO, &config_high_to_low, gpiote_event_watch_button_1_high_to_low);
APP_ERROR_CHECK(err_code);

nrf_drv_gpiote_in_event_enable(WATCH_BUTTON_1_PIN_NO, true);

With app_gptiote, I used to catch button event like this :

static void gpiote_init(void)
{
    uint32_t err_code;
    
    APP_GPIOTE_INIT(APP_GPIOTE_MAX_USERS);
    
    uint32_t active_high_states_mask = 0;
    uint32_t active_low_states_mask  = 0;
    
    //Watch button
    nrf_gpio_cfg_input(WATCH_BUTTON_PIN_NO, NRF_GPIO_PIN_PULLUP);  	
    
    active_high_states_mask |= (0x1UL << WATCH_BUTTON_PIN_NO);
    active_low_states_mask  |= (0x1UL << WATCH_BUTTON_PIN_NO);
    
    err_code = app_gpiote_user_register(&m_gpiote_watch_btn_id,
                                active_high_states_mask,
                                active_low_states_mask,
                                gpiote_event_watch_button_handler);
    
    APP_ERROR_CHECK(err_code);
    
    err_code = app_gpiote_user_enable(m_gpiote_watch_btn_id);
    APP_ERROR_CHECK(err_code);
}

static void gpiote_event_watch_button_handler(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low)
{        
    //Push
    if(event_pins_high_to_low)
        kernel_setSignal(SIGNAL_BTN_PUSH);	
    
    //Release
    if(event_pins_low_to_high)
        kernel_setSignal(SIGNAL_BTN_RELEASE);	
}
  • how can I know if the handler has been trigged by event "low to high" or "high to low"? Is there someone with the same need?

  • Hi Sébastien

    What if you configure your input pin as toggle. Something like

    nrf_drv_gpiote_in_config_t config_toggle = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);       
        err_code = nrf_drv_gpiote_in_init(WATCH_BUTTON_1_PIN_NO, &config_toggle, gpiote_event_watch_button_1_toggle);
    APP_ERROR_CHECK(err_code);
    

    I suspect you then get an event both on high-to-low and low-to-high signal. But you are correct that the nrf_drv_gpiote event does not report if the event was generated from high-to-low signal or from low-to-high signal. You could anyhow check the status of the pin manually in the nrf_drv_gpiote event handler, i.e. with

    static void gpiote_event_watch_button_1_toggle(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        if(nrf_drv_gpiote_in_is_set(pin))
        {
            //Event was triggered on low-to-high signal
        }
        else
        {
            //Event was triggered on high-to-low signal
        }
    }
    

    The potential flaw of this implementation is that already a few microseconds have passed since the pin state was changed until we check the state of the pin. If the pin signal triggering the event is very short, then we might be doing a false reading with this implementation. A better practice would be to read the pin state as soon as possible, i.e. in the nrf_drv_gpiote driver and let the driver forward the pin state to the application. However, if the pin signal has duration of milliseconds and not microseconds, this implementation should be just fine.

  • Thank you, checking the pin state did the trick!

    One more question : is there a limitation to enable critical section in this handler? I need to update a sensitive global variable when a button event occurs, and the fact to enable/disable the interrupt freeze the app. My code in the button event handler :

    if(nrf_drv_gpiote_in_is_set(pin))
    {
        //Event was triggered on low-to-high signal
    	
        //Disable interrupt
        uint32_t err_code;
    	uint8_t is_nested_critical_region;
    
        err_code = sd_nvic_critical_region_enter(&is_nested_critical_region);
    	APP_ERROR_CHECK(err_code);	    
    
    	m_signal |= SIGNAL_REL_1;   // setting the requested bit
    
    	//Enable interrupt
    	err_code = sd_nvic_critical_region_exit(is_nested_critical_region);
    	APP_ERROR_CHECK(err_code);
    }
    
  • Hi Sébastien

    I do not realize why critical_region_enter does not work in the button interrupt handler. Can you post your question on a new thread to give other a chance to answer.

Related