nrf desktop - how to add soft power off

Hi,

I'm using nRF Connect v2.1.0.

How can I add a soft power off to nrf_desktop with a gpio interrupt wakeup? It looks like all of the demo hardware uses disconnecting switches, where I have a dedicated GPIO input with a momentary button for powering on/off.

I used the simple button example to add power button detection to board.c, and I used the code from the system_off example to shut it down from within my button callback, but it just reboots and turns right back on. I also tried creating and submitting a power_down_event to send to the power manager (I tried both "power_down_event" and "force_power_down_event"), with the same result. I also tried calling the turn_board_off() function that was already in board.c, which didn't do much.

I thought maybe it was failing because I was shutting down from within my button ISR so I added a worker function that I kick off with k_work_reschedule from the ISR, and then submit the powerdown event from the worker function, but I get the same result. It turns off and right back on.

Thanks,

Glen

Parents
  • Hi Glen, 

    Could you show how you put the device to system off and how you configure the wake up source ?
    There could be a chance that the wake up source is triggered right after the device enter deep sleep. 

    Maybe you can try to test using different buttons, one for putting the device to sleep and another one to wake the device up ? 
    I don't think putting the device to deep sleep in an ISR could be the reason it wake up. 

    Have you tried to use force_power_down()  
    I tried this in the nRF Desktop code, compile with nRF52840 dk board and it seems to work: 

    void main(void)
    {
    	if (app_event_manager_init()) {
    		LOG_ERR("Application Event Manager not initialized");
    	} else {
    		module_set_state(MODULE_STATE_READY);
    	}
    	k_sleep(K_SECONDS(3));
    	force_power_down();
    }
    

    The board enter deep sleep after awhile (more than 3 seconds, but I assume it's because it takes time to shutdown). Pressing button 3 or 4 wakes the board up. 

Reply
  • Hi Glen, 

    Could you show how you put the device to system off and how you configure the wake up source ?
    There could be a chance that the wake up source is triggered right after the device enter deep sleep. 

    Maybe you can try to test using different buttons, one for putting the device to sleep and another one to wake the device up ? 
    I don't think putting the device to deep sleep in an ISR could be the reason it wake up. 

    Have you tried to use force_power_down()  
    I tried this in the nRF Desktop code, compile with nRF52840 dk board and it seems to work: 

    void main(void)
    {
    	if (app_event_manager_init()) {
    		LOG_ERR("Application Event Manager not initialized");
    	} else {
    		module_set_state(MODULE_STATE_READY);
    	}
    	k_sleep(K_SECONDS(3));
    	force_power_down();
    }
    

    The board enter deep sleep after awhile (more than 3 seconds, but I assume it's because it takes time to shutdown). Pressing button 3 or 4 wakes the board up. 

Children
  • Hmm - nice to know there's just a force_power_down function to call. It's still doing the same thing though, even when I put the call in main like you did so the button isn't involved.

    Is there some way to see the cause of a powerup, or some way to see what interrupts are active before I call the shutdown function that might be causing it to wake? I can set a breakpoint in my shut down function if there are some registers I can look at.

    Maybe some other pin in my system is still configured as an interrupt without me realizing it, or maybe some module isn't enabled for power management so it's waking me up. 

    None of the KEEP_ALIVE_EVENTS things in prj.conf are set to true.

    It might also be good if I can figure out how to disable parts of the code to see if it works up until I turn on the ADC or some other peripheral

    Here's the code I'm using for the wakeup button. I added it to the init part of app_event_handler in board.c:

    #define POWER_BTN_NODE	DT_ALIAS(powerbtn)
    static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(POWER_BTN_NODE, gpios, {0});
    static struct gpio_callback button_cb_data;
    
    
    static bool app_event_handler(const struct app_event_header *aeh)
    {
    	static bool initialized;
    
    	if (is_module_state_event(aeh)) {
    		const struct module_state_event *event = cast_module_state_event(aeh);
    
    		if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
    			__ASSERT_NO_MSG(!initialized);
    			initialized = true;
    
    			turn_board_on();
    
             // Set up the power button interrupt
             gpio_pin_configure_dt(&button, GPIO_INPUT);
             gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
             gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
             gpio_add_callback(button.port, &button_cb_data);

Related