みつきんのメモ

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

Yocto Zephyrアプリケーションのコンフィグを変更する

はじめに

YoctoでビルドするZephyrアプリケーションのコンフィグを設定する方法を調べた。

micro:bitの5x5 LEDを有効化する。

最終的にはmeta-armの修正が必要となった。

作業環境はYocto Zephyrに独自のアプリケーションを追加してみるを使用する。

環境変数の読み込み

最初にこれを実行し、bitbake関連のツールを使用できるようにしておく。

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

do_menuconfigタスク

ZephyrはLinuxカーネルのようにKconfigによってコンフィグを変更したりできる。

Yoctoでは、このような機能を持つコンポーネントのレシピの場合do_menuconfigタスクを実装している場合が多く、 それが利用でいないか確認してみた。

$ bitbake my-app -c listtasks | grep menuconfig
do_menuconfig       Runs 'make menuconfig' for the kernel

見つかったので実行してみる。

$ bitbake my-app -c menuconfig

残念ながら使用できない。

make: *** No rule to make target 'menuconfig'.  Stop.
Command failed.
Press any key to continue... 

コンフィグの変更

Zephyrアプリケーションのコンフィグを変更するにはprj.confに記述する。

Yocto Zephyrに独自のアプリケーションを追加してみるで作成した時には下記のように空の設定を記述していた。

# nothing here

micro:bitの5x5 LEDを有効化するためにはCONFIG_MICROBIT_DISPLAYを有効化する。

CONFIG_MICROBIT_DISPLAY=y

メニューコンフィグ

実際にこの設定が反映されているか確認したい。

本来であればメニューコンフィグを実行するのが手っ取り早い。do_menuconfigタスクは使えないが、実のところZephyrのメニューコンフィグを実行する手段はある。

下記のようにdo_configureタスクを実行したあと、do_devshellタスクを実行する。

$ bitbake my-app -c configure
$ bitbake my-app -c devshell

すると、開発用シェルが${S}で設定されているディレクトリに移動された状態で開く。

ビルドディレクトリにはbuild.ninjaが生成されているので、下記のようにするとZephyrのメニューコンフィグを実行することができる。

$ cd ../build
$ ninja menuconfig

f:id:mickey_happygolucky:20210828094011p:plain
メニューコンフィグ

MICROBIT_DISPLAY=n

/を押したあとでキーワードを入力すると、コンフィグを検索することができる。

MICROBIT_と入力すると下記のような画面になる。

f:id:mickey_happygolucky:20210828094033p:plain
MICROBIT_DISPLAY(=n)

MICROBIT_DISPLAY=nとなっており、prj.confの設定が反映されていない。

?で詳細を表示してこのコンフィグの依存関係を表示すると下記のようになっている。

Direct dependencies (=n):
     BOARD_BBC_MICROBIT(undefined/n)
  && PRINTK(=y)
  && GPIO(=y)
  && DISPLAY(=n)

BOARD_BBC_MICROBITDISPLAYの設定がnになっていることがわかる。

BOARDの設定を見るとBOARD_BBC_MICROBITはボード設定に依存しているようだ。 BOARD(=qemu_cortex_m0)はZephyrがターゲットボードを決定するための基本的な設定なのだろう。

f:id:mickey_happygolucky:20210828094020p:plain
BOARD(=qemu_cortex_m0)

BOARD(=qemu_cortex_m0)BOARD_QEMU_CORTEX_M0(=y)は対応しているように見える。つまりBOARD(=bbc_microbit)と設定すればBOARD_BBC_MICROBIT(=y)にできるのではないか。

BOARDの設定

meta-arm/conf/machine/microbit-v1.confを調べると、下記の様な記述が見つかる。

# Zephyr RTOS settings
ZEPHYR_BOARD = "qemu_cortex_m0"
ZEPHYR_INHERIT_CLASSES += "zephyr-qemuboot"
ARCH_qemu-cortex-m0 = "arm"

ZEPHYR_BOARDに設定された値がZephyrのCONFIG_BOARDに設定されているようだ。

ZEPHYR_BOARDの値を変更すれば良さそうだが、できればmeta-armを直接変更したくない。local.confで下記のようにすることで設定を上書きできないだろうか。

ZEPHYR_BOARD = "bbc_microbit"

結論から言うとこれはできない。

microbit-v1.confでZEPHYR_BOARDを設定する時に=を使って代入しているため、変数をあとから上書きすることができないからだ。

下記のように?=を使用して代入していればlocal.confなどであとから変更することができるようになる。

ZEPHYR_BOARD ?= "qemu_cortex_m0"

レイヤやMACHINEの定義をする場合、RAMのベースアドレスのように絶対に上書きされたくないような物以外はできるだけ?=を使うようにしてほしいが、 microbit-v1.confはmicro:bit専用の設定であるので、下記のように修正するのが本来正しい気もする。

- ZEPHYR_BOARD = "qemu_cortex_m0"
+ ZEPHYR_BOARD = "bbc_microbit"

最終的なコンフィグ

meta-arm/conf/machine/microbit-v1.confZEPHYR_BOARDbbc_microbitに設定したあと、meta-zephyr-app/recipes-example/my-app/files/my-app/prj.confを下記のように変更する。

CONFIG_DISPLAY=y
CONFIG_MICROBIT_DISPLAY=y

bitbake my-app -c configureでdo_configureタスクを実行したあとに、devshellでninja menuconfigを実行して、コンフィグの依存関係を確認すると下記のようになっている。

Direct dependencies (=y):
     BOARD_BBC_MICROBIT(=y)
  && PRINTK(=y)
  && GPIO(=y)
  && DISPLAY(=y)

これでCONFIG_MICROBIT_DISPLAYは有効化できた。

プログラムの修正

VSCode + PlatformIO で micro:bit + Zephyr RTOS 開発がちょうどZephyrで5x5 LEDを使用する方法を紹介している。

meta-zephyr-app/recipes-example/my-app/files/my-app/src/main.cを下記のように変更する。

#include <zephyr.h>
#include <display/mb_display.h>

void main(void)
{
    struct mb_image patterns[] = {
        MB_IMAGE(
            {0, 0, 0, 0, 0},
            {1, 1, 0, 1, 1},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0},
            {0, 1, 1, 1, 0},
        ),
    };
    struct mb_display *dpy = mb_display_get();
    mb_display_image(dpy, MB_DISPLAY_MODE_DEFAULT, SYS_FOREVER_MS, patterns, 1);
}

レシピの修正

5x5 LEDは実機に書き込まないと確認できないし、毎回objcopyでbinary形式に変換するのも面倒なので、 do_deployタスクに処理を追加する。

include recipes-kernel/zephyr-kernel/zephyr-sample.inc

SRC_URI += "file://my-app"

ZEPHYR_SRC_DIR = "${S}/../my-app"

do_deploy_append () {
    local src=${B}/zephyr/${ZEPHYR_MAKE_OUTPUT}
    src=${src%.*}.bin
    install -D ${src} ${DEPLOYDIR}/${PN}.bin
}

ビルド

下記のようにビルドを実行する。

$ bitbake my-app

すると、tmp/deploy/images/microbit-v1my-app.binも配置されるようになった。

これをmicro:bitの実機に書き込んで動作を確認してみる。

$ cd tmp/deploy/images/microbit-v1/
$ cp ./my-app.bin /media/mickey/MICROBIT/

f:id:mickey_happygolucky:20210828094041j:plain
実行結果

まとめ

YoctoでビルドするZephyrアプリケーションのコンフィグを変更して5x5 LEDを使用してみた。

下記のような問題があったが力技でなんとか回避した。

  1. do_menuconfigタスクが使えない
  2. ZephyrのBOARDコンフィグの変更のためにmeta-armを直接修正する必要がある。

ちょっと標準と外れたことをしようとすると、急にハードルが上がってしまうのがこの手の便利ツールのツライところ。

ただ、その中でもYoctoは比較的自由度が高いため、いろいろ手を尽くして回避することができる。 meta-arm提供のconfファイルで=で代入しているため、変更したいところがlocal.confで上書きできないのは、ちょっと気に入らない。