Calling teensy_post_compile without bootloader update?

nickdaria

Member
Hey all,

We have a product that utilizes Teensy 4.1. We wrote a simple Windows flasher program which has been verified to work correctly to distribute a small patch.
  1. Periodically run teensy_ports until a Teensy is detected
  2. Run teensy_post_compile with appropriate arguments, show success/fail screen based on returned output
However we ran into an issue with older units. When a bootloader update is done, teensy_post_compile returns a success well before the bootloader update ends, meaning users are told they can unplug the device before it is safe to do so.

Is there any way to prevent the bootloader update step (older teensy.exe)? Or is there a Win32 approach for telling when Teensy.exe is completely done flashing (Reboot OK message)?

Thanks!
 
AFAIK, bootloader update is only done once and only when necessary. Maybe I miss the problem?
 
Last edited:
IFAIK, bootloader update is only done once and only when necessary. Maybe I miss the problem?
Indeed, they are rare and one time events performed only by the PJRC Teensy.exe. That is a change to software on the bootloader chip and is very rare with non in recent memory - but will be done when Teensy.exe performs an upload and detects old version.

The bootloader performs the flashing of the sketch the amount of Flash chip erase done based on the code to be uploaded and the minimum area the Teensy must overwrite - this can change the response and return time for the completion of the upload and time for the Teensy to come back running.

Watching Teensy.exe 'Help / Verbose' will give some idea of the process and timing that might show something useful?
 
Indeed, they are rare and one time events performed only by the PJRC Teensy.exe. That is a change to software on the bootloader chip and is very rare with non in recent memory - but will be done when Teensy.exe performs an upload and detects old version.

The bootloader performs the flashing of the sketch the amount of Flash chip erase done based on the code to be uploaded and the minimum area the Teensy must overwrite - this can change the response and return time for the completion of the upload and time for the Teensy to come back running.

Watching Teensy.exe 'Help / Verbose' will give some idea of the process and timing that might show something useful?
Yeah, it's a timing game since the bootloader update is so long. I was just hoping to get a return directly from the CLI program without having to completely retool to the teensy_loader_cli.

The Help/Verbose window has what I need, but no way to access it from my application.

My current approach is to use the Win32 API to monitor the open window titles and watch for the "Programming" window. Unfortunately it does not get removed from the window list until teensy closes so I will have to use a timer from programming start which I'm just not a fan of programmatically.
 
Indeed the timing is based on the original design from 2009 where Arduino just gets the files ready and causes the chip to go into bootloader mode, then Teensy Loader takes care of the rest. The only feedback mechanism was meant to be visual confirmation on the screen. Good for humans, not so good for a script.

Just to be realistic, this design probably isn't going to change anytime soon. It's baked deep into the software and would take a lot of work to redo. That work would detract from a lot of other developments that so many people want.

I will mention just briefly, the bootloader update process is well protected against power loss. In a bad case scenario, you can end up with a Teensy that needs a button press (same as any normal programming where power is lost before the flash is fully written with a good program). But a power loss during the actual writing of the bootloader will recover and redo the write upon power restored. You won't end up with a bricked board.

As Defragster mentioned, bootloader updates are extremely rare. So far since release of Teensy 4.0 in 2019, we've had just 1 update. Another might come in 2024. But it's not the sort of thing done very often.
 
Thanks for the information. I am currently testing between monitoring Win32 window titles for Teensy "Programming" to appear, and I will also test @h4yn0nnym0u5e suggestion of continuing to monitor teensy_ports for a Teensy without the bootloader flag.

Thanks!
 
For anyone that may stumble upon this thread, I wrote a very quick and dirty C# proof of concept to verify the solution proposed by @h4yn0nnym0u5e and it works well. I am going to begin writing a proper implementation of this for production use. Should note that this basic CLI implementation is not multi-Teensy friendly for obvious reasons.

Output after flash:
Code:
Connected

[History]
 -> usb:0/140000/0/5/3/4/2 COM5 (Teensy 4.0) Serial
 -> {empty}
 -> usb:0/140000/0/5/3/4/2 hid#vid_16c0&pid_0478 (Teensy 4.0) Bootloader

[Current]
usb:0/140000/0/5/3/4/2 COM5 (Teensy 4.0) Serial

C#:
using System.Diagnostics;

namespace TeensyFlashDetectionCLI
{
    internal class Program
    {
        //  Program Constants
        const string ports_path = @"";    //    Paste your teensy_ports path here
        const string ports_args = "-L";
        const string bootloader_ident = "Bootloader";
        const string not_ready_ident = "[no_device]";

        //  List of unique CLI returns
        public static List<string> returnHistory = new List<string>();

        static void Main(string[] args)
        {
            SetConsoleColorAndClear(ColorSet.IDLE);

            //  Monitor Ports
            while(true)
            {
                //  Check ports
                Loop();

                //  Wait
                Task.Delay(200).Wait();
            }
        }

        static void Loop()
        {
            //  Enumerate with basic teensy_ports output
            string ret = ExecuteCommand(ports_path, ports_args);

            //  If unique, add to history
            if (!returnHistory.Contains(ret))
            {
                returnHistory.Add(ret);
            }

            //  Change terminal color and indicate between No Teensy Connected/Connected in Bootloader/Connected normal
            if(String.IsNullOrWhiteSpace(ret) || ret.Contains(not_ready_ident))
            {
                //  Not connected
                SetConsoleColorAndClear(ColorSet.IDLE);
                Console.WriteLine("Not Connected");
            }
            else if(ret.Contains(bootloader_ident))
            {
                //  Connected, bootloader
                SetConsoleColorAndClear(ColorSet.RED);
                Console.WriteLine("Bootloader");
            }
            else
            {
                //  Connected
                SetConsoleColorAndClear(ColorSet.GREEN);
                Console.WriteLine("Connected");
            }
            Console.WriteLine();

            //  Print historical results
            Console.WriteLine("[History]");
            foreach (string line in returnHistory)
            {
                Console.Write(" -> ");
                if (String.IsNullOrWhiteSpace(line))    { Console.WriteLine("{empty}"); }
                else                                    { Console.WriteLine(line.Replace(Environment.NewLine, String.Empty)); }
            }

            //  Print current output
            Console.WriteLine();
            Console.WriteLine("[Current]");
            Console.WriteLine($"{ret}");
        }

        public enum ColorSet { IDLE, GREEN, RED};
        static void SetConsoleColorAndClear(ColorSet color)
        {
            switch(color)
            {
                case ColorSet.GREEN:
                    Console.BackgroundColor = ConsoleColor.Green;
                    Console.ForegroundColor = ConsoleColor.Black;
                    break;
                case ColorSet.RED:
                    Console.BackgroundColor = ConsoleColor.Red;
                    Console.ForegroundColor = ConsoleColor.Black;
                    break;
                default:
                    Console.BackgroundColor = ConsoleColor.Black;
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
            }

            Console.Clear();
        }

        public static string ExecuteCommand(string command, string arguments = "")
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo(command)
            {
                Arguments = arguments,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };

            using (Process process = new Process())
            {
                process.StartInfo = processStartInfo;
                process.Start();

                // Read the output of the command
                string output = process.StandardOutput.ReadToEnd();

                // Wait for the process to finish
                process.WaitForExit();

                return output;
            }
        }
    }
}
 
Last edited:
Follow up. Here is the output after a bootloader update. It does NOT report Connected until the bootloader update is fully complete, satisfying my requirements.
Code:
Connected

[History]
 -> {empty}
 -> usb:0/140000/0/5/3/4/2 hid#vid_16c0&pid_0486 (Teensy 4.0) RawHID
 -> usb:0/140000/0/5/3/4/2 hid#vid_16c0&pid_0478 (Teensy 4.0) Bootloader
 -> usb:0/140000/0/5/3/4/2 [no_device] (Teensy 4.0) Serial
 -> usb:0/140000/0/5/3/4/2 COM37 (Teensy 4.0) Serial

[Current]
usb:0/140000/0/5/3/4/2 COM37 (Teensy 4.0) Serial
 
Back
Top