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

Thread: C# Library for Uploading Firmware from User Applications

  1. #1
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594

    C# Library for Uploading Firmware from User Applications

    Hello all,

    I'm currently working on a commercial project which will include a Teensy 3.1. As discussed a few times in the forum for many applications it is desirable to upload new firmware from within windows applications. I therefore wrote a little easy to use C# library which handles uploads to Teensy boards. For the protocol I used the algorithms from the Teensy_Loader_CLI. Communication with the board is done via Mike O'Brians HIDLibrary (https://github.com/mikeobrien/HidLibrary). The lib is published it at GitHub (https://github.com/luni64/TeensySharp, VS2013 Solution).

    The usage is quite simple. Below you find some pseudo code showing the idea. A working test app is included in the repo
    Code:
                        
    var Board = PJRC_Board.Teensy_31;  // all boards implemented but only Teensy 3.1 tested so far           
    var FlashImage = SharpUploader.GetEmptyFlashImage(Board);  //Get an empty flash image with the correct size and all bytes cleared (i.e. set to 0xFF)    
    
    // Open the hex file, parse it and write the result into the image file
    var HexStream = File.OpenText(testfile);
    SharpHexParser.ParseStream(HexStream, FlashImage);    
    
    // Upload the image to the board and reboot
    int result = SharpUploader.Upload(FlashImage, Board, reboot: true);
    The Lib works nicely for T3.1. I don't have other Teensies so I couldn't test it for those boards. Any feedback, test results and improvement suggestions welcome

    Have fun
    Lutz
    Last edited by luni; 07-01-2015 at 08:56 PM.

  2. #2
    Senior Member
    Join Date
    Jul 2014
    Posts
    140
    This looks great, thank you.

  3. #3
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    I updated the TeensySharp library with a class to find all Teensies on the USB tree of a windows system. This class can be used in your Windows applications to provide a list of all currently connected Teensies (USB Serial) together with their Serialnumbers and the Port Names (COMXY). Windows has a habit of changing those Com Port Numbers from time to time which can be quite confusing for the average user.
    With the libaray you can open the SerialPort without having the user to know or select the Port Number from a list or whatever. You can even attach an eventhandler which will notify you if somebody connected / disconnected a Teensy board. Effectively this will allow for a fully transparent autoconnect feature in your applications (You can automatically open the ComPort when a user plugs in your Teensy Device)

    Documentation, source code and examples can be found on GitHub. https://github.com/luni64/TeensySharp


    Questions:
    1. To upload firmware I still have to start HalfKay by pressing the program button. Pauls GUI Loader can do this automagically, I didn't find any documentation on how to achieve this. Any pointers?
    2. If Teensy is running the USB Serial protocoll it reports a nice (unique?) serial number in the DeviceID. This comes in handy if you have more than one board connected. HalfKay does not seem to report this number, at least I didn't find it. This would be a very nice feature. (e.g. In a production system I want to be sure that my users download the firmware to the correct device which can be difficult if I have more than one Teensy running)


    Lutz

  4. #4
    Senior Member Koromix's Avatar
    Join Date
    Dec 2013
    Location
    Lille, France
    Posts
    202
    You can reboot a board in serial mode by setting the baudrate to 134. The procedure is obviously different if your board runs in HID (such as Raw HID), then it involves sending a magic feature report

    HalfKay reports the serial number, but with a few caveats:
    - it's hexadecimal (e.g. 000116FF)
    - since Teensyduino 1.19 (IIRC) the running serial number is multiplied by ten to work around a bug in the OSX serial driver (so 000116FF in HalfKay == 714230 when running)

    So to match the running serial number, you just have to convert the number from hexadecimal and multiply it by ten unless it's equal or superior to 10000000. I send you to the core commit related to this: https://github.com/PaulStoffregen/co...9bb2e90aaf194d

    I believe you can get the serial number from a HID handle with HidD_GetSerialNumberString().

  5. #5
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    Thanks for the information Koromix, that helps a lot. I will try the HalfKay serial number parsing this evening.
    I assume in order to reboot I have to set the baudrate to 136 on the teensy firmware? If so, I still don't understand how the TeensyLoader is able to start HalfKay regardless what firmware is running...

  6. #6
    Senior Member Koromix's Avatar
    Join Date
    Dec 2013
    Location
    Lille, France
    Posts
    202
    Nono, you do it on the computer using SetCommState() on the device HANDLE, which you get by opening the COM port. I don't know much about the .NET framework and if it provides anything to manage serial ports, but here is some (untested) C/Win32 code to do it (without error management).

    Code:
    DCB dcb;
    DWORD previous_rate;
    
    dcb.DCBlength = sizeof(dcb);
    
    /* Get this HANDLE with CreateFile("COMx") */
    GetCommState(handle, &dcb);
    previous_rate = dcb.BaudRate;
    
    dcb.BaudRate = 134;
    SetCommState(handle, &dcb);
    
    /* Restore the previous baudrate, to make sure Windows does not try to apply this setting on
        a future device/Teensy (and reboot it again) */
    dcb.BaudRate = previous_rate;
    SetCommState(handle, &dcb);

  7. #7
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    Great, that works perfectly. In .net it is as simple as

    Code:
    ...
    var Com = new SerialPort("COM14"); 
    Com.Open();
    
    int OldBaudRate = Com.BaudRate; 
    Com.BaudRate = 134;
    Com.BaudRate = OldBaudRate;
    ...
    Thanks a lot

  8. #8
    Junior Member
    Join Date
    Jan 2018
    Posts
    14
    Thanks for sharing that library. How reliable is it? Have you ever bricked a Teensy with it?

  9. #9
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    I never bricked a Teensy with it and I never got any complaints.
    The library uses the algorithms from Pauls CLI uploader. I'm quite sure that technically you can not brick a Teensy by downloading firmware but of course I can not guarantee anything.

  10. #10
    Senior Member
    Join Date
    Dec 2016
    Location
    Montreal, Canada
    Posts
    3,852
    you cant “brick” a teensy unless you intentionally try to erase the flash boot sector or short the wiring, ir apply too much voltage to any pin...

  11. #11
    Quote Originally Posted by tonton81 View Post
    or apply too much voltage to any pin...
    That would be "smoking" or "blowing", not "bricking".

  12. #12
    Junior Member
    Join Date
    Jan 2018
    Posts
    14
    Quote Originally Posted by luni View Post
    Pauls CLI uploader.
    Is the code for that uploader available somewhere?

    I was just looking at TeensySharp source code and could not find a Teensy 3.2 value in PJRC_Board. I guess I should just use Teensy_31 since both 3.1 and 3.2 boards are compatible right?

  13. #13
    Junior Member
    Join Date
    Jan 2018
    Posts
    14
    So I just gave it a try and TeensyWatcher could not find my board as it's not matching any of the expected product IDs.
    My product ID is 0x0476 but that very much depends how you configured it.
    For Teensy 3.2 I've noted the the following product IDs for instance:
    const int KProductIdTeensy32KeyboardMouseJoystick = 0x0482;
    const int KProductIdTeensy32RawHid = 0x0486;
    const int KProductIdTeensy32AllTheThings = 0x0476;

    The TeensyWatcher code is expecting either:
    const uint serPid = 0x483;
    const uint halfKayPid = 0x478;

    Is this a limitation of the uploader or an issue with TeensyWatcher implementation?

  14. #14
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    Uploader: https://github.com/PaulStoffregen/teensy_loader_cli

    I guess I should just use Teensy_31 since both 3.1 and 3.2 boards are compatible right?
    Yes

  15. #15
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    The TeensyWatcher code is expecting either:
    const uint serPid = 0x483;
    const uint halfKayPid = 0x478;

    Is this a limitation of the uploader or an issue with TeensyWatcher implementation?
    This is not a principle limitation. When I did TeensySharp / TeensyWatcher I only implemented it for Teensies in serial mode (0x483). Extending to the other modes is possible (and not really difficult) but since I didn't have a use case / request until now I never did it.

  16. #16
    Member DIYLAB's Avatar
    Join Date
    Jun 2020
    Location
    Germany
    Posts
    62
    Hi Lutz,

    I have taken the liberty to paste your answer to the TeensySharp in the Teensyduino 1.54 thread here and link to it:

    Quote Originally Posted by luni View Post
    TeensySharp was written some 6 years ago and has a rather small user base (<300 downloads at nuget). So, I have to admit that it was not very well maintained over the years. However, ~two years ago I spent some time to upgrade it to the then new multiple Serial ports which also required supporting the IAD descriptors. This upgraded version works but was never really finished and not much tested. It lives in the development branch of the repo. I recently got a request to support the new MicroMode versions so, I started to work on it again (at least whenever I find some time...). I would be glad if you could give it a try and identify open bugs.
    First of all, thanks a lot that you are still working on this project at all!

    Sometimes life could be so simple ;o)
    Your TeensySharp is the main part of my project and I was absolutely thrilled with it until Teensyduino version 1.53 - everything ran perfectly. The desktop configuration program is intended for setting a Teensy audio visualizer and finds the used Teensy unerringly and reliably thanks to your software. Here are a few screenshots, so you know what it's all about: https://www.diylab.de/revox-a700-aud...r-software-de/

    I also used only one class from your project, the "TeensyWatcher" class and therefore used the "TeensyWatcher.cs" directly without including the whole package via NuGet.

    This (old) class is clearly understandable for me.
    Honestly, that's all it needs, your project should be called "C# library for finding Teensies on the USB tree" - who needs the rest?

    So now you have completely turned the whole construct upside down and I have to understand what you are actually doing, I am quite frustrated at the moment.

    Imagine if you had only implemented this simple function to identify a connected Teensy and provide the port and then provided a simple explanation that everyone understands, that would be interesting for a lot of users.

    I have to take a step back and get used to the fact that everything is different with Teensyduino 1.54 now. Whether it is better, I do not like to judge.
    I'm going to pull weeds first ;o)

    Kind regards
    DIYLAB (Bruno)

  17. #17
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    If you are only interested in the COM ports of the connected Teensies and don't need their serial number and don't want to upload firmware you can simply hack TeensyWatcher.cs:

    From the point of view of the WMI database the IAD descriptor generates two logical devices one composite device containing the serial number and one Serial device containing the Port. The PNPClass of the first device is "USB" the PNPClass of the second device is "Ports". You can just ignore all devices with PNPClass != Ports and read out the COM port from the remaining devices via the "Caption" property:

    Code:
     protected USB_Device MakeDevice(ManagementBaseObject mgmtObj)
     {
           var DeviceIdParts = ((string)mgmtObj["PNPDeviceID"]).Split("\\".ToArray());
           if (DeviceIdParts[0] != "USB") return null;
    
           int start = DeviceIdParts[1].IndexOf("PID_") + 4;
           uint pid = Convert.ToUInt32(DeviceIdParts[1].Substring(start, 4), 16);
           if (pid == serPid)
           {
    // change from here on ..........................................
               string port = null;
               uint serNum = 0;
               //uint serNum = Convert.ToUInt32(DeviceIdParts[2]);
               
               if ((string)mgmtObj["PNPClass"] == "Ports")
               {
                    port = (((string)mgmtObj["Caption"]).Split("()".ToArray()))[1];
               }
               else return null;
    //.....
    Remarks:

    So now you have completely turned the whole construct upside down and I have to understand what you are actually doing, I am quite frustrated at the moment.
    Actually this statement is quite rude. You copied out a class from a free library and now you complain that an updated version of this free library requires you to rethink? I don't want to comment on this further.

    Imagine if you had only implemented this simple function to identify a connected Teensy and provide the port and then provided a simple explanation that everyone understands, that would be interesting for a lot of users.
    Main use case of the library is to upload firmware from within a c# user application. The fact that you are only interested in a small part of it does not necessarily apply for other users. Anyway, it's open source, feel free to fork and improve it.

  18. #18
    Member DIYLAB's Avatar
    Join Date
    Jun 2020
    Location
    Germany
    Posts
    62
    Quote Originally Posted by luni View Post
    Actually this statement is quite rude.
    Oh, if that's how it was taken, then I'm honestly sorry!
    I wanted to say that I am unhappy about the state of my project per se and that is of course not exclusively related to TeensySharp. So sorry!
    I appreciate what you are doing, of course.

  19. #19
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    Accepted.

    Did you try if the hack is working?

  20. #20
    Member DIYLAB's Avatar
    Join Date
    Jun 2020
    Location
    Germany
    Posts
    62
    Quote Originally Posted by luni View Post
    Did you try if the hack is working?
    It works ;o)
    Finally something goes right today - THANK YOU!

  21. #21
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,594
    Great, let me know if you find something else.

Posting Permissions

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