Assuming you have used one of Nordic’s Development Kits for development so far, they all have two main chips on them:
The onboard debugger uses its direct access to program and debug the nRF chip. However, when producing custom PCBs, we do not want to have an extra chip on all our boards. So we need a solution to program the nRF chip standalone. That is what DFU does: It is a method for sending new firmware to the chip so it can reprogram parts of itself.
DFU can theoretically be performed using any communication protocol, and the nRF Connect SDK has support for DFU over many different protocols. Let’s first have a look at one of the most basic cases: DFU over UART. There are two types of DFU over UART.
We start with the Application and Bootloader. From the previous section, we know that we can not change the Immutable Bootloader. So, for DFU, we can only upload new firmware for the application.
Now, should we run our DFU receiver code in the Bootloader or in the Application?
Our new firmware is supposed to be a new application, and since we can not overwrite the application while the application is running, we will run the DFU receiver code in the bootloader.
So for DFU over UART, the bootloader can enter into DFU mode instead of booting the application. Typically, the user has to hold a button or toggle a pin at power-up for the bootloader to enter DFU mode (This is user-configurable). A significant advantage of running DFU mode in the bootloader is that no matter how the application crashes, the device can just be reset into DFU mode, and then the application can be reprogrammed again. For this reason, MCUboot refers to DFU mode from the bootloader as Serial Recovery.
When the bootloader is in DFU mode, an external device, for example, a PC, transfers the new firmware hex in chunks over UART. The bootloader receives these and writes the new firmware hex to non-volatile memory. Then the chip is reset again and on the new reboot, the bootloader will boot into the new firmware if verification is successful.
Q: In all the figures, there is an empty white space at the top. What is this for?
A: If the application does not fill up all available non-volatile memory, the extra space is available to the developer for non-volatile storage of anything, for example using NVS.
In some situations, we would not want to run DFU drivers in the bootloader.
For example, when communication drivers are large, such as for Bluetooth Low Energy. We will see how that works later, but for now, let’s stick to UART. However, we can not overwrite the application from itself. To solve this, we can write the update to another part of the non-volatile memory, and then let the bootloader move the new application over after. As such:
As we can see from the illustration above, the image is transferred over UART to the application instead of the bootloader. Then the application writes this to empty non-volatile storage. After this, the device reboots to run the bootloader again. The bootloader will check the empty non-volatile storage, and if it finds valid firmware, it will move the new firmware to overwrite the application. Usually, the bootloader and the application must be configured with the same start address and size for where in non-volatile memory, the new firmware is stored. These pre-decided memory areas are referred to as slots. Since this method has two slots, it is often referred to as dual slot DFU.
A downside of this method is that the available space for the application is halved.
There is a problem with the above solution. If the new application is faulty and can not run, we can no longer update it again, as the application is responsible for receiving the DFU.
To solve this, the previous application is saved inside the empty non-volatile memory where the new app was moved from. This is called swapping the firmware.
If the bootloader detects anything wrong with the new application, it will swap the previous application back to the middle.
One of the MCUboot developers, David Brown, has published two videos explaining the concept of how MCUboot handles swapping: MCUboot swap-scratch algorithm and The Swap-Move algorithm in MCUboot.
DFU over wireless signals, such as Bluetooth Low Energy, cellular IoT (LTE-M and NB-IoT) or Wi-Fi is often referred to as Firmware Over The Air (FOTA). Since wireless protocols are complex and require relatively large amounts of memory to operate, they are impractical to run in the bootloader. Therefore we usually run FOTA from the application as dual slot DFU.
The only difference from the above dual-slot example is that now a wireless protocol is used for the transmission instead of UART. In the coming sections, we will explore how different kinds of FOTA are handled in practice.