Hi there! –
We’ve been working for a week on the ability for our product to do automatic firmware update. In production, firmware update will happen through BLE or Wifi. But for the sake of simplicity and to make sure we understand and master all the pieces, we are doing it via USB for the moment.
We took inspiration from the best:
We are currently using the application
.hex file to upload our firmware update. From the bootloader, we receive and parse the
.hex and write it to the MCU flash.
We are wondering if we should do it with the
.bin file instead. The idea (and we might be terribly wrong) would be to:
- in the application, receive the update as
.bin and store it to QSPI Flash
- reboot the device
- have the bootloader flash the new firmware (read from QSPI Flash) with FlashIAP to the MCU, “packet by packet”
- launch the application
Would that work? And if so,
As I said, we have been working on that for very little time, so we might be missing the big picture. Any advice, warning or resources that might help us in the future regarding the whole process would be greatly appreciated!
We are doing something similar with our product… Upload the binary via USB into storage, we are putting it on an SD card then rebooting and picking it up on the bootloader during the boot sequence. This is working well for us.
You will notice the benefit of ihex files is that each line contains a checksum value and has a start frame of : I think. So it allows a convienent way of transfering a file and manage to some extent the integrity of each line. Transfering a raw binary will mean you need to handle this your own way if you care about getting each byte correctly. The positive however if you compare the size of an ihex and a binary the binary is alot smaller. For every byte of binary it is represented by two bytes of ASCII .
Some things to consider… Transfering binary files may conflict with any ASCII characters transfered with it such as command or control characters and may require consideration around binary framing and escapping, also packet integrity with checksum or CRC .
In conclusion the simplest way is to convert everything to an ASCII representation of bytes such as hex, pack it into ASCII frames and send it (I.e ihex) however it means transfering a larger file. The quicker way is to transfer the binary, packing and crc checking on the fly with custom framing.
Anyway this is my experience and would like to hear what others think as I am no way an expert, this is just what worked for us and with a few tests ended up being fastest way to load binaries with full error checking and file validation.
Thanks a lot @Zanev for your insights!
We have the ability to do that as well. We also have 3 QSPI flash memories, that we wanted to use for that : one with the factory firmware, one for the current firmware and the third one for the update, with two and three switching with each update. The idea was to be able to roll back to the previous working version if the update fails and to factory firmware (read only) in case everything fails.
We also have a SD card for storing assets (images, .wav, videos, etc.) that we could use for that as well.
Yes, we are using the the ihex checksum to check for integrity.
That being said, checking each line is fine if I’m able to send them again until I get the right checksum. This is easy with USB but a lot less easy with BLE or Wifi where I can lose the connection.
In this case, I will need to start again from the beginning, so I’d say that having a global checksum is better. If it’s correct I can do the update, if not, I just boot the regular application and let the user know it did not work.
With the ihex, I’m also wondering about encrypted firmware update. Should I encrypt/decrypt each line to check fo the checksum? With bin, my (maybe wrong) understanding is that I can encrypt the file, have checksum on the encrypted file and only decrypt if the checksum is correct.
That’s a good point and in a way, adding binary framing is kind of reinventing the ihex. We’ve already done that for something else: we send commands from a device through BLE, and those commands have specific structure as a lot of commands are sent and need to be processed.
One follow-up question: what about security? Do you have anything in place for that?
Thanks again for your kind answer!
@ladislas, one more benefit over ihex with doing binary framing is that you can now send more data per frame and we are putting a CRC checksum on each of these frames. I am also sending file position per frame. If you loose connection temporarily or have a corrupt package you can request the stream to restart back at that position… We stream frames to the device as fast as possible and don’t acknowledge all frames.
And then when the file is on the storage device we double check the overall file CRC and compare that with the desired CRC.
As for security this is where we have not done anything and this is mainly because it is over USB, perhaps a different kettle of fish when you want to stream over ble or wifi but definitely worth consideration. Sorry I can’t really help you with that one yet.
We are actually working on signing our firmware with some header bytes after compile that allows the device to verify the author is us and will not load anyone elses binaries. I think that one is more important for us.
Flat binary (.bin) here. We have used various fragmentation protocols to transfer the binary to a file system (where the bootloader picks it up on restart). The latest protocol we’re using is CoAP with blockwise transfer. mbed has some built in support for CoAP, but the code takes some massaging to dump the packets onto the file system