Due RTC with low power backup mode

Hi, we are building a custom board around the Due design for a mixing machine and plan to utilise the onboard RTC with a lithium coin battery. I understand the power supply to the VDDBU (power that RTC uses) on MCU needs to be split out as the standard Due board ties it together with the 3.3V rail, fairly straightforward by the looks of it and our battery will keep the RTC alive and nothing else.

I have used the RTCDue library (GitHub - MarkusLange/RTCDue: Library for the RTC from the Arduino Due) which works nicely to read and write the RTC, thanks Markus. So far so good.

Now, once our machine is powered off (either deliberately by the user or unexpectedly due to power cut which we'll handle with a capacitor on the supply side to give us time to trigger the shutdown), obviously we need to put the MCU to sleep and let the battery keep the RTC ticking over.

My understanding is the best mode to use is the SAM backup mode. Essentially we want to be able to wake the device on a pin interrupt (ie user presses a button, or power is restored) and re-enter Loop() or at least reboot the chip from scratch. The chip doesn't need to be doing anything other than keeping the RTC going when asleep. We'll have all our machine parameters stored in flash so can restore our state regardless of where the code re-enters at wake point.

Now I've read everything I can about the various sleep, wait and backup modes and tried all variants of examples in the forums without any luck. By that I mean pmc_enable_sleepmode(0) doesn't seem to enter sleep (or if it does it instantly re-wakes) and pmc_enable_backupmode() and pmc_enable_waitmode() also seemingly do nothing so clearly there is more to it than a couple of lines.

So the questions are :

  • Has anybody successfully done something similar to the above using backup mode ?
  • Is it as simple as using the ASF library functions above or do we need to disable/enable peripherals one by one ?
  • Would you be kind enough to share your working code ?
  • What power/current does the SAM MCU pull when in backup mode and therefore what size battery is recommended for keeping the RTC alive for 10+ years ?

Thanks for any help good people of the interwebs......*8)

There are several ways to enter and exit from back up mode, here is one of them in the snippet below. In all cases, when you exit from back up mode, you return in the setup().

I used RTT to provide an interrupt, you could choose another one.

To further reduce power consumption in low power mode, you will need to disable the maximum of your peripherals before entering this mode ( and maybe clock your uc to the minimum frequency just before ).

Do not power down your uc in the middle of a backup procedure or your board will become a brick for about 5 minutes.

/*******************************************************************
             Backup mode with Alternate Way and wake up on Interrupt
*******************************************************************/

#define   SUPC_KEY                    (0xA5)
const uint32_t AL = 5;  // Alarm Timestamp = AL * T seconds

void setup() {

Serial.begin(250000);

RTT->RTT_MR = RTT_MR_RTTRST
            | RTT_MR_RTPRES (0x8000)  // T = 1 second
            | RTT_MR_ALMIEN;  
           
RTT->RTT_AR = RTT_AR_ALMV(AL); 
           
NVIC_DisableIRQ       ( RTT_IRQn ); 
NVIC_ClearPendingIRQ  ( RTT_IRQn ); 
NVIC_SetPriority      ( RTT_IRQn, 0 ); 
NVIC_EnableIRQ        ( RTT_IRQn ); 

SUPC->SUPC_WUMR |= SUPC_WUMR_RTTEN;
             
Serial.println("\n\rHELLO ALL !!"); 
Serial.print("GPBR[0] = ");Serial.println(GPBR->SYS_GPBR[0]); 
delay(1000);
}

void loop() {
 
GPBR->SYS_GPBR[0] += 1;            // Increment one of the 8 General Purpose Backup Registers

if (GPBR->SYS_GPBR[0] < 4) {

Serial.print("Entering backup mode : Do NOT stop the software now  |:");
Serial.end();                     // Exit from Serial

//alternate way to enter backup mode 
SUPC->SUPC_CR = SUPC_CR_VROFF_STOP_VREG | SUPC_CR_KEY(SUPC_KEY); 

}

Serial.println("Definitive Exit from backup mode");
Serial.println("Now you can stop the software");
Serial.println(GPBR->SYS_GPBR[0]); 
delay(5000);

}

void RTT_Handler () {
  RTT->RTT_SR;

}

Thanks, I'll wrap my head around it, give this a try and let you know. :slight_smile: