デバイスツリーの読み方・書き方
組み込みLinux開発で、独自のハードウェアをOSが正しく認識するための要となるのが「デバイスツリー」です。OSを使用しないベアメタル開発からLinux環境へ移行した際、C言語のソースコード内にハードウェア情報を直接書き込めないことに戸惑うエンジニアは少なくありません。
デバイスツリーは、既存のソースコードを「読み解き」、要件にあわせて「上書き(オーバーライド)」するのが実務での基本スタンスです。本記事では、中級エンジニアに向けて、dts/dtsiファイルの基本構造から、実務で必須となるプロパティの書き方、Yocto環境でのカスタマイズ、そして実機での確認方法までを解説します。
- デバイスツリーの書き方入門:dts/dtsiの基本構造と構文ルール
- 実務で必須となる標準プロパティとハードウェア定義の書き方
- 既存環境を安全に変更する「デバイスツリー・オーバーレイ」
- 実機(Linux上)でのデバイスツリーの表示と確認方法
デバイスツリーの書き方入門:dts/dtsiの基本構造と構文ルール
デバイスツリーを正しく書くためには、まずその役割と基本的な構文ルールを理解する必要があります。
デバイスツリー(Device Tree)とは何か
デバイスツリーとは、ハードウェアの構成情報(メモリの番地、割り込み番号など)をソースコードから切り離し、データ構造としてカーネルに渡す仕組みです。従来は基板ごとのハードウェア情報をC言語のソースコードに直接記述(ハードコード)していましたが、カーネルソースコードが肥大化する問題がありました。この問題を解決するため、ハードウェア情報を独立したテキストファイルで定義し、OS起動時に読み込むアーキテクチャが採用されています。
dts/dtsiファイルの場所と関係性
デバイスツリーは主に2種類のファイルで構成され、共通定義を取り込み、ボード側で差分を追加・上書きするような関係性を持ちます。
- .dtsi(インクルードファイル):SoC(System on a Chip)メーカが提供する、CPU内蔵ペリフェラルなどの共通定義ファイルです。
- .dts(ソースコードファイル):基板固有の設定(LEDやセンサの追加など)を記述するファイルです。先頭で.dtsiをインクルードして使います。インクルードの記述は /include/ "xxx.dtsi" が基本ですが、Linuxカーネルなど、ビルド時にCプリプロセッサを通す環境では #include が使われる場合もあります。
これらのファイルは、Linuxカーネルソースコードツリー内のアーキテクチャごとのディレクトリ(例:arch/arm/boot/dts/やarch/arm64/boot/dts/)に配置されています。
ノードとプロパティの基本的な記述ルール
デバイスツリーは、ルートノード(/)を頂点とした階層的なツリー構造で記述します。各ハードウェアブロックは「ノード」として定義し、ノード名@アドレス{ ... };という規則で命名されます。ノードの中には、ハードウェアの具体的な設定を示す「プロパティ」を「キーと値」のペアで記述します。値には文字列、数値(<>で囲む)、配列などを使用します。
エイリアス(aliases)とラベルによる参照方法
実務でよく使われるのが「ラベル」を使った上書きテクニックです。SoC共通の.dtsiファイルで定義されたノードに対し、label:node@addressのようにラベルを付けておきます。基板固有の.dtsファイルでは、ツリーの階層をたどるかわりに&label{ ... };と記述することで、特定のノードだけをピンポイントで参照・上書きできます。また、aliasesノードを利用すると、/soc/serial@12340000のような長いパスをserial0といった短い名前に置き換えられ、アプリケーション側からのアクセスが容易になります。
実務で必須となる標準プロパティとハードウェア定義の書き方
次に、デバイスが動作するために最小限必要となる標準的なプロパティを解説します。
デバイスを認識させる「compatible」と「status」
ハードウェアを動かすうえで特に重要なのが以下の2つです。
- compatible:「このハードウェアを制御するには、どのデバイスドライバを使えばよいか」をカーネルに伝えるプロパティです。"ベンダ名,デバイス名"の形式で記述します。
- status:デバイスの有効/無効を切り換えます。実務では、共通の.dtsi側でstatus = "disabled";となっている機能を、自社ボード用の.dts側でstatus = "okay";と上書きして有効にするパターンが基本です。
メモリアドレスを指定する「reg」プロパティ
regプロパティは、デバイスが使用するレジスタのアドレスとサイズ(範囲)を指定します。書き方は親ノードの設定に依存しており、親ノードで定義された#address-cells(アドレスを何個の32bit値で表すか)と#size-cells(サイズを何個の32bit値で表すか)の数値に従って記述する必要があります。
- I2Cなどのバス配下デバイスは reg が「バス上のアドレス」のみを表すケースが多いです。
ピンマルチプレクス(pinctrl)の設定方法
組み込みマイコンでは、用途にあわせてピンの機能(GPIO、I2C、SPIなど)を切り換える「ピンマルチプレクス」が採用されています。デバイスツリーでは、pinctrl-names = "default";およびpinctrl-0 = <&特定のピン設定ラベル>;と記述することで、そのデバイスを使用する際にピンの機能を自動的に切り換えられます。
サウンドデバイスなど特定ハードウェア機能の定義例
実務では、データシートを読み解きながらノードを追加します。以下はI2C接続のオーディオコーデックを追加する際の実践的な記述例です。
DTS
&i2c1 {
status = "okay";
/* I2Cアドレス 0x0a にオーディオコーデックを定義 */
audio_codec: codec@0a {
compatible = "vendor,audio-codec";
reg = <0x0a>;
/* 割り込みピンの指定 */
interrupt-parent = <&gpio1>;
interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
};
};
- 実際の compatible 文字列は、使用するデバイスのデータシートまたはカーネルの DT バインディングで確認してください。
既存環境を安全に変更する「デバイスツリー・オーバーレイ」
デバイスツリーでは、動的なハードウェア構成の変更が求められる場合もあります。「デバイスツリー・オーバーレイ」は、既存環境を変更する際に役立つ方法の一つです。
オーバーレイ(Overlay)の仕組みとメリット
通常、デバイスツリーは起動時に一度だけ読み込まれます。しかし、「デバイスツリー・オーバーレイ(.dtbo)」という仕組みを使えば、ベースとなるツリー(.dtb)を再コンパイルすることなく、差分の追加・変更が可能です。ブートローダがオーバーレイの読み込みに対応している、またはLinux側でオーバーレイ適用機構を有効化しているなど、システムが対応していれば、OS起動後やブートローダの段階で動的に適用できます。
「デバイスツリー・オーバーレイ」はシングルボードコンピュータ(SBC)向けの拡張ボード(HAT)などで、接続された基板に応じてピン設定を自動変更する際によく使われる強力な技術です。
Yocto Project環境でのデバイスツリーのカスタマイズ手順
実務で標準となっているYocto Project環境では、ベースのカーネルソースコードを直接編集するのは不適切です。かわりに、自社用のメタ層(metaレイヤ)に linux-yocto_%.bbappend のような追加レシピを作成します。そこにデバイスツリーのパッチファイル(.patch)や独自の.dtsファイルを配置して SRC_URI に追加し、カーネルソースコードへ反映させます。さらに、必要に応じてビルド対象となるDTB(例:KERNEL_DEVICETREE)を設定することで、ビルド時に自動でカスタマイズが適用されるように構成します。
実機(Linux上)でのデバイスツリーの表示と確認方法
自分が書いたデバイスツリーが正しくコンパイルされ、実機で認識されているかを確認する手法を紹介します。
dtbファイルへのコンパイル(dtcコマンド)
テキスト形式の.dtsファイルは、OSが読み込めるバイナリ形式の.dtbファイルへ変換する必要があります。変換に使用するのが「Device Tree Compiler(dtcコマンド)」です。コンパイルは「dtc -I dts -O dtb -o output.dtb input.dts」のように実行します。逆に、実機から取り出した.dtbファイルをテキストに逆コンパイル(dtc -I dtb -O dts -o output.dts input.dtb)することもでき、実際にカーネルにどのようなツリーが渡されているかを確認するトラブルシューティングに役立ちます。
/proc/device-treeを用いたシステム上での反映確認
Linuxが起動した後、カーネルが読み込んだデバイスツリーの最終的な状態は、仮想ファイルシステムを通じて直接確認できます。起動後の反映確認は /proc/device-tree/(/sys/firmware/devicetree/base/ へのシンボリックリンク)でおこなうことが一般的です。ディレクトリに移動すると、ツリー構造がそのままディレクトリとして表現されていることがわかります。たとえば、cat statusやhexdump -C regといったコマンドを実行することで、自分が記述したプロパティの値がシステム上で正しく認識・反映されているかを容易に検証できます。※これらの仮想ファイルシステムからの情報取得は、主にデバッグおよび確認用途として利用されます。


