Problem Completing a DFU Update

I've developing an application for the nRF52833 that uses the v7.2.0 s140 Soft Device and the secure BLE DFU bootloader.

  • I'm able to compile the bootloader (taken from examples\dfu\secure_bootloader\pca10100_s140_ble)
  • I'm able to compile my application (starting at flash address 0x2700 to allow room for the MBR/Soft Device)
  • I'm able to build a dfu zip package of my application using nrfutil
  • I'm able to build a combined firmware image that merges the Soft Device, Application, Bootloader, and Bootloader Settings File

My application works if flashed independently (combined with s140 Soft Device as part of the project).

If I erase the target and flash the bootloader, I'm able to deploy the dfu package using the BLE DFU app on my phone and boot into my application.

If I flash the combined firmware image, the target successfully boots into my custom application. If I then send it a recognized command message (via Bluetooth Mesh), it reboots into the bootloader (GPREGRET). At this point I can discover the device using the BLE DFU phone app and execute an update, but the device fails to load into my updated application after "successfully" completing the update.

As a final test, if I erase and flash the bootloader, deploy the dfu package, then instruct the application to return to the bootloader (GPREGRET), it behaves as above successfully deploying the update OTA, but failing to load into the updated application once finished.

My application primarily uses BLE Mesh, and I know there are important pages of settings and things stored in flash, and my guess is that region is being messed up during the update process, and not recognized and unwritten memory by the mesh stack. Is there a way to manually require those pages are reset on boot, and what would be the best way for the bootloader to signal to the application that this is a "first boot" the needs to reset those pages?

Since this only happens after a DFU update, it's difficult to debug and any insight would be appreciated.

Thanks,
Jeremy

I'm including my generation scripts in case they are useful or something is wrong with them, but they are pretty much copy/paste from the guide and appear to be working independently, just not if "re-deploying" the application.

DFU Update Package Generation Script:

#!/bin/bash

# nRF Util (https://www.nordicsemi.com/Products/Development-tools/nrf-util)
NRFUTIL="/usr/local/bin/nrfutil"

# SDK 7.2.0 SoftDevice Lookups
#  s113_nrf52_7.2.0 = 0x102
#  s132_nrf52_7.2.0 = 0x101
#  s140_nrf52_7.2.0 = 0x100
SOFT_DEVICE=0x100

APPLICATION_VERSION=00010000
APPLICATION_FILE="../../build/scanner_nrf52833_xxAA_s140_7.2.0\_Release/scanner_nrf52833_xxAA_s140_7.2.0.hex"

eval "$NRFUTIL pkg generate --application $APPLICATION_FILE \\
	--application-version $APPLICATION_VERSION \\
	--hw-version 52 \\
	--sd-req $SOFT_DEVICE \\
	--key-file ../../dfuKeys/private.pem \\
	../dfu_package_v$APPLICATION_VERSION.zip"

Combined Firmware File Generation Script:

#!/bin/bash

# nRF Util (https://www.nordicsemi.com/Products/Development-tools/nrf-util)
NRFUTIL="/usr/local/bin/nrfutil"

# Part of Command Line Tools (https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools)
MERGEHEX="/usr/local/bin/mergehex"

# Secure UART bootloader
BOOTLOADER_VERSION=00010000
BOOTLOADER_FILE="../../Bootloader/Output/Release/Exe/secure_bootloader_ble_nrf52833_xxAA_s140.hex"

# Application
APPLICATION_VERSION=00010000
APPLICATION_FILE="../../build/scanner_nrf52833_xxAA_s140_7.2.0\_Release/scanner_nrf52833_xxAA_s140_7.2.0.hex"

# Copied from the nRF52 7.2.0 SDK locally for convenience
SOFT_DEVICE_FILE="../bin/softdevice/s140_nrf52_7.2.0_softdevice.hex"

# Generate bootloader settings file.
BOOTLOADER_SETTINGS_FILE="../bin/bootloader_settings_nRF52833.hex"
eval "$NRFUTIL settings generate --family NRF52 \\
	--softdevice $SOFT_DEVICE_FILE \\
	--application $APPLICATION_FILE \\
	--application-version $APPLICATION_VERSION \\
	--bootloader-version $BOOTLOADER_VERSION \\
	--bl-settings-version 2 \\
	$BOOTLOADER_SETTINGS_FILE"

# Combine hex files for combined output
eval "$MERGEHEX --merge $SOFT_DEVICE_FILE $APPLICATION_FILE $BOOTLOADER_FILE $BOOTLOADER_SETTINGS_FILE \\
	--output ../bin/combined.hex"

Parents
  • I should have thought of this earlier, but I compiled "blinky" modified for the nRF52833 PCA10100 and to include the s140 Soft Device (not needed for blinky, but to keep the overall memory architecture the same), and it is able to deploy without issue.

    That is to say I flash the "combined" firmware (sd + custom app + bootloader + bootloader settings), signal my custom app to drop to the bootloader, then deploy the new "blinky" test via BLE DFU. After the DFU update finishes, "blinky" appears to start up and work without issue.

    I believe this confirms my suspicion that I don't have a DFU issue, but a first run issue that only comes up when I try to overwrite my custom application with another version of the same BLE Mesh application.

  • Hi,

    It sounds like you found the explanation, yes. The applications that do not require a SoftDevice (SD) and the applications who do, have different memory layout. In nRF5 SDK, for applications with SD, the SD will occupy the beginning of flash with the application on top. For applications without SD, the application is placed where the SD would otherwise be. This definitely could mess up things if DFU-ing from one to the other, yes. Allowing such updates (from SD to no-SD or from no-SD to SD) might require changes to the DFU bootloader. We do however support SD updates where the SD changes in size, although that does void the application so you would then have to use DFU for installing a new application which starts at the end of the new SD.

    Regards,
    Terje

  • I'm aware of the different memory layout, I was just clarifying that I adjusted the "blinky" example to include the s140 SoftDevice (adding "debug_additional_load_file", the "S140" preprocessor definition, and changing FLASH_START to 0x2700) so it would be compatible with my application which also uses the s140 bootloader.

    I was able to successfully deploy this modified blinky example, which to me confirms that:

    1. The combined image is valid (SD + custom application + bootloader)
    2. The DFU update process is working ("blinky" started normally after being deployed via BLE DFU)

    The question that remains is why my custom application is unable to be deployed in the same way. It works the first time (if I flash a naked bootloader and start with a DFU update), but if I drop back to the bootloader or start with the combined image, "re-deploying" the custom application succeeds but it fails to start.

    My custom application uses Bluetooth Mesh which I believe relies on configuration data written to dynamic flash pages, and I think that's where my issue is coming from. I could attempt to clear all stored data and re-provision, but I'd like to only do that after a firmware update and not every time the device is powered on.

    My questions are:

    1. Does this hypothesis about corrupted Bluetooth Mesh flash configuration data pages make sense?
    2. What would be the best way to send a signal to the application from the bootloader to inform it that an update has just taken place and it needs to clear it's data and re-provision?

    Thanks,
    Jeremy

Reply
  • I'm aware of the different memory layout, I was just clarifying that I adjusted the "blinky" example to include the s140 SoftDevice (adding "debug_additional_load_file", the "S140" preprocessor definition, and changing FLASH_START to 0x2700) so it would be compatible with my application which also uses the s140 bootloader.

    I was able to successfully deploy this modified blinky example, which to me confirms that:

    1. The combined image is valid (SD + custom application + bootloader)
    2. The DFU update process is working ("blinky" started normally after being deployed via BLE DFU)

    The question that remains is why my custom application is unable to be deployed in the same way. It works the first time (if I flash a naked bootloader and start with a DFU update), but if I drop back to the bootloader or start with the combined image, "re-deploying" the custom application succeeds but it fails to start.

    My custom application uses Bluetooth Mesh which I believe relies on configuration data written to dynamic flash pages, and I think that's where my issue is coming from. I could attempt to clear all stored data and re-provision, but I'd like to only do that after a firmware update and not every time the device is powered on.

    My questions are:

    1. Does this hypothesis about corrupted Bluetooth Mesh flash configuration data pages make sense?
    2. What would be the best way to send a signal to the application from the bootloader to inform it that an update has just taken place and it needs to clear it's data and re-provision?

    Thanks,
    Jeremy

Children
  • I found some more time to dig into my assumptions, and think I'm good to go now. Just a summary post to wrap this up in case somebody finds this in the future.

    My problem did have to do with the Bluetooth Mesh flash configuration getting corrupted during the dfu update process. If I add a "stack_config_clear_and_reset()" call to the power-on initialize function my application works being deployed multiple times in a row without issue.

    Of course, clearing Mesh configuration every power-up and needing to rejoin the network isn't ideal, but I found another helpful post on the DevZone that addresses passing data between the bootloader and application ( RAM variables exchange between bootloader and application ). I haven't actually implemented this yet, but being able to optionally trigger the configuration wipe only after a firmware update by setting a flag from the bootloader solves my issue completely.

Related