Boron RTC not retaining time after System.reset

Using Boron 2G/3G, Device OS version 2.1.0, LiPO battery and 5V power connected.
I am having difficulty getting the RTC to store the current time in retained memory. I can successfully store my own variables in retained memory, and have them available after a software reset. According to the documentation (under Time.isValid()), RTC time should be stored under the same conditions as retained memory, but I am finding otherwise.

This is the code that I am using to test behaviour;

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);

SystemSleepConfiguration longSleep;

// Send Logging output over USB serial
SerialLogHandler logHandler;

// Persisted Variables
retained std::chrono::milliseconds longSleepDuration = 14min;
retained float timeZoneOffset = 0;
retained time_t UNIXTimestamp;

// Global variables
const std::chrono::milliseconds connectTimeout = 6min;
time_t lastSyncTimestamp;

void setup() {
  System.enableFeature(FEATURE_RETAINED_MEMORY);
  
  // Set time zone, and Local Time format
  Time.zone(timeZoneOffset);
  Time.setFormat(TIME_FORMAT_ISO8601_FULL);
  
  // Set graceful cloud disconnect, 5 seconds timeout
  Particle.setDisconnectOptions(CloudDisconnectOptions().graceful(true).timeout(5s));
  
  // Long Sleep parameters
  longSleep.mode(SystemSleepMode::ULTRA_LOW_POWER);
  longSleep.duration(2min);
  
  // Make sure that the modem is off
  Particle.disconnect();
  Cellular.off();
  
  // Delay to allow for a serial connection
  delay(10s);
  
  // Display Local time
  if (Time.isValid()) {
    Log.info("Local Time : %s", Time.format().c_str());
  } else {
    Log.error("Local Time not Set");
    // Set from stored value if valid
    if (UNIXTimestamp > 0) {
      Time.setTime(UNIXTimestamp);
      Log.info("Time set to stored value : %s", Time.format().c_str());
    }
    
  }
  
  // Display stored timezone offset
  Log.info("Stored Timezone offset : %.2f", timeZoneOffset);
  
  Cellular.on();
  Particle.connect();
}

void loop() {
  // Wait for a connection to be established
  if (millis() > connectTimeout.count()) {
    Log.error("No cloud connection, resetting");
    delay(5s);
    System.reset(RESET_NO_WAIT);
  }
  
  if (Particle.connected()) {
    delay(5s);
    Particle.timeSyncedLast(lastSyncTimestamp);
    if (lastSyncTimestamp > 0) {
      Log.info("Time received from Particle Device Cloud was: %s", Time.timeStr(lastSyncTimestamp).c_str());
    } else {
      Particle.syncTime();
      waitUntil(Particle.syncTimeDone);
    }
    
    // Display Local time
    if (Time.isValid()) {
      Log.info("Local Time : %s", Time.format().c_str());
    } else {
      Log.error("Local Time not Set");
    }
    delay(1s);
    Log.info("Sleeping");
    Particle.disconnect();
    Cellular.off();
    System.sleep(longSleep);
    
    // Store timestamp before reset
    UNIXTimestamp = Time.now();
    
    System.reset(RESET_NO_WAIT);
  }
}

On the first run, this is the relevant parts of the logging output;

0000010280 [app] ERROR: Local Time not Set
0000010280 [app] INFO: Stored Timezone offset : 12.00
0000041030 [app] INFO: Time received from Particle Device Cloud was: Mon Aug  9 21:30:59 2021
0000041031 [app] INFO: Local Time : 2021-08-09T21:31:04+12:00
0000042032 [app] INFO: Sleeping

and this is what I get on second run;

0000010280 [app] ERROR: Local Time not Set
0000010281 [app] INFO: Time set to stored value : 2021-08-09T21:33:09+12:00
0000010281 [app] INFO: Stored Timezone offset : 12.00
0000054015 [app] INFO: Time received from Particle Device Cloud was: Mon Aug  9 21:33:59 2021
0000054016 [app] INFO: Local Time : 2021-08-09T21:34:04+12:00
0000055017 [app] INFO: Sleeping

So I can ‘manually’ store and set the time again, as a work-around, but either I have made an error, or the system is not behaving as described. Any ideas?? Thanks.

In your code below, try moving the System.enableFeature() outside of setup()

void setup() {
  System.enableFeature(FEATURE_RETAINED_MEMORY);
  
  // Set time zone, and Local Time format

perhaps like so:

STARTUP(System.enableFeature(FEATURE_RETAINED_MEMORY)); //corrected

// Persisted Variables
retained std::chrono::milliseconds longSleepDuration = 14min;
retained float timeZoneOffset = 0;
retained time_t UNIXTimestamp;

// Global variables
const std::chrono::milliseconds connectTimeout = 6min;
time_t lastSyncTimestamp;

void setup() {
  
  // Set time zone, and Local Time format

Here is a tip that might help:
https://community.particle.io/t/retained-memory-tips/38137

1 Like

IIRC there is no need for special treatment to keep the RTC (on Gen3 devices rather a RealTimeCounter than a RealTimeClock) persisting its count across a mere reset.
About this portion of the docs

https://docs.particle.io/reference/device-os/firmware/#isvalid--1

See information on Backup RAM (SRAM) for cases when RTC retains the time. RTC is part of the backup domain and retains its counters under the same conditions as Backup RAM.

This only means the same rules apply, not that the user needs to store the timestamp in retained memory.

However, to properly enable the retained memory it should be executed inside the STARTUP() section as shown in the link. Just calling that function from outside setup() will fail to build.

Thanks for catching my mistake! :slightly_smiling_face:

2 Likes

Thanks for the suggestions both of you.

I have moved the relevant line inside STARTUP(), but the behaviour is unchanged; the RTC does not retain time across a reset. I tried removing the RESET_NO_WAIT flag also, and that made no difference.

I note that the documentation for the retained memory feature has
System.enableFeature(FEATURE_RETAINED_MEMORY);
inside setup() rather than STARTUP().
From what I can see from testing, both options enable normal use of retained variables but neither has an effect on the RTC.

I just tested the same code on an Electron, and it seems that the RTC on the Electron does keep time after a software reset!

Relevant log from first run

0000010021 [app] ERROR: Local Time not Set
0000010022 [app] INFO: Stored Timezone offset : 0.00
0000041956 [app] INFO: Time received from Particle Device Cloud was: Tue Aug 10 08:08:12 2021
0000041957 [app] INFO: Local Time : 2021-08-10T08:08:17Z
0000042957 [app] INFO: Sleeping

and second run

0000010020 [app] INFO: Local Time : 2021-08-10T08:10:38Z
0000010020 [app] INFO: Stored Timezone offset : 0.00
0000038613 [app] INFO: Local Time : 2021-08-10T08:11:08Z
0000039613 [app] INFO: Sleeping

I have run out of device types to test, so if anyone feels like trying this test it might shed some light on where the problem lies. Thanks!

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.