2023-05-26 04:42 AM
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
2023-05-26 06:09 AM
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
2023-05-26 06:18 AM
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
2023-05-26 09:08 AM
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.
2023-05-27 08:24 AM
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
2023-05-27 09:08 PM
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;
}