I'm working on a battery powered system which needs to keep track of an absolute time stamp. So I need the RTC module and some kind of energy saving mode. As the RTC is not running in System Off I use the System On sleep mode when Idle.
To decrease the current consumption in sleep mode, I also disable RAM beforehand. I noticed that I need to keep RAM Block3 enabled to be able to wake up again (I guess because it contains the Stack, right?) However, the content of RAM Blocks 0,1,2 is not useable after wake up, so I perform a soft reset. Problem is that this resets the RTC COUNTER register. Is there a possibility to retain this register?
I was also thinking about making the compiler use RAM Block 3 for a part of my code, which then will still be usable after wake up and where I would save the counter value before resetting. I think I need to change the linker script but I couldn't find how exactly. Any ideas? (I'm using GCC 5.3.0)
I'm also using soft device S110, which I disable before entering sleep mode. Here's the code snippet where sleep mode is initiated:
sd_softdevice_disable();
// Disable RAM-Blocks 0,1,2 (Block 3 must stay enabled as it contains the Stack)
NRF_POWER->RAMON = POWER_RAMON_OFFRAM0_RAM0Off << POWER_RAMON_OFFRAM0_Pos
| POWER_RAMON_OFFRAM1_RAM1Off << POWER_RAMON_OFFRAM1_Pos
| POWER_RAMON_ONRAM0_RAM0Off << POWER_RAMON_ONRAM0_Pos
| POWER_RAMON_ONRAM1_RAM1Off << POWER_RAMON_ONRAM1_Pos;
NRF_POWER->RAMONB = POWER_RAMONB_OFFRAM2_RAM2Off << POWER_RAMONB_OFFRAM2_Pos
| POWER_RAMONB_OFFRAM3_RAM3Off << POWER_RAMONB_OFFRAM3_Pos
| POWER_RAMONB_ONRAM2_RAM2Off << POWER_RAMONB_ONRAM2_Pos
| POWER_RAMONB_ONRAM3_RAM3On << POWER_RAMONB_ONRAM3_Pos;
__set_PRIMASK(1); // prevent execution of isr when waking up
__WFI(); // enter sleep mode
/* RAMON and RAMONB Registers are retained. Therefore RAM needs to be enabled
prior to soft reset in order to make it accessible for the next startup. */
NRF_POWER->RAMON = POWER_RAMON_OFFRAM0_RAM0On << POWER_RAMON_OFFRAM0_Pos
| POWER_RAMON_OFFRAM1_RAM1On << POWER_RAMON_OFFRAM1_Pos
| POWER_RAMON_ONRAM0_RAM0On << POWER_RAMON_ONRAM0_Pos
| POWER_RAMON_ONRAM1_RAM1On << POWER_RAMON_ONRAM1_Pos;
NRF_POWER->RAMONB = POWER_RAMONB_OFFRAM2_RAM2On << POWER_RAMONB_OFFRAM2_Pos
| POWER_RAMONB_OFFRAM3_RAM3On << POWER_RAMONB_OFFRAM3_Pos
| POWER_RAMONB_ONRAM2_RAM2On << POWER_RAMONB_ONRAM2_Pos
| POWER_RAMONB_ONRAM3_RAM3On << POWER_RAMONB_ONRAM3_Pos;
NVIC_SystemReset(); // Perform soft reset because content of RAM was lost during sleep mode