nRF52832 のファームウェアが読み出し禁止だとOpenOCD と ST-Link v2 では書き換えできない

ABSniffer USB Dongle 528 が使用している Nordic nRF52832  のファームウェアを OpenOCD と ST-Link v2 で書き換えようとしてみた。結果的にはファームウェアのReadback Protection が設定されていなければ(読み出し禁止になっていなければ)、ファームウェアの書き換えができた。

しかし、Readback Protection が設定されていると、(少なくとも) OpenOCDとST-Link v2 の組み合わせでは、Readback Protectionを解除する方法がわからず、ファームウェアの書き換えができなかった。nRFgo Studio と Segger/J-Link を使用すればReadback Protection が設定されているプログラムで、プログラムを消去してReadback Protectionを解除し、ファームウェアを書き換えることができることは「ABSniffer USB Dongle 528 のファームウェアを nRF Sniffer v2 に書き換える」で確かめている。

OpenOCDで利用したいデバイス

  • ST-Link v2互換デバイス (いわゆる、中華ST-Link v2)
  • nRF52832 USBドングル
    • April Brother  ABSniffer USB Dongle 528

ST-Link v2

いわゆる中華 ST-Link v2 を利用した。Aliexpress でUS$2 くらいであった。

ST-Link v2 のファームウェアのバージョンアップ

OpenOCDでST-Link v2 を利用できるようにするためには、ST-Link v2のファームウェアのバージョンアップが必要であった。ST-Link v2のファームウェアのバージョンアップについては、別記事「ST-Link v2 を OpenOCDで利用できるようにする」を参照のこと。

OpenOCD

利用した OpenOCD のバージョンは次の通り。

> version
Open On-Chip Debugger 0.10.0+dev-00541-g723fc07dd (2018-09-27-18:55)

OpenOCDのビルドについては、別記事「OpenOCD (Open On-Chip Debugger) のWindows10上でのビルド」を参照のこと。その記事にしたがってOpenOCDが構築されていることを前提に以下の説明を行う。

OpenOCDの起動

MSYS2のShellを起動して、そこからOpenOCDを起動する。

interface や target があるscripts パスの指定が必要。試した環境では以下のパスに scriptがあった。

/mingw64/share/openocd/scripts

ST-Link v2 をインタフェースとして使い ( -f interface/stlink-v2.cfg )、対象のプロセッサが nrf52 シリーズの場合には ( -f target/nrf52.cfg )、次のコマンドを実行する。

openocd -s /mingw64/share/openocd/scripts -f interface/stlink-v2.cfg -f target/nrf52.cfg

正しく起動されれば、次のような画面となる。

telnetの接続

MSYS2のShellを新たに起動する。そのShellでtelnetを実行し、起動しておいたOpenOCDに接続する。接続後は、OpenOCDをコマンドで操作できる。

telnet localhost 4444

次のようにして、OpenOCDに接続する。

$ telnet localhost 4444
Trying ::1...
Connection failed: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
>

ファームウェアの書き込み

フラッシュメモリにファームウェアを書き込む。

初期化とプロセッサの停止

telnetで次のコマンドを入力し、初期化をし、プロセッサを停止させる。

init
reset init

次のようにプロセッサが停止したことが示されればうまく処理ができている。

> init
> reset init
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x00000518 msp: 0x200067c8

フラッシュメモリの消去

フラッシュを消去して保護を解除するために次のコマンドがある。

nrf5 mass_erase

うまく消去できれば特にメッセージは出ない。

> nrf5 mass_erase

フラッシュへのファームウェアの書き込み

flash write_image コマンドを使うことで、 ファイルの内容をフラッシュメモリに書き込む。

コマンドの書式は、次の通り:

flash write_image [erase] [unlock] filename [offset] [type]

次の例では、ファイルC:/msys64/home/kunse/sniffer_pca10040_51296aa.hex のプログラムを フラッシュメモリの0 番地から書き込む。

flash write_image C:/msys64/home/kunse/sniffer_pca10040_51296aa.hex 0

うまく書き込みができれば、以下のようなメッセージが表示される。

> flash write_image C:/msys64/home/kunse/sniffer_pca10040_51296aa.hex 0
using fast async flash loader. This is currently supported
only with ST-Link and CMSIS-DAP. If you have issues, add
"set WORKAREASIZE 0" before sourcing nrf51.cfg/nrf52.cfg to disable it
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000001e msp: 0x200067c8
wrote 14452 bytes from file C:/msys64/home/kunse/sniffer_pca10040_51296aa.hex in 0.959002s (14.717 KiB/s)

ファームウェアのベリファイ

次のコマンドでフラッシュの内容とファイルの内容が一致しているかベリファイをする。

verify_image C:/msys64/home/kunse/sniffer_pca10040_51296aa.hex 0

同じ内容であることが確認できる場合には、以下のような表示がなされる。

> verify_image C:/msys64/home/kunse/sniffer_pca10040_51296aa.hex 0
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000002e msp: 0x200067c8
verified 14452 bytes in 0.148999s (94.721 KiB/s)

リセット

以下のように reset run を実行することで、リセットされ、プログラムが実行される。

> reset run

以上でフラッシュの書き込みは終わっている。

Readback Protection の影響

NRF52 RBP (Readback protection) unexpected behavior に書かれているチップのバージョンでは、Readback Protection が他のバージョンとは異なる動作をするようだ。

ABSniffer USB Dongle 528 で利用されていたnRF52832 のチップのバージョンは、OpenOCDの次のコマンドから nRF52832-QFAA(build code: B0) であった。

> flash probe 0
nRF52832-QFAA(build code: B0) 512kB Flash
flash 'nrf5' found at 0x00000000
> flash banks
#0 : nrf52.flash (nrf5) at 0x00000000, size 0x00080000, buswidth 1, chipwidth 1
#1 : nrf52.uicr (nrf5) at 0x10001000, size 0x00000000, buswidth 1, chipwidth 1

チップのバージョンが関連しているのかどうかは不明であるが、Readback Protectionが設定されている状態では、OpenOCD から プロセッサを停止することができない。次のように停止させようとしてもhaltしない。

> reset init
timed out while waiting for target halted
TARGET: nrf52.cpu - Not halted
in procedure 'reset'
in procedure 'ocd_bouncer'

プロセッサを停止させることができないので、nrf5 mass_erase を利用することができず、Readback Protection を解除することができない。

たとえば、次のコマンドを実行すると

nrf5 mass_erase

次のように表示され、失敗する。

> nrf5 mass_erase
Unknown device (HWID 0x00000000)
auto_probe failed

つまり、OpenOCDとST-Link v2 を利用してファームウェアの書き換えができない。

強引に、flash write_image で書き込みをしようとしてみても以下のようになり、書き込めない。

> flash write_image C:/msys64/home/kunse/sniffer_pca10040_51296aa.hex 0
using fast async flash loader. This is currently supported
only with ST-Link and CMSIS-DAP. If you have issues, add
"set WORKAREASIZE 0" before sourcing nrf51.cfg/nrf52.cfg to disable it
timeout waiting for algorithm, a target reset is recommended
Failed to write to nrf5 flash
error writing to flash at address 0x00000000 at offset 0x00000000
in procedure 'flash'

Segger/J-Linkを接続して nRFgo Studio を使用した場合には recover によって Readback Protection の解除とフラッシュの消去ができたので (「ABSniffer USB Dongle 528 のファームウェアを nRF Sniffer v2 に書き換える」参照)、プロセッサを停止させることやファームウェアの消去などはOpenOCDでもできるようにすることが可能と思われるが、試した範囲では成功しなかった。

Readback protectionが有効になっているnRF52832 のファームウェアが OpenOCD と ST-Link v2 では書き換えられないことに「NRF52 RBP (Readback protection) unexpected behavior 」に書かれているチップのバージョン(バグ?)が影響しているのか否か確認できていない。

OpenOCDとST-Linkの組み合わせが問題なのか OpenOCDとSegger/J-Linkなどでも同様の問題が起きるのかは確かめていない。確認する必要があろう。