別記事で予告だけして書けてませんでしたが、今回は、Jetson Nano上でのカーネルの再構築(Device Treeの更新も含む)の方法をまとめておきます。
ちなみに、今回、NVIDIA Jetson Linux Driver Package (L4T) のバージョンは、2021/8/3にリリースされた32.6.1をベースに記述します。
ソースファイルのダウンロードと展開
[Manually Downloading and Expanding Kernel Sources]
(https://docs.nvidia.com/jetson/l4t/#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/kernel_custom.html#wwpID0E0LD0HA)
に従って、手動でソースファイル一式をダウンロード。
ソースファイル一式のファイル名は、public_sources.tbz2。
$ tar -xvjf public_sources.tbz2
などと展開。そして、カーネルのソースは、kernel_src.tbz2というファイル名で、Linux_for_Tegra/source/publicに置かれているので、それも展開。
カーネルのビルド作業
[Building the NVIDIA Kernel]
(https://docs.nvidia.com/jetson/l4t/#page/Tegra%20Linux%20Driver%20Package%20Development%20Guide/kernel_custom.html#wwpID0E06C0HA)
に従ってカーネルのビルド作業。上記のページの対応を書くと、
- ツールチェインのインストール(To build the Jetson Linux Kernelの2.)
- 環境変数の設定(To build the Jetson Linux Kernelの1.など)
- ビルド実行(To build the Jetson Linux Kernelの3.と4.)
- インストール領域へのコピー(To build the Jetson Linux Kernelの5.と6.と7.)
という感じ。ツールチェインのインストールは、Jetson Nano上でビルドする場合は必要なし。
環境変数の設定
export LOCALVERSION=-tegra
export DTB=tegra210-p3448-0000-p3449-0000-b00.dtb
LOCALVERSIONの指定は、指定しないと、4.9.253などというバージョン番号だけになる、LOCALVERSION=-tegraとすると4.9.253-tegraとなる、というだけで別に必須ではない。
DTBは、下での作業で楽になるように設定しているだけで、長いファイル名をタイプすることを気にしないならば必要なし。
これらの環境変数の設定は、例えば、build_setup.shに上記のような環境変数一式の設定を記述しておいて、sourceコマンドにて実行する。
ビルド作業
$ cd (kernel-4.9のディレクトリ)
$ source build_setup.sh
そして、いよいよ、カーネルのビルドの実行。
まずは、カーネルのコンフィグの初期化。
$ make tegra_defconfig
ARCH=arm64は、セルフビルドの場合は必要なし、O=$TEGRA_KERNEL_OUTも、現在のディレクトリの直下にビルド結果を出力してよいならば指定する必要なし(逆に、別のディレクトリに出力したければ指定可能)。
既に実施すべきカーネルのカスタマイズがあるのならば、その対応をここで実施。
例えば、新規のドライバのソースファイルの追加、Makefileの編集、など。
また、.configも編集。
現在のカーネルをベースにコンフィグを変更したい場合は、
$ gzip -d -c /proc/config.gz > .config
で.configを生成してから編集。
そして、以下のように、コンフィグ、ビルド、と作業を進める。
$ make oldconfig
$ make -j4
ここまでで、カーネル、Device Tree、モジュール、などが一式生成される。
そして、以下は、上記のビルド作業で生成された成果物(カーネル、Device Tree、ドライバ)を一式、インストール領域にコピーする作業。
この部分、NVIDIAのサイトの記述(To build the Jetson Linux Kernelの5.と6.と7.)はちょっと分かりにくい。要するに、この後の、flash.shの実行に備えて、カーネルイメージはkernel/Imageに、Device Treeファイルはkernel/dtb/に、modulesは、ターゲットのrootファイルシステム内のlib/modulesに、それぞれコピーする、ということ。なので、Jetson Nano本体でビルドしている場合は、以下のように、直接、/boot/にコピーなどすればよい。
$ sudo make modules_install
$ sudo cp -p arch/arm64/boot/Image /boot/
$ sudo cp -p arch/arm64/boot/dts/$DTB /boot/
$ sudo cp -p arch/arm64/boot/dts/$DTB /boot/dtb/
ここで、/boot/dtb/などにコピーしているDevice Treeのファイルだが、ここにコピーしておけば、Jetson-IOによってそれをベースに上書きして使用することができるようなので、このファイルコピーも追加で実行している。逆に言うと、/boot/にコピーするだけで更新されるわけではない、ということのようである。
Device Treeの更新の手順は次で示す。
Device Treeの更新
Jetson-IOを用いたDevice Treeの更新方法を紹介する。
sudo /opt/nvidia/jetson-io/jetson-io.py
ここで、デフォルトのままのターミナルだと、ちょっと縦の長さが短くて、jetson-ioの表示がすべてうまく表示されない、というしょうもないお話がありますので、ターミナルの縦方向をある程度延ばした上で実行するとよいでしょう。
そうすると、
Select one of the following:
Configure Jetson 40pin Header
Configure Jetson Nano CSI Connector
Configure Jetson M.2 Key E Slot
Exit
などと、4つの選択肢から選択するように言われますので、上下キーで一番上の、「40ピンのヘッダーをコンフィグする」を選択し、次に現れる、
Jetson 40pin Header:
Configure for compatible hardware
Configure header pins manually
Back
から、2番目の「ヘッダピンを手動でコンフィグする」を選択します。
すると、40ピンに対して、使いたいものを有効無効にする画面が表示されますので、そこで、なにか有効にしたい機能があれば、その行にカーソルを合わせて、Enterを押すと、[*] とマークを付けることができます。
上記のようにして、ヘッダピンの各ピンの[*]のマークを変更してBackしてくると、
Export as Device-Tree Overlay
Save pin changes
Discard pin changes
の選択肢が現れるので、ここで、「ピンの変更を保存する」を選択して、またここで現れる選択肢、
Save and reboot to reconfigure pins
Save and exit without rebooting
の中から、「保存して再起動する」を選択すると、出力されたDevice Treeファイルが表示されつつ、リブートできる。
別にヘッダピンを使いたいわけではない、という人にも、このJetson-ioを紹介しているのは、これを使うと、Linux PCからSDK Managerあるいはそれに含まれるflash.shを使用して、Jetson NanoをForce Recoveryモードに入れて起動して、、みたいな作業を行う必要がなく、Device Treeを更新することができる、ということ。
ヘッダピンの機能を変更しない場合は、Jetson-IOはDevice Treeを更新することができないようなので、ダミー的に、2度変更しながらDTBファイルをカスタマイズすることにより、更新できる。
その他
以上が、Jetson Nano上で自分のカーネルをカスタマイズする方法でした。Ubuntu PCなどのクロス環境での方法は別記事で書いています。
「Device Treeの更新」の部分の日本語が、「ちょっと何を言っているかわからない」と思う人は、質問受け付けます。^^