Skip to content

Bootloader

joric edited this page Sep 14, 2024 · 626 revisions

Generic Bluetooth modules such as E73 usually sell blank so you have to write your own bootloader. They also come write-protection-locked so you have to remove protection (latest E73 batches are sometimes factory-unlocked).

Pro Micro-compatible boards have a bootloader, so you may skip this page and go ZMK (double reset to open USB drive).

Downloads

nRF52840

For 2G4M08S1C modules you can use either a standard pca10056 bootloader from the Adafruit nRF52 Bootloader releases section or a customized pca10056 with nRFMicro patch that blinks and supports OTA (maps LED to 1.10 and DFU to 1.02):

These bootloaders support both UF2 Mass Storage updates and DFU serial, press RESET (short RST with GND) twice within 500 ms for the update mode. ZMK doesn't need softdevice (sd, Nordic Bluetooth stack) but you can flash it separately, if needed.

There's reset firmware for ZMK that erases bonds (updated 31 oct 2023): zmk_clear.uf2, old one is here: erase_flash.uf2.

The nice!nano bootloader flashes the same way, documentation and files are here https://nicekeyboards.com/docs/nice-nano.

nRF52833

For 2G4M08S1E modules (nRF52833-based) you will need a pca10100-based bootloader. See ZMK#nrf52833 if something goes wrong. See releases section for updates. Also see https://github.com/krikun98/zmk/tree/nrf52833.

ZMK reset: 833_reset.uf2. Bootloader update in UF2: update-nrfmicro_833_bootloader-0.6.3-49-ge18dabd-dirty_nosd.uf2.

SWD Programmers

To flash the bootloader you need J-Link or ST-Link or the Bluepill board or Raspberry Pi. Original J-Link is pretty expensive. ST-LINK/V2 needs CMSIS-DAP patch or Blackmagic firmware. The cheapest option is a Bluepill board as a Blackmagic probe.

Bluepill

You can flash Bluepill into Blackmagic probe. It's much cheaper than stock ST-LINK, it provides an extra virtual COM port for debugging and it does not use OpenOCD (there is an embedded GDB in the Blackmagic firmware). Beware of the resistor issue in the latest boards: https://github.com/joric/bluetosis/issues/13.

You will also need UART adapter but just once (to upgrade Bluepill to the Blackmagic probe). Direct links to Aliexpress:

Avoid STM32F103C6T6A-based bluepills (32K), buy STM32F103C8T6 (64K). See https://github.com/joric/nrfmicro/issues/61.

If you build Blackmagic from scratch it needs to be stripped down to 64kb as here (only stm32f1 and nrf5x supported)

Downloads

Locally hosted blackmagic binaries, just in case

Bluepill flashing on Windows

  • Hook up an UART adapter to Bluepill (A9 - RX pin, A10 - TX pin).
  • Set Bluepill jumpers to the bootloader mode (BOOT0 jumper=1, BOOT1 jumper=0).
  • Plug in UART adapter to the computer. Run "STM32 Flash loader demonstrator".
  • Download to device blackmagic_dfu.bin at offset 0x8000000 with "Global Erase" option.
  • Download to device blackmagic.bin at offset 0x8002000 with "Erase necessary pages" option.
  • Put Bluepill jumpers back to the operational mode (BOOT0 jumper=0, BOOT1 jumper=0).
  • Remove UART adapter, plug in Bluepill to the computer via its own onboard USB.
  • Update USB drivers with libusb-win32 from "Zadig" (Options - List All Devices).

Make sure you got both "Black Magic GDB server" and "Black Magic UART port", you need GDB port (e.g. COM9).

devices

Now, if you run this, you should get blackmagic version from the command line:

arm-none-eabi-gdb --batch -ex "target extended-remote \\.\COM9" -ex "monitor"

Black Magic Probe (Firmware v1.6.1-267-g302ff20) (Hardware Version 0)        
Copyright (C) 2015  Black Sphere Technologies Ltd.                           
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

Possible issues

ST-Link

You can use ST-Link either with OpenOCD or with blackmagic. You can buy ST-Link/V2 for about $2 on Aliexpress.

This tool flashes ST-LINK/V2 via USB into a Blackmagic probe (you can revert it back):

There's sakana280's fork for Windows:

Newer stlink-tool (31 oct 2023):

Blackmagic apparently resets after power off (this is expected behavior), so you have to reflash it with stlink-tool each time.

Unlocking nRF52 and flashing bootloader

Power up nRFMicro from USB-C, plug in your selected programmer into the same computer (you need common ground), press and hold SWD and SWC pins against nRFMicro pads on the back (Bluepill A5 is SWC, B14 is SWD), then run commands.

Blackmagic

First line is unlock, second line is flash. For Blackmagic you would need GNU Arm Embedded Toolchain (make sure arm-none-eabi-gdb is in the PATH).

You usually don't need Unlock for already preflashed boards. Also most boards come factory unlocked now.

  • Unlock: arm-none-eabi-gdb --batch -ex "target extended-remote \\.\COM5" -ex "mon swdp_scan" -ex "att 1" -ex "mon erase_mass"
  • Flash: arm-none-eabi-gdb --batch -ex "target extended-remote \\.\COM5" -ex "mon swdp_scan" -ex "file bootloader.hex" -ex "att 1" -ex "mon erase" -ex load

Explanation: target 2 is protected and "mon erase_mass" is the only available command on target 1. After erasing with "mon erase_mass" on target 1, the next scan should recognize target 1 as Nordic nRF52. COM5 in this example is the first virtual port in the device manager (the second port is UART for debugging). Some versions mix targets up, try "att 2" instead of "att 1".

Console log for unlocking (see https://github.com/AndruPol/nrf52832-recover/issues/1#issuecomment-478393782):

arm-none-eabi-gdb.exe
For help, type "help".                                                                
Type "apropos word" to search for commands related to "word".                         
(gdb) target extended-remote \\.\COM8                                                 
Remote debugging using \\.\COM8                                                       
(gdb) mon swdp_scan                                                                   
Target voltage: unknown                                                               
Available Targets:                                                                    
No. Att Driver                                                                        
 1      ARM Cortex-M                                                                  
 2      Nordic nRF52 Access Port                                                      
(gdb) attach 2                                                                        
Attaching to Remote target                                                            
warning: while parsing target description: no element found                           
warning: Could not load XML target description; ignoring                              
PC register is not available                                                          
(gdb) mon erase_mass                                                                  
(gdb) quit                                              
A debugging session is active.                          
                                                        
        Inferior 1 [Remote target] will be detached.    
                                                        
Quit anyway? (y or n) y                                 
Detaching from program: , Remote target                 
[Inferior 1 (Remote target) detached]                   
                                                        
C:\SDK\gcc-arm-none-eabi-8-2018-q4-major-win32\bin>    

Actual "erase_mass" took just a moment (I guess it just removed the protection bits). After that it becomes fully programmable.

ST-LINK/V2

I recommend flashing ST-LINK/V2 into a blackmagic probe as above. If you prefer generic ST-LINK/V2 with an OpenOCD client software mind that it needs a CMSIS-DAP patch to unlock the chip. Possible OpenOCD commands (untested):

  • Unlock: openocd -d2 -f interface/cmsis-dap.cfg -f target/nrf52.cfg -c "nrf52.dap apreg 1 0x04 0x01"
  • Flash: openocd -f interface/stlink.cfg -f target/nrf52.cfg -c "gdb_flash_program enable" -c "gdb_breakpoint_override hard" -c "init" -c "reset halt" -c "flash write_image erase ./bootloader.hex"

J-Link

This is the last resort, the very expensive option (starts from $30, segger clones may cost $15). I haven't used that much.

  • Unlock: nrfjprog --recover --log
  • Flash: nrfjprog -f nrf52 --program bootloader.hex --sectorerase

There's a guide on J-Link here: https://github.com/Ladniy/jiran-ble-lite/wiki/Firmware

Flashing the nRF52's bootloader using Raspberry Pi's GPIO and OpenOCD

Confirmed working on Raspberry Pi 3 Model B rev 1.3 with latest software / firmware at the time of the writing but should work on any other Raspberry Pi.

You will need:

  • Raspberry Pi
  • USB cable to connect nRFMicro to Raspberry Pi
  • Two jumper wires to connect GPIO to nRFMicro

Preparation

Connect your RPi to the Internet.

Compiling OpenOCD

Open terminal, run the following commands:

sudo apt update
sudo apt install git autoconf libtool make pkg-config libusb-1.0-0 libusb-1.0-0-dev telnet
git clone http://openocd.zylin.com/openocd
cd openocd
./bootstrap
./configure --enable-bcm2835gpio
make 
sudo make install

NB that "make" command will take a long time.

Creating RPi specific configuration
mkdir openocd-config 
cd openocd-config 
nano openocd.cfg

Paste the following contents comment / uncomment stuff for your particular setup and save the file:

adapter driver bcm2835gpio

# Raspi1 peripheral_base address
# bcm2835gpio peripheral_base 0x20000000
# Raspi2 and Raspi3 peripheral_base address
bcm2835gpio peripheral_base 0x3F000000
# Raspi4 peripheral_base address 
# bcm2835gpio peripheral_base 0xFE000000


# Raspi1 BCM2835: (700Mhz)
# bcm2835gpio speed_coeffs 113714 28
# Raspi2 BCM2836 (900Mhz):
# bcm2835gpio speed_coeffs 146203 36
# Raspi3 BCM2837 (1200Mhz): 
bcm2835gpio speed_coeffs 194938 48
# Raspi4 BCM2711 (1500Mhz):
# bcm2835gpio speed_coeffs 236181 60

# SWD GPIO set: swclk swdio
bcm2835gpio swd_nums 25 24

transport select swd

set CHIPNAME nrf52840
source [find target/nrf52.cfg]

# Uncomment & lower speed to address errors, defaults to 1000
# adapter speed 800

init
targets
reset halt

It's a good idea to download the bootloader to the same folder, I will go with the one linked above, namely pca10056_bootloader-0.2.11_s140_6.1.1.hex:

wget https://github.com/adafruit/Adafruit_nRF52_Bootloader/releases/download/0.2.11/pca10056_bootloader-0.2.11_s140_6.1.1.hex

You can use a more recent release, be sure to use the correct filename when flashing in that case.

Connecting nRFMicro to RPi
  • Connect nRFMicro using USB cable to one of RPi's USB ports.
  • Use two jumper wires to connect GPIO25 to SWC and GPIO24 to SWD.

You need to ensure a proper connection or maybe even to apply some pressure to the jumpers with your finger for it to work. If something's not working, check the physical connection or lower the adapter speed.

Flashing the bootloader using OpenOCD

Running OpenOCD

Launch OpenOCD: sudo openocd

If it's successfully connected, you'll see the following:

Open On-Chip Debugger 0.11.0+dev-00210-gbb81ec8bf-dirty (2021-06-11-18:27)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : clock speed 802 kHz
Info : SWD DPIDR 0x2ba01477
Info : nrf52840.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for nrf52840.cpu on 3333
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x00000a80 msp: 0x20000400
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

Open another terminal instance and run: telnet localhost 4444

You can check the chip state with: targets, banks with: flash banks, registers with: reg.

Checking unlock state and unlocking

My module arrived unlocked from the factory, so I can't tell whether you can unlock it with this method or not.

You can check whether your chip is locked using: nrf52840.dap apreg 1 0x0C, if it outputs 1 means unlocked and 0 means locked. Supposedly, you can unlock it with: nrf52840.dap apreg 1 0x04 0x00000001 or nrf52_recover.

Flashing the bootloader

Erase the storage with: nrf5 mass_erase.

To flash the bootloader, run the following command: flash write_image pca10056_bootloader-0.2.11_s140_6.1.1.hex You should see the following:

Padding image section 0 at 0x00000b00 with 1280 bytes
Flash write discontinued at 0x00025de8, next section at 0x000f4000
wrote 183992 bytes from file pca10056_bootloader-0.2.11_s140_6.1.1.hex in 1.870176s (96.076 KiB/s)

Verify the result: flash verify_image pca10056_bootloader-0.2.11_s140_6.1.1.hex. If it's successful, you are done.

Reset the chip with reset run.

It should mount as USB storage and you'll be able to drag and drop or use wget download and flash the firmware.

Picoprobe

For flashing the bootloader, you can also use a raspberrypi pico with picoprobe firmware. This command line will work on ubuntu:

openocd -d2 -f interface/cmsis-dap.cfg -f target/nrf52.cfg -s tcl

Linux guide

(Taken from here: https://okke-formsma.github.io/blackmagic-on-a-bluepill.html)

To flash nrfmicro chips, you can use a bluepill with blackmagic installed.

The bluepill has some issues with wrong resistors (I had to change R3 on the bluepill from 100k to 10k ohm). The blackpill with stm32f103 processor does not have this problem, and is recommended. (Black Magic is not supported on blackpill 1.2 (stm32f401) or blackpill 2.0 (stm32f411) at this time.

  • Connect the usb-to-uart converter to the bluemicro and set the bluemicro boot0 jumper to 1.
  • Find the usb port that the converter is attached to
> dmesg | grep tty
[157210.247340] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0
[157221.140041] usb 1-2: cp210x converter now attached to ttyUSB0
  • Install the dfu. Run stm32loader.py on python2 with the pySerial package installed: python2 stm32loader.py -p /dev/ttyUSB0 -ewv blackmagic_dfu.bin
  • Install the blackmagic firmware: stm32flash -w blackmagic.bin /dev/ttyUSB0 -S 0x08002000
  • Set the jumper back to 0, disconnect the uart adapter, connect the bluepill to usb. *Check if the blackmagic probe is recognized with lsusb.

OTA updates

This was never tested. The bootloader apparently can be used for OTA (Over The Air) wireless updates but I haven't tried that (it would need a signed firmware package), see https://github.com/adafruit/Adafruit_nRF52_Bootloader

  • DFU = LOW and FRST = LOW: Enter bootloader with OTA, to upgrade with a mobile application such as Nordic nrfConnect/Toolbox

You'd need to short two pins to ground, 0.12 is FRST and 0.11 is DFU in pca10056. Mind that 0.11 does not exist on E73 module so it would need fixing and recompiling the bootloader (e.g. put DFU button BUTTON_1 to pin 1.02 in pca10056/board.h).

That still needs a specialized software such as nRFGo Studio so it's not very convenient. Read this article for details:

Video

References