Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: can RAM keep contents after reset?

  1. #1
    Junior Member
    Join Date
    Oct 2021
    Posts
    14

    can RAM keep contents after reset?

    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
    	
      .my_data1 (NOLOAD) :    {
        KEEP(*(.myRAMData1))
      } > RAM
      
    
    	.bss.dma (NOLOAD) : {
    		*(.dmabuffers)
    		. = ALIGN(32);
    	} > RAM
    
    	.bss.extram (NOLOAD) : {
    		*(.externalram)
    	} > ERAM
    
      .my_data2 (NOLOAD) :    {
        KEEP(*(.myRAMData2))
      } > RAM
    
    
    . . .

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,081
    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:
      arm_dcache_flush( vv, sizeof( int) * 2 );
    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 by defragster; 10-14-2021 at 09:36 PM. Reason: add cache note

  3. #3
    Junior Member
    Join Date
    Oct 2021
    Posts
    14
    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);
    	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;
    	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
    }

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,081
    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;
      arm_dcache_flush( vv, sizeof( int)*2 );
      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;
      }
      else {
        vv[0]++;
        vv[1]++;
      }
      arm_dcache_flush( vv, sizeof( int) * 2 );
      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:
    }

  5. #5
    Junior Member
    Join Date
    Oct 2021
    Posts
    14
    That's it!!! Thank you so much!!!

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    15,081
    Quote Originally Posted by Jian View Post
    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

  7. #7
    Junior Member
    Join Date
    Oct 2021
    Posts
    14
    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.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •