Over the air updates

Congratulations! Sometimes it helps just to know that it is possible, no?

Yes and thanks to you, jonr and all the other contributors! This would not be possible on my own!


I'm a bit confused what you mean with lower and upper. There is a nice Memory Layout picture in https://www.pjrc.com/store/teensy40.html; you'll see that all regular code is copied into RAM1 at startup, leaving only FLASHMEM code and PROGMEM variables in flash memory. Teensy 4.0 flash starts at 0x60000000 and is 0x200000 in size. So I store the new firmware as received into the region starting at 0x60100000 first ("upper"), then I check, then I move to 0x60000000 ("lower") first erasing pages as I go, then I reboot. I don't bother to erase the "upper" half after copying as I want to make the "copy to lower and reboot" as fast and robust as possible, because indeed if that goes wrong the mechanism could well get stuck and then what's left is to revert to USB programming.

In my mind, the lower was the higher number but I see now that I was wrong. I took the available memory 0x200000 subtracted the 0x10000 area and divided it into 2 leaving 0xF8000 in each section.
So I can load up to a 0xF8000 byte file. I start building the new file at 0x600F8000 and when done move it up to 0x60000000.
The only reason I erase the upper section after is the thinking of protecting my code. Also once the Lower is erased and the file is moved to 0x60000000 then if power is lost it will still work even if it's interrupted while erasing the Upper. I see no negative about erasing the upper after moving it. Please correct me if I'm wrong. :)



As I'm forwarding the Intel Hex format data as I receive it streamed via MQTT my sender does not need to have the full file in memory.

Interesting. I don't believe I'm talented enough to pull that off... yet.....



Yes, indeed, it's not bullet proof. More robust designs (companion uC talking CAN etc.) are surely possible, but also require a bit more effort.

I started looking into making a very simple upload sketch to replace the 4K known good blink sketch that is located at the top of the memory. However, I found a comment by Paul that this area is irreversibly fused to read-only :(

If there was a way to change this 4K area all I would have to expose is the button to make it so I never need the USB.


I'm also thought about using an SD card or memory chip to hold the uploaded file then send to 0x60000000.
But currently, my biggest file is only 10% of the 50% available to me with this type of upload.
 
I've written a CAN-CAN array sender with CRC verification, probably useful if you have the SD loaded or file in memory. It works on CAN2.0 and CANFD modes. But of course this is Teensy to Teensy specific. Payloads are dynamically adjusted with the transfers and capability (DLC) of the remote nodes (teensy)
 
Hello,

Congratulations for the falsher 4 version !
Works fine for me. I update via I2C from rapspberry.
I have a question: is it possible to increased flashed code size ?
#define MAX_FIRMWARE_SIZE (256 * 1024)
to be replaced by
#define MAX_FIRMWARE_SIZE (384 * 1024)

I understand that is must be allocated in ram via malloc but why max is 256 Ko ?

Regards
 
Hello,

Congratulations for the falsher 4 version !
Works fine for me. I update via I2C from rapspberry.
I have a question: is it possible to increased flashed code size ?
#define MAX_FIRMWARE_SIZE (256 * 1024)
to be replaced by
#define MAX_FIRMWARE_SIZE (384 * 1024)

I understand that is must be allocated in ram via malloc but why max is 256 Ko ?

Regards

When I was playing with it I could increase the size to 0x50000 but I kept it at 0x40000 (256 * 1024) and just copied 0x40000 or less at a time until I filled half the available memory 0xF8000.
 
OK, I know I have some margin since I currently update by 140Kocts of program.
For the moment it works very well.
I free all the memory i can before to do the update.
I am not very good at the memory usage, but I may understand that the malloc is on the second bank of 512k where as static and stack are on the first 512 Ko.
Would be wonderfull if this is confirmed by someone

Philippe

Regards
 
OK, I know I have some margin since I currently update by 140Kocts of program.
For the moment it works very well.
I free all the memory i can before to do the update.
I am not very good at the memory usage, but I may understand that the malloc is on the second bank of 512k where as static and stack are on the first 512 Ko.
Would be wonderfull if this is confirmed by someone

Philippe

Regards

If you go to the Teensy 4.0 product page (https://www.pjrc.com/store/teensy40.html), it has a graphic that shows the memory map.
  • Ram1 (512K) has the FASTRUN code; initialized static/global variables; uninitialized static/global variables; and the stack.
  • Ram2 (512K) has the DMAMEM variables, plus the space where malloc memory comes from.
  • Flash (2048K) has the FLASHMEM code, PROGMEM variables, the initial values that are copied into Ram1, EEPROM emulation, and the 4K restore program.
 
Hello All,

I have been using the flasher code successfully with Teensy 3.2's but I am struggling 3.5's.

Its not the code itself, but my HEX files. I am compiling using the Arduino IDE and Teensyduino, grabbing the HEX files from my temp folder:
C:\Users\xx\AppData\Local\Temp

This is fine for Teensy 3.2 where, it can write 4 byte words, but the 3.5 keeps throwing an error telling me the files arn't 64 bit. I have found an example of some pesky HEX:

:04243C00F8B500BF30

(Line 581)

Is there anyway to force the compiler to create usable hex files?

Cheers,
Josh
 
Hello All,

I have been using the flasher code successfully with Teensy 3.2's but I am struggling 3.5's.

Its not the code itself, but my HEX files. I am compiling using the Arduino IDE and Teensyduino, grabbing the HEX files from my temp folder:
C:\Users\xx\AppData\Local\Temp

This is fine for Teensy 3.2 where, it can write 4 byte words, but the 3.5 keeps throwing an error telling me the files arn't 64 bit. I have found an example of some pesky HEX:

:04243C00F8B500BF30

(Line 581)

Is there anyway to force the compiler to create usable hex files?

Cheers,
Josh

Not sure if this is helpful or not but when I am dealing with Hex files for 4.0 I used the Arduino ide under Sketch click Export compiled binary. This saves a file to the folder containing that sketch.
Was faster and easier for me then finding it in the temp file location.

I have never played with a 3.5 so I can't help with that.
 
Not sure if this is helpful or not but when I am dealing with Hex files for 4.0 I used the Arduino ide under Sketch click Export compiled binary. This saves a file to the folder containing that sketch.
Was faster and easier for me then finding it in the temp file location.

I have never played with a 3.5 so I can't help with that.

Hi bigboosted,

Thanks for the reply. This gives me a nice way of exported HEX files, cheers!

Still no luck, I get these lines in my HEX files that means I can't flash them onto Teensy 3.5's:

:08B79000016600003504000011
:04B79800F8B500BF41
:08B79C0068F3FF7F01000000CB
 
Still no luck, I get these lines in my HEX files that means I can't flash them onto Teensy 3.5's:

:08B79000016600003504000011
:04B79800F8B500BF41
:08B79C0068F3FF7F01000000CB

If I'm not mistaken then this is an excerpt of a perfectly valid HEX file. So I guess you'd have to rewrite the flasher4 or whatever you use to buffer the binary stream as it is being decode, and to flush to flash only whenever you collected 8 bytes or the address changes, in the latter case padding the binary to complete 8 bytes.

LG, Sebastian
 
If I'm not mistaken then this is an excerpt of a perfectly valid HEX file. So I guess you'd have to rewrite the flasher4 or whatever you use to buffer the binary stream as it is being decode, and to flush to flash only whenever you collected 8 bytes or the address changes, in the latter case padding the binary to complete 8 bytes.

LG, Sebastian

Hi Wangnick,

I got this working in the end.

I read the whole HEX file in, picking out the data and ignoring the checksums etc. I then send this down to the controller in 16 byte chunks, in the same format as a HEX file, writing my own intel checksums at the end of each line. It was... intensive. Its the first time I have dealt with the HEX file format, but a nice little project.

This works for both Teensy 3.5 and 3.2.

Cheers,
Josh
 
Hi Wangnick,

I got this working in the end.

I read the whole HEX file in, picking out the data and ignoring the checksums etc. I then send this down to the controller in 16 byte chunks, in the same format as a HEX file, writing my own intel checksums at the end of each line. It was... intensive. Its the first time I have dealt with the HEX file format, but a nice little project.

This works for both Teensy 3.5 and 3.2.

Cheers,
Josh

Hi Josh,

Can you provide any example code with this working? I'm having the same issue on a T3.6 where my compiled hex also contains some 4 and 8 byte lines, meaning that when I try to flash I get a flash block align error.

Cheers.
 
It seems the Teensy4 flash is sensitive to timing related issues. I was getting hangups during the flashing phase and stumbled across this thread - https://forum.pjrc.com/threads/57898-Teensy-4-0-and-EEPROM-h-problem

They mentioned that any other compilation setting other than O2 caused flash_wait to hang. I couldn't get O2 to work, but adding #pragma GCC optimize ("O1") to the front of code was the solution (or FASTRUN static void flash_wait() __attribute__((optimize("O1"))) ).
 
Last edited:
I'll fix this if I can duplicate it. What arduino and teensyduino versions are you using?
 
Since flash_wait() is Paul's core code, I'll follow his lead and not change code to work around what appears to be a compiler issue. For now, note that you may need different optimization settings (fast, faster, fastest?) for any write to flash (eeprom or flasher4).

Thanks for tracking down and reporting the issue.
 
Hey guys, I've been trying to get T3.6 OTA working. It's almost there, but I'm crashing on the flash move. I can actually flash a super small hex file as long as it can flash completely before the address where the flash move crashes. Maybe somebody with more knowledge here would want to take a look? Or point me in a direction, I'd really like to make this work!

I started with alex-arc's repo and fixed the part that accounted for and buffered the 4byte hex lines that the T3.6 hex files have. I can make it all the way through the SD card to flash process but the flash move crashes right at the erase for address 0x3000. (Note: I was running this lib in a different program and observed this same behavior, only crashing at a larger address, something like 0x13000 if I remember correctly)

My best guess is that the flash_move function is being run from flash and not from ram even though it should be. Then the erase wipes out that function and causes a crash? Just a guess, I'm not very familiar with the inner workings of running flash/ram functions.

My Fork: https://github.com/ipaq3115/FirmwareFlasher/tree/flash_from_udp
Note that checking for compatible firmware is disabled so that I could compile a hex small enough to flash.

I'm just flashing from the sdcard for now since that was easy.

examples/sd_flasher_test/test/test.ino is the simple flasher program, reads test.hex from the root of the 3.6 sdcard and flashes it.
examples/sd_flasher_test/test/test.hex is the flasher program compiled for the 3.6, flashing this from the sdcard will fail
examples/sd_flasher_test/test2/test2.ino and the hex in that folder is just a tiny program that writes to Serial, this is the program that's small enough to actually flash and run

Running Arduino 1.8.13 and teensyduino 1.53
 
Very minor change - leave interrupts off when done flashing.
 

Attachments

  • flasher4.zip
    60.1 KB · Views: 184
Does anyone have a working example of adapting flasher4 to load .hex firmware from an SD card? I've spent a fair number hours reading through this thread, the code, and the instructions, and can't quite figure out how to do it.
I'd be eternally grateful if someone has already done this and was willing to share how they did it!

Great work on this btw! Super excited to bring it to my projects!

(Using a Teensy 4.1)
 
Does anyone have a working example of adapting flasher4 to load .hex firmware from an SD card? I've spent a fair number hours reading through this thread, the code, and the instructions, and can't quite figure out how to do it.
I'd be eternally grateful if someone has already done this and was willing to share how they did it!

Great work on this btw! Super excited to bring it to my projects!

(Using a Teensy 4.1)

I have not. However it's pretty straight forward because the library is meant to be adapted for whatever you want. A hex file is just lines of text, you can read it in any text editor. You'll need to read each line of that file and pass it to the flash_hex_line(string) function in the flasher4 library. If you look at the upgrade_firmware() function in flasher4.ino you can see that it does pretty much this exact same thing with the serial port, you'll just replace the serial port read with a sdcard read from your hex file. There's lots of sdcard examples in the sdcard library that explain reading from a text file. After that, send a flash command string like this flash_hex_line(":flash 9999") once you are all done reading from the file. Replace 9999 with the number of lines that you read from the file.
 
This has been fun...

I managed to integrate this into an existing project, which uses HttpClient via cellular modem to download the HEX file before feeding it into flash_hex_line(). Everything seems to work correctly, except it buggers out with:
bad hex line :10010000D8041808000000000000000000000000

I have verified that the HEX file is being downloaded accurately and completely by dumping the HTTP content to the serial console and comparing it with the file, so it's not a file integrity issue.

The HEX file I'm testing with was compiled from the unmodified Blink example that comes with Teensyduino 1.8.14. Before I started testing with the Blink HEX file, I was trying to use a real compiled program, and it also blew its snot with the same error (which is why I switched to using something simpler to test with).

When I grep that hex line, it's on line 18 of a 1,176 line file (not that line number is important, just pointing out that it's in a seemingly random place). So does this mean the flasher was happy with the first 17 lines of the HEX file? How do I troubleshoot why it stops on that (or any) line?

This is for a Teensy 4.1, by the way.
 
How do I troubleshoot why it stops on that (or any) line?.

On further thought... I see the parse_hex_line() function has a lots of reasons to return 0. I guess I could change them all to return a unique <0 value to spot which condition is failing...

So it's bailing out on the third check in the parse_hex_line() function: sscanf( ptr, PSTR("%02x"), &len ). Makes my head hurt. I should take a break.
 
Last edited:
Back
Top