リネオブログ

Zephyrブログ 第五回 「Zephyr アプリに挑戦(中編)」

2026 年 09 月 04 日   ソリューション統括部

はじめに

Zephyr OS とは ? について解説するブログの第五回目です。
Zephyr アプリに挑戦(中編)では、前編で構築した見本アプリ app を Zephyr 上で使えるようにしていきます。

「Zephyr アプリに挑戦」は全三回を予定しています。前編はこちら。後編は 10 月中旬頃の公開予定です。

これまでの Zephyr ブログを読んでいない方は 「Zephyrブログ 第一回 はじめての Zephyr(前編)」から読んでいただけると、より理解が深まります。

目次

モジュールの追加

applications/CMakeLists.txt ファイルには次のような行があるので、これらのファイルを cmake が読み込んでくれれば良さそうです。

  • add_subdirectory(drivers)
  • add_subdirectory(lib)

そのためには applications ディレクトリがモジュールとして登録できれば良さそうと考えました。
モジュールとは、「はじめての Zephyr」の回で簡単に述べましたが、Zephyr とは無関係にメンテされているソースコードで Zephyr の構築システムに組み込まれたもののことです。
では、モジュール として登録するにはどうすればよいのでしょうか?そもそも example-application リポジトリはモジュールとして使用することができるのでしょうか?

まず、モジュールとして使用できるのかどうかですが、
https://docs.zephyrproject.org/latest/develop/modules.html#module-yaml-file-description
によると、モジュールは zephyr/module.yml ファイルによってその内容を記述できると書かれています。
example-application リポジトリにはファイル zephyr/module.yml があります。モジュールとして使用されることが想定されているようです。

次に、モジュールとして登録するにはどうすればよいかですが、
https://docs.zephyrproject.org/latest/develop/modules.html#integrate-modules-in-zephyr-build-system によれば、EXTRA_ZEPHYR_MODULES という CMake 変数ないし環境変数があって、これを使ってモジュールを追加できるようです。

環境変数でもよいということで、次のようにしてみました。

$ export EXTRA_ZEPHYR_MODULES=$PWD
$ west build -b mimxrt1170_evk/mimxrt1176/cm7 app

the undefined symbol BLINK エラーは出ませんでした。うまくいったようです。

モジュールの追加まとめ

構築するためには applications ディレクトリをモジュールとして登録する必要があります。
そのためには環境変数 EXTRA_ZEPHYR_MODULES に applications ディレクトリの絶対パスを次のように設定した上で west build コマンドを実行すればよいです。

$ cd ~/zephyrproject/applications
$ export EXTRA_ZEPHYR_MODULES=$PWD

アプリに DTS ファイルを追加

applications ディレクトリをモジュールとして登録することによって the undefined symbol BLINK エラーは出なくなったのですが、別のエラーが出てしまいました。 そのエラーメッセージだけ抜粋します。

..(snip)..
/home/hoge/zephyrproject/applications/app/src/main.c: In function 'main':
/home/hoge/zephyrproject/zephyr/include/zephyr/device.h:96:41: error: '__device_dts_ord_DT_N_NODELABEL_example_sensor_ORD' undeclared (first use in this function)
   96 | #define DEVICE_NAME_GET(dev_id) _CONCAT(__device_, dev_id)
      |                                         ^~~~~~~~~
..(snip)..
/home/hoge/zephyrproject/applications/app/src/main.c:28:18: note: in expansion of macro 'DEVICE_DT_GET'
   28 |         sensor = DEVICE_DT_GET(DT_NODELABEL(example_sensor));
      |                  ^~~~~~~~~~~~~

app/src/main.c の 28 行目の DT_NODELABEL(example_sensor) マクロの展開で
'__device_dts_ord_DT_N_NODELABEL_example_sensor_ORD' undeclared エラーになっているようです。

このエラーは、調べてみますと、デバイスツリーのノードラベル example_sensor を参照したもので、そのノードラベルの定義が存在しないために発生しているようです。

はじめての Zephyr」の回でと述べましたが、Zephyr はデバイスツリーでソースコードの構成ができます。
それは上記のように C マクロを使ってデバイスツリーのノードやプロパティを参照できるようにしていることに依るのです。
example_sensor はアプリディレクトリ配下の boards/nucleo_f302r8.overlay で定義されていました。当該箇所を引用します。

/ {
        example_sensor: example-sensor {
                compatible = "zephyr,example-sensor";
                input-gpios = <&gpioc 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
        };

        blink_led: blink-led {
                compatible = "blink-gpio-led";
                led-gpios = <&gpiob 13 GPIO_ACTIVE_HIGH>;
                blink-period-ms = <1000>;
        };
};

&gpioc {
        status = "okay";
};

したがって、MIMXRT1170-EVKB ボード用の example_sensor (と blink_led) ノードを定義すればよさそうです。
その定義をどこに書けばよいのでしょうか ?
デバイスツリーノードの追加定義の仕方を知るためには、Zephyr ではデバイスツリーがどのように構成されているのかを知る必要がありました。
Zephyr では最終的なデバイスツリーソースは 4 種類ある DTS ファイルをマージして作成されます。

DTSファイルはファイル名のサフィックスを使って分類されています。
次のとおりです
https://docs.zephyrproject.org/latest/build/dts/intro-input-output.html#input-files より)。

  • .dts ファイル :各ボードのハードウェアを定義する DTS ファイル。
  • .dtsi ファイル :.dts や .dtsi ファイルから include される DTS ファイル。
  • .overlayファイル :.dts を拡張したり改変したりする DTS ファイル。
  • .yaml ファイル :デバイスツリーバインディングを定義するファイル。

最終的な DTS ファイルが生成される過程は次のようになります。
まず .dts ファイルを選択します。
そして include される .dtsi ファイル群をその位置に挿入します。
最後にそうしてできあがった DTS ファイルの末尾に .overlay ファイルを追加します。
DTS 構文は、より後ろに定義したほうが有効になるので、.overlay が意図している役割を果たすことができます。

さて、そうすると、最終的な DTS ファイルの生成に向かって、残る問題は次の二つです。

  • 使用する .dts ファイルの選択はどのように行われるのか。
  • 使用する .overlay ファイルの選択はどのように行われるのか。

前者の .dts ファイルはボードディレクトリ配下の .dts ファイルから選ばれます。
ボードディレクトリとその .dts ファイル名は west build コマンドの -b BOARD オプションを使って指定します。
BOARD について、このあたりで少し精密に議論してみましょう。

これまで -b オプションには引数 mimxrt1170_evk/mimxrt1176/cm7 を与えてきました。
これをボードターゲット といいます
https://docs.zephyrproject.org/latest/glossary.html#term-board-target 参照)。

この / で区切られた最初の要素がボード名であり、それがボードディレクトリ名となります。
それ以降は ボード修飾子 (qualifiers) といいます。
ボード修飾子は最大で次の三つの要素からなり、各々を / で区切ってボードターゲットを構成します。

  • SoC 部 : mimxrt1176 がそれに当たります。
  • CPU cluster 部 : cm7 がそれに当たります。
  • variant 部 : 上の例では存在しません。

なお、ボード修飾子は右から順に無くてもかまいません。全部無くてもかまいません。
ボードターゲットの構成要素にはこのほかに ボードリビジョン があります。
ボードリビジョンはボード修飾子の一部ではありません。

ボード名の後ろに @ を添えて追加できます。
たとえば mimxrt1170_evk@B/mimxrt1176/cm7 というようになります。
ボードターゲットからリビジョンがあれば取り除き、 / を _ に置き変えてできる文字列を としましょう。
すると .dts が使用される .dts ファイルの名前となります。
mimxrt1170_evk/mimxrt1176/cm7 の場合はファイル名は mimxrt1170_evk_mimxrt1176_cm7.dts となります。

次に、後者の .overlay ファイルですが、これはアプリディレクトリ配下の .overlay ファイルから選ばれます(シールドやリビジョン用の .overlay は除く)。
そのファイル名がボードターゲットから作られる点は .dts ファイルの場合と同様ですが、選び方がちょっと複雑です。
その選択規則は次のとおりです (https://docs.zephyrproject.org/latest/build/dts/howtos.html#set-devicetree-overlays より)。

  1. CMake 変数 DTC_OVERLAY_FILE が定義されていれば、それを使用する。
  2. 定義されていなければ、アプリコンフィグディレクトリ配下を次の順で調べる。
    1. socs/_.overlay
    2. boards/.overlay
    3. boards/_.overlay
    4. 前の手順で1つ以上のファイルあればそれらを使用し、ビルドシステムは検索を停止
    5. .overlay があればそれを使用し、ビルドシステムは検索を停止
    6. app.overlay

CMake 変数 DTC_OVERLAY_FILE には、空白かセミコロンで区切って複数の .overlay ファイルを並べることができます。
相対パスで指定した場合はアプリコンフィグディレクトリ配下を意味します。
1 の はボード修飾子を先に述べた変換規則に従って変換した文字列です。
ただし SoC 部はすでに示されているので、CPU cluster 部以下となります。例によって省略可能なようです。
<以上の結果選ばれた DTS ファイルがすべてマージされて、最終的な DTS ファイルが作成されます。
それは構築ディレクトリ配下の zephyr/zephyr.dts に出力されます。

また、C マクロ定義が同配下の
zephyr/include/generated/zephyr/devicetree_generated.hに出力されます。
その内容は が定義する C マクロ API(たとえば、前出の DT_NODELABEL() など)を通して参照されます。

以上から、アプリディレクトリ配下にboards/mimxrt1170_evk_mimxrt1176_cm7.overlay という名のファイルを作成すればよさそうです。
または、リビジョン B がデフォルトなので、boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay としてもよいです。

アプリに DTS ファイルを追加まとめ

  1. DTS ファイルのファイル名はボードターゲットから決まります。
  2. 最終的な DTS ファイルはボードディレクトリの .dts とアプリディレクトリの .overlay をマージして取得します。
  3. example_sensor ノードと blink_led ノードを定義するためにアプリディレクトリ配下に ファイル boards/mimxrt1170_evk_mimxrt1176_cm7.overlay を作成します。その内容は次節にて解説します。

補足: Kconfig コンフィグ設定

ソースコードの構成がデバイスツリーでもできることは、Zephyr の特徴のひとつといえるでしょう。

ここではもう一つのソースコードの構成方法、Kconfig コンフィグについて簡単に説明します。
本項は https://docs.zephyrproject.org/latest/build/kconfig/setting.html#the-initial-configuration をベースにしています。

デバイスツリーと Kconfig コンフィグの使い分け方はhttps://docs.zephyrproject.org/latest/build/dts/dt-vs-kconfig.html#devicetree-versus-kconfig に詳細があります。

簡単にいえば、

  • ハードウェアの構成はデバイスツリー
  • ソフトウェアの構成は Kconfig

ということになります。

ソースコードの構成という目的からは、どちらかがあればよいわけですが、このように分けておくことは意義があり、Linux kernel と同じ使い分けをするものと推測します。 ただし、例外事項があります。

Kconfig はデバイスツリーに比べて記述力が弱いので、それを補うためなら、ソフトウェアのことであってもデバイスツリー側で設定してもよいことになっています。
たとえば、ドライバが内部で使用するバッファのサイズなどです。

そのような目的のプロパティ名には zephyr, を接頭することになっています。
Kconfig コンフィグ設定も、デバイスツリー同様、複数のソースから作成されます。
それは次の 3 種類です(この並び順で優先順位が高くなります)。

  1. _defconfig ファイル
  2. CMake キャッシュ変数で CONFIG_ で始まるもの
  3. アプリコンフィグ

同じ CONFIG シンボルが複数回設定されているときはより優先順位の高いほうが採用されます。

この構成の仕方はデバイスツリーの場合と同じです。ボードディレクトリが基礎を提供し(1. の _defconfig)、アプリディレクトリがその修正を提供する(3. のアプリコンフィグ)、となっています。
_defconfig のほうは容易に想像できると思うので、アプリコンフィグについて説明します。

アプリコンフィグディレクトリ配下には .conf をサフィックスとするファイルがいくつか存在します。
これを Kconfig フラグメント (fragment) といいます。
アプリコンフィグ とは、Kconfig フラグメントファイルの中から次に述べる規則に従って選択されてマージされたものをいいます。
該当する項目があった時点で、ビルドシステムは検索を停止します。

  1. CONF_FILE 変数がセットされていれば、それらのファイルをすべてマージ。
  2. アプリコンフィグディレクトリ配下を次の順序で調査。
    1. boards/.conf ファイルが存在すれば、prj.confとマージ。
    2. ボードリビジョンが使用されていて boards/_.conf ファイルが 存在すれば、prj.conf, boards/.conf とマージ。
    3. prj.conf が使用される。prj.conf が存在しないときは致命的エラーとなる。

要約すれば、CONF_FILE 変数が設定されていればCONF_FILE 変数がが、設定されていなければアプリに固有のprj.conf にボードに固有の Kconfig フラグメントファイルをマージしたものが、アプリコンフィグとなります。

なお CONF_FILE 変数は CMake 変数のほかに環境変数としても設定することができます
https://docs.zephyrproject.org/latest/develop/application/index.html#important-build-system-variables 参照)。
空白かセミコロンで区切って複数の Kconfig フラグメントファイルを並べることができます。
相対パスの場合はアプリコンフィグディレクトリ配下を意味します。

以上の結果が構築ディレクトリ配下の zephyr/.config に出力されます。
これを初期コンフィグ (initial configuration) といいます。
初期コンフィグは menuconfig や guiconfig を使って編集することができます。

Yocto Project 公式実践講座 10 月 ~ 12 月 開催分 受講お申込み受付中!
Vigiles サポート
Yocto Project よもやま話
Yocto よもやま話 第 19 回 「Yocto Project 5.3 Whinlatter」
Yocto よもやま話 第 19 回 「Yocto Project 5.3 Whinlatter」

2026 年 02 月 09 日 Yocto Project よもやま話

Yocto よもやま話 第 18 回 「Yocto Project 5.2 Walnascar」
Yocto よもやま話 第 18 回 「Yocto Project 5.2 Walnascar」

2026 年 02 月 09 日 Yocto Project よもやま話

Yocto よもやま話 第 17 回 「Yocto Project 5.1 Styhead」
Yocto よもやま話 第 17 回 「Yocto Project 5.1 Styhead」

2026 年 02 月 09 日 Yocto Project よもやま話

Linux 技術ネタ
RISC-Vについて学ぶ-後編
RISC-Vについて学ぶ-後編

2024 年 01 月 10 日 Linux 技術ネタ

RISC-Vについて学ぶ-前編
RISC-Vについて学ぶ-前編

2023 年 12 月 12 日 Linux 技術ネタ

イベントレポート
EdgeTech+ West 2026 出展レポート
EdgeTech+ West 2026 出展レポート

2026 年 08 月 05 日 イベントレポート

EdgeTech+ 2025 出展レポート
EdgeTech+ 2025 出展レポート

2025 年 12 月 01 日 イベントレポート

EdgeTech+ West 2025 出展レポート
EdgeTech+ West 2025 出展レポート

2025 年 08 月 08 日 イベントレポート

リクルート
新卒採用、絶賛募集中!
新卒採用、絶賛募集中!

2025 年 04 月 01 日 リクルート

新卒採用、絶賛募集中!
新卒採用、絶賛募集中!

2023 年 05 月 30 日 リクルート

信州リネオ便り
第78回 諏訪湖祭湖上花火大会をレポート
第78回 諏訪湖祭湖上花火大会をレポート

2026 年 08 月 19 日 信州リネオ便り

松本市のアジサイ寺散策(法船寺・弘長寺)
松本市のアジサイ寺散策(法船寺・弘長寺)

2026 年 07 月 01 日 信州リネオ便り

新たな信州土産を入手しました
新たな信州土産を入手しました

2026 年 05 月 25 日 信州リネオ便り

ソリューション統括部
Zephyrブログ 第五回 「Zephyr アプリに挑戦(中編)」
Zephyrブログ 第五回 「Zephyr アプリに挑戦(中編)」

2026 年 09 月 04 日 ソリューション統括部

Zephyrブログ 第四回 「Zephyr アプリに挑戦(前編)」
Zephyrブログ 第四回 「Zephyr アプリに挑戦(前編)」

2026 年 08 月 07 日 ソリューション統括部

Zephyrブログ 第三回 「LCD に表示してみる」
Zephyrブログ 第三回 「LCD に表示してみる」

2026 年 05 月 26 日 ソリューション統括部

マーケティング統括部
大成功決起大会!!(ET2019)
大成功決起大会!!(ET2019)

2019 年 12 月 13 日 マーケティング統括部

ESEC 2019 決起大会
ESEC 2019 決起大会

2019 年 04 月 25 日 マーケティング統括部

シリコンバレー探検記 その 2
シリコンバレー探検記 その 2

2018 年 12 月 18 日 マーケティング統括部