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

Sleep mode, system off works but not system ON

Hi :) ,

My project continues quiet well, and now come the time to create final assembli of all my small block.

I'm using nrf52833, with s113.

I want my device most of the time in deep sleep mode. When the external  accelerometre detect movement, it set a pin to 1 to wake up the nrf52833.

A second source of wake up will be the internal rtc . It will periodically wake up the device , get spi information and wake up or not after evaluating the data.

I first used nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF); with success. I ere able to go into deepest sleep mode, and wake up by moving my accelerometer.

But then, i realize it was not possible to have rtc working in this mode ! So i tried to use in place of it : sd_app_evt_wait(); 

But it doesn't go to sleep anymore, it just overpass the function like it doens't exist. I red that if some event or interupt happens, this behavior can happen. So i tried to put this function directly after my main( entry point. But still same issue ! I'have checked that no interupt were enable in peripherals.

I also tried to use just before sd_app_evt_wait , this to clean potential interupt already on : sd_nvic_ClearPendingIRQ(Reset_IRQn); but without effect.

To sum up, i think i have to use POwer On mode ( i would like to activate ram retention too with this piece of code i found in example peripheral/ram retention ). Once i get the wake up on event with gpio or rtc timer, the program will continue after the function. As i am using spi and some gpio , should i re configure pins and pripheral or is it still keep in memory ? I already to started this with a state machine in my main.

NRF_POWER->RAM[0].POWERSET = (POWER_RAM_POWER_S0POWER_On << POWER_RAM_POWER_S0POWER_Pos) |

etc...
(POWER_RAM_POWER_S0RETENTION_On << POWER_RAM_POWER_S0RETENTION_Pos) |
(POWER_RAM_POWER_S1RETENTION_On << POWER_RAM_POWER_S1RETENTION_Pos) |
(POWER_RAM_POWER_S2RETENTION_On << POWER_RAM_POWER_S2RETENTION_Pos) |


Thank you !

Parents
  • Hello,

    It is correct that your RTC can't run in System_off mode, so if you want to wake up on this, you need to use system_on mode (sd_app_evt_wait()).

    As you can see from most of our ble_ examples in the SDK, app_evt_wait() is either called directly in the end of the main()-loop, or packed into idle_state_handle() (directly), or even inside nrf_pwr_mgmt_run() inside idle_state_handle().

    As long as this is in the end of your main()-loop, this will be called whenever you are done with all interruptions. Yes, it will wake up again, typically on softdevice events, or peripheral events. 

    Please note that if you believe that you have turned off everything, and still wake up from sd_app_evt_wait(), it is probably because something you turned off has finished turning off. As long as it just goes back into sd_app_evt_wait(), that is not a problem.

    The difficult part with this is that it is difficult to figure out yourself whether or not you are properly sleeping in sd_app_evt_wait(). If you try to log something before/after sd_app_evt_wait() this will be queued up, you go to sleep, and then the UART is finished logging, triggering the logging again. The same goes with everything from the app_timer. starting stopping timers will be scheduled, and executed later. So even if you stop the timer, you will go to sleep, wait up by the event that the timer stops, and go back to sleep (unless you start the timer again).

    One function you can use to check if your main loop is continuously running is nrf_gpio_pin_toggle(uint32_t pin_number); which will just set a register and return:

        // Enter main loop.
        for (;;)
        {
            nrf_gpio_pin_toggle(20);
            idle_state_handle();
        }

    If you set this to an LED, you can see when this is called. Please note that this may toggle really fast. I tested on the ble_app_uart event handler on an nRF52832 DK, using pin 20, which toggles LED4 on the DK. If I wrote something to the DK via UART it would toggle if I wrote an even number of bytes, and stay on/off if I wrote an odd number.

    The normal approach is to use sd_app_evt_wait() while you are running your application, and then use system_off if nothing connects before the advertisement timeout times out. Then you can wake on e.g. an accellerometer after that. If you want to wake on the RTC, you must keep using sd_app_evt_wait.

    Best regards,

    Edvin

  • Hi Edvin, thanks for this detailed reply.

    First i enabled , #define NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED 1. When i call sd_app_evt_wait(), I see the pin going high and after toggle two times (see picture) .

    I see this behavior on scope each second. Then i search for something happening each second that wake up my system, and it seems to come from :

        static void nrf_pwr_mgmt_timeout_handler(void * p_context)
        {
            PWR_MGMT_CPU_USAGE_MONITOR_UPDATE();
            PWR_MGMT_AUTO_SHUTDOWN_RETRY();
            PWR_MGMT_STANDBY_TIMEOUT_CHECK();
        }
    
        __STATIC_INLINE ret_code_t pwr_mgmt_timer_create(void)
        {
            ret_code_t ret_code = app_timer_create(&m_pwr_mgmt_timer,
                                                   APP_TIMER_MODE_REPEATED,
                                                   nrf_pwr_mgmt_timeout_handler);
            if (ret_code != NRF_SUCCESS)
            {
                return ret_code;
            }
    
            return app_timer_start(m_pwr_mgmt_timer, APP_TIMER_TICKS(1000), NULL);

    This timer seems create event each second and wake up my system. It's seems to be usefull to go into system power off. But in my case ( system on ) it seems to be problematic.

    So i disabled in sdk_config.h     #define NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY 0

    to not enable this timer. I don't have this waveform each second now.

    Questions:

    1.I'm using debugger, and i 'm able to block after calling idle_state_handle 2 times ( one time is not engough and program continue. After two i see debug pin going high and program stay here. Once i move my accelerometre, it wakes up and program continue. How can i check why i need to call two times. Is it a clean way to avoid this please ?

    Otherwise next, it advertise i can connect so that's great. Just still few details to debug but that's my job :D

  • I have issue with my algo : i start, configure all (no advertising) , then go into sleep mode, wake up, start state ADVERTISING, connect read sensors then i disconnect with smartphone and want to go back to sleep mode.But as advertising in already in execution , program goes over sleep mode because i guess softdevvice makes event with advertising. I tried to use 

    err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
    APP_ERROR_CHECK(err_code);

    But it seems to not stop advertising, and i can(t go into sleep mode anymore through the two call to idle_state_handle .

    What could be the good state machine with good function call to be able to go in sleep mode after starting advertising  please ? 

    Thanks a lot !

  • By default, the examples will start advertising in the BLE_GAP_EVT_DISCONNECTED event in ble_advertising.c if p_advertising->adv_modes_config.ble_adv_on_disconnect_disabled == false, which it is by default.

    Try to set 

    init.config.ble_adv_on_disconnect_disabled = true;

    in advertising_init() in your main.c file.

Reply Children
No Data
Related