This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Retain RTC during soft reset

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
Parents
  • stack pointer initialised, yes and no. A 'real' reset takes the stack pointer from 0x00000000 and sets it before it does anything else so in that way, no it's not reset by what you're doing. However just about every startup assembler file I've seen ever also quite early on sets the SP to something valid explicitly. If you're getting all the way into main() then it's very unlikely the SP hasn't been set 2 or 3 times and is valid. So you probably have a different error.

    Not sure that faking reset is the best way to go, it's hard to cover all the bases and get the chip in the same state it was in before. As John DeWitt suggests below, how about using a retained register and properly resetting. Also, if you just write it to a location in powered-on RAM, does that work, RAM isn't cleared by reset AFAIK.

Reply
  • stack pointer initialised, yes and no. A 'real' reset takes the stack pointer from 0x00000000 and sets it before it does anything else so in that way, no it's not reset by what you're doing. However just about every startup assembler file I've seen ever also quite early on sets the SP to something valid explicitly. If you're getting all the way into main() then it's very unlikely the SP hasn't been set 2 or 3 times and is valid. So you probably have a different error.

    Not sure that faking reset is the best way to go, it's hard to cover all the bases and get the chip in the same state it was in before. As John DeWitt suggests below, how about using a retained register and properly resetting. Also, if you just write it to a location in powered-on RAM, does that work, RAM isn't cleared by reset AFAIK.

Children
No Data
Related