How to use the internal RTC on nRF52833 SoC to keep system time across reboots

Hello,

I need your help on how to use the internal RTC on nRF52833 SoC to keep the system time under zypher.

I need the RTC to keep its time after,

1- Reboots

2- Sleep using k_sleep( Duration ) 

3- System Off mode, although this use case may not be necessary but still interested if it is possible.

Finally, looking at the nRF52833 RTC registers I could not find a way of setting the time. Is there one?

Kind regards

Mohamed

Parents Reply
  • You can only write once to the UICR registers and need to erase the whole UICR if you want any entirely different data to be stored in these registers. So I do not recommend writing to UICR if you need to update this over period of time. Best is to use Settings in Zephyr to write something to the reserved flash page before shutting the core and read from the stored value when waking up. You can still use the read value to add on top of the RTC value to get an essence of tracking the time from the start.

Children
  • Hi Susheel,

    Thank you for the tips on using the UICR. 

    Let's go back a step to my original question. I wanted to use the RTC to keep system time and you came back with three different suggestions but you never explained why the RTC cannot be used in this use case. 

    1- Persistent registers

    Please answer my question on persistent registers above. Also, If you do a search for '?' you will find all my questions. Please answer them if you can. Thank you.

    2- UICR

    You can only write once to the UICR registers and need to erase the whole UICR if you want any entirely different data to be stored in these registers. So I do not recommend writing to UICR if you need to update this over period of time.

    So, UICR is out of the running.

    3- Settings

    Best is to use Settings in Zephyr to write something to the reserved flash page before shutting the core and read from the stored value when waking up. You can still use the read value to add on top of the RTC value to get an essence of tracking the time from the start.

    I will have a look at the 'Settings' route but before I do I would like to understand why I can't use the RTC on its own to keep system time?

    Thank you.

    Kind regards

    Mohamed

  • Learner said:
    Please answer my question on persistent registers above. Also, If you do a search for '?

    This is what I found when I found searched for "?"

    Finally, looking at the nRF52833 RTC registers I could not find a way of setting the time. Is there one?

    None of the RTC's peripheral on embedded devices I know tells you time but tell you number of ticks. The frequency of tick increment depends on your configuration on PRESCALER: For actual time you either need to rely on the higher level libraries or utilities from the RTOS.

    Learner said:
    So, UICR is out of the running.

    If you want to update it more than once, then yes, UICR is not a solution for you.

    Learner said:
    I will have a look at the 'Settings' route but before I do I would like to understand why I can't use the RTC on its own to keep system time?

    Using RTC on its own to keep system time is not an issue here. That is very simple and can be used directly by accessing RTC register and converting the ticks read into any time unit you want. But I assumed that your main issue is to keep track of time between reboots. That is the trickiest part and that is where you need to access persistent storage. 

    I think we are mixing up two of your requriements.

    1. Keeping track of time can be done very easily using Zephyr utitities or other kernel timing API. You do not need to access RTC registers directly for this.
    2. Retaining time between reboots. This needs special handling from your application to save the previous time before reboot persistently and accessing again after new reboot to restore older value. You cannot restore old value into RTC register but you need to have your own application memory (static variable) or similar to remember the old offsets of time before reboot.

     

  • Did you try code what I have wrote? I dont have behavior you wrote. After reset the value = +1

  • Hi Susheel,

    Thank you.

    Finally, looking at the nRF52833 RTC registers I could not find a way of setting the time. Is there one?

    None of the RTC's peripheral on embedded devices I know tells you time but tell you number of ticks. The frequency of tick increment depends on your configuration on PRESCALER: For actual time you either need to rely on the higher level libraries or utilities from the RTOS.

    My question was about setting the RTC time (ticks) not reading it. I could not find a register that would allow such operation. 

    But I assumed that your main issue is to keep track of time between reboots. That is the trickiest part and that is where you need to access persistent storage. 

    Yes, this ticket, as the title suggests, is about keeping time between reboots. 

    You cannot restore old value into RTC register but you need to have your own application memory (static variable) or similar to remember the old offsets of time before reboot.

    I will probably have to store the old value in flash and read it back after reboot...

    Also, what does the first line in red mean?

    This information applies to the following SoftDevices: S130, S132, S332

    I do not know which SoftDevice I am using. How do I find out?

    Kind regards

    Mohamed

  • Not quite what you are looking for, but there is a way which seems to work fairly reliably; however note the only reliable solution is to use an external battery-backed RTC unless you can find a way to use the 2 x 8-bit GPREGRET registers, the latter by perhaps storing number of seconds since last flash write of full time field (note some bootloaders use GPREGRET registers for bootup modes so they may not be available).

    The trick which I use is to note that internal RAM is never reset, though it may be "corrupted". Provided one or more RAM areas are not selected for power down during Off, one or more instances of the tick can be held and used to continue operation after a reset. Memory corruption is detected by loading a unique value into the same RAM area. Time of startup after a reset is lost but that time may be measured (manual calibration step) and used as compensation after the reset provided the RTC is always restarted before any other time-consuming action. The example here ticks at 8 times per second, but typically once per second might be more appropriate. Note this method will not of course work across an extended power removal such as when a battery is removed.

    // Place following data in section .noinit so it doesn't get wiped on a reset
    #pragma default_variable_attributes = @ ".noinit"
      static volatile uint32_t mIamInitializedRTC; // Valid data indication for this data
      // Packet Sample Time timer interrupt, typically 8 times per second
      static volatile uint32_t mPacketSampleTimer;
      // 32-bit unsigned RTC time: number of 125 millisecond ticks from Jan 1st 2024
      static volatile uint32_t mPacketSampleTimer;
    #pragma default_variable_attributes =
    // End - Place following data in section .noinit so it doesn't get wiped on a reset
    
    bool CheckPacketSampleTimeValid(void)
    {
        // See if RTC data is valid - Use unique device ID as the valid signature
        return (mIamInitializedRTC == NRF_FICR->DEVICEID[0]);
    }
    
    void InitializeRTC(void)
    {
        // See if RTC data is valid - Use unique device ID as the valid signature
        if (!CheckPacketSampleTimeValid())
        {
           // RTC backup failed, clear the stored time
           mPacketSampleTimer = 0;
           // Indicated data is now valid - Use unique device ID as the valid signature
           mIamInitializedRTC = NRF_FICR->DEVICEID[0];
        }
        // Configure RTC and add in known reset startup time
        start lfclk and rtc
    }
    .

Related