cancel
Showing results for 
Search instead for 
Did you mean: 

Failsafe upgrades with STM32L476 Dfu

Adrian Sapio
Associate II
Posted on June 27, 2018 at 15:24

On the STM32L476, we have been using the Dfu program that comes loaded in system memory.

We've been using this ROM code succesfully as a way to load firmware on to the MCU flash over USB, with the documented Dfu file format + DfuSeDemo + DfuSe sample code, etc. So this has been helpful to get up and running with a loader solution over USB.

We're now planning to do field firmware upgrades on the MCU, and I'm running into what seems like a limitation of the Dfu ROM code: If we're in the middle of a Dfu transfer, and something breaks (USB gets disconnected, power glitch, PC crashes, etc), a partially-loaded image will be present on the MCU. Rebooting the MCU after that will essentially brick it, as I have no way to assert the Boot0 pin to go back into the DFU when this device is deployed in the field.

Has anyone run into this and created a 'failsafe' recovery flow for a situation like this? What I'd like is for the MCU to automatically go back into the Dfu after a failure of this type so the upgrade can be restarted, not try to run a corrupted image endlessly. Are there any recommended recovery methods or workarounds? I have read AN2606, AN3156 but I don't see a clear path forward.

The best options I have come up with so far are:

1) Create a 2nd stage loader and package that up with my application code, and have the Dfu always load my 2nd loader+app code. I'm not sure if I could get this approach to not have the same 'failsafe' vulnerability of the ROM Dfu.

2) Stop using the ST ROM Dfu altogether, and write my own bootloader with some failsafe features. Partition the flash to always have this bootloader resident, and only update the application code in the field - not the bootloader. This bootloader would always run first before my upgrade-able application code and always check the application code image integrity before booting it. 

Both of these are non-trivial efforts so if anyone can think of anything simpler I would really appreciate it.

5 REPLIES 5
Ben K
Senior III
Posted on June 27, 2018 at 17:16

The same problem and the realization of no simple solution drove me to go ahead with (2) and develop my own

https://github.com/IntergatedCircuits/DfuBootloader

. In a proper DFU implementation the final manifestation stage is responsible for checking the integrity of the downloaded image, and storing this information non-volatile.

My solution simply writes a specific word at the end of the application flash area at this stage. At startup if both the first word (stack pointer init value) and the last word are valid, the bootloader starts the application, otherwise it runs the DFU. This operation works because I stick to the original DFU specification, and erase the entire application flash at the very beginning of the update - unlike the DFUSE, which erases flash by the blocks. Of course you can define your own manifest format and use according to your needs.

The other benefit of this bootloader is that the DFU interface can be mounted as one of the USB device interfaces in application mode (while the interface's code is only located in the bootloader). In application mode the DFU interface can only be used to reboot the system into the bootloader. This is useful as only a USB control request is necessary to enter DFU mode, there is no need for hardware switches or using an application interface for rebooting.

BSP for STM32L476 isn't prepared for this project yet, but that I can solve rather easily, as I'm an owner of an L476Disco myself.

Posted on June 27, 2018 at 17:46

Can't the DFU image describe something that isn't the complete FLASH, ie something that starts at 0x08004000, say, and you have a small loader at the front capable of a) checking a CRC across the application image burned by the DFU and jumping in if valid/complete, or b) jumping into the ROM DFU mode to permit user recovery.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 27, 2018 at 18:45

Thanks for the detailed reply, Ben. I will take a look at your bootloader project as reference and consider the implications of an approach like this on our product.

Posted on June 27, 2018 at 19:07

Hi Clive, thanks for your help. My responses are below...

--> 'Can't the DFU image describe something that isn't the complete FLASH, ie something that starts at 0x08004000'

Yes, I believe the DFU image *can* describe something that isnt the complete FLASH: The DFU protocol in AN3156 includes a 'start address' for read/writes and also seems to do a per-block erase on demand (rather than erasing the whole flash as Ben mentioned above). So although it is not explicitly stated anywhere, I think it is possible due to these aspects of the DFU protocol. I guess I would have to setup an experiment to do just this and confirm it, to be 100% sure.

--> 'and you have a small loader at the front capable of a) checking a CRC across the application image burned by the DFU and jumping in if valid/complete, or b) jumping into the ROM DFU mode to permit user recovery.'

How would the 'small loader' be able to compute the CRC on the application image? It would have to know the image size in order to know what addresses to compute the CRC over, and I dont think the DFU stores this anywhere. Also, let's say it somehow could get the size and compute the CRC - what would it compare this CRC to? Although the image CRC is in the DFU file format (as per UM0391), I dont see anything that implies that the DFU stores the CRC anywhere in the MCU such that the small loader could read it.

As you can see I'm guessing here on some aspects of this based on limited documentation - it would be helpful to get the DFU ROM source code, which I don't have. Has anyone been able to get that?

Posted on June 28, 2018 at 07:33

You can make the binary image describe whatever you want, a CRC computation is like signing something with a hash, you can create self-contained blobs which have sizes, and longitudinal checksums. You could use a salted SHA-256 if you wanted. If you don&39t disclose the methods, or keys, you can make it significantly harder to download a modified binary.

There are unused vectors that can be used to store length information, you can even get the linkers to auto-generate these from available symbols. Data can also be extracted from .ELF/.AXF files which contain a lot of meta-data and symbols.

I&39ve built tools that can take object files and create images, including DFU files.

https://community.st.com/0D50X00009XkeovSAB

 

https://community.st.com/0D50X00009XkZVpSAN

 

>&gtAs you can see I&39m guessing here on some aspects of this based on limited documentation - it would be helpful to get the DFU ROM source code, which I don&39t have. Has anyone been able to get that?

You only need to understand the packaging format, which is documented, but like a russian-doll you can make it contain whatever you want, and you can build software on the target side to decode/check what you have burned into the flash. I created some annotated listings for the F1 and F4 parts I used. You might want to look at the assorted examples

STM32Cube_FW_L4_V1.10.0\Projects\STM32L476G_EVAL\Applications\USB_Device\DFU_Standalone

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..