This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

gpiote interrupt cannot wake sd_app_evt_wait?

I have tried to use sd_app_evt_wait() to sleep cpu, and use gpiote interrupt to wake up cpu from sleep. However, gpiote interrupt cannot wake up cpu. When I use __WFE(), gpiote interrupt can wake up cpu. And even if I use sd_app_evt_wait(), log print using Segger RTT seems to wake up cpu however log print place is after sleep loop. This is very strange.

Would you explain this phenomenon?

code is like below.

static void sf_gpiote_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
     _print_info("gpiote interrupt\r\n");
     s_is_resp_ready = true;
}


static void sf_wait_resp()
{
     while(!s_is_resp_ready)
     {
        __WFE();
        // sd_app_evt_wait();
     }
     s_is_resp_ready = false;

    //_print_info("resp_ready\r\n");
}
  • Can you show me the code used to initialize the GPIOTE channel?

    sd_app_evt_wait() is using WFE under the hood, so there shouldn't be a big difference between the two, except sd_app_evt_wait() is running the recommended sleep sequence:

    __WFE();
    __SEV();
    __WFE();
    

    If you only run __WFE(); once then you might not go to sleep at all, if there is already an event pending.

    Best regards

  • code is like below.

        /* config interrupt */
        nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
    
        if(!nrf_drv_gpiote_is_init())
            nrf_drv_gpiote_init();
    
        nrf_drv_gpiote_in_init(INT_N, &config, sf_gpiote_handler);
        nrf_drv_gpiote_in_event_enable(INT_N, true);
    

    is this collect?

  • Hi Haruki

    I tested the code with the ble_app_uart example, and I had no issues getting the GPIOTE interrupt to work, also when using sd_app_evt_wait().

    I made some minor changes to the code, to use the button 4 input for testing, but otherwise it is pretty much the same:

    static void sf_gpiote_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
        printf("gpiote interrupt\r\n");
         //s_is_resp_ready = true;
    }
    
    
    static void gpiote_init()
    {
         /* config interrupt */
        nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
        config.pull = NRF_GPIO_PIN_PULLUP;
    
        if(!nrf_drv_gpiote_is_init())
            nrf_drv_gpiote_init();
    
        nrf_drv_gpiote_in_init(BSP_BUTTON_3, &config, sf_gpiote_handler);
        nrf_drv_gpiote_in_event_enable(BSP_BUTTON_3, true);
    }
    

    If the log is delayed it could be because you are using the log library in deferred mode? In this mode the printing will be delayed until NRF_LOG_PROCESS() is called.

    Do you have a scope available?
    Then you could try to toggle an output pin in the interrupt instead, and look on the scope if the pin is toggled after the input changes.

    Best regards
    Torbjørn

  • You forgot the C optimizer:

    volatile int s_is_resp_ready;
    

    Without the volatile, the optimizer will replace the

    while(!s_is_resp_ready)
    

    with an unconditional loop. Look at the disassembly if you can.

  • I tried volatile, and it works well!! Still it is strange why __WFE() works well without volatile. I cannot understand compiler behavior. Can you explain? Anyway, thank you for your answer!

Related