System.sleep for more granular time than seconds on Gen3

My query is about Xenon but could be applied to any Gen3 device. In an effort to spin out battery life I am making as much use of System.sleep({},{},seconds); as possible during a sensor reading cycle. I would like to have a bit more granular control over the stop time than in units of seconds. Is there anyway to do this with the existing device OS API?

Hi @armor, there’s currently no support for this in Device OS, unfortunately. I’m told it should be possible with Gen3 devices, we just don’t have a readymade implementation for this at present.

Thanks for replying so quickly. Would there be a recommended ‘hack’ - I guess I could look at the source but just wondered if there might be a work around.

Not that I can think of apart from, as you suggest, going to the source itself. Sorry about that!

Looks like it’s

System.sleep calls system_sleep_pin_impl which then calls this guy:

int ret = HAL_Core_Enter_Stop_Mode_Ext(pins, pins_count, modes, modes_count, seconds, nullptr);

Which thens sets up an RTC event

        // Reconfigure RTC2 for wake-up
        exit_conditions |= STOP_MODE_EXIT_CONDITION_RTC;
        NVIC_ClearPendingIRQ(RTC2_IRQn);

        nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_TICK);
        nrf_rtc_event_enable(NRF_RTC2, RTC_EVTEN_TICK_Msk);
        // Make sure that RTC is ticking
        // See 'TASK and EVENT jitter/delay'
        // http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52840.ps%2Frtc.html
        while (!nrf_rtc_event_pending(NRF_RTC2, NRF_RTC_EVENT_TICK)) {
            ;
        }
        nrf_rtc_event_disable(NRF_RTC2, RTC_EVTEN_TICK_Msk);
        nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_TICK);

        nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_0);
        nrf_rtc_event_disable(NRF_RTC2, RTC_EVTEN_COMPARE0_Msk);

        // Configure CC0
        uint32_t counter = nrf_rtc_counter_get(NRF_RTC2);
        uint32_t cc = counter + seconds * 8;
        NVIC_EnableIRQ(RTC2_IRQn);
        nrf_rtc_cc_set(NRF_RTC2, 0, cc);
        nrf_rtc_event_clear(NRF_RTC2, NRF_RTC_EVENT_COMPARE_0);
        nrf_rtc_int_enable(NRF_RTC2, NRF_RTC_INT_COMPARE0_MASK);
        nrf_rtc_event_enable(NRF_RTC2, RTC_EVTEN_COMPARE0_Msk);

So it looks like the RTC is ticking every 0.125 sec. So, you could, in theory, run something similar in your own function before calling the sleep function. It’s definitely a hack and would require some testing but doable!

In the end, it’s better to connect the sensors’ interrupt pin to a pin on the Particle board that way it’s async and you wouldn’t have this problem. :wink:

1 Like

I assume you are using manual mode?

When your not using cloud/mesh functions you can call a Wait For Event. This should save you some power. It should drop your idle power usage from 16mW to 6mW. The system will stop the CPU until an event occurs, like the Systick, RTC timers, other interrupt.
Also don’t forget to turn off the pulsing LED.

__WFE();