cancel
Showing results for 
Search instead for 
Did you mean: 

Cache variable in RAM after software reset isn't working

MFrie.7
Associate II

For a specific task at my workstation, I need to cache a variable before the watchdog reset and query it again after the reset. For this I have implemented a timer that writes the variable to RAM just before the watchdog. For this I defined according to htt ps://andrehessling.de/2015/02/16/howto-remanent-data-after-microcontroller-software-reset/ a symbol _estack, which is at the end of the stack and then write with 

*((unsigned long *)(_estack)) = 0xDEADBEEF; into this variable. In the startup code I copy the content of the symbol to another symbol that is not overwritten in the startup code (I defined a noinit section in the linker file for this): 

 ldr r0, =_estack 

 ldr r1, [r0, #0] 

 ldr r2, =_blrequest 

 str r1, [r2, #0] 

 str r0, [r0, #0] 

As it turns out now, this works only conditionally. Sometimes it works and sometimes it doesn't. If I execute NVIC_SystemReset(); directly after writing from _estack, it doesn't work. But if I set a breakpoint on the line of NVIC_SystemReset(); it works.

If I just let the controller reset with the watchdog instead of NVIC_SystemReset(); sometimes it works and sometimes it doesn't (without any change in the code).

Why does this behavior exist and can I work around it somehow?

Best regards

Manuel

5 REPLIES 5

Which STM32?

In non-CortexM7, read back the memory position after writing (btw. you should qualify it as volatile).

In Cortex-M7, it's more complicated.

JW

MFrie.7
Associate II

Hi, thank you for your answer.

I'm using the STM32H755 M7.

To read it back, I simply:

  extern volatile uint32_t _blrequest;

  if (0xDEADBEEF == _blrequest)

  {

..

}

Best regards

Manuel

In Cortex-M, the stack pointer is decremented before push operation.

So the top of stack label (_estack) in linker scripts often points one byte after the end of a physical RAM block. Storing something at that address is hardly a good idea.

BSS or initialized data should work, if you read it in the startup code before it is initialized or zeroed.

As Pavel A. wrote, first check, if you write in valid portion of memory and in a properly aligned way (in other words, exactly what is value of _estack?)

Cortex-M7 is tricky.

The first thing which comes into mind are caches.

Then this:

https://community.st.com/s/question/0D50X0000AupcL4SQI/axi-sram-losing-last-few-writes-across-reset

JW

NEdom.1
Associate III

Don't know the tool chains you are using.​ Just show how I did in STM32CubeIDE using STM32F429.

In you flash.ld file, define a memory area that store your cached data.

/* Memories definition */
MEMORY
{
  CCMRAM    (xrw)        : ORIGIN = 0x10000000,   LENGTH = 64K
  RAM    (xrw)           : ORIGIN = 0x20000000,   LENGTH = 190K
  SHARED_DATA    (xrw)   : ORIGIN = 0x2002F800,   LENGTH = 2K  
  FLASH    (rx)          : ORIGIN = 0x8000000,    LENGTH = 128K
}
/* This will place the magic values not be cleared by software system reset */
  .magicSection (NOLOAD):
  {
  	. = ALIGN(4);
  	__magicSection_start__ = .;
  	*(.magicSection)
  	KEEP(*(.magicSection))
  	__magicSection_end__ = .;
  	. = ALIGN(4);
  } >SHARED_DATA
  /*check if SHARED_DATA usage exceeds MY_MEMORY size */
  ASSERT(LENGTH(SHARED_DATA) >= (__magicSection_end__ - __magicSection_start__), "SHARED_DATA memory overflowed !")

In this way, the SHARED_DATA will be no touched after a soft reset.

In your code , declare data that using this cached area.

SharedData_t sharedMagic __attribute__((section(".magicSection")));

You can write a key into this memory and test it after startup to see it is a cold power up or a hot reset.

if(!testMagicHash(sharedMagic.MAGIC_HASH)){
  	INFO_PRINT("Booting from power off.....\n");
  	initMagicHash(sharedMagic.MAGIC_HASH);
    sharedMagic.retryCount = 0;
  }