EMX EnableSystemUpdate Bootloader deploy problems

Hi There,

This is my situation:

  • EMX
  • GHI Library: 4.1.6.0 (100% sure, because laptop reinstalled last week, and downloaded latest from website)

I had created a single program that enables, accesses and loads SystemUpdate functionality:
This images should therefore be deployed multiple times. (right?)

 
public static void Main()
    {


        Debug.Print(SystemUpdate.GetMode().ToString());
        Thread LedThread = new Thread(LedLoop);
        LedThread.Start();

        // Subscribe to USB events
        USBHostController.DeviceConnectedEvent += new USBH_DeviceConnectionEventHandler(USBHostController_DeviceConnectedEvent);
        USBHostController.DeviceDisconnectedEvent += new USBH_DeviceConnectionEventHandler(USBHostController_DeviceDisconnectedEvent);
        // SD Storage mounten
        try
        {
            sd = new PersistentStorage("SD");
            sd.MountFileSystem();
        }
        catch(Exception ex)
        {
            Program.LogToFile("Error mounting SD");
        }

        Program.LogToFile(".");
        Program.LogToFile("VMC Bootloader started.");

        // Make notificationled's shortly visible
        Thread.Sleep(LedShowFor);

        if (SystemUpdate.GetMode() == SystemUpdate.SystemUpdateMode.NonFormatted)
        {
            Program.LogToFile("SystemUpdateMode : NonFormatted");
            Program.Run = false;
            Program.LogToFile("Enabling Bootloader..");
            SystemUpdate.EnableBootloader();
        }
        else if (SystemUpdate.GetMode() == SystemUpdate.SystemUpdateMode.Application)
        {
            Program.LogToFile("SystemUpdateMode : Application");
            Program.Run = false;
            Program.LogToFile("Accessing Bootloader..");
            SystemUpdate.AccessBootloader();
        }
        else if (SystemUpdate.GetMode() == SystemUpdate.SystemUpdateMode.Bootloader)
        {
            Program.LogToFile("SystemUpdateMode : Bootloader");
            try
            {
                #region Updatefunctionality

                if (SystemUpdate.GetMode() == SystemUpdate.SystemUpdateMode.Bootloader)
                {
                    
                    string File_UpdateApplication = string.Empty;

                    // Als updatefile niet op USB staat
                    if (File.Exists("\\USB\\UPDATE_APPLICATION.HEX"))
                    {
                        File_UpdateApplication = "\\USB\\UPDATE_APPLICATION.HEX";
                    }
                    else if (File.Exists("\\USB\\Update.xml"))
                    {
                        Program.LogToFile("Update.xml found!");

                        FileStream filestream = File.OpenRead("\\USB\\Update.xml");
                        long filelength = filestream.Length;
                        byte[] xmlBytes = new byte[filelength];

                        filestream.Read(xmlBytes, 0, (int)filelength);
                        XmlReader reader = XmlReader.Create(new MemoryStream(xmlBytes));

                        while (reader.Read())
                        {
                            switch (reader.NodeType)
                            {
                                case XmlNodeType.Element: // The node is an element.

                                    switch (reader.Name)
                                    {

                                        case "UpdateAction":
                                            reader.ReadToFollowing("Type");
                                            string Type = reader.ReadString();

                                            // System ApplicationUpdate
                                            if (Type == "1")
                                            {
                                                reader.ReadToFollowing("LocalPath");
                                                File_UpdateApplication = "\\USB\\" + reader.ReadString();
                                                break;
                                            }

                                            break;
                                    }

                                    break;
                            }
                        }

                        reader.Close();
                        filestream.Close();
                    }
                    else if (File.Exists(Program.DefaultRoot + "UPDATE_APPLICATION.HEX"))
                    {
                        File_UpdateApplication = Program.DefaultRoot + "UPDATE_APPLICATION.HEX";
                    }
                    else
                    {
                        throw new Exception("NO VALID UPDATEFILE FOUND");
                    }

                    if (File_UpdateApplication != string.Empty)
                    {
                        Program.LogToFile("Update started from : " + File_UpdateApplication);

                        Thread UpdateBusy_LedThread = new Thread(UpdateBusy_LedLoop);
                        UpdateBusy_LedThread.Start();

                        FileStream file = new FileStream(File_UpdateApplication, FileMode.Open, FileAccess.Read);

                        // start update
                        SystemUpdate.ApplicationUpdate.Start();

                        // read the file in chunks
                        byte[] buffer = new byte[10 * 1024];
                        int length;

                        do
                        {
                            length = file.Read(buffer, 0, buffer.Length);
                            SystemUpdate.ApplicationUpdate.Write(buffer, 0, length);

                        } while (length == buffer.Length);

                        file.Close();

                        Program.LogToFile("Update succesfully finished, accessing application mode now.");
                        SystemUpdate.ApplicationUpdate.End();

                    }
                    else
                    {
                        throw new Exception("No update hex found!");
                    }
                }
                else
                {
                    throw new InvalidOperationException("Unknown SystemUpdate Mode!");
                }
                #endregion
            }
            catch (Exception ex)
            {
                Program.LogToFile("Update main error : " + ex.Message);
            }
            finally
            {
 Thread.Sleep(5000);
                Program.Run = false;


                // Access the application
                SystemUpdate.AccessApplication();
            }
        }
        else
        {
            Program.LogToFile("Onbekende modus.");
        }


    }

This; i deploy want to deploy 3 times after deploying Firmware CLR, in my understanding, this should happen:

  1. Deploy and execute, and have this image enable SystemUpdate mode. It then comes into ‘application-mode’
  2. Have PC MFDeploy deploy it’s image again, it then comes into ‘bootloader-mode’, execute after deploy when using api
  3. Have PC MFDeploy deploy it’s Bootloaderimage, execute after deploy when using api.

In this bootloademode, it should be possible to update software, and let then AccessApplication end the update, and make program run normally.

The bootloader HEX is created as follows:

  1. Deploy image from Visual Studio.
  2. Extract image with MFDeploy, then create key pair en signature file from MFDeploy.

I wrote a program that does the following steps automatically, with Xmodem and mfdeploy api, but for the test to be clear, i did it manually too. This is how i do the update, and what the actual problem is

  1. TeraTerm, erase, and rewrite tinybooter.ghi with 1k check.
  2. MFDeploy, deploy CLR, CLR2 and Config file.
  3. MFDeploy, deploy bootloader.hex for the first time. (this will work)
  4. MFDeploy, deploy bootloader.hex for second time (this won’t work anymore). Saying signature file is wrong.

That is then my problem: i never get past step 4.

How can i fix this?

First I’d replace all those else if’s with a switch; it’ll be ever so slightly faster but also easier to read.

First deploy should enable SystemUpdates and restart the device. Debugger will disconnect, no redeploy required.

Next your application will see it is in application mode and immediately switch to bootloader mode. At this point deploy your bootloader application (which really should be separate).

The issue is probably you’re switching to bootloader immediately then you do an update and immediately run to application, which immediately runs to bootloader. Infinite loop.

Look at Pyxis 2; it does updates from SD card just like you’re trying to do.

Hi Skewworks,

the updating in field update part of the code works fine. I see that there are some parts in Roberts code that could be modified / changed for speed or reading improvements.

But the problem is with the deployment to the emx. Doesn’t the manual state that everything gets cleared after you issue the SystemUpdate.EnableBootloader() command?

[quote]Enabling System Update
To enable system update, use the following: SystemUpdate.EnableBootloader. This will enable the C# managed bootloader.
Note: once this is called the FLASH is formatted and your application will be erased. Also, the FLASH will be split into two regions, the bootloader and the application. The bootloader region is small as it is only intended to do a specific task.
This method needs few seconds to complete and the device will be rebooted automatically and then it will start in Application mode. If you have an LCD connected, you will see “Deployment Application Mode” on screen. Now you can write applications as normal. The Bootloader is in seperate place.
You can obtain the current mode at any time in any mode. This can be used if you do not have an LCD or for debugging purposes. This will obtain the mode: SystemUpdate.GetMode.
[/quote]
[url]http://www.ghielectronics.com/downloads/NETMF/Library%20Documentation/html/53c9fe92-8150-bd36-e2de-bf4fc6f13f8f.htm[/url]

If we read this correctly then everything is erased and we should then deploy an program that we are going to use as our bootloader. Mike said in another post that it would be easiest to make a bootloader program like this one and just deploy it multiple times (with the aid of a small program). This is because we need to deliver the products in quantities of at least 50pcs and installing and updating each board with the correct settings manually would be a real pain in the ass… But we aren’t able to deploy this multiple times. It accepts the signature during the first deployment, but after that it doesn’t anymore. Maybee Mike can help us a bit with this issue?

How does the singing work then? Because users can deploy programs without a signature through the mfdeploy program. But if you want to use the api for that then you need to provide a key. Does the mfdeploy program create a temp key in the background?

Regards,

Per

Per,

OK, I see what you’re doing and I think I understand the issue. You don’t need to redeploy the HEX file multiple times. Take a look at this excerpt from Pyxis 2’s update method:


static void InstallCompleteUpdate(string path)
        {
            bool bComplete = true;

            Installing = true;

            bmp.DrawText("INSTALLING UPDATES...", bld, Color.White, 4, y);
            bmp.Flush();


            // start update
            SystemUpdate.CompleteUpdate.Start();

            string[] files;
            switch (SystemInfo.SystemID.Model)
            {
                case 5: // Cobra
                    files = new string[] { "CLR.HEX", "CLR2.HEX", "Config.HEX", "pyxis2.hex", "bootloader.hex" };                   
                    break;
                case 6: // Chipworks
                    files = new string[] { "ER_FLASH", "ER_CONFIG", "pyxis2.hex", "bootloader.hex" };
                    break;
                default: // Unknown
                    bmp.DrawText("FAILED [0x" + SystemInfo.SystemID.Model + "]", bld, Color.White, 4 + TextWidth("INSTALLING UPDATES...", bld), y);
                    bmp.Flush();
                    Thread.Sleep(1000);
                    SystemUpdate.AccessApplication();
                    return;
            }

            for (int i = 0; i < files.Length; i++)
            {
                y += (fnt.Height + 4);
                bmp.DrawText(">> " + files[i] + "...", fnt, Color.White, 50, y);
                bmp.Flush();
                if (!CompleteInstallFile(path + files[i]))
                {
                    bmp.DrawText("FAILED", bld, ColorUtility.ColorFromRGB(255, 0, 0), 50 + TextWidth(">> " + files[i] + "...", fnt), y);
                    bmp.Flush();
                    bComplete = false;
                    Thread.Sleep(1000);
                    break;
                }
                else
                {
                    bmp.DrawText("OK", bld, ColorUtility.ColorFromRGB(0, 255, 0), 50 + TextWidth(">> " + files[i] + "...", fnt), y);
                    bmp.Flush();
                }

                try
                {
                    File.Delete(path + files[i]);
                }
                catch (Exception e)
                {
                    Debug.Print("Couldn't delete '" + files[i] + "'\r\n  >>" + e.Message);
                }

            }

            // End update
            if (bComplete) SystemUpdate.CompleteUpdate.End();

            // Access the application
            SystemUpdate.AccessApplication();
        }