nrf52 DFU Programming

Enabling DFU in a Bluetooth device seems like a no brainer, after all it is a radio. Unfortunately it looks as if this was a second thought. While implementing it for our Mobillyo board, I decided to document the process for my own benefit and that for others since it is so complicated. Please note I have been using SDK 12.2.0 and all references are to the documentation for examples in that SDK version. If you are using a different one you will have to make sure the links are relevant. Also external application may change version while the SDK requires an older version. 
The Nordic DFU for the nrF52 requires 3 separate programs: your application, the bootloader and the soft device. The soft device is pre-compiled so you only have to compile the 2 others for your board.  You can use any combination of the files for the DFU: App only, App + bootloader or all 3. I am assuming you want to program the Softdevice, Bootloader and your application the first time around using NRFgo Studio  and then test the DFU,you will need:
1- Bootloader hex file compiled to include the changes to I/O pins, crystal and DC-DC power and Softdevice hex file. 
2- Application hex output file
3-  a Key
4- Python3 
5- nrfutil  python script to generate the image that will be sent wirelessly to your Device
6- Version control for your application. You must give it a version and any subsequent DFU operation will have to use a new version.
7-  The GNU ARM Embedded Toolchain
8- MinGw
9- micro-ecc
10- A zip package file that you will create with nrfutil
It is important to understand that the bootloader, application and softdevice programs reside in these distinct memory locations: (reference:
Memory range nRF52 (S132 v3.0.x)
Bootloader settings 
0x0007 F000 - 0x0008 0000 (4 kB) 
MBR parameter storage 
0x0007 E000 - 0x0007 F000 (4 kB) 
0x0007 8000 - 0x0007 E000 (24 kB) 
Application area (incl. free space) 
0x0001 F000 - 0x0007 8000 (356 kB) 
0x0000 1000 - 0x0001 F000 (120 kB) 
Master Boot Record (MBR) 
0x0000 0000 - 0x0000 1000 (4 kB)

As I stated earlier, you will compile 2 programs, the bootloader and your application. You will have to set these memory values in Keil for both the bootloader and the application projects in the options/target irom1 and iram 1. The bootloader assumes the start address of the Application is the end address of the softdevice 0x0001f000  The screenshot is for the Bootloader:

The Nordic Semi documentation gives step by step instructions but many of these steps are actually a little project by themselves requiring lots of concentration and you sort of loose the thread of trying to get the DFU function working. For this reason, I have decided to get all the prerequisites done then compile and program the  board with the Softdevice and Bootloader using nRFgo Studio before generating the zip file for the DFU and testing it.
 Lets get started.

1- setup io pins and crystal
If you are starting from one of the example in the SDK, you must be aware that all examples are designed to run on the development boards and I/Os are configured for these boards. IO pins for your application may be different so you need to configure them in custom_board.h and include it in your project path. 
Note: I defined the LEDS that I am not using as pin 0. The Push buttons as pins I am not using.
 In Keil options/C/C++  Preprocessor symbols defines, remove BOARD_PCA10040  add BOARD_CUSTOM:

boards.h doesn't know (or need to know) where custom_board.h is located. What you need to do is make sure that the directory where you've placed your custom_board.h file is added to the include path in the compiler. I saved my new custom_board.h in the application project config folder: \nRF5_SDK_12_2\examples\ble_peripheral\ble_app_uart\pca10040\s132\config
and in the DFU project  \config folder. I also renamed the original custom_board.h to Original_custom_board.h just to make sure it is not used by error.
Do not forget do redefine the rc oscillator in the custom_board.h. if you do not have a low frequency crystal:
reference: s132_nrf52_3.0.0_migration_document.pdf
nrf_clock_lf_cfg_t rc_cfg = {
.source = NRF_CLOCK_LF_SRC_RC,
.rc_ctiv = 16, // Check temperature every 4 seconds
.rc_temp_ctiv = 2, // Calibrate at least every 8 seconds even if the temperature hasn't changed

The BMD300 comes with the Rigado firmware on it and with the chip locked. You have to unlock and erase the chip if you want to use it without the Rigado firmware. 
I gather that nordic's nrfjprog recover utility works but I've not tried it, Rigado also has a utility to unlock it which you can get from their github but you probably need to ask for access. (try the link if you like)
Alternatively you can do what I did which is put the commands straight into JLink off the command line, just start a session with 
JLinkExe -if swd -device nrf52
that command line is for OSX, I think on Windows it's just JLink
SWDWriteDP 1 0x50000000
SWDWriteDP 2 0x01000000
SWDWriteAP 1 0x00000001

nrfjprog -f NRF52 ––recover 

2- Getting all the prerequisites Installed

a- ARM'S Launchpad  and MinGW
follow this link for the information:

Make sure you download the version 4.9 and not the current version of  ARM Launchpad as I did in the screenshot.
When installing make sure you check the box for the Windows Environment variables:

Download and run MinGw, I did not understand how it woks but it just seems to work .
b- micro-ecc
Get micro-ecc from the referenced GitHub repo 
Just download the zip (green button to the right).

It probably will unzip into the wrong folder so create the folder InstallFolder\external\micro-ecc\micro-ecc and move it there.   InstallFolder is where you installed the SDK
Enter the subdirectory for the SoC and the toolchain that you are using to build your application:
On my machine: it is in MyUserName\Dropbox\nrf52dev\nrf5_sdk_12_2\external\micro-ecc\nrf52_keil\armgcc
Open a command Prompt type Make to compile the micro-ecc library. 

c- Python 2.7.13
You will need Python 2.7 from this link:
Install it. It may be necessary to add some path so the scripts find Python. Depending on your Windows version this may be done differently, Google "Python windows path".

d- Install nrfutil
Get the nfrutil documentation:
Pip is Python so step D must be done after step C.
In a Command Prompt window type : pip install nrfutil

e- Get keys
Create  a folder to keep your keys: C:\vault
Generate a key
               nrfutil keys generate c:\vault\privkeyForMyApp_xx.pem I like to add versions for everything so xx is a version.

Write the public key generated from your private key to the public key file:
nrfutil keys display --key pk --format code c:\vault\privkeyForMyApp_xx.pem --out_file c:\vault\publickeyForMyApp_xx.pem

Later you will copy these 2 files to the DFU project.

3- DFU
In the SDK you are using, go to .examples", duplicate the  DFU/Bootloader_secure project and rename the folder.
Open the renamed DFU/Bootloader_secure project in Keil:    secure_dfu_secure_dfu_ble_s132_pca10040.uvprojx   
Add the edited (I/Os and clock) custom_board.h  to the \pca10040\config\ folder.
This does not work omit for now.
Open the project, add the DC-DC converter enable if you are using the BMD-300 in main.
// Enable DC/DC converter
uint32_t err_code;
err_code = sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);

IN Keil Options for target/C/C++ Preprocessor Symbols delete   BOARD_PCA10040 and add BOAR_CUSTOM.  The defines are separated by spaces.

Copy the private and public key files to the project folder where the main.c is located.
Compile the project.  The output hex file is in the project's pca10040\arm5_no_packs\_build folder. 

4- Application

Duplicate the  DFU/Bootloader_secure project and rename the folder.
 Open the  this renamed project in Keil.
Add the edited (I/Os and clock) custom_board.h  to the \pca10040\config folder.

IN Keil Options for target/C/C++ Preprocessor Symbols delete   BOARD_PCA10040 and add BOAR_CUSTOM.  The defines are separated by spaces.

Compile the project.  The output hex file is in the project pca10040\arm5_no_packs\_build folder. You may need to rename it or you can change the name in Options Output before compiling.
5- Erasing the BMD-300 

I use nRFgo Studio to erase the BMD-300. 

This is the connection. The red line is pin 1. The blue board is the Nordic Semiconductor development board for the nRF52.

nRFgo Studio will see a locked device and show a screen similar to this one  with a RECOVER button.  Press the recover button and wait a few seconds. 

After the recovery you should see this screen with all the regions (Bootloader, Application, Softdevice)  erased.

6- Burn of the SoftDevice and Bootloader using NrfGo Studio 
Connect your board with the 10 pin jlink. In NrfGo Studio connect to the board, erase all then program the softdevice found here:  SDKYouAreUsing\components\softdevice\s132\hex\
Then program the Bootloader hex file you created earlier.
Your device is now ready for an Application update by DFU.
7- Firmware package

Enter the following command to generate a package named from the application file nrf52832_MobApp01.hex with application version 1 that
requires hardware version 52 and SoftDevice S132v3.0.0 (0x8c) and is signed with the private
key that is stored in private1.pem :

nrfutil pkg generate --hw-version 52 --sd-req 0x8c --application-version 1 --application  c:\Nrf52DFUImages\nrf52832_MobApp01.hex --key-file c:\vault\private1.pem

Install the nRF Toolbox from the App store on your mobile device.
e-mail the zip file to your Mobile phone. In mail open the attachment with the nRFToolbox.

In the App select  the device then upload


1- BMD-300 DC-Dc converter

I found this in one post but when I put this code in, my application does not start so i lekt it out.

If you are using the BMD-300 enable DC/DC converter:
// Enable DC/DC converter  this does not work application stalls no errors codes
uint32_t err_code;
err_code = sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);

2- Other development IDEs

I am using Keil uVision5 on a Windows system. Other development systems may need different steps.