#1.はじめに
ARM CPUを内蔵するFPGAをLinuxで動作させているうちに、デバイスツリーだけでなく、デバイツリー オーバーレイという仕組みを使うと良いことがあること分かりました(FPGAをコンフィグレーションできるとか)。
デバイツリー オーバーレイの使い方について調べてみた内容を書かせていただきます。(主にFPGAのLinuxを開発している人向け, 実機での動作確認はIntel系のFPGAでのみやっております:DeviceTree Overlay でのFPGAコンフィグ(DE10nano) )。
なお、ここでは「デバイスツリー」についての内容は含みません。そちらについては別の資料ををご覧ください( デバイスツリーについて調べてみた もあります)。
Devicetree Overlay でできること
Kernelは、起動時にbootloaderから指定されたデバイスツリーを読み込みます(base tree)。通常は、デバイスツリー情報は再起動しない限り変更はできないのですが、デバイツリーオーバーレイを使えば、base treeの内容に対し、
- node(=デバイス)の追加
- propertyの追加
- propertyのvalue変更
といったことが再起動なしできるようになります。
オーバーレイする内容は、オーバーレイファイルで記述し、そのファイルを読み込むことで実施されます。オーバーレイファイルは、複数読み込むことも可能です。
また、オーバーレイした内容は、オーバーレイファイル単位で削除することが可能となり、そのオーバーレイファイルを読み込む前の状態に戻すこともできるようになってます。
オーバーレイファイルを読み込んだり、削除したりすることでデバイスツリーの内容が変化しますが、その点でのデバイスツリーの内容は、live treeと呼ばれます。デバイツリーオーバーレイが実行されてなければ、live tree = base tree です。
Devicetree Overlay ファイルの書き方
デバイスツリーオーバーレイファイルも、テキストソースとバイナリがあり、デバイスツリーと同じくdtcでコンパイルします。デバイスツリーファイルと区別するため、ここではオーバーレイソースの拡張子を.dtso, オーバーレイバイナリの拡張子を.dtboとしてます。
必要最小限度のオーバーレイファイルは以下です。
/dts-v1/;
/plugin/;
/ {
fragment@0 { /* node名は何でも良い */
target = <phandle>; /* overlayするnodeの phandle */
/* もしくは */
target-path="/path"; /* overlayするnodeの path */
__overlay__ {
/* オーバーレイする property 定義 たち*/
/* オーバーレイする node 定義 たち*/
};
};
};
必要な内容はシンプルで、
- 冒頭の /dts-v1/; の後に
/plugin/;
- ルートnode
- ルートnodeの子node。 nodeの名前は何でも良い
- 子node に
target
(もしくはtarget-path
)propertyと__overlay__
nodeを持たせる-
target
ortarget-path
propertyで、オーバレイ対象となるnodeを指定-
target
ではphandleで指定(もしくはラベル) -
target-path
ではpath stringで指定
-
-
__overlay__
node 内に具体的にオーバーレイする内容を記述- 追加したいpropertyやnodeたちを定義する
-
となります。冒頭の /plugin/;
は、オーバーレイファイルの記述中に、過去に読み込んだデバイスツリー(live tree)で定義したlabelを参照できるようにするためのものです。例えば、target
のvalueとしてbase treeで定義されているラベル名を使えるようになります(オーバーレイファイル中にこのファイル内で定義されていないラベルがあってもdtcでエラーとならない)。
ただし、base tree が、dtcでのコンパイル時に.dtbにシンボル情報も含めるよう -@ オプションが付けられている必要があります(FPGA用のGitリポジトリにあるKernel Sourceでmakeした .dtb なら -@ 付でコンパイルされていると思います)。
Devicetree Overlayの実行方法
FPGAベンダがメンテナンスしているのGitリポジトリのKernel SourceにはConfigFsというドライバ入っており、デフォルトで使えるようになっています(参考資料1,2より)のでこの仕組みを使っていきます。
残念ながら、ユーザーランド(ユーザーコマンドやアプリケーション)からOverlayを行う方法は、現時点ではMainline Kernelに取り込まれていません(5.7.0-rc6)。Overlayを行うKernel driverを自分で書く必要があります。configfsの仕組みだとどんなDvicetree nodeでも任意のタイミング書き換えられてしまうので、そのようなことを想定していないドライバで問題が起こる...といった問題が挙げられている様で。Mainlineに入るのはもう少し時間がかかりそうです。
以下、デバイスツリーオーバーレイ用のconfigfsのpathを $OVL_PATH とします。
X系: OVL_PATH=/configfs/device-tree/overlays
I系: OVL_PATH=/sys/kernel/config/device-tree/overlays
(X系では、mkdir /configfs; mount -t configfs configfs /configfs
を事前にしておく必要ありそうな)
オーバレイ実施
次のの2つのステップで実行されます。
- $OVL_PATH ディレクトリ下に任意の名前でディレクトリを作る。
- 作成したディレクトリ下に自動的に dtbo ファイルが生成されるので、その dtbo ファイルに自分のオーバレイファイル(.dtbo)を書き込む。
my_overlay1_dir ディレクトリを作り、my_overlay1.dtbo というオーバーレイファイル読み込ませる例は以下となります。(root ユーザでの実行を想定してます)
# mkdir $OVL_PATH/my_overlay1_dir
# cat my_overlay1.dtbo > $OVL_PATH/my_overlay1_dir/dtbo
オーバーレイ削除
削除は1ステップで実行されます。
- オーバーレイ用に生成した $OVL_PATH ディレクトリ下のディレクトリを削除する
上の例でオーバーレイした内容を削除する場合は、
# rmdir $OVL_PATH/my_overlay1_dir
その他の機能
オーバーレイ用に作成したディレクトリ下には、dtbo
以外に path
, status
というファイルが自動で生成されます。
path
は、dtbo
と同様にオバーレイ実施を行えるインターフェースですが、/lib/firmware/ 下に置いたオーバーレイファイルを読み込むもので、以下のコマンドにより /lib/firmware/の下にある abc.dtbo でオバーレイを行います。
# echo "abc.dtbo" > $OVL_PATH/my_overlay1_dir/path
status
は、オーバーレイ用ディレクトリの状態を知ることができるインターフェースで、cat することでこのディレクトリの dtboもしくはpath を使ってオーバーレイが実施されているかを知ることが可能です。
# cat $OVL_PATH/my_overlay1_dir/status
/*applied か unapplied がprint される*/
参考資料
参考資料1: Solution Zynq PL Programming With FPGA Manager
参考資料2: Rockeboards.org HowToCreate a DeviceTree
FPGA+SoC+LinuxでDevice Tree Overlayを試してみた :@ikwzm さんの記事、いつも参考にさせていただいておりますm(--)m