can RAM keep contents after reset?

Jian

Member
For Teensy 4.1, I like to see some RAM values in custom sections to be kept after reset (not power off). The following is my code and linker script. What I can see from this code is that v1 and v2 always get random value after reset, rather than the previously assigned value. Is that the correct behavior? Is there any other way to reset the controller so the v1, v2 will be kept?

Code:
. . .
__attribute__((used)) __attribute__((section(".myRAMData1"))) int v1;
__attribute__((used)) __attribute__((section(".myRAMData2"))) int v2;

extern "C" int main(void)
{

	Serial.begin(230400);
	char buf[100];
	sprintf(buf,"after reset: v1=%d, v2=%d",v1,v2);
	Serial.println(buf);
	v1 = 100;
	v2 = 108;
	sprintf(buf,"assigned: v1=%d, v2=%d",v1,v2);
	Serial.println(buf);
	delay(1000);
	Serial.println("restart");
	delay(1000);
        SCB_AIRCR = 0x05FA0004;    // firmware reset
}


Code:
. . .
SECTIONS
{
	.text.progmem : {
		KEEP(*(.flashconfig))
		FILL(0xFF)
		. = ORIGIN(FLASH) + 0x1000;
		KEEP(*(.ivt))
		KEEP(*(.bootdata))
		KEEP(*(.vectors))
		KEEP(*(.startup))
		*(.flashmem*)
		*(.progmem*)
                . = ALIGN(4);
                KEEP(*(.init))
                __preinit_array_start = .;
                KEEP (*(.preinit_array))
                __preinit_array_end = .;
                __init_array_start = .;
                KEEP (*(.init_array))
                __init_array_end = .;
		. = ALIGN(16);
	} > FLASH
	

	.text.itcm : {
		. = . + 32; /* MPU to trap NULL pointer deref */
		*(.fastrun)
		*(.text*)    
		. = ALIGN(16);
	} > ITCM  AT> FLASH

	.ARM.exidx : {
		__exidx_start = .;
		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
		__exidx_end = .;
	} > ITCM  AT> FLASH

	.text.itcm.padding (NOLOAD) : {
		. = ALIGN(32768);
	} > ITCM

	.data : {
		*(.rodata*)
		*(.data*)
		. = ALIGN(16);
	} > DTCM  AT> FLASH

	.bss ALIGN(4) : {
		*(.bss*)
		*(COMMON)
		. = ALIGN(32);
		. = . + 32; /* MPU to trap stack overflow */
	} > DTCM
	
[COLOR="#FF0000"]  .my_data1 (NOLOAD) :    {
    KEEP(*(.myRAMData1))
  } > RAM[/COLOR]
  

	.bss.dma (NOLOAD) : {
		*(.dmabuffers)
		. = ALIGN(32);
	} > RAM

	.bss.extram (NOLOAD) : {
		*(.externalram)
	} > ERAM

[COLOR="#FF0000"]  .my_data2 (NOLOAD) :    {
    KEEP(*(.myRAMData2))
  } > RAM
[/COLOR]

. . .
 
Using the following - should show the values survive a Warm restart:
DMAMEM int v1;
DMAMEM int v2;

DMAMEM is not forcibly reset/zeroed like RAM1 on startup.

<edit> BUT writes to DMAMEM go quickly to processor cache - not the underlying storage!!!
When doing this to assure the data will be present on WARM restarts the cache area of interest must be flushed!!!

Code:
[B]  arm_dcache_flush( vv, sizeof( int) * 2 );[/B]

Though the first lower portion (32KB-64KB) of DMAMEM does get touched during the boot process for secure boot.

This explicit manual pointer to DMAMEM is outside any maintained or known data allocation method - so malloc() or other use growing from the bottom could violate this area without notice.
This is an extreme alloc of 430KB for an LFS RamDisk:
Code:
#define LFS_BUF_SIZE 430*1024
void *LFS_BUF = (void*)(0x2027ff00-LFS_BUF_SIZE); // RAM2 Addr :: typically survives Restart/Upload, avoid lower 64KB 0x2020000, upper CrashReport area

So something like this should give two safe ints to use that will persist across warm restarts and uploads:
Code:
int *vv = (int*)((void*)(0x2027ff00- 2*sizeof(int))); // use as vv[0] and vv[1] with "2*sizeof(int)"

<edit>
psudo code doing this might give usable persistent memory in the same place as well - as long as other mallocs don't shift anything:
> int * skipdynamic = malloc(64*1024)
> int * vv = malloc( sizeof( int ) * 2 )
> // use as vv[0] and vv[1] with "2*sizeof(int)"
 
Last edited:
I tried both define v1, v1 at DMAMEM region and using the "int *vv = (int*)((void*)(0x2027ff00- 2*sizeof(int)));" trick. none of them worked. Still getting the output as the following:
-----------------------------------------------------
after reset: v1=1698846984, v2=-1207963969
assigned: v1=100, v2=108
restart
-----------------------------------------------------

Code:
extern "C" int main(void)
{
	Serial.begin(230400);
	[COLOR="#FF0000"]int *vv = (int*)((void*)(0x2027ff00- 2*sizeof(int)));[/COLOR]
	char buf[100];
	sprintf(buf,"after reset: v1=%d, v2=%d",vv[0],vv[1]);
	Serial.println(buf);
	vv[0] = 100;
	vv[1] = 108;
	sprintf(buf,"assigned: v1=%d, v2=%d",vv[0],vv[1]);
	Serial.println(buf);
	delay(1000);
	Serial.println("restart");
	delay(1000);
        SCB_AIRCR = 0x05FA0004;    // firmware reset
}
 
Opps - forgot ....

That only writes to the cache and restart will leave it there added : arm_dcache_flush( vv, sizeof( int)*2 );

Code:
void setup() {
    Serial.begin(230400);
  int *vv = (int*)((void*)(0x2027ff00- 2*sizeof(int)));
  char buf[100];
  sprintf(buf,"after reset: v1=%d, v2=%d",vv[0],vv[1]);
  Serial.println(buf);
  vv[0] = 100;
  vv[1] = 108;
  [B]arm_dcache_flush( vv, sizeof( int)*2 );[/B]
  sprintf(buf,"assigned: v1=%d, v2=%d",vv[0],vv[1]);
  Serial.println(buf);
  delay(1000);
  Serial.println("restart");
  delay(1000);
//        SCB_AIRCR = 0x05FA0004;    // firmware reset
}
void loop() {
  // put your main code here, to run repeatedly:
}

And this:
Code:
void setup() {
  Serial.begin(230400);
  int *vv = (int*)((void*)(0x2027ff00 - 2 * sizeof(int)));
  char buf[100];
  sprintf(buf, "after reset: v1=%d, v2=%d", vv[0], vv[1]);
  Serial.println(buf);
  if ( vv[0] > 1000000 ) {
    vv[0] = 100;
    vv[1] = 108;
  }
[B]  else {
    vv[0]++;
    vv[1]++;
  }
  arm_dcache_flush( vv, sizeof( int) * 2 );[/B]
  sprintf(buf, "assigned: v1=%d, v2=%d", vv[0], vv[1]);
  Serial.println(buf);
  delay(1000);
  Serial.println("restart");
  delay(1000);
  SCB_AIRCR = 0x05FA0004;    // firmware reset
}
void loop() {
  // put your main code here, to run repeatedly:
}
 
That's it!!! Thank you so much!!!

Glad to help!

It can be a bit cleaner :: int *vv = (int*)(0x2027ff00 - 2 * sizeof(int));

But that hardcoded number "0x2027ff00" is the 1062's top of DMAMEM less the bytes used for CrashReport storage.

Coming down from the top avoids the 1062 Secure boot thrashing of the lower KB's of DMAMEM and also stays clear of malloc() that builds upwards.

But nothing protects that from other use or change ... and using that ugly number ... 0x2027ff00
 
That makes all the sense. The key is flashing the cache. I knew it may have something to do with the location of the RAM. That is why I had setup two separate sections for v1 and v2. At least v2 should have worked had I known the command to flash the cache. Thank you again.
 
Back
Top