When developing mobile apps for connected devices, handling device firmware updates (DFU) is a common task we need to tackle. Device firmware updating is the process of installing new programming onto an embedded device. By leveraging BLE communication, we can use mobile phones to initiate a DFU mode and transmit the new firmware to the embedded device. However, in order to accomplish this, the embedded device must have support for performing the DFU transfer via BLE. Ultimately, we’ll want to hide this whole process underneath the hood, so that the end user of the application has a quick and easy experience when updating firmware on their connected device.
What is a Device Firmware Update (DFU)?
When designing software (or firmware), it’s important to provide a way to update it. We’re all very familiar with updating apps on our phone or computer. With a connected device, whether it’s some new gadget, wearable, or medical device, the method of updating the program running on that device is a little more complicated. Some devices, such as a smart plug or lightbulb, may have Wifi connectivity and could be programmed to fetch and install firmware updates automatically. Other devices may rely only on BLE connectivity, and do not have a direct connection to the web. There are also devices that we would only want to update when explicitly told to do so, such as a medical device.
Common Components that Need Updates
There may be multiple components that need to be updated on an embedded device. This could include the bootloader, the application, or the BLE stack (known as SoftDevice in Nordic nomenclature). The update process may take multiple steps. There may be memory constraints as the embedded device can only handle storing a small amount of data during the process. The bootloader might need an update, and after that completes, the application update process would begin. In the end, most of these details are not relevant to the end user, so it’s important to design an experience that feels smooth and easy when creating this functionality in a mobile app.
Two Ways to Perform a Firmware Update
In order to perform a device firmware update, embedded devices often must be placed into a “DFU mode.” This instructs the device to go into a state where it’s ready to accept the firmware transfer. Frequently, this is handled in one of two ways: either a “button initiated,” or “buttonless.” A buttonless approach would utilize communication via BLE to initiate the DFU mode. This might be a special byte or packet written to a specific BLE characteristic, or communication on a specific DFU BLE service. Once the device receives that packet, it would reboot in DFU mode. When a device has entered DFU mode, it’s ready for the update.
The process for performing the update can vary. It’ll depend on the device architecture, the hardware involved, and how the firmware was designed. If a Nordic chip is being used, it provides a documented method of providing a DFU service as part of the BLE GATT profile. Nordic also provides frameworks for both iOS and Android that help facilitate the firmware update transfer. In other cases, the process may be a bit more custom-designed. A device may have firmware that provides a UART interface over BLE. In this case, there may be a special packet that the mobile device can send to inform the device that a firmware transfer is about to begin. Determining how to configure the communication protocol for this transfer process may require some communication between mobile developers and firmware developers working on the project.
Designing a DFU Experience on Mobile
When designing a DFU experience for a hardware device that communicates with a mobile device, one important aspect is simplicity. The end user of the mobile app most likely does not want to deal with the device update, they just want to use their device. The user also likely does not want to be interrupted. The update experience should be easy to initiate, and be designed to be as robust as possible so that any issues that arise can be resolved by the app automatically. The complexity of any recovery scenarios can be hidden from the user so they see the update process as a simple experience.
The firmware update process might require multiple stages, such as updating the bootloader and following that with an application update. From the end user’s perspective these details can be kept under the hood. The app could be designed to show a single progress bar and limits the info provided to the user, so all they see is a simple update experience. This depends on the target audience as well. A device that is more likely used by tinkerers or engineers may want to design the update process to be more transparent, and provide exact details of what’s going on with each step of the update process.
Bug Fix or Additional Feature?
Depending on the nature of the firmware update, the process from the mobile app could be forced or optional. If the firmware update is addressing some critical bug that impacts the functionality of the device, it may be deemed necessary. In this case, it may make sense to force the user into the update process the next time they open the app or connect to their device. On the other hand, if a firmware update is adding some additional functionality with a newer version, but does not impact the current functionality of the device, it may make sense to present the update within the mobile app as an optional update. There’s also the possibility of striking a balance between these options. The app could be designed to prompt the user of an available update, and warn them that they need to perform the update soon. Perhaps after the third time opening the app or connecting to their device, the update could then be prompted as required. These are business decisions that should be determined before implementing DFU support in a mobile app for a connected device.
Important tip: If your firmware update is altering or adding any BLE services or characteristics, it’s important to ensure your firmware is sending an indication on the Service Changed characteristic of the Generic Attribute Service. Your mobile apps may also need to re-discover services, as they may have cached the GATT table. Read more about this here.
Ensuring a Recovery Path
When designing the experience of DFU within a mobile app, it’s very important to cover all scenarios. The app should minimize any potential that a customer could end up with a device that cannot update successfully or becomes “bricked.” If you’re using Nordic components, and utilizing their mobile frameworks, they provide some extra safety to prevent bricking a device. If you’re using a more custom solution, you’ll want to ensure a path to recover should anything get interrupted or go wrong during an update.. When adding DFU support in an app, you’ll be adding the ability to update the device from a functional state. But, you should also add support for recovering a device that is currently already stuck in the DFU state.
Advertising in DFU Mode
In some cases, a BLE device in DFU mode will advertise a specific service UUID that’s different from the device’s normal service. A device in DFU mode may also advertise with a different name. In the case of Nordic devices, they may use a name such as “DfuTest” or “DfuTarg.” One strategy to ensure your mobile app is capable of detecting and recovering a device in DFU mode is to alter the app’s BLE scan logic. An app designed to work with a BLE connected device will have scan logic in place to find and establish a connection to the device. By changing this scan logic to alternate between looking for the device in its expected state, and a device in the DFU state, you can ensure the app is able to handle either scenario. For example, the app could be configured to scan for the expected service UUID of the device for 10 seconds. If after that time no device is found, the scan could be stopped and a new scan looking for the DFU service or name could then run. By repeating this scan loop, the app will be able to find a device in either state. If a device is found in DFU mode, the app can then attempt to initiate a firmware update to bring the DFU device back to a functional state.
Designing Firmware Update UI
When it comes to creating the UI for a firmware update, typically you can keep it simple. Some text informing the user what’s happening, and a progress bar indicating the progress through the firmware transfer should suffice. Depending on the target audience, you can opt to display additional information. For an app meant to be used by engineers, it may make sense to show more details. The app could display what stage the update is in (if it’s a multi-stage update), the speed of the transfer, or other details. But, when designing an app that works with a medical device peripheral that targets an older audience, the app should probably not display any technical details and keep the UI as simple as possible. If the update is doing a multi-stage update, such as a bootloader update followed by an application update, there is the option of only showing a single progress bar that fills between 0% – 50% for the first stage, and 50% – 100% for the second stage. This helps reduce the info shown to the user and keeps the UI very simple.
In any case, it would be a good idea to show some text that informs the user to keep the phone near the device throughout the update. It would also be wise to ensure the update can only begin if the phone has plenty of battery (perhaps >50%) or is plugged in to power. If anything goes wrong during the update, the app’s DFU logic could be configured to try again a few times before surfacing the error to the user. If after a few tries there is still a problem, at that point the UI can update to indicate there has been an error and provide some instructions on any other things the user could try, such as cycling power on their device, or reaching out to a support email or phone number for additional help.
Testing your software is always important. But when implementing DFU features, it’s really important to thoroughly test the software to try and catch any issues before you release an update to users. A worst-case scenario could result in a bricked device, which will result in a very unhappy user! Make sure to test the process with real phones and real hardware across various phone models and OS versions. Spend some time trying to break your software — what happens if you turn off bluetooth in the middle of an update process? Or if you walk out of bluetooth range while an update is about to begin? Try to think of all the possible scenarios an end user could run into and test it out yourself.
Final Thoughts about Designing the DFU Experience
Utilizing the BLE capability of mobile phones is an efficient way to update firmware on connected devices. Updated firmware can be bundled in the app and included in an app update, or the mobile app can be programmed to check and download the latest software from the web. By having the ability to update firmware on a connected device, it allows better support and extended lifetime of connected devices.
For those that prefer, here is a tl;dr:
- Device Firmware Update (DFU) is a mode that allows devices to receive updated programming.
- DFU can be facilitated by a mobile phone to a connected device via BLE.
- When designing the UI for DFU experience on a mobile device, in general, keep it simple.
- Make the mobile app DFU process robust by ensuring any issues that could occur are accounted for.
- Test your implementation thoroughly.