Skip to content
OTA-DFU server for Linux and NRF51
Python Makefile C
Branch: master
Clone or download
Pull request Compare This branch is 31 commits ahead, 18 commits behind astronomer80:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Python nRF5 OTA DFU Controller

This is my fork of astronomer80's fork of foldedtoad's Python OTA DFU utility. I've made some substantial changes to the code from the original repo, mainly:

  • Improved code structure and readability
  • Add support for the new secure bootloader from NRF SDK 12

What does it do?

This is a Python program that uses gatttool (provided with the Linux BlueZ driver) to achieve Over The Air (OTA) Device Firmware Updates (DFU) to a Nordic Semiconductor nRF5 (either nRF51 or nRF52) device via Bluetooth Low Energy (BLE).

Main features:

  • Perform OTA DFU to an nRF5 peripheral without an external USB BLE dongle.
  • Ability to detect if the peripheral is running in application mode or bootloader, and automatically switch if needed (buttonless).
  • Support for both Legacy (SDK <= 11) and Secure (SDK >= 12) bootloader.

Before using this utility the nRF5 peripheral device needs to be programmed with a DFU bootloader (see Nordic Semiconductor documentation/examples for instructions on that).

This project assumes you are developing on and deploying to a Linux system. Astronomer80 has repos for similar applications for Windows and Mac OS X.


  • BlueZ 5.4 or above
  • Python 2.7
  • Python pexpect module (available via pip)
  • Python intelhex module (available via pip)

Firmware Build Requirement

  • Your nRF5 peripheral firmware build method will produce a firmware file ending with either *.hex or *.bin.
  • Your nRF5 firmware build method will produce an Init file ending with .dat.
  • The typical naming convention is application.bin and application.dat, but this utility will accept other names.

Generating init files

Legacy bootloader

Use the gen_dat application (you need to compile it with gcc gen_dat.c -o gen_dat on first run) to generate a .dat file from your .bin file. Example:

./gen_dat application.bin application.dat

Note: The gen_dat utility expects a .bin file input, so you'll get Cyclic Redundancy Check (CRC) errors during DFU using a .dat file generated from a .hex file.

An alternative is to use nrfutil from Nordic Semiconductor, but I've found this method to be easier. You may need to edit the gen_dat source to fit your specific application.

Secure bootloader

You need to use nrfutil to generate firmware packages for the new secure bootloader (SDK > 12) as the package needs to be signed with a private/public key pair. Note that the bootloader will need to be programmed with the corresponding public key. See the nrfutil repo for details.

Note: I've had problems with the pip version of nrfutil. I recommend installing from source instead.


There are two ways to specify firmware files for this utility. Either by specifying both the .hex or .bin file with the .dat file, or more easily by the .zip file, which contains both the hex and dat files.

The new .zip file form is encouraged by Nordic, but the older hex/bin + dat file methods should still work.

Usage Examples

> sudo ./ -f ~/application.hex -d ~/application.dat -a CD:E3:4A:47:1C:E4


> sudo ./ -z ~/ -a CD:E3:4A:47:1C:E4

You can use the hcitool lescan to figure out the address of a DFU target, for example:

$ sudo hcitool -i hci0 lescan
LE Scan ...
CD:E3:4A:47:1C:E4 (unknown)

Example Output

    ==                            ==
    ==         DFU Server         ==
    ==                            ==

Sending file application.bin to CD:E3:4A:47:1C:E4
bin array size:  60788
Checking DFU State...
Board needs to switch in DFU mode
Switching to DFU mode
Enable Notifications in DFU mode
Sending hex file size
Waiting for Image Size notification
Waiting for INIT DFU notification
Begin DFU
Progress: |xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| 100.0% Complete (60788 of 60788 bytes)

Upload complete in 0 minutes and 14 seconds
segments sent: 3040
Waiting for DFU complete notification
Waiting for Firmware Validation notification
Activate and reset
DFU Server done


  • Implement link-loss procedure for Legacy Controller.
  • Update example output in readme.
  • Add makefile examples.
  • More code cleanup.

Info & References

You can’t perform that action at this time.