119 lines
5.2 KiB
Markdown
119 lines
5.2 KiB
Markdown
|
# Python nRF5 OTA DFU Controller
|
||
|
|
||
|
So... this is my fork of dingara's fork of astronomer80's fork of
|
||
|
foldedtoad's Python OTA DFU utility.
|
||
|
|
||
|
My own contribution is little more than a brute force conversion to
|
||
|
python3. It is sparsely tested so there are likely to be a few
|
||
|
remaining bytes versus string bugs remaining in the places I didn't test
|
||
|
. I used it primarily as part of
|
||
|
[wasp-os](https://github.com/daniel-thompson/wasp-os) as a way to
|
||
|
deliver OTA updates to nRF52-based smart watches, especially the
|
||
|
[Pine64 PineTime](https://www.pine64.org/pinetime/).
|
||
|
|
||
|
## 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).
|
||
|
|
||
|
## Prerequisites
|
||
|
|
||
|
* BlueZ 5.4 or above
|
||
|
* Python 3.6
|
||
|
* 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](https://github.com/NordicSemiconductor/pc-nrfutil) for details.
|
||
|
|
||
|
Note: I've had problems with the pip version of `nrfutil`. I recommend [installing from source](https://github.com/NordicSemiconductor/pc-nrfutil#running-and-installing-from-source) instead.
|
||
|
|
||
|
## Usage
|
||
|
|
||
|
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 ./dfu.py -f ~/application.hex -d ~/application.dat -a CD:E3:4A:47:1C:E4
|
||
|
|
||
|
or:
|
||
|
|
||
|
> sudo ./dfu.py -z ~/application.zip -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 <TARGET_NAME>
|
||
|
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
|
||
|
|
||
|
## TODO:
|
||
|
|
||
|
* Implement link-loss procedure for Legacy Controller.
|
||
|
* Update example output in readme.
|
||
|
* Add makefile examples.
|
||
|
* More code cleanup.
|
||
|
|
||
|
## Info & References
|
||
|
|
||
|
* [Nordic Legacy DFU Service](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/bledfu_transport_bleservice.html?cp=4_0_3_4_3_1_4_1)
|
||
|
* [Nordic Legacy DFU sequence diagrams](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v11.0.0/bledfu_transport_bleprofile.html?cp=4_0_3_4_3_1_4_0_1_6#ota_profile_pkt_rcpt_notif)
|
||
|
* [Nordic Secure DFU bootloader](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v12.2.0/lib_dfu_transport_ble.html?cp=4_0_1_3_5_2_2)
|
||
|
* [nrfutil](https://github.com/NordicSemiconductor/pc-nrfutil)
|