DevAcademy “Adding custom board support” (4)

2024/07/25

引き続き DevAcademy IntermediateのAdding custom board supportを見ていく。

Exercise 1 は動きはしたものの、nRF5340 はマルチコアなので Exercise 2 もやる。


Exercise 2 – Custom board for a multi-core & TF-M capable SoC/SiP

Exercise 2 だが、残念ながら私が持っている nRF5340 ではなく nRF9161DK ベースの課題だった。 nrf9161dk_nrf9161をコピーして、リネームしたり置換したりでExerciseの半分を使っている。。。 そしてビルドして動かしたら終わりっぽい。。。

TF-Mが有効な場合、作成した Build Configuration をビルドすると現れるフォルダの中に “Trusted Fimrware-M” が現れる。 これは Exercise 1 のビルド結果だが、NS が付いた方は TF-M があることがわかる。

image

MCUboot があると同じようにフォルダにぶら下がるので、これはどちらのビルド結果にも MCUboot は入っていないということになる。


1core - CONFIG_BOOTLOADER_MCUBOOT=y

マルチコアやTF-Mを一から扱うのは難しいのでどれかをベースにせよ、ということなのだろうか? 実際、MDBT53で提供されたボード定義ファイルはThingy53をベースにしている。

ともかく、この Lesson では評価ボードnRF5340 MDBT53-1Mモジュールピッチ変換基板のボード定義ファイルでサンプルアプリが立ち上がらない直接の原因はわからなかったということになる。 これからどうしたものか。

MCUbootからmain()までたどり着けていないので、MCUbootの設定だと思う。 今までは定義済みのボードをベースにしていたが、そういえば Exercise 1 で一から作ったボード定義ファイルで MCUboot を使うパターンは試していなかった。

1core - CONFIG_BOOTLOADER_MCUBOOT=y

やってみると、動いたではないか。

image


再Build Configurationするとエラーになる

なんとなく、Build Configuration を削除せずに”Edit Build Configuration”を開いてボタンだけクリックするとFile not found: C:/ncs/v2.6.1/bootloader/mcuboot/boot/zephyr/.でエラーになった。
存在するのだが。。。いや、ディレクトリではなくファイルが見つからないだから"."をファイルとして扱っている? よくわからない。。。

-- Including generated dts.cmake file: U:/Prog/BLE/nrf-ncs/blinky_devaca/build/mcuboot/zephyr/dts.cmake
CMake Error at C:/ncs/v2.6.1/zephyr/cmake/modules/kconfig.cmake:290 (message):
  File not found: C:/ncs/v2.6.1/bootloader/mcuboot/boot/zephyr/.

“Build after generating configuration”のチェックを外してボタンを押してもエラーが起きたので、Build Configuration を後から変更するのは難しい。 Clean してもエラーになる。これは単純にビルドに失敗していてファイルが作られなかったためだろう。

-- west build: running target clean
ninja: error: loading 'build.ninja': 指定されたファイルが見つかりません。

なお、Windows11 だと Clean で出力されたエラー文字列が文字化けしていたのだが、Windowsの設定からUTF-8に変更すると読めるようになった。ありがたや。 cmd.exeだったらいっそのこと英語出力の方がありがたいのだけどね。westcmd.exe込みで実行するので永続化しないといけない。AutoRunで変更するやり方が使えるのかもしれない。

【Windows11】CMDの文字コードをUTF-8に設定する方法 #備忘録 - Qiita

ビルドするコマンドはこうなっていた(“Copy Build Command”でコピーできる)。 u:/Prog/BLE/nrf-ncs/blinky_devacaはアプリのプロジェクトディレクトリである。

west build \
  --build-dir u:/Prog/BLE/nrf-ncs/blinky_devaca/build \
    u:/Prog/BLE/nrf-ncs/blinky_devaca \
  --pristine \
  --board devacademy_nrf5340 \
  --no-sysbuild \
  -- \
    -DNCS_TOOLCHAIN_VERSION=NONE \
    -DBOARD_ROOT=c:/ncs/custom_boards;u:/prog/ble/nrf-ncs/blinky_devaca \
    -Dmcuboot_OVERLAY_CONFIG=.;C:/ncs/v2.6.1/nrf/subsys/partition_manager/partition_manager_enabled.conf \
    -DCACHED_CONF_FILE=u:/Prog/BLE/nrf-ncs/blinky_devaca/prj.conf

試しにこれをvscodeのTerminalに貼り付けて実行したが、やはりエラーになった。 貼り付けて実行するとエラーの箇所が赤文字になるのでわかりやすいが、違いはそれくらいか。

エラーになっている kconfig.cmake:290 はこういう内容。

foreach(root ${kconfig_soc_root})
  file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.soc.defconfig
       "osource \"${root}/soc/$(ARCH)/*/Kconfig.defconfig\"\n"
  )
  file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.soc
       "osource \"${root}/soc/$(ARCH)/*/Kconfig.soc\"\n"
  )
  file(${OPERATION} ${KCONFIG_BINARY_DIR}/Kconfig.soc.arch
       "osource \"${root}/soc/$(ARCH)/Kconfig\"\n"
       "osource \"${root}/soc/$(ARCH)/*/Kconfig\"\n"
  )
  set(OPERATION APPEND)
endforeach()

${kconfig_soc_root}は、たぶんSoCのKconfigファイルだかDTSファイルだかが入ったディレクトリ文字列の配列なんだろう。 うん、私では何もできないな。 Build Configurationを一度作った後は変更できないと思っておこう。削除して作り直せば済むだけだ。 いや、作り直さず新たに追加すれば良いだけか。悩むことはなかった。。。
Build Configurationで変更できる項目はその場限りのものなので、変更したいならprj.confなりなんなりを変更しなさいということだ。


デフォルトのOptimization level

Build Configurationをやり直そうと思ったのは Optimization level を変更してデバッグできるようにしたかったからだ。

image

デフォルト値は何も設定しなかった場合はどうなっているのだろう? GUIを名前で検索すると出てきたが2つ現れた。 上が”C Library”、下が”Build and Link Features > Compiler Options”だった。

image

デフォルトではサイズ優先で最適化されているようだ。 しかし、GUIではラジオボタンなのにKconfigではboolなのは不思議だ。 Kconfig searchの検索によると

MCUbootあり(1core)

では 1コア(TF-M無し)でMCUbootを有効にした状態で最適化をデバッグありビルドにしてデバッグを行う。

reset.Sで止まるのがよくわからないが、main()で止まるのもよくわからない。 ブレークポイントを設定していなくてもアプリのエントリーポイントで止まるようになっているのだろうか。

では C:\ncs\v2.6.1\bootloader\mcuboot\boot\zephyr\main.cmain()先頭近くにブレークポイントを設定してデバッグ実行。 よくわからないがFIH_CALL()の行で止まった。

FIHFIH_CALLの定義ファイルからすると “Fault Injection Hardening” の略だろう。 CFI(Control Flow Integrity)みたいな略語がポンポン出てくるが、深入りしないようにする。 とにかくセキュリティ関連の何かだからデバッグなどはほとんどできないだろう。

ともかくMCUbootは通っていると思っていて良かろう。

1core - non-secure - CONFIG_BOOTLOADER_MCUBOOT=y

では、non-secure の方も試してみる。 まずはdevacademy_nrf5340_ns_defconfigCONFIG_BOOTLOADER_MCUBOOT=yだけを追加してビルドするのだがエラーになった。

CMake Warning at C:/ncs/v2.6.1/zephyr/cmake/modules/boards.cmake:112 (message):
  BOARD_DIR:
  U:/Prog/BLE/nrf-ncs/blinky_devaca/boards/arm/devacademy_nrf5340_ns has been
  moved or deleted.  Trying to find new location.

そのディレクトリもあるのだが。。。

念のためCONFIG_BOOTLOADER_MCUBOOTを無しにしたり=nにしたりしてビルドしてもエラーは出ない。 設定がないとか間違っているとかではなくディレクトリが無いという。
_nsのディレクトリごと vscode の BOARD_ROOT のディレクトリに移動させたのだが、エラーはディレクトリ名が移動先になった上に出てくる。 パスが分かってるやん!

cmakeのスクリプトを確認。

  if(BOARD_DIR AND NOT EXISTS ${BOARD_DIR}/${BOARD}_defconfig)

ああ、${BOARD_DIR}ではなく${BOARD_DIR}/${BOARD}_defconfigで確認しているのか。 そしてそちらの変数で出力すると(略)/boards/arm/devacademy_nrf5340_ns/devacademy_nrf5340_defconfigとなっていた。 つまり${BOARD}の方が正しくないということになる。 _nsが抜けているが、そういえば Naming については制限があったのをルール違反していたのか。

devacademy_nrf5340_nsからdevacademyns_nrf5340に変更して作り直した。
これでビルドは進んだものの違う箇所でエラーになった。

CMake Error at C:/ncs/v2.6.1/nrf/lib/fprotect/CMakeLists.txt:15 (message):
  No fprotect backend selected.

CONFIG_FPROTECT

Enable the software library FPROTECT that may or may not be used by other systems to protect flash from writes and possibly also reads. Does not protect against execution. May use the HW peripherals BPROT, ACL, or SPU to achieve this.

Hardware flash write protectionというものらしい。

ソフトウェアレベルでFlash書込みの保護ができる?

“backend”と呼んでいるのは以下のいずれか。

MDBT53のビルドを見たところ、cpunet は CONFIG_HAS_HW_NRF_ACL=y、MCUboot含む cpuapp はCONFIG_HAS_HW_NRF_SPU=yになっていた。 ACL“Access Control List”SPU“System Protection Unit”BPROTはnRF5340には載っていないようだ。

SPU(System Protection Unit)とflash_sim

まずSPUだが、nrf5340_cpuapp.dtsiには設定があるのだがnsの方にない。 MDBT53では有効になっているのだが、これはflash_sim.overlayを参照していた。 flash_simについては以前調べていて-Dmcuboot_DTC_OVERLAY_FILE="C:/ncs/v2.6.1/nrf/modules/mcuboot/flash_sim.overlay"のようになっていた。

“Extra CMake arguments”はビルドするとGUIに反映されるのだが、この値がどこからくるのかはわからないままだった。 少なくともMDBT53用に提供されたボード定義ファイルにはなかった。

もしかしてCONFIG_FLASH_SIMULATOR=yか? CONFIG_HAS_HW_NRF_SPU=yの代わりにCONFIG_FLASH_SIMULATOR=yを設定するとエラーが変わった。

warning: FLASH_SIMULATOR (defined at drivers/flash/Kconfig.simulator:6) was assigned the value 'y'
but got the value 'n'. Check these unsatisfied dependencies: DT_HAS_ZEPHYR_SIM_FLASH_ENABLED (=n),
FLASH (=n).

この手のwarningがしばしば出るのだが、”but got the value ‘n’” はどこから得た値なのだろうか。 これか?

image

<boardID>_defconfigyを書いたのだから、まあ上書きしようと思えばできるだろう。 MDBT53ボード定義ファイルはどうしていたかというと、ssci_mdbt53_dev_board_cpuapp.confというファイルを ncs の MCUboot 以下にコピーしていた。 このファイルはKconfigのデフォルト値MCUboot版という位置づけなのだろうか。

だいたいCONFIG_FLASH_SIMULATORのデフォルト値はyとなっているのだが。 Kconfig GUIで見るとDT_HAS_ZEPHYR_SIM_FLASH_ENABLEDのせいであることがわかった。 DT_ということはDeviceTreeか? MDBT53ではflash_sim0が有効になっていた。

image

image

overlay ファイルを作るなら、取りあえずchild_image/mcuboot.overlayになるのかな、と思ったが、そういえばflash_sim.overlayを使いたいのが元々の話だった。 flash_sim.overlayを使うことができればよいのだが、そのためにCONFIG_FLASH_SIMULATOR=yにしたい。 CONFIG_FLASH_SIMULATOR=yにするためにはDT_HAS_ZEPHYR_SIM_FLASH_ENABLED=yになるようにするのだが、それにはflash_sim.overlayがいる??

ならmcuboot_DTC_OVERLAY_FILEを先に有効にすれば良いのか? 無理やり board.cmake に追加してみたが、読込はされたもののビルドはやはり失敗。

では逆にssci_mdbt53_dev_board_cpuapp.confを削除してMDBT53でビルドしたらflash_simは使えなくなるのか?
使えました。flash_sim.overlayも使われている。
ということはこのconfファイルではなくボード定義ファイルに秘密があるはず。

MDBT53のボード定義ファイルからflash_sim.overlayを使わなくなるように削除してみたところ、external flash だの mx25r64 だのを削除するとうまくいった(ビルドは成功しないが)。
つまりflash_simは外部接続したflashにアクセスするためのものということで間違いなさそうだ。 ではDT_HAS_ZEPHYR_SIM_FLASH_ENABLED=nのままにしてCONFIG_FLASH_SIMULATOR=nのままでよいことになる。
flash_simのことは忘れよう。

ではCONFIG_HAS_HW_NRF_SPU=yflash_simだからSPUを使うことになったのだろうか?
System Protection Unitのページを見たが説明が長い。。。 ただ図の中に内部Flashは出てこず外部Flashしか描かれていない。 外部FlashについてはSPUで、内部FlashについてはACLということか。

ACL(Access Control List)

ACLの最初に “on-chip flash” と書いてあるので、そうなのだと思いたい。 設定が8つまでできるので、CPUNET専用ではないはずだ。。。

MDBT53のcpunet側devicetreeをGUIで見ると、soc の下に acl があった。

image

が、aclC:\ncs\v2.6.1\zephyr\dts\arm\nordic\nrf5340_cpunet.dtsiにあるもののcpuappには無い。 今までの様子からすると、これはcpuappでは扱えないと考えた方がよいだろう。 サンプルにはmulti-imageなども書いてあるし。

うーん。。。