nRF52840 DKで遊ぼう⑤~DFU over Mesh~

はじめに

nRF5 SDK for MeshののDevice Firmware Update (DFU) サンプルを動かしてみます。 このサンプルでは、Mesh経由でfirmwareを更新します。

www.nordicsemi.com

IoT時代の組込みデバイスでは、firmware更新はできて当然ですからね!

動作確認

実際の手順は次のページにあります。この手順に沿って、firmwareの更新を試します。

www.nordicsemi.com

Mesh DFUには2つのモードがあります。

  • side-by-side DFU
  • bootloader DFU

違いは、アプリケーションがDFUの工程に介入するかどうかです。 side-by-sideでは、firmwareを送り終わったら、アプリケーションが新しいfirmwareを書き込みます。

一方、bootloader DFUでは、bootloaderがfirmwareの転送を取り扱います。 こちらの場合では、アプリケーションが機能していない場合でも、firmware更新が可能です。

今回動かすサンプルは、side-by-side DFUです。

このサンプルでは、カスタマイズされたnrfutilが必要です。カスタマイズされたnrfutilを使って、シリアルからDFUパケットをデバイスに送ります。 DFUパケットを受け取ったデバイスは、DFUパケットをMeshネットワークに転送します。

10手ステップもあって大変ですが、1つずつやっていきます。今回はOptionalな項目もやります。

  1. Optional: nrfutilで署名鍵を生成する
  2. Optional: nrfutilから公開鍵をデバイスに追加する
  3. nrfutilでDFUアーカイブを作成する
  4. tools/dfuで16進数版のデバイスページを作成する
  5. 全てのデバイスのメモリを消去する
  6. SoftDeviceを全てのデバイスFlashに書き込む
  7. 全てのデバイスにbootloaderを書き込む
  8. 全てのデバイスの最初のアプリケーションを書き込む
  9. 全てのデバイスにデバイスページを書き込む
  10. nrfutilでDFUアーカイブを転送する

1. Optional: nrfutilで署名鍵を生成する

セキュリティを向上するために、署名検証の機能を使うことができます。 nrfutilを使って、署名鍵を生成できます。まずは、秘密鍵を生成します。

nrfutil keys --gen-key private_key.txt
$ head -n 2 private_key.txt 
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIO+ejE5y96dSbg9MrRRAdFRgPaiDRVPFcfAyV0h05hgpoAoGCCqGSM49

この署名鍵を紛失すると、DFUの権限を失います。その場合、全てのデバイスを手動でリフレッシュする必要があります。恐ろしい!

2. Optional: nrfutilから公開鍵をデバイスに追加する

秘密鍵から、公開鍵を取得します。

$ nrfutil keys --show-vk hex private_key.txt
Verification key Qx: 5078c0e4031642416f0b3c355f2f3cf1aae189a1a76bc086833422afb5be48d8
Verification key Qy: 0efed2ebf936e5d8b9330f035b2862139201da00a137833fb1b59923fd0434bd

DFU可能なMeshデバイスは、デバイスfirmware情報を含んだデバイスページが必要です。 デバイスページは、tools/dfudevice_page_generator.pyで生成できます。スクリプトに入力する設定は、JSONで書きます。

{
    "bootloader_config": {
        "bootloader_id": 1,
        "bootloader_version": 1,
        "company_id": 89,
        "application_id": 1,
        "application_version": 1,
        "public_key": "5078c0e4031642416f0b3c355f2f3cf1aae189a1a76bc086833422afb5be48d80efed2ebf936e5d8b9330f035b2862139201da00a137833fb1b59923fd0434bd"
    }
}

public_keyのフィールドは、nrfutilで取得した公開鍵を繋げたものを記述します。

これで、転送されたfirmware秘密鍵で署名されているか、検証することが可能です。

3. nrfutilでDFUアーカイブを作成する

DFUアーカイブはzipファイルです。このzipファイルはアプリケーションバイナリとメタデータを含みます。 アプリケーションバイナリは16進数ファイルです。nRF5 SDK for Meshのbin/blinkyにある16進数ファイルを使います。

nrfutilを使って、DFUアーカイブを作成します。

nrfutil dfu genpkg --application bin/blinky/blinky_nrf52840_xxAA_s140_6.1.0.hex \
    --company-id 0x00000059 \
    --application-id 1 \
    --application-version 2 \
    --key-file private_key.txt \
    --sd-req 0xAE \
    --mesh dfu_test.zip

application-idは、デバイスページで記述したものと一致しなければなりません。application-versionは、以前のイメージより大きいバージョン番号にします。

SoftDeviceのバージョンs140_nrf52_6.1.0に対応する--sd-req0xAEです (nrfutilを参照)。

4. tools/dfuで16進数版のデバイスページを作成する

device_page_generator.pyを使ってデバイスページを作成します。

# tools/dfu
$ python device_page_generator.py -d nrf52840_xxAA -sd "s140_6.1.0"
Wrote device page for nrf52840_xxAA with the s140_6.1.0 SoftDevice to bin/device_page_nrf52840_xxAA_s140_6.1.0.hex.

$ cat bin/device_page_nrf52840_xxAA_s140_6.1.0.hex 
:02000004000FEB
:10F0000004010808110001005078C0E403164241D1
:10F010006F0B3C355F2F3CF1AAE189A1A76BC0863D
:10F02000833422AFB5BE48D80EFED2EBF936E5D810
:10F03000B9330F035B2862139201DA00A137833FD3
:10F04000B1B59923FD0434BD030012000060020035
:10F0500000100D000300100000100000006002000E
:10F060000300110000800F00006000000500020096
:10F07000AE00010159000000010001000000FFFF87
:0CF0800002000400FFFFFFFFFFFFFF7F06
:00000001FF

このファイルは手順9で使います。

5. 全てのデバイスのメモリを消去する

nrfjprog --eraseall

6. SoftDeviceを全てのデバイスFlashに書き込む

nrfjprog --program bin/softdevice/s140_nrf52_6.1.0_softdevice.hex --chiperase

7. 全てのデバイスにbootloaderを書き込む

precompiledのbootloaderを書き込みます。

nrfjprog --program bin/bootloader/gccarmemb/mesh_bootloader_serial_gccarmemb_nrf52840_xxAA.hex

8. 全てのデバイスの最初のアプリケーションを書き込む

nrfjprog --program build/examples/dfu/dfu_nrf52840_xxAA_s140_6.1.0.hex

9. 全てのデバイスにデバイスページを書き込む

手順4で作ったデバイスページを書き込みます。

nrfjprog --program tools/dfu/bin/device_page_nrf52840_xxAA_s140_6.1.0.hex
nrfjprog --reset

この時点では、LEDが全てOFFになります。

10. nrfutilでDFUアーカイブを転送する

$ nrfutil dfu serial -pkg dfu_test.zip -p /dev/ttyACM0 -b 115200 -fc --mesh
Upgrading target on /dev/ttyACM0 with DFU package /home/tomoyuki/work/05.nrf52840/02.SDK/nRF5-SDK-for-Mesh/dfu_test.zip. Flow control is enabled.
  [####################################]  100%             
Device programmed.

けっこう時間かかります。1分強くらい待ちました。DFU中は、LED1とLED3が点灯します。

DFUが完了すると、LED2が点滅します。