Okay, now I have a legitimate issue.
I've been quite successful with downloading a hex file over HTTP and saving it to an external flash chip via LittleFS. This part of the process worked perfectly every time, so when the actual upgrade process starts, it has a perfect hex file.
When it comes time to read the stored hex file line-by-line into flash_hex_line(), this too works perfectly every time. Every call to flash_move() succeeds, which means every call to flash_erase_sector() and flash_write() and flash_wait() all succeed. I'm quite pleased with how well this all works!
The trouble comes at the very end, where it seems to hang after writing to the last address.
I modified the flash_move() function to spit out the sector address being erased and each address being written to, so I can see the progress and confirm that the entire address range (in the case of the Blink test sketch, 60000000 to 6000492c) is written. When it gets to the very last address, 6000492c, the entire process seems to hang. After the for() loop in flash_move(), I have a Serial.print() to indicate that the flash is complete, but this never fires. Because flash_move() doesn't finish, flash_hex_line() never returns 8, and thus upgrade_firmware() never finishes.
Here's what my modified flash_move() looks like:
Code:
void flash_move( uint32_t addressMin, uint32_t addressMax )
{
SerialUSB.println( "Flashing..." );
if( addressMin != FLASH_BASE || WRITE_SIZE != 4 )
{
sprintf( flashErrorString, "Base address incorrect\n" );
flashError( 15 );
return;
}
// below here is critical - we are writing to flash that could contain active code
__disable_irq();
// copy upper to lower, always erasing as we go up
for( uint32_t address = addressMin; address <= addressMax; address += WRITE_SIZE )
{
if( ( address & ( FLASH_SECTOR_SIZE - 1 ) ) == 0 )
{
SerialUSB.printf( "\tErasing sector %x\n", address );
flash_erase_sector( (void *)address );
delay( 100 );
}
uint32_t from = *(uint32_t *)( (uint32_t)hexBuffer + ( address - FLASH_BASE ) ); // 4 bytes from buffer
SerialUSB.printf( "\t\tWriting to %x...", address );
flash_write( (void *)address, &from, WRITE_SIZE );
SerialUSB.println( "done." );
delay( 100 );
}
SerialUSB.println( "...flash complete." );
__enable_irq();
delay( 1000 );
} // flash_move()
As you can see, I'm printing to serial before and after the flash_write(). When the sketch hangs after the last write, the Serial.print() afterward does fire, so it's not the flash_write() that's getting stuck. It's like the for() loop just stops, which doesn't make sense.
If I cycle power on the Teensy 4.1, the Blink sketch runs. So everything appears to work perfectly, just not at the very end after writing the last address.
Here's an excerpt of what my modified flesher is dumping to the serial console:
Code:
Bootup at 08:45 on Thursday, 15 July 2021
----------------------------------------------------------------------------------------------------
Booting into firmware update mode.
----------------------------------------------------------------------------------------------------
Preparing modem.....done.
Waiting for cellular network.......................................ready.
Connecting to cellular network...done.
IMEI: 868963044845386
ICCID: 8944501109207912266F
Carrier: T-Mobile Hologram
Signal: -75 dBm
IP Address: 10.111.143.96
Configuring the clock...done.
2021-07-15T08:47:06-05:00
Initiating firmware upgrade...
Connecting to __.___.___._ on port 80... request for firmware sent.
Downloading 50408 bytes...
[ 1] :0200000460009A
[ 2] :100000004643464200000156000000000103030081
...
[1174] :10491C00000000000000000000000000000000008B
[1175] :040000056000100087
[1176] :00000001FF
Download complete.
Lines: 1176 expected, 1176 received
Bytes: 50408 processed out of 50408 total, 51591 saved to flash
Reading firmware file...
[ 1] :0200000460009A
[ 2] :100000004643464200000156000000000103030081
...
[1174] :10491C00000000000000000000000000000000008B
[1175] :040000056000100087
[1176] :00000001FF
Firmware ready: 1176 hex lines, address range 60000000:6000492c. Waiting for ':flash 1176' command.
[1177] :flash 1176
Received :flash command.
Applying new firmware.
Flashing...
Erasing sector 60000000
Writing to 60000000...done.
Writing to 60000004...done.
...
Writing to 60000ff8...done.
Writing to 60000ffc...done.
Erasing sector 60001000
Writing to 60001000...done.
Writing to 60001004...done.
...
Writing to 60001ff8...done.
Writing to 60001ffc...done.
Erasing sector 60002000
...
Writing to 60004928...done.
Writing to 6000492c...done. <== Here is where the sketch stops.
What I expect to see after this is:
Code:
...
Writing to 6000492c...done. <== Here is where the sketch stops.
...flash complete. <== This comes after the for() loop in flash_move()
Firmware update complete! <== This would come from the loop in upgrade_firmware() when the flash_hex_line() returns 8
Rebooting into normal mode... <== This would come from a call to reboot(), which should fire after upgrade_firmware() completes
I'm using EEPROM to help my sketch determine whether it should boot into "normal" mode or firmware update mode. My reboot() contains an EEPROM write to reset that boot mode flag, but since this never fires, that flags is always set to firmware upgrade mode, so even a manual reboot would not allow my sketch to start up in "normal" mode again.
Just in case my use of EEPROM, which I understand is emulated in flash, was causing some kind of collision, I commented it all out, but it didn't help any.
Out of the dozens of times I've tested this, there were two instances where I saw my "Firmware upgrade complete!" message, and it rebooted. But that's it, and I have no idea why it worked those two times and not for the other 99 times.
Any ideas?