In-Field Update

Hello again everyone. I’m about to deploy a project a long way from home and would like to be able to keep it up to date with the IFU class and an SD Card. However, I’m rather new to this and need some more details than what is provided at this address; https://www.ghielectronics.com/docs/147/in-field-update

Some questions I have like; What is Config.hex, how can I generate it, and do I need it.

Here is the code I’ve Tried.


using GHI.Processor;
using System.IO;
using System.Threading;

namespace G120.Programs
{
    class IFU
    {
        public const int BLOCK_SIZE = 65536;

        public static void FlashFirmware()
        {
            // Reserve the memory needed to buffer the update.
            // A lot of RAM is needed so it is recommended to do this at the program start.
            InFieldUpdate.Initialize(InFieldUpdate.Types.Firmware | InFieldUpdate.Types.Configuration);

            if (!SAL.Detect.SD_Card())
            {
                Sally.StatusLED[3].Write(true);

                return;
            }

            // Start loading the new firmware on the RAM reserved in last step.
            // Nothing is written to FLASH In this stage. Power loss and failures are okay
            // Simply abort this stage any way you like!
            // Files can come from Storage, from network, from serial bus and any Other way.
            //LoadFile("\\SD\\Config.hex", InFieldUpdate.Types.Configuration);
            LoadFile("\\SD\\Upgrades\\Firmware.hex", InFieldUpdate.Types.Firmware);
            //LoadFile("\\SD\\Firmware2.hex", InFieldUpdate.Types.Firmware); //Only if your device has two firmware files.

            // This method will copy The new firmware from RAM to FLASH.
            // This function will not return But will reset the system when done.
            // Power loss during Before this function resets the system quill result in a corrupted firmware.
            // A manual update will be needed if this method failed, due to power loss for example.

            Sally.StatusLED[1].Write(true);

            while (Sally.LDR0.Read() & Sally.LDR1.Read())
            {
                Thread.Sleep(1000);
            }

            Sally.StatusLED[2].Write(true);

            InFieldUpdate.FlashAndReset();
        }

        public static void LoadFile(string filename, InFieldUpdate.Types type)
        {
            using (var stream = new FileStream(filename, FileMode.Open))
            {
                var data = new byte[BLOCK_SIZE];

                for (int i = 0; i < stream.Length / BLOCK_SIZE; i++)
                {
                    stream.Read(data, 0, BLOCK_SIZE);
                    InFieldUpdate.Load(type, data, BLOCK_SIZE);
                }

                stream.Read(data, 0, (int)stream.Length % BLOCK_SIZE);
                InFieldUpdate.Load(type, data, (int)stream.Length % BLOCK_SIZE);
            }
        }
    }
}

Here is the error I get.


    #### Exception System.ArgumentException - 0xfd000000 (1) ####
    #### Message: 
    #### GHI.Processor.InFieldUpdate::NativeLoad [IP: 0000] ####
    #### GHI.Processor.InFieldUpdate::Load [IP: 004d] ####
    #### G120.Programs.IFU::LoadFile [IP: 002c] ####
    #### G120.Programs.IFU::FlashFirmware [IP: 0022] ####
    #### G120.Program::Launcher [IP: 0028] ####
    #### G120.Program::Main [IP: 0025] ####

It happens at “InFieldUpdate.Load(type, data, BLOCK_SIZE);”

Thanks in advance.

Try changing the type of data to byte and not var. The error is the wrong type in one of the arguments. I’ve seen this before where I’ve passed in a different type and it didn’t automatically cast.

Thanks Again Dave.

I’ve found something that works. I had to change the type to application and initialize the application loader first.
I would still like to know how to generate the config and firmware hex files, What the difference is and how to load them.

Thanks. here is the code that works.


using GHI.Processor;
using System.IO;
using System.Threading;

namespace G120.Programs
{
    class IFU
    {
        public const int BLOCK_SIZE = 65536;

        public static void FlashFirmware()
        {
            // Reserve the memory needed to buffer the update.
            // A lot of RAM is needed so it is recommended to do this at the program start.
            InFieldUpdate.Initialize(InFieldUpdate.Types.Firmware | InFieldUpdate.Types.Configuration | InFieldUpdate.Types.Application);

            if (!SAL.Detect.SD_Card())
            {
                Sally.StatusLED[3].Write(true);

                return;
            }

            // Start loading the new firmware on the RAM reserved in last step.
            // Nothing is written to FLASH In this stage. Power loss and failures are okay
            // Simply abort this stage any way you like!
            // Files can come from Storage, from network, from serial bus and any Other way.
            //LoadFile("\\SD\\Config.hex", InFieldUpdate.Types.Configuration);
            LoadFile("\\SD\\Upgrades\\Firmware.hex", InFieldUpdate.Types.Application);
            //LoadFile("\\SD\\Firmware2.hex", InFieldUpdate.Types.Firmware); //Only if your device has two firmware files.

            // This method will copy The new firmware from RAM to FLASH.
            // This function will not return But will reset the system when done.
            // Power loss during Before this function resets the system quill result in a corrupted firmware.
            // A manual update will be needed if this method failed, due to power loss for example.

            Sally.StatusLED[1].Write(true);

            while (Sally.LDR0.Read() & Sally.LDR1.Read())
            {
                Thread.Sleep(1000);
            }

            Sally.StatusLED[2].Write(true);

            InFieldUpdate.FlashAndReset();
        }

        public static void LoadFile(string filename, InFieldUpdate.Types type)
        {
            using (var stream = new FileStream(filename, FileMode.Open))
            {
                var data = new byte[BLOCK_SIZE];

                for (int i = 0; i < stream.Length / BLOCK_SIZE; i++)
                {
                    stream.Read(data, 0, BLOCK_SIZE);
                    InFieldUpdate.Load(type, data, BLOCK_SIZE);
                }

                stream.Read(data, 0, (int)stream.Length % BLOCK_SIZE);
                InFieldUpdate.Load(type, data, (int)stream.Length % BLOCK_SIZE);
            }
        }
    }
}

Config and firmware should be in the GHI folder. These are the files you use to update your board with the latest GHI release.

If you deployed board runs the same firmware you develop with, you don’t need to update them, only the app file.

@ stotech -

At post #2


That must be an exception here, unless the Firmware.hex is application because you changed its name.

First post is correct, it should work. 
Second post is incorrect. It should not work.
You get it working at 2nd post just because you changed your application.hex to firmware.hex.
Its name is firmware.hex but that is actually application, so it will work with Types.Application.

OH NO Batman, What have I been doing? Here is my complete IFU class.
I’ve been using this no problem, but I’ve just discovered that I’m missing the Firmware2.hex file? How has this been working then? Or is it that the firmware has not changed since I started?

using GHI.Processor;

using System.IO;
using System.Threading;

namespace Mustang
{
public static class IFU
{
public const int BLOCK_SIZE = 65536;

    public static void Flash_App()
    {
        // Reserve the memory needed to buffer the update.
        // A lot of RAM is needed so it is recommended to do this at the program start.
        InFieldUpdate.Initialize(InFieldUpdate.Types.Firmware | InFieldUpdate.Types.Configuration | InFieldUpdate.Types.Application);

        if (!Detect.SD_Card())
        {
            LEDs.Show(3);

            return;
        }

        // Start loading the new firmware on the RAM reserved in last step.
        // Nothing is written to FLASH In this stage. Power loss and failures are okay
        // Simply abort this stage any way you like!
        // Files can come from Storage, from network, from serial bus and any Other way.
        //LoadFile("\\SD\\Upgrades\\Firmware.hex", InFieldUpdate.Types.Firmware);
        //LoadFile("\\SD\\Upgrades\\Config.hex", InFieldUpdate.Types.Configuration);
        LoadFile("\\SD\\Upgrades\\App.hex", InFieldUpdate.Types.Application);

        LEDs.Show(2);

        while (SAL.LDR0.Read())
        {
            Thread.Sleep(1000);
        }

        LEDs.Show(4);

        // This method will copy The new firmware from RAM to FLASH.
        // This function will not return But will reset the system when done.
        // Power loss during Before this function resets the system quill result in a corrupted firmware.
        // A manual update will be needed if this method failed, due to power loss for example.

        InFieldUpdate.FlashAndReset();
    }

    public static void Flash_All()
    {
        // Reserve the memory needed to buffer the update.
        // A lot of RAM is needed so it is recommended to do this at the program start.
        InFieldUpdate.Initialize(InFieldUpdate.Types.Firmware | InFieldUpdate.Types.Configuration | InFieldUpdate.Types.Application);

        if (!Detect.SD_Card())
        {
            LEDs.Show(3);

            return;
        }

        // Start loading the new firmware on the RAM reserved in last step.
        // Nothing is written to FLASH In this stage. Power loss and failures are okay
        // Simply abort this stage any way you like!
        // Files can come from Storage, from network, from serial bus and any Other way.
        LoadFile("\\SD\\Upgrades\\Firmware.hex", InFieldUpdate.Types.Firmware);
        LoadFile("\\SD\\Upgrades\\Config.hex", InFieldUpdate.Types.Configuration);
        LoadFile("\\SD\\Upgrades\\App.hex", InFieldUpdate.Types.Application);

        LEDs.Show(2);

        while (SAL.LDR1.Read())
        {
            Thread.Sleep(1000);
        }

        LEDs.Show(4);

        // This method will copy The new firmware from RAM to FLASH.
        // This function will not return But will reset the system when done.
        // Power loss during Before this function resets the system quill result in a corrupted firmware.
        // A manual update will be needed if this method failed, due to power loss for example.

        InFieldUpdate.FlashAndReset();
    }

    private static void LoadFile(string filename, InFieldUpdate.Types type)
    {
        using (var stream = new FileStream(filename, FileMode.Open))
        {
            var data = new byte[BLOCK_SIZE];

            for (int i = 0; i < stream.Length / BLOCK_SIZE; i++)
            {
                stream.Read(data, 0, BLOCK_SIZE);
                InFieldUpdate.Load(type, data, BLOCK_SIZE);
            }

            stream.Read(data, 0, (int)stream.Length % BLOCK_SIZE);
            InFieldUpdate.Load(type, data, (int)stream.Length % BLOCK_SIZE);
        }
    }
}

}

I also just realised that devices lose their name after IFU, What was once called mustang, is now called g120 again, can this be fixed?

Since you flash the config region in your IFU example, all data in configuration is lost. This includes device name.

Will it work if I don’t load the Config.hex?

Unfortunately there is no guarantee that the format or contents of config doesn’t change between releases. So you’d need to thoroughly test it on your end if you don’t.

Perhaps you can configure a system in your lab with the configuration you desire (device name, default network & MAC addresses, etc.) using the target F/W release, then create a Config.HEX file using FEZ Config, Then send the new config with the new F/W to your in-field unit for IFU.

Legend, I’ll give it a whirl and see how I go.

can I download a config.hex from a deployed device?

You can read the entire configuration sector as an opaque binary blob using our Configuration class. Keep in mind my disclaimer above though.