Forum Rule: Always post complete source code & details to reproduce any issue!
Page 4 of 4 FirstFirst ... 2 3 4
Results 76 to 98 of 98

Thread: 'Over the Air' firmware updates, changes for flashing Teensy 3.5 & 3.6

  1. #76
    I've built a new version of Flasher to allow the largest possible upload by identifying empty sectors from the top of existing firmware to the bottom of flash reserve. This eliminates the need to explicitly specify the flash buffer location when building "small" or "large" programs, which gets very confusing. If an upload will not fit in the available space, you can use the two-step process of uploading a small program, and then uploading the larger one. The largest possible upload is FLASH_SIZE - smallest possible "flasher" program.

    There was one important change required to make this work. At the end of flash_move(), after the new firmware has overwritten the old, and before the reboot, flash is erased sector-by-sector from the top of the new firmware to the bottom of the flash reserve. This leaves the flash in the same condition as if the upload had been done with the Teensy loader, which seems like a good thing. Prior versions left the upper flash un-erased, so the first step for an upload was to call flash_erase_upper(), and that is no longer necessary. Other changes include adding a new argument uint32_t flash_buffer_addr to several functions.

    Let me know your thoughts, and I'll post the new version if you agree it sounds okay.

  2. #77
    Junior Member
    Join Date
    Dec 2020
    Posts
    13
    Quote Originally Posted by joepasquariello View Post
    @gonzales, yes, you're right. I simply replaced FLASH_SIZE/2 with FLASH_BUF_ADDR everywhere. In that case, the original code should have been (FLASH_SIZE - FLASH_SIZE/2 - RESERVE_FLASH) and the new code (FLASH_SIZE - FLASH_BUF_ADDR - RESERVE_FLASH).

    Let us know if it works correctly for you and I will upload another ZIP file with the correction.
    I tryed many times to flash my teensy 3.5. Work fine!!!

    joepasquariello - Thanks a lot!!!

    One more extension: for Teensy 3.5 you can use #define FLASH_BUFFER_ADDR (FLASH_SIZE/8) for small loader and #define FLASH_BUFFER_ADDR (7 * FLASH_SIZE/8) for large program, so you have 7/8 of flash size for you program/

  3. #78
    How can i use flasher over Ethernet?

    I have the Teensy Ethernet kit and want to try to update my firmware over ethernet.

    Ty

  4. #79
    Over Ethernet is something I'm working on, have not been able to finish it yet. lots of other stuff todo.
    The path I'm on is sending the flash data in the body of a post request, then code the teensy side to strip the data out of the body.
    Sending the data is easy, Using curl to send the hex file in the body but I still need to write teensy code to handle the data.

  5. #80
    Junior Member
    Join Date
    Jan 2021
    Posts
    7
    Hi everyone

    I have one question, why are we using flasher4 or flasher3 is it because of that its not possible to write a new bootloader or modify the existing bootloader or is it because of its the only way for new methods for firmware updates

  6. #81
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    8,567
    Quote Originally Posted by the_boss View Post
    Hi everyone

    I have one question, why are we using flasher4 or flasher3 is it because of that its not possible to write a new bootloader or modify the existing bootloader or is it because of its the only way for new methods for firmware updates
    I answered your question about a month ago...
    No, it's not possible to write a new bootloader or to modify the existing one. It is protected.
    No you don't need flasher for firmware updates. Just use the bootloader
    Flasher is only needed if you don't want to use the default bootloader.

  7. #82
    What Frank said. If you need to do updates via Ethernet, work on getting Ethernet communication working, and you'll be able to combine with Flasher to do firmware updates that way.

  8. #83
    Senior Member Davidelvig's Avatar
    Join Date
    Aug 2015
    Location
    Wisconsin
    Posts
    325
    OK... trying to grok this...

    I'd like to Over-the-Air (OTA) update using BLE on a custom Teensy-3.2-designed board that has a Teensy Bootloader.
    The board also has an internal uSD card for temporary storage of a HEX if needed.

    My users will want the OTA nearly all of the time (from their phones) unless my OTA process "bricks" the Teensy while flashing...

    Than I'd love it if the user could connect the USB cable and use a TyCmd-wrapped PC/Mac app to initiate an "un-bricking".
    Most users would never need the PC/Mac app.

    Again, I have the Teensy bootloader chip on my board... I just want OTA as the routine solution.

    Is this a reasonable solution?
    Should I dig in to the Flasher option, knowing I can recover from a "Brick" with TyCmd, USB and a Teensy Bootloader?

  9. #84
    Yes, you can use the approach within Flasher3 for your OTA solution. Think of Flasher3 not as a production solution, but as an example of how to write new firmware to Flash once you have (somehow) transferred the new code to your board. Flasher3 does the transfer via USB serial and buffers the new code in unused (upper) program flash. If your application occupies less than 1/2 of the 256K T3.2 program flash, you can use this method, and I see no reason to use the SD card. If your program is larger than 128K (half of T3.2 program flash), you can still use Flasher3, but you have to do 2-step updates. Step 1 would be to write a small program to flash to make more flash available for buffering, and step 2 would be to send your new application using the now-larger available flash buffer. If you choose to buffer your code in the SD card rather than flash, you have some more development to do, but I think there are threads on the forum about other people doing that. Whichever way you buffer the new program, the code to erase the existing program and write the new program to Flash must be executed from RAM, with interrupts disabled. Flasher3 shows how to do that. Study it carefully before you try a new method, because there are ways that you can brick your board that are NOT recoverable via the Teensy bootloader. Specifically, when you write new code to T3.2 program flash, you MUST be certain to write the correct value to the FSEC and FOPT locations. If you fail to do that, you can brick your T3.2 in a way that is unrecoverable.

  10. #85

    FlasherX - OTA updates for Teensy LC, 3.x, 4.x

    FlasherX is a merge of Flasher3 and Flasher4 by Jon Zeeff, with some new features and updates. It works for Teensy LC, 3.2, 3.5, 3.6, 4.0, and 4.1, with a few caveats. I tested 3 transfer methods for each Teensy:

    1) hex file transfer via Serial (USB) using terminal emulator
    2) hex file transfer via Serial1 (UART) using terminal emulator
    3) block file transfer via Serial1 (UART) using custom client

    My objective was to support #3, transfer via custom client, so everything common to the 3 transfer methods is in file FlashTxx.cpp, and FlasherX.ino contains everything specific to hex file transfer via USB or UART. My platform was TeensyDuino 1.53 and Arduino 1.8.13 on Windows 7 Pro 64-bit, and I used TeraTerm for the file transfers.

    For method #1, hex file transfer via USB, I found that the reliability of transfer was improved if each hex line was echoed back by the Teensy, while for method #2, hex file transfer via UART, the transfers were most reliable without this echo. I don't know why this is the case, perhaps Paul or someone else can explain it.

    All of my testing with Serial1 was done at 115200 baud.

    For Teensy LC, reliable updates via file transfer required a 1 ms delay after each hex line. TeraTerm supports this option.

    For Teensy 3.6, clock frequency had to be reduced to 120 MHz for reliable file transfers. With the custom client the T3.6 is okay at 180 MHz.

    FlasherX buffers the new code in flash by default, and automatically defines the largest possible flash buffer, from the top of existing code to the bottom of FLASH_RESERVE (settable in FlashTxx.h). After moving the new code from the buffer to the program flash, the flash buffer is erased. This leaves the flash in the same state as if the code was uploaded via TeensyDuino. If the new code to be sent via FlasherX is smaller than the available buffer, the update can be done in one step. If the new code is larger than the available flash, a two-step process can be used. Step 1 would be to send a minimal application with "Flasher" capability, and step2 would be to send the new, larger application.

    |<------------------------------ FLASH_SIZE ------------------------------>|
    ^FLASH_BASE_ADDR
    |<------- code ------->|<--------- buffer ---------->|<-- FLASH_RESERVE -->|

    For T4.x, new code can optionally be buffered in RAM by setting macro RAM_BUFFER_SIZE in FlashTxx.h to a value > 0. For my testing I used RAM_BUFFER_SIZE (256*1024).

    To switch between Serial USB and Serial1 (or any UART), just change the "serial" variable definition in FlasherX.ino. This variable, along with buffer_addr and buffer_size, are arguments to update_firmware(). update_firmware() is substantially rewritten from Flasher3/4, but does the same things. There is hex_info_t data structure, which I think makes it easier to see what's going on and what we need to keep track of during the file transfer. When the file transfer is complete, the number of lines received is displayed and the user is prompted to enter that value to trigger the udpate, or enter 0 to cancel.

    For transfers via custom clients, these functions in FlashTxx.cpp provide the necessary API within your Teensy application:

    flash_buffer_init -- determine the address and size of the flash buffer
    flash_write_block -- write each received "block" of new code to the flash buffer
    flash_check_id -- confirm that the new code was built for the intended target
    flash_move -- move the (complete) new code from buffer to program flash
    flash_buffer_free -- erase the flash buffer or free the RAM buffer in the event of error/abort

    The flash write/erase primitives for all Teensy are also in FlashTxx.cpp, conditionally compiled by target. As in Flasher4, the write/erase functions are taken from Teensy4 core file eeprom.c. For Flasher3, the write/erase functions are based on Frank B's KinetisFlash module, with changes required to keep interrupts disabled during flash_move(). Note that kinetis_hsrun_disable/enable are called in flash_exec(), which I found was necessary to avoid baud rate issues with T3.6. Again, why T3.6 is different isn't clear to me.

    Please give it a try.
    Attached Files Attached Files
    Last edited by joepasquariello; 06-14-2021 at 06:45 PM.

  11. #86
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    991
    Nice work. The intent is that other byte streams as input/out (eg, SPI or CAN bus) will be implemented with a Stream class?

  12. #87
    Quote Originally Posted by jonr View Post
    Nice work. The intent is that other byte streams as input/out (eg, SPI or CAN bus) will be implemented with a Stream class?
    Thanks, Jon. My use of the Stream class was purely to allow switching between Serial (USB) and Serial1 (UART) without touching update_firmware(). I intend to develop Flasher capability for Ethernet via a custom client. I haven't thought at all about SPI or CAN.

  13. #88
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,422
    Not tried - but that indeed seems like nice work.

    T_3.6 issues over 120 MHz is the fact that the sketch as compiled sets core clocking based on the compile speed - doing the speed drop to 120 MHz required for FLASH write alters clocks using the core clock, so devices based on those common core clocks ( UART, other ) doing transfers across that 'window' will be garbled by mismatching clocks.

    The #3 block transfer it would seem pauses I/O between blocks during the FLASH writes?

  14. #89
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,071
    One thing that might be helpful for some users that want to put Teensies in the field is to add an option to take the firmware image from a SD card. I would imagine in the startup code, there would be a check whether a project specific button was pressed and if so, go and load the firmware. I would imagine, you would want to specify the pin the SD reader is on, and which SPI port to use (including alternate SPI ports for Teensy 3.x using the audio adapter).

  15. #90
    Quote Originally Posted by defragster View Post
    T_3.6 issues over 120 MHz is the fact that the sketch as compiled sets core clocking based on the compile speed - doing the speed drop to 120 MHz required for FLASH write alters clocks using the core clock, so devices based on those common core clocks ( UART, other ) doing transfers across that 'window' will be garbled by mismatching clocks.

    The #3 block transfer it would seem pauses I/O between blocks during the FLASH writes?
    defragster, yes, I finally looked at kinetis_hsrun_disable(), and it's only relevant for CPU_F > 120 MHz, so, the calls to hsrun_disable/enable in FlashTxx.cpp don't do anything on LC, T3.2, or T3.5, and won't do anything on T3.6 if the application is built for 120 Mhz.

    For the #3 transfer, what I mean by "block" is a block file format as alternative to intel hex. My custom client reads the Teensy Intel Hex file into memory, then sends the code to Teensy in packets, each containing 256 bytes of code. The Teensy replies after each block is received. There is no pause in I/O, if I understand your question correctly.

  16. #91
    Quote Originally Posted by MichaelMeissner View Post
    One thing that might be helpful for some users that want to put Teensies in the field is to add an option to take the firmware image from a SD card. I would imagine in the startup code, there would be a check whether a project specific button was pressed and if so, go and load the firmware. I would imagine, you would want to specify the pin the SD reader is on, and which SPI port to use (including alternate SPI ports for Teensy 3.x using the audio adapter).
    Michael, yes, I agree. I'll start with the on-board SD for T3.5, T3.6, T4.1. I've barely used SD, so I may leave it to others to go beyond that.

  17. #92
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,422
    Quote Originally Posted by joepasquariello View Post
    ...
    For the #3 transfer, what I mean by "block" is a block file format as alternative to intel hex. My custom client reads the Teensy Intel Hex file into memory, then sends the code to Teensy in packets, each containing 256 bytes of code. The Teensy replies after each block is received. There is no pause in I/O, if I understand your question correctly.
    That pause per packet/block across T_3.6 writing ( where the hsrun speed and chip voltage is dropped ) allows the clocks to be restored before the next transfer when the Teensy issues the 'block received' to the source when the next packet/block is transmitted.

    <add edit>: Using RTS/CTS might allow similar behavior when supported for option #2.
    And what MichaelM said about SDcard would be cool. Frank B had a scheme worked out for T_3.2 that would read SD card and seeing a 'new firmware' indication would then load the indicated firmware and set the 'new' to 'not new' so it wouldn't repeat endlessly on each restart. That was tested to work with the 'half EEPROM' limit.

  18. #93
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    991
    I wouldn't put any knowledge of SD cards (or any I/O device) into the flasher library itself. SD support would be done in an application code example (implementing a Stream subclass) that reads from a SD card file and calls flasher code.

  19. #94
    Quote Originally Posted by defragster View Post
    That pause per packet/block across T_3.6 writing ( where the hsrun speed and chip voltage is dropped ) allows the clocks to be restored before the next transfer when the Teensy issues the 'block received' to the source when the next packet/block is transmitted.
    Interrupts are disabled and hsrun disabled only during the actual flash write/erase operations, which are quite short. When the transfer is complete, interrupts are disabled for the entire duration of flash_move(), and the subsequent reboot.

  20. #95
    Quote Originally Posted by jonr View Post
    I wouldn't put any knowledge of SD cards (or any I/O device) into the flasher library itself. SD support would be done in an application code example (implementing a Stream subclass) that reads from a SD card file and calls flasher code.
    Definitely. I should be able to create FlasherX-SD, FlasherX-Ethernet, etc., with no changes to FlashTxx.cpp/h.

    FlashTxx.cpp uses macros FLASH_BASE_ADDR, FLASH_SIZE, FLASH_WRITE_SIZE, and FLASH_RESERVE, but all other addresses are passed to functions as arguments, so flash_move() works for a buffer anywhere in RAM or FLASH.
    Last edited by joepasquariello; 06-14-2021 at 10:09 PM.

  21. #96
    Junior Member
    Join Date
    Jun 2021
    Posts
    1
    Thank you so much for the hard work so far to get it to this point.

    I've been trying to get the FlasherX working on my Teensy 3.5, and I've managed to get to the point now where it's checking the value of the FSEC field, but I get an error indicating it's not set correctly.
    Code:
    abort - FSEC value FFFFFFFF should be FFFFF9DE
    The program I was trying to flash was a simple led blinker that printed "fs_teensy35" to serial before it started.

    Is this something I have to set in my code before compiling (i.e. like the FLASH_ID) or is there a step i'm missing.


    As a seperate question:
    My plan is to have this as a permananet bootloader on my teensy, I was going to modify the flasher to write to an address after where the flasher was stored in flash.
    On boot the flasher would start and if it didn't get a program within 10 sec it would then jump to the start of my program (so jump to another address)
    Any reason this won't work?
    Last edited by martinmoen; 06-23-2021 at 01:32 PM. Reason: Typos

  22. #97
    Quote Originally Posted by martinmoen View Post
    The program I was trying to flash was a simple led blinker that printed "fs_teensy35" to serial before it started. Is this something I have to set in my code before compiling (i.e. like the FLASH_ID) or is there a step i'm missing.

    My plan is to have this as a permananet bootloader on my teensy, I was going to modify the flasher to write to an address after where the flasher was stored in flash. On boot the flasher would start and if it didn't get a program within 10 sec it would then jump to the start of my program (so jump to another address)
    Any reason this won't work?
    If you have not simply built and run the FlasherX sketch on your T3.5, that would be my first step. To include flasher capability in your own program, you must have FlashTxx.cpp and FlashTxx.h in your sketch folder and #include <FlashTxx.h> in your INO file (and others if necessary). You haven't said how you are transferring the new code, so I can't comment on why your FSEC value is not correct. In my original FlasherX post, I outline the process of init/upload/write. If you post your code, I will look at it.

    Regarding a permanent bootloader, that may be possible, but there is at least one problem you would have to solve. When you build an application with TeensyDuino, it is built to execute from FLASH_BASE_ADDR, and my guess is that it generally uses absolute addressing. If your bootloader is a complete program built by TeensyDuino, I don't think it will run from any location except FLASH_BASE_ADDR, which is 0 for T3.x. There are probably ways to work around that, but they would not be trivial. Flasher is designed to allow an application to be updated. It is not a bootloader.

  23. #98
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    991
    > On boot the flasher would start and if it didn't get a program within 10 sec it would then jump to the start of my program

    The flasher code has/had a routine called "boot_check()" for exactly this. All programs loaded must have the flasher code compiled in.

Posting Permissions

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