One last question (regarding temperature), again just because I'm curious: Is there a measurable difference in power consumption? @Defragster
Quite possible.
Was the flash preservation feature (for files) added in bootloader 1.06 or 1.07?
If it was 1.06 - if I buy a T4.x now - will it have the feature?
Oops is right. This is the first time I have run this test with a Lock Teensy....
Anyways. Been playing with LFS flash sizes to try and determine failure point for corrupted file system when using a Locked T4 when the program size is around the size of the UncannyEyes sketch with the added LittleFS and Dump code:
...Code:[B]PASS: #define PROG_FLASH_SIZE 1024*256 // (void*)0x601b0000 PASS: #define PROG_FLASH_SIZE 1024*512 // (void*)0x60170000 PASS: #define PROG_FLASH_SIZE 1024*768 // (void*)0x60130000[/B] [COLOR="#FF0000"][B]FAIL: #define PROG_FLASH_SIZE 1024*1024 // (void*)0x600f0000[/B][/COLOR]
uint32_t title_address = ((uint32_t)&title_function) & ~1;
if (title_address >= [B]begin_address [/B]&& title_address < [B]end_address[/B]) {
Serial.println("Pass: title_function() is within encrypted region");
} else {
Serial.println("Fail: title_function() is not in encrypted region");
ok--;
}
That's a question for Paul - but it seems minimal flash write is unique to new 1.07 bootloader.
Seems the MMod bootloader would have done been months before release to be stable and ready for release.
IIRC - when LOCKED the Forced Flash erase is 1024x1024 ... 1MB, force erase unlocked is only 512MB.
This PASS test from https://github.com/Defragster/T4LockBeta/tree/main/T4MemInfoSink :: isEncrypt():
Code:uint32_t title_address = ((uint32_t)&title_function) & ~1; if (title_address >= [B]begin_address [/B]&& title_address < [B]end_address[/B]) { Serial.println("Pass: title_function() is within encrypted region"); } else { Serial.println("Fail: title_function() is not in encrypted region"); ok--; }
Shows the reference to begin_ and end_ that might expose the end_address used by Code/Data in FLASH. When LOCKED that might cross beyond 1MB with large program. But it might be under - and may not include all the tidbits if any come after that.
On a small program that won't help - on a large sketch it might show where it would conflict with FLS PROG storage.
The TMM is at bootloader 1.06 and does not support encryption, ie, fuseWrite. I tested that this morning as well as an older T4. See posts #73 and #75 on page 3.
void loop() {
//float testTemp = tempmonGetTemp() - myTemp;
Serial.print((millis()-time_now)*0.00001667,4);Serial.print(", ");
Serial.println(tempmonGetTemp(),2);
delay(500);
}
Kitchen with modified loop:
Both T4's running the same sketch. One teensy 4 is a production T4 at version 1.05 the other is the locked T4 at version 1.07 basically just getting the temperature. Power was not measured.Code:void loop() { //float testTemp = tempmonGetTemp() - myTemp; Serial.print((millis()-time_now)*0.00001667,4);Serial.print(", "); Serial.println(tempmonGetTemp(),2); delay(500); }
...
EDIT: Not sure what to try next.
Yep using the pre-LFS test sketch. Here is what I used for temp measurement on both boardsThat doesn't match what I saw - maybe the PROD T4 I have is different gen than what is there? Can you measure current ... would take me like 5 minutes to get a crude DMM reading on mine.
That is Kitchen pre-LFS ... the LFS add halts temp check while idle waiting for input ... I should post that version too ... or you could Mike.
// https://forum.pjrc.com/threads/33443-How-to-display-free-ram
#include <MemoryHexDump.h> // https://github.com/KurtE/MemoryHexDump
long time_now;
uint32_t *ptrFreeITCM; // Set to Usable ITCM free RAM
uint32_t sizeofFreeITCM; // sizeof free RAM in uint32_t units.
extern unsigned long _stextload;
extern char _stext[], _etext[], _sbss[], _ebss[], _sdata[], _edata[],
_estack[], _heap_start[], _heap_end[], _itcm_block_count[], *__brkval;
float myTemp;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial);
if ( CrashReport) Serial.print( CrashReport);
Serial.println("\n" __FILE__ " " __DATE__ " " __TIME__);
if ( CrashReport ) Serial.print ( CrashReport );
myTemp = tempmonGetTemp();
Serial.printf( "\n\tdeg C=%f\t F_CPU=%u\n" , myTemp, F_CPU_ACTUAL );
memInfo();
getFreeITCM();
extern const uint32_t hab_csf[768]; // placeholder for HAB signature
Serial.println();
//dumpRam(Serial, 0x60000000 + ptrFreeITCM - 1024, 1024);
// Serial.println((uint32_t)&_stextload + (uint32_t)&_etext, HEX);
MemoryHexDump(Serial, hab_csf , 128, true, "---\thab_csf\n");
MemoryHexDump(Serial, ptrFreeITCM - 1024, 128, true, "---\tITCM used\n");
MemoryHexDump(Serial, ptrFreeITCM, sizeofFreeITCM * sizeof(uint32_t), true, "---\tITCM filler to DTCM\t test 3 \n");
MemoryHexDump(Serial, (uint8_t *)0, 128, true, " ITCM Start: \n");
isEncrypt();
time_now = millis();
}
void loop() {
//float testTemp = tempmonGetTemp() - myTemp;
Serial.print((millis()-time_now)*0.00001667,4);Serial.print(", ");
Serial.println(tempmonGetTemp(),2);
delay(500);
}
#define printf Serial.printf
void memInfo () {
constexpr auto RAM_BASE = 0x2020'0000;
constexpr auto RAM_SIZE = 512 << 10;
constexpr auto FLASH_BASE = 0x6000'0000;
#if ARDUINO_TEENSY40
constexpr auto FLASH_SIZE = 2 << 20;
#elif ARDUINO_TEENSY41
constexpr auto FLASH_SIZE = 8 << 20;
#endif
// note: these values are defined by the linker, they are not valid memory
// locations in all cases - by defining them as arrays, the C++ compiler
// will use the address of these definitions - it's a big hack, but there's
// really no clean way to get at linker-defined symbols from the .ld file
auto sp = (char*) __builtin_frame_address(0);
printf("_stext %08x\n", _stext);
printf("_etext %08x +%db\n", _etext, _etext - _stext);
printf("_sdata %08x\n", _sdata);
printf("_edata %08x +%db\n", _edata, _edata - _sdata);
printf("_sbss %08x\n", _sbss);
printf("_ebss %08x +%db\n", _ebss, _ebss - _sbss);
printf("curr stack %08x +%db\n", sp, sp - _ebss);
printf("_estack %08x +%db\n", _estack, _estack - sp);
printf("_heap_start %08x\n", _heap_start);
printf("__brkval %08x +%db\n", __brkval, __brkval - _heap_start);
printf("_heap_end %08x +%db\n", _heap_end, _heap_end - __brkval);
#if ARDUINO_TEENSY41
extern char _extram_start[], _extram_end[], *__brkval;
printf("_extram_start %08x\n", _extram_start);
printf("_extram_end %08x +%db\n", _extram_end,
_extram_end - _extram_start);
#endif
printf("\n");
printf("<ITCM> %08x .. %08x\n",
_stext, _stext + ((int) _itcm_block_count << 15) - 1);
printf("<DTCM> %08x .. %08x\n",
_sdata, _estack - 1);
printf("<RAM> %08x .. %08x\n",
RAM_BASE, RAM_BASE + RAM_SIZE - 1);
printf("<FLASH> %08x .. %08x\n",
FLASH_BASE, FLASH_BASE + FLASH_SIZE - 1);
#if ARDUINO_TEENSY41
extern uint8_t external_psram_size;
if (external_psram_size > 0)
printf("<PSRAM> %08x .. %08x\n",
_extram_start, _extram_start + (external_psram_size << 20) - 1);
#endif
printf("\n");
auto stack = sp - _ebss;
printf("avail STACK % 8d b % 5d kb\t<<RAM1\n", stack, stack >> 10);
auto heap = _heap_end - __brkval;
printf("avail HEAP % 8d b % 5d kb\t<<RAM2\n", heap, heap >> 10);
#if ARDUINO_TEENSY41
auto psram = _extram_start + (external_psram_size << 20) - _extram_end;
printf("avail PSRAM % 8d b % 5d kb\n", psram, psram >> 10);
#endif
}
uint32_t SizeLeft_etext;
FLASHMEM
void getFreeITCM() { // end of CODE ITCM, skip full 32 bits
Serial.println("\n\n++++++++++++++++++++++");
SizeLeft_etext = (32 * 1024) - (((uint32_t)&_etext - (uint32_t)&_stext) % (32 * 1024));
sizeofFreeITCM = SizeLeft_etext - 4;
sizeofFreeITCM /= sizeof(ptrFreeITCM[0]);
ptrFreeITCM = (uint32_t *) ( (uint32_t)&_stext + (uint32_t)&_etext + 4 );
printf( "Size of Free ITCM in Bytes = % u\n", sizeofFreeITCM * sizeof(ptrFreeITCM[0]) );
printf( "Start of Free ITCM = % u [ % X] \n", ptrFreeITCM, ptrFreeITCM);
printf( "End of Free ITCM = % u [ % X] \n", ptrFreeITCM + sizeofFreeITCM, ptrFreeITCM + sizeofFreeITCM);
for ( uint ii = 0; ii < sizeofFreeITCM; ii++) ptrFreeITCM[ii] = 1;
uint jj = 0;
for ( uint ii = 0; ii < sizeofFreeITCM; ii++) jj += ptrFreeITCM[ii];
printf( "ITCM DWORD cnt = % u [#bytes=%u] \n", jj, jj * 4);
}
// https://forum.pjrc.com/threads/33443-How-to-display-free-ram?p=275013&viewfull=1#post275013
extern char *__brkval;
int freeram() {
return _heap_end - __brkval;
}
PROGMEM char title_text[] = "Verify secure code is running properly";
FLASHMEM void title_function() {
Serial.println( title_text );
Serial.println();
}
//extern "C" uint32_t _sdata, _edata, _sdataload; /* special linker symbols */
extern "C" uint32_t _sdataload; /* special linker symbols */
extern const uint32_t hab_csf[768]; // placeholder for HAB signature
int isEncrypt() {
int ok=0;
title_function();
if ((IOMUXC_GPR_GPR11 & 0x100) == 0x100) {
Serial.println("Pass: Bus Encryption Engine is active");
} else {
Serial.println("Fail: Bus Encryption Engine is not active");
ok--;
}
uint32_t begin_address = IOMUXC_GPR_GPR18 & ~0x3FF;
if (begin_address == 0x60001400) {
Serial.println("Pass: Encryption region starts at proper address");
} else {
Serial.println("Fail: Encryption region starts at wrong address");
ok--;
}
uint32_t end_address = IOMUXC_GPR_GPR19 & ~0x3FF;
uint32_t data_end = (uint32_t)&_sdataload + (uint32_t)&_edata - (uint32_t)&_sdata;
if (data_end <= end_address) {
Serial.println("Pass: Program data is entirely within encrypted region");
} else {
Serial.println("Fail: Program data is not within encrypted region");
ok--;
}
uint32_t title_address = ((uint32_t)&title_function) & ~1;
if (title_address >= begin_address && title_address < end_address) {
Serial.println("Pass: title_function() is within encrypted region");
} else {
Serial.println("Fail: title_function() is not in encrypted region");
ok--;
}
if ((uint32_t)title_text >= begin_address && (uint32_t)title_text < end_address) {
Serial.println("Pass: title_text[] is within encrypted region");
} else {
Serial.println("Fail: title_text[] is not in encrypted region");
ok--;
}
uint jj = 0;
for ( uint ii = 0; ii < sizeof(hab_csf) / sizeof(hab_csf[0]); ii++ ) jj += hab_csf[ii];
if ( jj ) {
Serial.println("Pass: csf not Zero");
} else {
Serial.println("Fail: csf is Zero");
ok--;
}
// TODO: check HAB version and HAB logfile status
Serial.println();
if (0==ok) Serial.println("All Tests Passed. :-)");
else printf(" %d Tests failed. :-(", -ok);
return ok;
}
DMM showing this for current idling running the posted SINK sketch:
#1 - Production T4_1.05 - bare board :: 98mA-99mA : 48 °C
#2 - Unfused T4_1.07 in T4 PJRC Beta breakout :: 109 mA (powering breakout LED and other on the board?) : 59 °C
#3 - Fused T4_1.07 with key.pem - bare board :: 99 mA-100 mA : 55 °C
Not sure why #'s 1 and 3 can be so close and the temp read so diff is 1 mA that much extra heat?
Next step would be external measure - but that is more arbitrary ...
Memory Usage on Teensy 4.0:
FLASH: code:56572, data:588516, headers:8220 free for files:1378308
RAM1: variables:17504, code:54824, padding:10712 free for local variables:441248
RAM2: variables:37088 free for malloc/new:487200
:0200000460009A
:100000004643464200000156000000000103030081
:1000100000000000000000000000000000000000E0
:1000200000000000000000000000000000000000D0
...
<To ending lines at about line 40845>
:0CF7F40000000000000000000000000009
:040000056000100087
:00000001FF
:0200000460009A
:20000000464346420000015600000000010303000000000000000000000000000000000071
:200020000000000000000000000000000000000000000000000000000000000000000000C0
...
<To ending lines at about line 20582>
:2093000000000000000000000000000000000000000000000000000000000000000000004D
:2093200000000000000000000000000000000000000000000000000000000000000000002D
:2093400000000000000000000000000000000000000000000000000000000000000000000D
:00000001FF
Had to see how far I could push this. So this should be my final result for this:
1024x1023 works and maintains file system integrity across uploads but 1024x1024 does not. So think the max for an encrypted T4 will be 1024x1023 bytes.
const uint32_t program_size = (uint32_t)&_flashimagelen + 4096; // extra 4K for CSF
For example they both start with the first same line but diverge quickly and their endings are completely different
:20A3A00000000000000000000000000000000000000000000000000000000000000000009D
:20A3C00000000000000000000000000000000000000000000000000000000000000000007D
:20A3E00000000000000000000000000000000000000000000000000000000000000000005D
:00000001FF
:020000042020BA
:20800000D10020402184202000000000000000002080202000802020608720200000000083
:20802000008020206013000000000000704782B0002301E0019B01330193019B8342F9D38F
:2080400002B07047024B4022C820C3F88820EEE700801B40024B4022C3F88420704700BF89
:2080600000801B402DE9F04100268046344680251B4B15EA080F4FF40072194F14BFC3F8AC
So question to myself and others who hopefully can answer it and/or beet me to it.
Does both the HEX file and EHEX file take up the same space on flash memory?
That is do we have the same space left in both cases for a possible LittleFS FS?
Writing public key hash
public key hash is good :-)
Decryption key was previously written & locked
Error: Key can not be used
Testing Bus Encryption Engine
Error: ciphertext decryption did not match plaintext!
plain: 17 F5 7F 98
cipher: 05 EF 63 D7
dcrypt: 05 EF 63 D7
Error: JTAG can not be disabled
Error: Secure mode can not be set
Thanks for the detailed explanation on sizes - sounds like something that should get added to the documentationPaulStoffregen said:In secure mode, the available space for LittleFS should be 960 blocks of 1024 bytes, when code uses 1M or less.
6000,0000 to 600F,FFFF is always supposed to be erased, even if the prior program doesn't appear to use all that space. You can put LittleFS data here, but it will be wiped during code uploads.
6010,0000 to 601EF,FFFF is the space which can be used for a filesystem or other data which persists across uploads. If you write a *lot* of code or have huge PROGMEM const arrays, your code can use some or all of this region. Uploading is supposed to erase this space in 64K blocks as needed by your program's size.
601F,0000 to 601F,F000 is reserved for EEPROM emulation. Code is never uploaded here. Uploading doesn't touch this space.
601F,F000 to 601F,FFFF is reserved for the 15 sec restore program data, and this last 4K is hardware locked to read-only.
Will test this change as well.Looking at the LittleFS code, I see it has an overly cautious 4K margin.
Code:
1.54 added CSF allocation to the program size, and this 1.55-beta1 fixed some lingering bugs in computing _flashimagelen. So would should be able to delete this extra 4096 byte size estimate.Code:const uint32_t program_size = (uint32_t)&_flashimagelen + 4096; // extra 4K for CSF
Probably it makes sense to align(16 or 32) it? I don't know how the littlefs works and what is in the first bytes or directory.Looking at the LittleFS code, I see it has an overly cautious 4K margin.
Code:const uint32_t program_size = (uint32_t)&_flashimagelen + 4096; // extra 4K for CSF
PaulStoffregen said:In secure mode, the available space for LittleFS should be 960 blocks of 1024 bytes, when code uses 1M or less.
Erased Area
600FFF00 - FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF : ........ ........
... 14 duplicate line(s) removed.
600FFFF0 - FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF : ........ ........
LittleFS Test
FLASH_SIZE - 2031616, program_size - 91136
available_space = 1940480
[B]baseaddr = 60100000
TotalSize (Bytes): 983040[/B]
Erased Area
600FFF00 - FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF : ........ ........
... 14 duplicate line(s) removed.
600FFFF0 - FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF : ........ ........
LittleFS Test
Program flash begin
size in bytes - 1047552
FLASH_SIZE - 2031616, program_size - 91136
available_space = 1940480
[B]size - 983040, baseaddr = 60100000
TotalSize (Bytes): 983040[/B]
size = size & 0xFFFF0000;
Erased Area
600FFF00 - FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF : ........ ........
... 14 duplicate line(s) removed.
600FFFF0 - FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF : ........ ........
LittleFS Test
Program flash begin
size in bytes - 1048576
FLASH_SIZE - 2031616, program_size - 87040
available_space = 1944576
size - 1048576, baseaddr = 600f0000
TotalSize (Bytes): 1048576
Not sure if this is desired... this way, size will (probably) be less than requested. Is that ok?Code:size = size & 0xFFFF0000;