みつきんのメモ

組み込みエンジニアです。Interface誌で「My オリジナルLinuxの作り方」連載中

Yocto BBC micro:bit V1向けのZephyrを試してみる

はじめに

YoctoでZephyrをビルドできるっぽいことは知っていたが、試したことがなかったのでやってみる。

使用するバージョンはhardknott

構築手順

ソース取得

下記のコマンドでソースを取得する。

$ mkdir -p mb-hardknott && cd mb-hardknott
$ git clone git://git.yoctoproject.org/poky.git -b hardknott

環境変数設定

$ source poky/oe-init-build-env build

自動的にビルドディレクトリに移動される。 これで、bitbake関連のツールが使用可能になる。

レイヤ追加

下記のコマンドでビルド対象にmeta-armmeta-zephyrを追加する。

$ bitbake-layers layerindex-fetch meta-arm meta-zephyr

複数のレイヤを一度に指定することもできる。

レイヤ 目的
meta-arm MACHINEでmicrobit-v1を使用するため
meta-zephyr Zephyrをビルドするため

local.confの修正

MACHINEをmicrobit-v1に設定する。

MACHINE = "microbit-v1"
DL_DIR ?= "${TOPDIR}/../downloads"

ビルド

hello worldをビルドしてみる。

$ bitbake zephyr-helloworld

build/tmp/deploy/images/microbit-v1以下にビルド結果のelfが配置される。

  • zephyr-helloworld-image-microbit-v1.elf
  • zephyr-helloworld-image-microbit-v1.qemuboot.conf
  • zephyr-helloworld-microbit-v1-20210826075435.qemuboot.conf
  • zephyr-helloworld.elf

プログラム本体はzephyr-helloworld.elf

Linuxをビルド

ためしにcore-image-baseをビルドしようとしてみる。

$ bitbake-layers show-layers 
NOTE: Starting bitbake server...
layer                 path                                      priority
==========================================================================
meta                  /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta  5
meta-poky             /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta-poky  5
meta-yocto-bsp        /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta-yocto-bsp  5
meta-arm-toolchain    /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta-arm/meta-arm-toolchain  5
meta-oe               /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta-openembedded/meta-oe  6
meta-python           /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta-openembedded/meta-python  7
meta-arm              /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta-arm/meta-arm  5
meta-zephyr           /home/mickey/work/yocto/x86-hardknott/mb-hardknott/poky/meta-zephyr  6
mickey@yocto-build:~/work/yocto/x86-hardknott/mb-hardknott/build$ vim ./conf/local.conf 
mickey@yocto-build:~/work/yocto/x86-hardknott/mb-hardknott/build$ bitbake core-image-base
Loading cache: 100% |                                                                | ETA:  --:--:--
Loaded 0 entries from dependency cache.
Parsing recipes: 100% |###############################################################| Time: 0:00:34
Parsing of 2123 .bb files complete (0 cached, 2123 parsed). 3398 targets, 180 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
ERROR: Nothing PROVIDES 'virtual/kernel'
linux-yocto PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
linux-dummy PROVIDES virtual/kernel but was skipped: incompatible with host arm-poky-eabi (not in COMPATIBLE_HOST)
linux-yocto-rt PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
linux-yocto-tiny PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
linux-arm64-ack PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
linux-yocto-dev PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
linux-yocto PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
linux-yocto-tiny PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
linux-yocto-rt PROVIDES virtual/kernel but was skipped: incompatible with machine microbit-v1 (not in COMPATIBLE_MACHINE)
ERROR: Required build target 'core-image-base' has no buildable providers.
Missing or unbuildable dependency chain was: ['core-image-base', 'virtual/kernel']

Summary: There were 2 ERROR messages shown, returning a non-zero exit code.

非対応のマシンということでちゃんとエラーになった。

エミュレータ(qemu)で実行

下記のようにするとqemuでプログラムを実行することができる。

$ runqemu
(... snip ...)

*** Booting Zephyr OS build zephyr-v2.5.0  ***
Hello World! qemu_cortex_m0

ssh越しなどで、うまく文字列が表示されない場合は下記のようにオプションを渡して、シリアルの出力先を標準出力などに変えてやると、うまく行くことがある。

$ runqemu qemux86 qemuparams="-serial mon:stdio"

実機に書き込む

micro:bitの実機にプログラムを書き込む場合は、elfからbinary形式に変換する必要がある。

$ cd tmp/deploy/images/microbit-v1
$ arm-none-eabi-objcopy zephyr-helloworld.elf zephyr-helloworld.bin -O binary

micro:bitUbuntu 20.04のマシンににUSBで接続すると、/media/mickey/MICROBIT/として見えるようになる。

変換したbinary形式のファイルを下記のようにmicro:bitにコピーすると自動的リセットがかかり、新しいプログラムが読み込まれる。

cp ./zephyr-helloworld.bin /media/mickey/MICROBIT/

micro:bitのUSB-UARTは/dev/ttyACM0として見えているので、minicomなどで開く。

minicom -D /dev/ttyACM0

この状態でmicro:bitのリセットボタンを押すと下記のように出力される。

*�*** Booting Zephyr OS build zephyr-v2.5.0  ***
Hello World! qemu_cortex_m0

リセット直後の出力にゴミが入るが、プログラムは正しく動いているようだ。

バイナリファイルについて

実際のところ、bitbakeの結果としてzephyr.binも出来上がっている。 しかし、zephyr-hellworld.bbから読み込まれるzephyr-sample.incで定義されているdo_deployタスクが 下記のようにelfのみをコピーするようになっているので、binは放置されているようだ。

do_deploy () {
    install -D ${B}/zephyr/${ZEPHYR_MAKE_OUTPUT} ${DEPLOYDIR}/${PN}.elf
}

まとめ

Yocto Projectを使用してZephyrのmicro:bit向けバイナリをビルドすることができた。 生成されたバイナリはqemuでも実機でも動作することが確認できた。

実際Zephyrを直接ビルドするよりも、bitbakeのほうが時間かかる。 bitbakeでツールチェインやzephyrのカーネルなど、すべて構築されるのでそこはメリットと言えるかもしれない。