IFU sequence, firmware is wiped

I have implemented IFU support in out application.

I can update the application, but when I tries to update all files (config, firmware, firmware2 and application/deployment) the firmware is wiped.

The update process works fine. After call to FlashAndReset() the device reboots but never wakes up.

Unitl I load the config, firmware and firmware2 with FezConfig. And now it has the latest application.

This is my sequence.


if (SystemUpdate.CurrentSystemUpdateStatus == SystemUpdate.SystemUpdateStatus.Inactive)
{
    // Set that we are going to update all areas, we may not do all but there is no way later to adjust it.
    SystemUpdate.Initialize(SystemUpdate.SystemUpdateType.Deployment |
                            SystemUpdate.SystemUpdateType.Config |
                            SystemUpdate.SystemUpdateType.Firmware);
}

SystemUpdate.Load(SystemUpdate.SystemUpdateType.Config, hex, count)
SystemUpdate.Load(SystemUpdate.SystemUpdateType.Firmware, hex, count)
SystemUpdate.Load(SystemUpdate.SystemUpdateType.Firmware, hex, count) // Firmware 2
SystemUpdate.Load(SystemUpdate.SystemUpdateType.Deployment, hex, count) // Application

What device are you using? and which from firmware?

A little bit more description then we can test here. If there is different about TinyBooter, it won’t work

G120

At the moment I am fault tracing this error with firmware 4.2.11.0.

Will it not work to do a IFU update from 4.2.10.1 to 4.2.11.0 if the TinyBooter is 4.2.10.1.

Forgot to tell:

I am reading the firmware’s from CDC stream to updater.
As application update works fine, this shouldn’t be the problem.

Have any else this issue?

@ Honken -

Hello, I just came back 4.2.10.1 and try upgrade t0 4.2.11.0 by IFU and everthing works fine, Although this works but not recommended because there is different tinybooter (4.2.10.0 and 4.2.11.0)

Can you post your code so we can try here quickly.

We tested by an SD, we can test by CDC but if you have time, post your code to make sure we are same.

Okey, that’s good new. It must be something I do wrong.

Heres my methods for update, I also tested from SD but with same problem. Firmware is wipped.


public static string FIRMWARE_PATH = @ "\SD\Firmware\";

/// <summary>
/// Check if there is any firmware files on SD to update system with
/// </summary>
public static bool CheckForUpdates()
{
	if (Directory.Exists(FIRMWARE_PATH))
	{
		bool loaded = false;
		string[] files = Directory.GetFiles(FIRMWARE_PATH);
		foreach (string file in files)
		{
			using (FileStream fs = new FileStream(file, FileMode.Open))
			{
				if (!LoadFirmware(Path.GetFileName(file), fs, fs.Length))
					return false;

				loaded = true;
			}
		}

		FlashAndReset();
	}

	return true;
}

public static bool LoadFirmware(string filename, Stream dataStream, long length)
{
	//LogHandler.Instance.LogInformation("Updater", "Loading file: " + filename);
	SystemUpdate.SystemUpdateType updateType;

	try
	{
		updateType = GetUpdateType(filename);

		if (updateType == 0)
		{
			//LogHandler.Instance.LogError("Updater", "Unknown file type!");
			return false;
		}

		if (SystemUpdate.CurrentSystemUpdateStatus == SystemUpdate.SystemUpdateStatus.Inactive)
		{
			//SystemUpdate.Initialize(updateType);
			// Set that we are going to update all areas, we may not do all but there is no way later to adjust it.
			SystemUpdate.Initialize(SystemUpdate.SystemUpdateType.Deployment |
									SystemUpdate.SystemUpdateType.Config |
									SystemUpdate.SystemUpdateType.Firmware);
		}

		string fileExtension = Path.GetExtension(filename).ToUpper();

		if (fileExtension != ".HEX" && fileExtension != ".CHX")    // Normal or crypted file
		{
			//LogHandler.Instance.LogInformation("Updater", "Wrong file extenstion (" + fileExtension + ")");
			SystemUpdate.Abort();
			return false;
		}

		if (!Updater.LoadFirmware(dataStream,
			length,
			GetUpdateType(filename),
			fileExtension == ".CHX" ? true : false))
		{
			SystemUpdate.Abort();
			//LogHandler.Instance.LogError("Updater", "Error while loading file.");
			return false;
		}

		//LogHandler.Instance.LogInformation("Updater", "File loaded succesful!");

		if (SystemUpdate.CanUpdate)
			return true;

	}
	catch (Exception e)
	{
		//LogHandler.Instance.LogException("Updater", e);
		SystemUpdate.Abort();
		return false;
	}

	SystemUpdate.Abort();
	Log.//LogHandler.Instance.LogError("Updater", "Not possible to flash device!");
	return false;
}

public static SystemUpdate.SystemUpdateType GetUpdateType(string fileName)
{
	if (StringExtensions.IsNullOrEmpty(fileName))
		return 0;

	string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName).ToUpper();
	if (fileNameWithoutExtension.StartsWith("APPLICATION"))
		return SystemUpdate.SystemUpdateType.Deployment;
	else if (fileNameWithoutExtension.StartsWith("FIRMWARE"))
		return SystemUpdate.SystemUpdateType.Firmware;
	else if (fileNameWithoutExtension.StartsWith("CONFIG"))
		return SystemUpdate.SystemUpdateType.Config;

	return 0;
}

public static bool LoadFirmware(Stream stream, long length, SystemUpdate.SystemUpdateType ifutype, bool encrypted)
{
	int rest;
	byte[] hex, data;
	int blocknum;
	int blockCount = 0;
	int byteCount = 0;
	int count = 0;

	if (stream == null)
		return false;

	//Crypter crypter = new Crypter();

	blocknum = (int)length / BLOCK_SIZE;
	rest = (int)length % BLOCK_SIZE;
	data = new byte[BLOCK_SIZE];
	hex = new byte[BLOCK_SIZE];

	if (stream.CanTimeout)
		stream.ReadTimeout = 10000; // To support CDC stream

	do
	{
		count = stream.Read(data, 0, (int)(length - byteCount < BLOCK_SIZE ? length - byteCount : BLOCK_SIZE));    // Read the remainging part
		if (count <= 0)
			break;

		if (blockCount == 0 && stream.CanTimeout)
			stream.ReadTimeout = 1000;  // We are now in sync, reduce timeout

		if (encrypted)
			hex = crypter.Decrypt(data, count);
		else
			hex = data;

		// Check that the line starts with a 'S' (0x53) and ends with line feed 0x0D + 0x0A)
		if (hex[0] != 0x53 || hex[count - 2] != 0x0D || hex[count - 1] != 0x0A)
		{
			//LogHandler.Instance.LogError("Updater",
			//	"Wrong start or end of hex line." +
			//	" Start: " + Converter.ToString(hex[0], true) +
			//	" End: " + Converter.ToString(hex[count - 1], true) +
			//	". Block " + blockCount++ + "/" + blocknum + ", Bytes: " + byteCount + "/" + length);
			return false;
		}

		SystemUpdate.Load(ifutype, hex, count);
		byteCount += count;

		//LogHandler.Instance.LogInformation("Updater", "Block " + blockCount++ + "/" + blocknum + ", Bytes: " + byteCount + "/" + length);

	} while (count == BLOCK_SIZE);

	hex = null;
	//Debug.GC(true);

	if (byteCount != length)
		return false;

	return true;
}

public static void FlashAndReset()
{
	SystemUpdate.FlashAndReset();
}

@ Honken -

I am not sure but I think something wrong with these,


do
   {
      count = stream.Read(data, 0, (int)(length - byteCount < BLOCK_SIZE ? length - byteCount : BLOCK_SIZE));    // Read the remainging part
      if (count <= 0)
         break;

      if (blockCount == 0 && stream.CanTimeout)
         stream.ReadTimeout = 1000;  // We are now in sync, reduce timeout

      if (encrypted)
         hex = crypter.Decrypt(data, count);
      else
         hex = data;

      // Check that the line starts with a 'S' (0x53) and ends with line feed 0x0D + 0x0A)
      if (hex[0] != 0x53 || hex[count - 2] != 0x0D || hex[count - 1] != 0x0A)
      {
         //LogHandler.Instance.LogError("Updater",
         // "Wrong start or end of hex line." +
         // " Start: " + Converter.ToString(hex[0], true) +
         // " End: " + Converter.ToString(hex[count - 1], true) +
         // ". Block " + blockCount++ + "/" + blocknum + ", Bytes: " + byteCount + "/" + length);
         return false;
      }

      SystemUpdate.Load(ifutype, hex, count);
      byteCount += count;

      //LogHandler.Instance.LogInformation("Updater", "Block " + blockCount++ + "/" + blocknum + ", Bytes: " + byteCount + "/" + length);

   } while (count == BLOCK_SIZE); - See more at: https://www.ghielectronics.com/community/forum/topic?id=14142&page=1#msg144346

1- Why do you need to check them:


IFU does it inside and if there is wrong format, an exception will be raised. and the second and the third , 0x0D and 0x0A, why are they these number? I remmember if they are in a line, the last will be CRC and the last -1 is our firmware data, nothing like 0xD and 0xA

2- Where is the rest, let say you have 101 bytes, block is 10, so the rest will be 1, where is that?

3- I don't think this condition is correct, try to add debug.print to see data is loaded correctly or not.


```cs
 
do 
{ 
.... 
} 
while (count == BLOCK_SIZE); 

  1. I check this to make sure, if file is crypted, that we have a complete decryption without any data loss. As the HEX file is in ASCII, each line ends with CR and LF.
    But if this check is already in the IFU I can remove it.

  2. As I always try to read a complete block (BLOCK_SIZE = 1024 * 48; // Each row in hex file is 46 + 2 (line feed))
    The rest in your example is read the last time in loop. At while (count == BLOCK_SIZE) where we have only read the last byte it will break. At this point we have made a call to read from stream 11 times.

I have debugged the code but can find any “hole” in it.
But may have missed something.

If the last line in hex file is missing will IFU sense this and raise a exception?
When I load my application it’s loaded, flashed and restarted without any problem, but if there is no “complete” check of the hex file it may be a bigger problem for the firmware files as the may have start vector information at this point.

Did you have the possibility to run my code?

@ Honken -

No, it won’t. IFU doesn’t know how big the firmware is, so IFU doesn’t check it.

[quote]
Did you have the possibility to run my code?[/quote]

I will try with your code on tomorrow.

Running your code will not benefit here as we know it is not going to work. I suggest you build a checksum feature so you can check the firmware validity, along with any other security measures.

What CRC algorithm is used in the SystemUpdate.CalculateCRC()?

Yes it is,

for 4.2.11.0 firmware, crc will be: 6608

For config and deployment, crc will be different between your tool and the one installed on the device, but firmware must be same.

The built in CRC in system update is made for verifying your firmware and app is valid. Some customers needed this as an extra precaution step on power up. This is not what you need to check the validity of your files.

I like to verify that the file I sent to the device is the same that is loaded in ifu before I call flashandrestart. So I need the type of CRC in IFU, CRC8 or CRC16?

There is no way to do this and it is not needed anyway. When you send TEH new firmware to the device through IFU it is only buffered in RAM, nothing is stored on the device, till you all flash. Meaning, the CRC is on the data on flash, the old firmware data.

Aha!, I have got it wrong, thanks for explaining.

I will debug my code to make sure all data is loaded in the IFU.

I have now tested my code and it put all data as it should to the ifu loader.

The test I did was to create a new file for each call to LoadFirmware method and save the same hex array as IFU gets to the file.

I then compared all three files Firmware, Firmware 2 and Config from my save with GHI files and they match.

So there must be something in my application that stops the IFU from doing it as it should.

Could it be some registers, EEPROM etc…

If I load the following files:

Firmware2.hex
Config.hex
Application.hex

the application boots fine after flash and reset, but as soon as I try to include the Firmware.hex it will not boot???

Hi, not looking to change the original issue behind this thread, but can I ask what if any issues could arise from having a different tinybooter? I was planning on using IFU to update all my client’s EMX applications out on site from 4.2.10.1 → 4.2.11.0. I have tested in the office and haven’t come across any problems.

Thanks.