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

Thread: Teensy 4.x Battery backed Non volitile memory

  1. #1
    Junior Member
    Join Date
    Jul 2017
    Posts
    4

    Teensy 4.x Battery backed Non volitile memory

    Howdy, all! This is as much of a check your work post as any. I was reading a previous post: https://forum.pjrc.com/threads/45854...-backed-NV-RAM
    regarding using the extra 28 free bytes of the 32 bytes of non-volatile battery-backed memory for run data I would like to keep after a restart.
    I would like to implement a solution like this on the 4.x boards but looking at the memory map at: https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf page: 1242 it appears that the battery-backed memory only allows for 4 bytes starting at address 0x400D4100. Firstly, am I even reading this correctly or even looking at the correct section of memory? I could not find in the teensy 4core where the RTC is even storing the time. I'm a little out of my pay grade here but trying to fake it as best I can.

    Aside: This data I wish to keep is only 12 bytes but is very volatile so EPROM isn't really suitable.

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,095
    There is NVRAM on the 1062 in the T_4.x's. There are 4 32 bit words.

    Below is code that shows it in use from Feb 2021 - discussed in a post somewhere ...
    > It did some things to show function including a 'r' Reset that picks up with the values intact.
    > Added a 't' command it seems that isn't in the startup printing: Looks to give some idea of the timing of doing multiple writes

    Key thing was finding this :: SNVS_LPCR |= (1 << 24); //Enable NVRAM - documented in SDK
    Frank B found that poking bits that were not documented in the manual IIRC.
    Code:
    // TWO ways to access as 4 32 bit DWORDS of NVRAM backed data
    // #define NVRAM_UINT32 ((uint32_t *)0x400D4100)
    uint32_t *NVRAM_UINT32 ((uint32_t *)0x400D4100);
    uint32_t tRam[4];
    
    elapsedMillis tSome;
    void setup() {
    	SNVS_LPCR |= (1 << 24); //Enable NVRAM - documented in SDK
    	Serial.begin(115200);
    	while (!Serial && millis() < 4000 );
    	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
    	tSome = 0;
    	Serial.print(" 'r':RESTART 'z':ZERO '?':INC 100 to each\n");
    	for ( int ii = 0; ii < 4; ii++ ) {
    		tRam[ii] = 0;
    	}
    }
    
    #define SNVS_LPGPR0      (IMXRT_SNVS.offset100)
    #define SNVS_LPGPR1      (IMXRT_SNVS.offset104)
    #define SNVS_LPGPR2      (IMXRT_SNVS.offset108)
    #define SNVS_LPGPR3      (IMXRT_SNVS.offset10C)
    
    void loop() {
    	if ( tSome >= 1000 ) {
    		tSome -= 1000;
    		for ( int ii = 0; ii < 4; ii++ ) {
    			Serial.print( '\t' );
    			Serial.print( NVRAM_UINT32[ii] );
    		}
    		Serial.println();
    		for ( int ii = 0; ii < 4; ii++ ) {
    			NVRAM_UINT32[ii]++;
    		}
    	}
    	while ( Serial.available() ) {
    		char cc = Serial.read();
    		if ( 'r' == cc ) {
    			SCB_AIRCR = 0x5FA0004;
    			while (true);
    		}
    		else if ( 'z' == cc ) {
    			Serial.print( "_ZERO_ NVRAM\n" );
    			for ( int ii = 0; ii < 4; ii++ ) {
    				NVRAM_UINT32[ii] = ii * 1000;
    			}
    		}
    		else if ( 't' == cc ) {
    			Serial.print( "_Add_1K_ NVRAM\n" );
    			uint32_t tt = micros();
    			for ( int jj = 0; jj < 1000; jj++ ) {
    				for ( int ii = 0; ii < 4; ii++ ) {
    					NVRAM_UINT32[ii]++;
    				}
    			}
    			tt = micros() - tt;
    			Serial.printf("\t%lu us\t for 1K increments of 4 RTC DWORDS\n", tt );
    
    			tt = micros();
    			for ( int jj = 0; jj < 1000; jj++ ) {
    				SNVS_LPGPR0 += 1;
    				SNVS_LPGPR1 += 2;
    				SNVS_LPGPR2 += 3;
    				SNVS_LPGPR3 += 4;
    			}
    			tt = micros() - tt;
    			Serial.printf("\t%lu us\t for 1K increments of 4 RTC #define DWORDS\n", tt );
    
    			tt = micros();
    			for ( int jj = 0; jj < 1000; jj++ ) {
    				for ( int ii = 0; ii < 4; ii++ ) {
    					tRam[ii]++;
    				}
    			}
    			tt = micros() - tt;
    			Serial.printf("\t%lu us\t\t for 1K increments of 4 RAM DWORDS\n", tt );
    		}
    		else {
    			Serial.print( "_10_INC_ NVRAM\n" );
    			tSome += 10000;
    		}
    	}
    }

  3. #3
    Junior Member
    Join Date
    Jul 2017
    Posts
    4
    This is great! Sorry for the redundancy if I missed a previous post. I will experiment with your code this evening. Cheers!

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,095
    Quote Originally Posted by Mupeg View Post
    This is great! Sorry for the redundancy if I missed a previous post. I will experiment with your code this evening. Cheers!
    Hope it helps - post didn't pop up for me either so resorted to finding the sample sketch. One sketch does link to April 2019 - but that was before the Enable was found to make it usable.

  5. #5
    Junior Member
    Join Date
    Jul 2017
    Posts
    4
    Quote Originally Posted by defragster View Post
    Hope it helps - post didn't pop up for me either so resorted to finding the sample sketch. One sketch does link to April 2019 - but that was before the Enable was found to make it usable.
    I tested out your code and it works brilliantly! I'm pretty pleased I was on the right track finding the starting address for the general-purpose registers but I doubt I would have ever found the secret sauce of the enable code. Or even realized I needed to enable it for that matter.
    Thank you kindly, defragster and Frank B!

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,095
    Awesome. It is cool to have those 4 dwords on hand to track and save EEPROM and have safe workspace. They do take measurable time to write as they pass through the low speed barrier to the other half of the chip.

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,095
    Not that anyone asked - but for another purpose - the post#2 code for T_4.x NVRAM was updated to do the same for T_3.x's.

    Tested this to work on :: T_4.1 and T_3.6 and T_3.0 { should work on anything but a T_LC }::
    Code:
    // TWO ways to access as 4 32 bit DWORDS of NVRAM backed data
    // For T_3.x :: https://forum.pjrc.com/threads/45854-Battery-backed-NV-RAM
    // #define NVRAM_UINT32 ((uint32_t *)0x400D4100)
    
    #if defined(__IMXRT1062__)
    uint32_t *NVRAM_UINT32 ((uint32_t *)0x400D4100);
    #define DWORDS 4
    #else
    uint32_t *NVRAM_UINT32 ((uint32_t *)0x4003E000);
    #define DWORDS 7
    #endif
    
    uint32_t tRam[DWORDS]; // just for speed compare of writes
    
    elapsedMillis tSome;
    void setup() {
    #if defined(__IMXRT1062__)
    	SNVS_LPCR |= (1 << 24); //Enable NVRAM - documented in SDK
    #endif
    	Serial.begin(115200);
    	while (!Serial && millis() < 4000 );
    	Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
    	tSome = 0;
    	showHelp();
    	for ( int ii = 0; ii < DWORDS; ii++ ) {
    		tRam[ii] = 0;
    	}
    }
    
    void loop() {
    	if ( tSome >= 1000 ) {
    		tSome -= 1000;
    		for ( int ii = 0; ii < DWORDS; ii++ ) {
    			Serial.print( '\t' );
    			Serial.print( NVRAM_UINT32[ii] );
    		}
    		Serial.println();
    		for ( int ii = 0; ii < DWORDS; ii++ ) {
    			NVRAM_UINT32[ii]++;
    		}
    	}
    	while ( Serial.available() ) {
    		char cc = Serial.read();
    		if ( 'r' == cc ) {
    			SCB_AIRCR = 0x5FA0004;
    			while (true);
    		}
    		else if ( 'z' == cc ) {
    			Serial.print( "_ZERO_ NVRAM\n" );
    			for ( int ii = 0; ii < DWORDS; ii++ ) {
    				NVRAM_UINT32[ii] = ii * 1000;
    			}
    		}
    		else if ( 't' == cc ) {
    			Serial.print( "_Add_1K_ NVRAM\n" );
    			uint32_t tt = micros();
    			for ( int jj = 0; jj < 1000; jj++ ) {
    				for ( int ii = 0; ii < DWORDS; ii++ ) {
    					NVRAM_UINT32[ii]++;
    				}
    			}
    			tt = micros() - tt;
    			Serial.printf("\t%lu us\t for 1K increments of 4 (7) RTC DWORDS\n", tt );
    			tt = micros();
    #if defined(__IMXRT1062__)
    			for ( int jj = 0; jj < 1000; jj++ ) {
    				SNVS_LPGPR0 += 1;
    				SNVS_LPGPR1 += 2;
    				SNVS_LPGPR2 += 3;
    				SNVS_LPGPR3 += 4;
    			}
    #else
    			for ( int jj = 0; jj < 1000; jj++ ) {
    				for ( int ii = 0; ii < DWORDS; ii++ ) {
    					NVRAM_UINT32[ii] += 1+ii ;
    				}
    			}
    #endif
    
    			tt = micros() - tt;
    			Serial.printf("\t%lu us\t for 1K increments of 4 (7) RTC #define DWORDS\n", tt );
    
    			tt = micros();
    			for ( int jj = 0; jj < 1000; jj++ ) {
    				for ( int ii = 0; ii < DWORDS; ii++ ) {
    					tRam[ii]++;
    				}
    			}
    			tt = micros() - tt;
    			Serial.printf("\t%lu us\t\t for 1K increments of 4 (7) RAM DWORDS\n", tt );
    		}
    		else if ( '?' == cc ) {
    			showHelp();
    		}
    		else {
    			Serial.print( "_10_INC_ NVRAM\n" );
    			tSome += 10000;
    		}
    	}
    }
    
    void showHelp() {
    	Serial.print(" 'r':RESTART 'z':ZERO '?':Help t:INC 1K else:INC 10 to each\n");
    }

Posting Permissions

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