nRF connect SDK:FOTA(Firmware Over The Air)

#FOTA＝アップデート
近年のデバイスはインターネットに接続されていればケーブルを接続せずアップデートできるというのが当たり前になりました。FOTAはその機能のことを指しています。
ちなみにNordicではDFU(Device Firmware Update)という表現をすることもありますが意味は同じです。なんとなく日本人はDFUと言い、外国人はFOTAと言うような住みわけがあるようなないような気がします(笑)
#nRF SDKよりも簡単になった・・・？
nRF SDKではBootloaderのプロジェクトとAppのプロジェクトを別々に生成する必要がありましたが、nRF connect SDKではCONFIGに指定して、ほんの少しメインにAPIを追加するだけでBootloaderを組み込むことができます。
#ソースコード
ソースコードに以下のコンフィギュレーションとソースコードを組み込むだけでDFUを実装できます。ただし、後述する参考スレッドに出てくるコンフィギュレーションは最新のnRF connect SDKでは廃止されているため置き換える必要があります。
####余談
製品を作るにあたってDFUは必須なのでメチャクチャ調べていたのですが全然分かりませんでした。諦めていたのですが、少し間を開けたらある日突然関連記事を見つけて実装できてしまったんですよね・・・調べものなんて得てしてそういうものだとは思いますが。
##main

```main.c
#include <tinycbor/cbor.h>
#include "cborattr/cborattr.h"
#include <mgmt/mgmt.h>
#include <mgmt/mcumgr/smp_bt.h>
#include <mgmt/mcumgr/buf.h>
#include <mgmt/mcumgr/smp.h>
#include "os_mgmt/os_mgmt.h"
#include "os_mgmt/os_mgmt_impl.h"
#include "os_mgmt/os_mgmt_config.h"
#include "img_mgmt/image.h"
#include "img_mgmt/img_mgmt.h"
#include "img_mgmt/img_mgmt_impl.h"
#include "img_mgmt/img_mgmt_config.h"

void main(void)
{
    ...

    // For FOTA
    os_mgmt_register_group();
    img_mgmt_register_group();
    smp_bt_register();

    ...
}
```

##prj.conf
###SDK1.6以前
```proj.conf
# Added for FOTA
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUMGR=y
CONFIG_MCUMGR_CMD_OS_MGMT=y
CONFIG_MCUMGR_CMD_IMG_MGMT=y
CONFIG_MCUMGR_SMP_BT=y
CONFIG_IMG_ERASE_PROGRESSIVELY=y
CONFIG_MCUMGR_SMP_BT_AUTHEN=n
CONFIG_BT_L2CAP_TX_MTU=252
CONFIG_BT_L2CAP_RX_MTU=252
CONFIG_BT_RX_BUF_LEN=260
CONFIG_BT_CTLR_TX_BUFFER_SIZE=251
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
```

###SDK1.6以降
```proj.conf
# Added for FOTA
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUMGR=y
CONFIG_MCUMGR_CMD_OS_MGMT=y
CONFIG_MCUMGR_CMD_IMG_MGMT=y
CONFIG_MCUMGR_SMP_BT=y
CONFIG_IMG_ERASE_PROGRESSIVELY=y
CONFIG_MCUMGR_SMP_BT_AUTHEN=n
CONFIG_BT_L2CAP_TX_MTU=252
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_BUF_ACL_RX_SIZE=251
```

#Secure Bootloader
ここまで読み進めてきて「あれ？」と思ったあなた、鋭いです。そうですね、秘密鍵の生成が出てきていないにもかかわらずFOTAができてしまいました。つまり、今までのFOTAはnRF SDKで言うところのOpen Bootloaderに相当するものです。(厳密には秘密鍵のファイルがSDKに含まれていて誰でも入手できるものを使っているためです)
ここからSecure Bootloader相当にするにはもうひと手間必要になります。
##秘密鍵の作成
MCUMGRではRSA-2048という暗号を使用します。nRF SDKで使っていたものとは異なるため使いまわすことはできません。
Pythonで以下のスクリプトを実行すると秘密鍵を生成できます。

```
python C:\Nordic\v1.7.0\nrf\scripts\bootloader\keygen.py --private -o priv.pem
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/11f757a3-49c1-b457-2aaa-ee0f732d0e38.png)
##コンフィギュレーションの変更
秘密鍵を読み込ませるためのコンフィギュレーションを追加します。

```prj.conf
CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/Nordic/projects/dfu_advertising/priv.pem"
```
ここまで来たらあとはコンパイルするだけです。
##セキュアになっているかチェック！
DFUをする前に一旦Flashを消去して中身を確認します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/c26c5cbd-d4c6-1a74-5953-1c30e3696320.png)
いよいよDFUです。ちゃんと弾いてくれますよね・・・ドキドキ
![Screenshot_20211012-165445.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/da82eb37-f7fa-887c-72b5-8d10a3f10245.png)
![Screenshot_20211012-165524.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/93be60ca-ee4d-57c1-a2f7-757ce3abf69f.png)
![Screenshot_20211012-165533.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/340602/a1b237b8-fba2-2501-29b4-f25d92087076.png)
ファーーーーー！
アップロードが始まった？！？！？！
どういうことなの・・・？
落胆しながら確認してみると・・・おや？アドバタイズ名が変わっていない・・・？ProgrammerでFlash ROMの中身を覗いてみても何も書き込まれていない。つまり、nRF SDKと違ってアップロード前にはじくのではなく、アップロードし終わってから何らかの形で照合して書き込みを拒否する(もしくは消去する)ようです。
よっしゃあぁぁぁ！
ということでSecure Bootloaderの完成です。
#注意点
##同じファームウェアでのFOTAはスキップ
全く同じファームウェアでFOTAを実行するとスキップされます。ファイル名を変えてもダメなのでバイナリレベルで照合していると思われます。
##再FOTA
再度FOTAするには、FOTAしたファームウェアもFOTAできる設定が必要です。ある意味、当たり前の説明ではありますが・・・。

#Appendix
##原文
https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/app_bootloaders.html
##参考スレッド
https://devzone.nordicsemi.com/f/nordic-q-a/72803/ncs-ota-dfu-failed-in-nrf52832/300842#300842