blog.dbrgn.ch

Removing flash protection from the nRF52 using JLink + OpenOCD

written on Saturday, May 16, 2020 by

When you receive a new nRF52 (e.g. nRF52832 or nRF52840) based development board (e.g. the Ebyte E73-TBB), you will notice that connecting to it through OpenOCD fails initially:

$ openocd \
    -c 'interface jlink; transport select swd; source [find target/nrf52.cfg]' \
    -c 'init'
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
adapter speed: 10000 kHz
cortex_m reset_config sysresetreq
Info : No device selected, using first device.
Info : J-Link V10 compiled Jan  7 2020 16:51:47
Info : Hardware version: 10.10
Info : VTarget = 3.315 V
Info : clock speed 10000 kHz
Info : SWD DPIDR 0x2ba01477
Error: Could not find MEM-AP to control the core

The reason for this is that the nRF52 often has Access Port Protection (APP) enabled. From the datasheet:

APP Overview

So to disable access protection, we need to issue the ERASEALL command, which will erase flash, UICR and RAM.

TL;DR

If you're in a hurry, here are the instructions on how to unlock the nRF52 using OpenOCD and a JLink debug probe:

$ openocd -c 'interface jlink; transport select swd; source [find target/nrf52.cfg]'
$ telnet localhost 4444
> dap apreg 1 0x04 0x01

Then unplug and reconnect your JLink. You should now be able to debug the nRF52.

How it works

The APP (Access Port Protection) is controlled using the following five registers:

APP Registers

First, start OpenOCD:

$ openocd -c 'interface jlink; transport select swd; source [find target/nrf52.cfg]'
...
Error: Could not find MEM-AP to control the core
Info : accepting 'telnet' connection on tcp/4444

Then connect to the OpenOCD server through a TCP client like telnet (on port 4444):

$ telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Open On-Chip Debugger
>

In OpenOCD, these registers can be controlled through the dap apreg command. The command parameters are the APP number (1 in this case, since the nRF52 only has one APP) and the register offset. If a third argument is provided, that value will be written to the register, otherwise the current contents will be returned.

First, let's query the APPROTECTSTATUS register:

APPROTECTSTATUS register docs

The offset is 0x0C, so call the dap apreg command like this:

> dap apreg 1 0x0c
0x00000000

The current value is 0, which means that the protection status is "enabled".

As you could read in the APP peripheral overview:

Access port protection can only be disabled by issuing an ERASEALL command via CTRL-AP. This command will erase the Flash, UICR, and RAM.

So let's do that, by using the ERASEALL register:

ERASEALL register docs

The register has the offset 0x04. Write the value 0x01 to start the erase process:

> dap apreg 1 0x04 0x01

Wait a few seconds, then unplug and reconnect your JLink. Restart OpenOCD. In the output, instead of "Error: Could not find MEM-AP to control the core", you should now see the following:

Info : nrf52.cpu: hardware has 6 breakpoints, 4 watchpoints

Let's connect with telnet again and query the APPROTECTSTATUS register:

> dap apreg 1 0x0c
0x00000001

Success, the value of 1 means that protection status is "disabled"! You can now flash and debug your nRF52. Have fun!

This entry was tagged hardware, nrf52 and openocd