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

Thread: Firmware update without button...

  1. #1
    Junior Member
    Join Date
    Sep 2019
    Location
    United States
    Posts
    18

    Firmware update without button...

    Hi,
    I have been working with an NXP evaluation board for the '1062, and recently decided to take a go at
    the Teensy4.x. I am working on a 6-channel microphone board that the Teensy4.x will plug into
    and the application will essentially be a 6-channel USB audio device. I have pieces of this working on
    the eval board, but want to transition over to Teensy4.x.
    Anyway, my board needs to be update-able without manual intervention (pushing the button). I've
    seen some discussion of this on the forum but nothing that appeared to be applicable when Teensy
    looks like a usb audio device.
    The only solution that occurs to me is to create a composite USB device (Audio-in and COM) so
    that a host could connect to the COM port and issue a command that would toggle a pulled-up
    GPIO pin that would be tied to the PROG pin on the board (causing the MKL02 to reboot the '1062
    running HalfKay).
    I saw some mention of _reboot_Teensyduino_ but didn't see it in the core library. Does that apply
    to the 4.x hardware?
    Any suggestions would be helpful!
    Thanks,
    Ed

  2. #2
    Junior Member
    Join Date
    Sep 2019
    Location
    United States
    Posts
    18
    Replying to my own question here...

    Ok, I realize now that the external connection to the PROG pin isn't necessary (at least not for cases where the processor has remained sane). I now use the __asm__ volatile ("bkpt") instruction which puts the '1062 in debug mode and does some magic on JTAG to let the MKL02 know that has happened. Apparently (please correct me if I'm wrong), the MKL02 detects this transition, and takes over control of the '1062 with JTAG and boots HalfKay automatically. Very nice!

    So, assuming the running code is sane, for now I can use some unusual combination of USB-audio control (say vol=0, vol=max, vol=0 within 1 second) to call the "bkpt" instruction. Once that occurs, teensy_loader_cli (or some customized version of that) can be used to do the upgrade; hence, I now have the ability to do a "hands-free" firmware update my Teensy4.x based audio hardware.

    If anyone reads this and disagrees please let me know...
    Thanks in advance,

  3. #3
    Senior Member
    Join Date
    Dec 2014
    Posts
    304
    The "teensy loader" software can load firmware into the Teensy without you pressing the button, and without you doing special things in your firmware.

    That being said -- the whole brilliance of the Teensy ecosystem, is that it uses a small, second, microcontroller, whose entire job is to push a small USB firmware into the RAM of the MCU, that the teensyloader can then talk to to download the firmware. If you're not using a teensy or board with that microcontroller (or something equivalent,) then you're going to want to use a JTAG programmer to load the firmware instead.

    You are right that _reboot_Teensyduino_() seems declared, but never defined, in the teensy4 firmware:

    Code:
    PS C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores> grep -r _reboot_ .
    ./teensy/core_pins.h:void _reboot_Teensyduino_(void) __attribute__((noreturn));
    ./teensy/pins_teensy.c:void _reboot_Teensyduino_(void)
    ./teensy/usb_common.h:extern void _reboot_Teensyduino_(void) __attribute__((noreturn));
    ./teensy3/core_pins.h:void _reboot_Teensyduino_(void) __attribute__((noreturn));
    ./teensy3/usb_dev.c:volatile uint8_t usb_reboot_timer = 0;
    ./teensy3/usb_dev.c:                            if (line_coding[0] == 134) usb_reboot_timer = 15;
    ./teensy3/usb_dev.c:                    usb_reboot_timer = 5;
    ./teensy3/usb_dev.c:void _reboot_Teensyduino_(void)
    ./teensy3/usb_dev.c:                    t = usb_reboot_timer;
    ./teensy3/usb_dev.c:                            usb_reboot_timer = --t;
    ./teensy3/usb_dev.c:                            if (!t) _reboot_Teensyduino_();
    ./teensy4/core_pins.h:void _reboot_Teensyduino_(void) __attribute__((noreturn));
    ./teensy4/usb.c:static uint8_t usb_reboot_timer = 0;
    ./teensy4/usb.c:                //printf("sof %d\n", usb_reboot_timer);
    ./teensy4/usb.c:                if (usb_reboot_timer) {
    ./teensy4/usb.c:                        if (--usb_reboot_timer == 0) {
    ./teensy4/usb.c:                        usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec
    ./teensy4/usb.c:                        usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec
    ./teensy4/usb.c:                        usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec
    ./teensy4/usb.c:                usb_reboot_timer = 80; // TODO: 10 if only 12 Mbit/sec
    ./usb_disk/usb.c:                                               _reboot_Teensyduino_();
    ./usb_flightsim/usb.c:                                          _reboot_Teensyduino_();
    ./usb_hid/usb.c:                                                _reboot_Teensyduino_();
    ./usb_midi/usb.c:                                               _reboot_Teensyduino_();
    ./usb_rawhid/usb.c:                                             _reboot_Teensyduino_();
    ./usb_serial/usb.c:                             if (!t) _reboot_Teensyduino_();
    ./usb_serial_hid/usb.c:                         if (!t) _reboot_Teensyduino_();
    But, attempting to use it, I get a linker error:

    Code:
    #include <core_pins.h>
    
    void setup() {
    }
    
    void loop() {
      if (milliseconds() > 300000) {
        _reboot_Teensyduino_();
      }
    }
    Code:
    C:\Users\jwatte\AppData\Local\Temp\arduino_build_967071\sketch\led_strip_teensy40.ino.cpp.o: In function `loop':
    C:\Users\jwatte\code\led_strip_teensy40/led_strip_teensy40.ino:62: undefined reference to `_reboot_Teensyduino_'

  4. #4
    Junior Member
    Join Date
    Sep 2019
    Location
    United States
    Posts
    18
    The teensy_loader_cli code issues some USB magic to cause the board to call __asm__ volatile ("bkpt");
    So, in your code, just replace _reboot_Teenshduino_(); with __asm__ volatile ("bkpt");
    and you'll transition to HalfKay.

    Not sure why _reboot_Teensyduino_() isn't in the core anymore, but that function was just a wrapper for
    the "bkpt" instruction as far as I can tell.

  5. #5
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    11,765
    Indeed usb.c watches for some incoming variation of this:: if (baud == 134UL) reboot_timer = 15; ... on T_4.x :: if (usb_cdc_line_coding[0] == 134) {
    Then when the timer is ripe on T_4.x it does :: asm("bkpt #251"); // run bootloader

  6. #6
    Junior Member
    Join Date
    Sep 2019
    Location
    United States
    Posts
    18
    This is probably a question only the writer of HalfKay can answer...
    Is there any significance to the '251' argument?

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,082
    Quote Originally Posted by edsut View Post
    Is there any significance to the '251' argument?
    Today, no. In the future, maybe.

  8. #8
    Junior Member
    Join Date
    Sep 2019
    Location
    United States
    Posts
    18
    I haven't worked at the bit level with JTAG, but I'm guessing you have access to that value...
    One interesting feature of HalfKay would be to provide a "bkpt NNN" that simply told
    it to hard-reset the main '1062 processor.

Posting Permissions

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