XIAO SAMD21 strange reset issue using backup registers

Hi, I have the following code which should handle a sleep persistence register. It almost works.

Upon cold boot, I do three blinks which makes me identify when a cold boot occurs. Then I write the magic number to the backup register and still within the setup function (!) send the XIAO to a timered sleep for the first time. (I cannot remove this sleep function as the loop function will to myRtc.begin which won’t when coming directly from setup which has already done myRtc.begin).

After waking up, it continues into the while() loop as the XIAO continues the code after where it went to sleep (as compared to an ESP32 which will re-run the code from the beginning after deep sleep wake up).

This is where the odd thing happens. The sanity check (reading the magic number from the register) fails and the XIAO reboots. BUT: after ths NVIC_SystemReset(); the code works as designed and the XIAO shows the heartbeat every 5 seconds. Tested for hours.

Why does the first reset occur?

Thank you all in advance!

#include "RTC_SAMD21.h"
#include "DateTime.h"
#include <EnergySaving.h>

RTC_SAMD21 myRtc;
EnergySaving myPowSave;

#define MAGIC_NUMBER 0xDEADBEEF
#define MAGIC_REGISTER 0 // Use backup register 0

volatile uint32_t* backupRegister = (volatile uint32_t*)(0x40001450 + 4 * MAGIC_REGISTER);

void safeDelay(unsigned long duration); // forward declare function

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); // LED off (active LOW)

  // blink yellow led three times (boot signature)
  pinMode(LED_BUILTIN, OUTPUT);
  for (int i = 0; i < 3; i++) {
    digitalWrite(LED_BUILTIN, LOW);
    delay(50);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(50);
  }
  safeDelay(2500);

  myRtc.begin();
  myPowSave.begin(WAKE_RTC_ALARM);

  PM->APBAMASK.reg |= PM_APBAMASK_RTC; // Enable RTC clock

  // Check for cold/warm boot
  if (*backupRegister != MAGIC_NUMBER) {
    *backupRegister = MAGIC_NUMBER; // Cold boot: Initialize
  }

  while (1) {

    // led heartbeat
    digitalWrite(LED_BUILTIN, LOW);
    safeDelay(10);
    digitalWrite(LED_BUILTIN, HIGH);

    myRtc.begin();

    // re-enable RTC clock after wake-up
    PM->APBAMASK.reg |= PM_APBAMASK_RTC;

    // reset if sanity check fails
    if (*backupRegister != MAGIC_NUMBER) {
      NVIC_SystemReset(); // cold boot if check failed
    }

    // Configure RTC alarm for 5 seconds
    DateTime timeNow = myRtc.now();
    DateTime alarmTime = timeNow + TimeSpan(5); // Wake in 5 seconds
    myRtc.setAlarm(alarmTime);
    myRtc.enableAlarm(myRtc.MATCH_SS);

    // Enter deep sleep
    myPowSave.standby();

    safeDelay(1000);

  }
}

void loop() {
  // never happens (turn on yellow LED)
  digitalWrite(LED_BUILTIN, HIGH);
  safeDelay(5000);
}

void safeDelay(unsigned long duration) {
  unsigned long start = millis();
  for (;;) {
    unsigned long now = millis();
    if (now - start >= duration) { return; }
    yield();
  }
}

You don’t need NVIC_SystemReset() if the RTC domain is properly retained.