Maximum sleep time nRF52840

Hallo,

currently I'm testing sleep variants for nRF52840. I'm using nRF52840-DK and Zephyr build v2.7.99-ncs1-1.

By means of the RTC timer one can handle sleeping quite comfortable:

z_nrf_rtc_timer_set((int32_t)rtc_chan, rtc_ticks, rtc_expiry_handler, NULL);

k_sleep(K_FOREVER);

will set the timer and after that line one can sleep forever. An expiring timer (after rtc_ticks) will call the rtc_expiry_handler function, where a wake-up of the main thread can be done.The value for rtc_ticks is calculated by means of:

rtc_ticks = z_nrf_rtc_timer_get_ticks(t);

"t" in the end is an uint32_t type.

My test implementation runs well in a small test app for sleep times up to 512 seconds. For longer times z_nrf_rtc_timer_get_ticks(..) comes up with error -22. First I thought that there is an issue of register length, since in z_nrf_rtc_timer_get_ticks(..) there is a COUNTER_SPAN, which is defined as

#define COUNTER_BIT_WIDTH 24U
#define COUNTER_SPAN BIT(COUNTER_BIT_WIDTH)

But I realised that for the 512 second case the number of ticks is 16851770, which is already more than a 24-bit-value. In general, much higher tick values should be possible - the return value of z_nrf_rtc_timer_get_ticks(..) is an uint64_t.

Therefore the question: What should I do to extend the sleep time of (much) more than 512 seconds?

Parents Reply Children
  • Hallo Kenneth,

    shortly the intermediate result so far:

    - I still can't find a function to set a prescaler value directly from a main function running at nRF.

    - I can modify in /nrfx/hal/nrf_rtc.h the function nrf_rtc_cc_set(..) by adding a simple prescaler setting, e.g.:

      p_reg->PRESCALER = (uint32_t)1;

      But it is not my intension to modify the nRF or Zephyr sources.

    - With the modification, I can double short periods (longer values I didn't test so far, but I assume the doubling will work). But in that case I also modify the uptime counter, which runs slower too - the reported time stays the same, even if the sleep time effectively doubles. The reason for that is in my current opinion that in /drivers/timer/nrf_rtc_timer.c there is a fixed definition: #define RTC NRF_RTC1 (line 21), which means there is no chance to change the RTC used maybe to NRF_RTC2.

    So I'm still looking for a feasible solution.

    Kind regards

    Axel

  • Maybe you are spending much time on something that can be solved different ways, for instanc if you want to run something every 1000seconds, you can just set a 500second timeout, and have a counter in the 500second timeout handler to know that you need to run something every second time.

    Doing this way will have no impact on the sleep current, e.g. assume wakeup of 50us every 500second for 5mA = ~0.5nA.

    Kenneth

  • Hallo Kenneth,

    you're right, there might be different ways to solve those questions. So e.g. I'm not really sure if I need an uptime counter - if not, I can also deal with the solution described above (and doing this little source modification, what I want to avoid normally). But the general question in this case is, why I can't use the possibilities the IC offers. In my case with nRF52840 I have three RTCs, and by means of a prescaler setting I could realise really long sleeping periods. But there is no access to it so far.

    I can imagine that there are a lot of problems to be solved when integrating Zephyr, BlueTooth and a lot of different ICs, and the RTC topic is not the most important one. But it would be nice to keep this on the agenda.

    Even if I might earn the Necromancer Achievement again, I'll report my final solution in case there is one.

    Best regards

    Axel

Related