Fail to use gpiote edge triggering to wake the system up

I am now developing nRF52805 with SDK 17.1.0. I am trying to use long pressing to enter the sleeping mode and wake the system up using the short press. However, there is an issue that if I long-press the button, the system will enter the system off as expected, but instantly wake up operating like restarting. After I read the datasheet for nRF52, I realize that the wake-up should be triggered by the GPIO DETECT signal, however, if I would like to solve the above issue, I find that some developers use GPIOTE: GPIOTE_CONFIG_IN_SENSE_HITOLO function to sense the high-to-low signal of the gpio. But unfortunately, I try this function several times, but when I set the high accuracy as false, the function works the same as sense active low for the pin, while when I changed to set the high accuracy as true, the wake-up function could not work properly and stuck on the system off mode. Could anyone give me a way to solve these problems as I search the discussions but many of them meet the same issue but don't solve it? The following is my sample code. Thank you for the help.

#define BSP_BUTTON_0    20
#define BUTTON_0_ID     bsp_board_pin_to_button_idx(BSP_BUTTON_0)     // Define the button pin 20 ID

/**@brief Handler for shutdown preparation.
 */
bool shutdown_handler(nrf_pwr_mgmt_evt_t event)
{

    uint32_t err_code;

    switch (event)
    {
        // NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF = NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
        // Once the NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF is achieved, the system will jump to NRF_PWR_MGMT_EVT_PREPARE_WAKEUP directly
        case NRF_PWR_MGMT_EVT_PREPARE_WAKEUP:

            NRF_LOG_INFO("The machine enters the SLEEP MODE!");
            
            
            NRF_LOG_INFO("To wake up the machine, please press the button!");

            nrf_drv_gpiote_in_uninit(BSP_BUTTON_0);           
	
            
            nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
            

            in_config.pull = NRF_GPIO_PIN_PULLUP;                                           
            err_code = nrf_drv_gpiote_in_init(BSP_BUTTON_0, &in_config, NULL);           
            APP_ERROR_CHECK(err_code);
                                                                   
            nrf_drv_gpiote_in_event_enable(BSP_BUTTON_0, true);
            
            
            // Soft device system off function
            sd_power_system_off();
    
            break;
    }

    err_code = app_timer_stop_all();
    APP_ERROR_CHECK(err_code);

    return true;
}

static void short_button_press_cnt_timer_handler(void * p_content){}

/**@brief Register application shutdown handler with priority 0. */
NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, 0);


static void bsp_event_handler(bsp_event_t bsp_event)
{
    uint32_t err_code;

    switch (bsp_event)
    {   
        // BSP event for long press
        case BSP_EVENT_SLEEP:
            isLongPress = true; // Check the long pressing

            NRF_LOG_INFO("Long button press");
            NRF_LOG_INFO("The machine will enter SLEEP MODE in 1 second!");
            
            nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF); //Enter the sleep mode
        break;
    }
}


void buttons_leds_init(bool * erase_bonds)
{
  // Initialize the BSP 
    uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler);
    APP_ERROR_CHECK(err_code);
    
    // Assign the Button RELEASE action to WAKEUP event
    err_code = bsp_event_to_button_action_assign(BUTTON_0_ID, BSP_BUTTON_ACTION_RELEASE, BSP_EVENT_WAKEUP);
    APP_ERROR_CHECK(err_code);
    
    // Assign the Button LONG PRESS action to SLEEP event
    err_code = bsp_event_to_button_action_assign(BUTTON_0_ID, BSP_BUTTON_ACTION_LONG_PUSH, BSP_EVENT_SLEEP);
    APP_ERROR_CHECK(err_code);

}

Parents
  • Hi,

    Have you checked the pin with a scope, to see if there is any bouncing signals from the button that can wake the chip too early? If you enter System OFF immediately when the long button press is detected, the chip may haven entered System OFF before you release the button. If there is then some bouncing signals on the pin when the long press is released, the chip may wake up from this.

    Configuring the GPIO with hi_accuracy will not work, as this will configure the pin using GPIOTE IN event, which is not active in System OFF mode. Setting hi_accuracy to false will use the GPIOTE PORT event, which will also configure the GPIO in sense mode. GPIO Sense mode is what is used to wakeup from System OFF.

    Best regards,
    Jørgen

  • If you need to use the same button to enter and exit System OFF mode, you should probably read the state of the pin before entering System OFF, to make sure the button is in the "released" state. You may also schedule the entering of System OFF mode a few seconds in the future (for instance using a app_timer) when receiving the long press button event, to give the user some time to release the button. During this time you may configure the button for a normal pressed interrupt and enter normal System ON idle mode. In case the user press the button to wake the device before it enters System OFF mode, you should cancel the scheduled entering System OFF mode action/timer.

Reply
  • If you need to use the same button to enter and exit System OFF mode, you should probably read the state of the pin before entering System OFF, to make sure the button is in the "released" state. You may also schedule the entering of System OFF mode a few seconds in the future (for instance using a app_timer) when receiving the long press button event, to give the user some time to release the button. During this time you may configure the button for a normal pressed interrupt and enter normal System ON idle mode. In case the user press the button to wake the device before it enters System OFF mode, you should cancel the scheduled entering System OFF mode action/timer.

Children
  • Thank you for your reply Jorgen. Exactly, that is the way I consider before. For example, I set a 1-second delay and show the reminder that 'the machine will enter sleep mode, please release the button' something like that, to prevent the restart issue. Or I move the system off function to the release event. Only when the user long-pressing the button and then release it, the system off function will be activated as expected. Both methods could definitely solve the restart issue to some extent. But is it possible to activate the system off function without releasing the button once the user is long-pressing the button, and also, prevent the restart issue? I am sorry to make it tricky, but thank you for your help.

    Best regards,

    XIANGYU YU

  • If the wakeup is caused by bounce noise from the button/switch (you should be able to see this if you look at the signal from the button on a scope), there is no other workaround you can do in the code to go directly to System OFF and prevent wakeup when the button is released.

    You may consider adding a R-C filter on the button in your HW, to prevent the bounce signals in the first place. Google "switch bouncing" should give you some nice articles with suggestions.

  • Thank you for your reply Jorgen. Actually, in the HW, there is a bypass C to avoid the notch or glitch of the button bouncing issue. Finally, I change my code format, and activate the system off function only after the button released from long-pressing action. Thank you again for your help. Best!

Related