This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

DFU service support: fromelf generates multiple files, nrfutil fails

I'm trying to add DFU service support to my application on an nRF51 development board, using the instructions here: Adding DFU Service support to an application. I'm using the example bootloader in those instructions.

Without DFU service support, I've already managed to use the fromelf and nrfutil tools to update firmware over DFU, using the nRF Master Control Panel app on my (Android) phone. Everything works fine: I can modify the program and the new program will be loaded.

However, when I try to add DFU service support to my application, I can't generate the ZIP file to upload to my device. Even if I remove all new DFU support code in my application, such that there is no source code change and the only change to the entire project is the addition of the requisite software components (which then aren't used), the following all still happens.

I've added the following software components to my project (which wouldn't be needed but for DFU service support): device_manager ble_dfu pstorage dfu_app_handler dfu_bootloader dfu_bootloader_settings dfu_bootloader_util dfu_transport app_scheduler app_trace crc16 hci_mem_pool hci_slip hci_transport.

Context. I'm on an nRF51 development board (so an nRF51422), and my target memory area settings for my application are:
IROM1: start 0x18000, size 0x24000
IRAM1: start 0x20002000, size 0x6000

Observation 1. Rather than a single bin file, fromelf generates a directory with two files:

> ls .\Objects\myproject.bin
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       14/09/2015     15:26              4 ER$$.ARM.__AT_0x10001014
-a----       14/09/2015     15:26          10656 ER_IROM1

Based on the ARM documentation from fromelf, I understand that this means there are two load regions.

Question 1. Am I correct in believing that the ER_IROM1 file is the actual program (which would go into the IROM1 region specified in Keil), and that the ER$$.ARM.__AT_0x10001014 file is to be programmed into the UICR register at address 0x10001014?

Observation 2. The contents of the ER$$.ARM.__AT_0x10001014 are 00 c0 03 00. I read the UICR register at 0x10001014 on my device and it seems to already have that value:

> nrfjprog --memrd 0x10001014
0x10001014: 0003C000                              |....|

Question 2. Does this mean I don't actually need to include the ER$$.ARM.__AT_0x10001014 file when generating the ZIP file using nrfutil?

Observation 3. Obviously you can't pass in a directory to nrfutil as if it were a bin file, so I tried using nrfutil on the ER_IROM1 file to generate the ZIP file (ignoring the ER$$.ARM.__AT_0x10001014 file). Then this happens:

> nrfutil dfu genpkg --application path/to/ER_IROM1 path/to/myproject.zip
Traceback (most recent call last):
  File "__main__.py", line 303, in <module>
  File "click\core.pyc", line 664, in __call__
  File "click\core.pyc", line 644, in main
  File "click\core.pyc", line 991, in invoke
  File "click\core.pyc", line 991, in invoke
  File "click\core.pyc", line 837, in invoke
  File "click\core.pyc", line 464, in invoke
  File "__main__.py", line 236, in genpkg
  File "nordicsemi\dfu\package.pyc", line 189, in generate_package
  File "nordicsemi\dfu\package.pyc", line 329, in normalize_firmware_to_bin
  File "nordicsemi\dfu\nrfhex.pyc", line 63, in __init__
  File "nordicsemi\dfu\intelhex\__init__.pyc", line 241, in loadfile
  File "nordicsemi\dfu\intelhex\__init__.pyc", line 204, in loadhex
  File "nordicsemi\dfu\intelhex\__init__.pyc", line 115, in _decode_record
nordicsemi.dfu.intelhex.HexRecordError: Hex file contains invalid record at line 1

Question 3. Is using the ER_IROM1 file is the right approach, or should I be doing something else?

On another note—the Nordic Infocenter calls the utility for generating the image file nrf.exe. This didn't exist on my installation (Master Control Panel 3.10.0.14) and nrfutil.exe seems to behave as expected, so I'm guessing that's what it was meant to be.

Edit. Another detail that might be relevant: My application doesn't use a SoftDevice, i.e., the only reason we are using BLE (or indeed the nRF51422) is because we want to use its OTA DFU capabilities. So there is no existing BLE support code in the application. Of course, the device has a SoftDevice programmed on it in order for the DFU bootloader to work.

  • Hi Chuan-Zheng Lee,

    You should not have any data at address 0x10001014 in your application. This is the area of UICR use to store the address of the bootloader. And it should already be written when you flash the bootloader. I suspect you have smth like this in your application code: uint32_t m_uicr_bootloader_start_address attribute((at(NRF_UICR_BOOT_START_ADDRESS))) = BOOTLOADER_REGION_START;

    This will tell the compiler to create a hex file with BOOTLOADER_REGION_START at address NRF_UICR_BOOT_START_ADDRESS.

    The application doesn't need this. ( Don't include bootloader_setting.c in your application).

    You can test the nrfutil.exe or fromelf with the app-dfu example we made in the SDK, please have a look at ble_app_hrs with dfu example at \examples\ble_peripheral\ble_app_hrs\pca10028\s110_with_dfu.

    We recently change the name of the nrf tool from nrf.exe to nrfutil.exe. We will update this on the infocenter.

  • Thanks. I tried removing bootloader_settings.c. Here's what happens. The "dialog box" refers to the "Manage Run-Time Environment" dialog box.

    1. Remove dfu_bootloader_settings. bootloader.o requires bootloader_util_settings_get from bootloader_settings.c. The dialog box warns about this with an orange box.

    2. Remove dfu_bootloader. I realized I had also selected the "Serial" option for dfu_transport, so I changed this to "Ble"—my mistake. The dialog box shows no warnings.

      • dfu_transport_ble.o requires bootloader_dfu_update_process, which appears to be in bootloader.c.
      • It also requires dfu_data_pkt_handle and seven other functions, all of which are in dfu_dual_bank.c.
      • It also requires dfu_ble_peer_data_get, which I can't find, will raise in a separate question.

    Am I correctly removing unneeded modules, or is there a stray dependency somewhere?

  • Never mind—I removed dfu_transport as well and now it compiles and links successfully, with only a single bin file output from fromelf that I can convert to a ZIP file with nrfutil. Haven't tried uploading to device yet so celebrations might be premature, but it at least solves this problem!

Related