JETSON TX1が来てやったこと（３日目）

今日はKernelビルドについて調査を進めます。

#Road to kernel build
ひとまず、Development Guideの「Getting Started」の通りに作業を進めます。
Linuxは不慣れなもので、何から手を付けたら良いのか全く分からず……
「Building the NVIDIA Kernel」という項だけ読めば良いような気もしますが
Linuxに慣れるため、お勉強も兼ねてページの先頭から順にこなして行きます。

#ルートファイルシステムの構築サンプル
手順に書いてある通り、`DriverPackage`や`SampleFileSystem`をダウンロードして適切な場所に解凍していきます。
ダウンロードする物が多すぎて、何が何だか分からなくなってきたぞ……
あとはスクリプトを2個流すだけで、TX1が再インストールされます。簡単！
1. `sudo ./apply_binaries.sh`を実行すると、Nvidiaのユーザー空間ライブラリ（要はソースコードが公開されない、プロプライエタリなライブラリの事？）がコピーされる。[前回の記事](http://qiita.com/threecups/items/6207d8e9552b2a64b4fc)に書いた`nvcamerasrc`ってのも、多分ココでコピーされてる
2. `sudo ./flash.sh jetson-tx1 mmcblk0p1`を実行すると、ルートファイルシステムがTX1に転送されるっぽい。あとブートローダーの設定とかそういう諸々

Boot Optionsで色々設定すれば、「システムファイルを何処に置くか」というのを選択出来るようです。
USB、SD、Networkなど、色々選べるようですがひとまず内蔵eMMCを選択しています。
これで昨日までの設定やら何やらが全部消えて、３度手間になっちゃうんだなぁ……やむを得ず

転送完了後TX1を再起動すると、当然というべきかOSが初期状態に戻っているようです。
一応、動作確認として例のGstreamコマンドを打ってみたところ、問題なくカメラ画像が表示されました。
確認用コマンド`sha1sum -c /etc/nv_tegra_release`も問題なく動作（`**** : OK`というログが何行か表示される）

#いざかMakeら
さて、ここからが本題
ようやく「Building the NVIDIA Kernel」の項まで進んだので、いよいよカーネルのビルドを試みます。
と意気込んだところに早速出たーMakefile特有の長い環境変数ー！！
`export CROSS_COMPILE=<crossbin>`
`export CROSS32CC=<cross32bin>gcc`
`export TEGRA_KERNEL_OUT=<outdir>`
`export ARCH=arm64`
VisualStudioの開発環境に慣れている人はきっと一目見ただけで拒絶反応を起こすと思うんだ……

※WindowsのPATH環境変数もゴミ仕様だとは思いますけどね
（いや、憎むべきはPATH環境変数を使う前提で書かれたプログラムの方か……）
開発用PCなんて、PATH変数が長すぎて新しいツールがインストールできないとか、タスクバーの表示がバグるとか
いろいろと不具合が出始めてるからね……
シンボリックリンクを活用してはいるけど、それでも限度ってものがある
（参考：[WindowsのPATHが長すぎる件](http://sceneryandfish.withnotes.net/?p=1982)）

っと、話を本題に戻しましょう。
下の2行は普通に読めます
`export TEGRA_KERNEL_OUT=<outdir>`とは、ビルド結果の出力先を定義するだけ
`export ARCH=arm64`とは、ターゲットのプラットフォームを定義しているだけでしょう
問題は上の2行なんだけど……何だこれは
コンパイラのパスを指定しているんだろうということは分かりますが、何このコンパイラ？
Linaroって名前だけは聞いたことあるけど、apg-getで取ってくるの？
そもそも初日にインストールした開発環境？（Jetpack for L4T）に入ってないの？
入ってるとしたら何処にあるの？（Windowsユーザー特有の、フォルダ構成わからない問題）
→参考：[WindowsのあのフォルダはUNIX/Linuxで言えばあそこだ](http://qiita.com/yuba/items/669f718fe6e62dbaab19)

色々と分からない事が出てきましたが、フォーラムの見よう見まねで「[Linaro tool chain](https://releases.linaro.org/components/toolchain/binaries/latest-5/)」というのをインストールしました。
窓の杜とかと違って分かりにくいんだけど、ディレクトリを潜りながら
- `aarch64-linux-gnu/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu.tar.xz`
- `arm-linux-gnueabihf/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf.tar.xz`
という2つのファイルをダウンロード、`/opt/linaro`に解凍する……で、合ってる？
ここまで来たら、環境変数の設定も問題なく出来るはずです。
最終的に、上の2行はこんな形で収まりました。
`export CROSS_COMPILE=/opt/linaro/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-`
`export CROSS32CC=/opt/linaro/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc`

>
余談ですが、Tegra X1は半精度浮動小数点数による演算をサポートしているようです。
開発環境にチョクチョク出てくる「hf」ってprefixは、「half floating point」の略だと思います。
TK1の記述を色々引きずってるのか、「何か微妙に違くね？」って場面に出くわすことが多いです。

あとは以下のコマンドを打ち込めば、カーネルのビルドが始まります。
`make O=$TEGRA_KERNEL_OUT tegra21_defconfig`
`make O=$TEGRA_KERNEL_OUT zImage`

#コンパイルエラーーーー
おや、ガイダンス通りにすすめてきたのにコンパイルエラーで止まりますね？
どうやらLinaro tool chainのバージョンが上がってからエラーが出るようです。
（HPからダウンロードしたソースでも、gitからcloneしてきたソースでもダメでした）
[フォーラム](https://devtalk.nvidia.com/default/topic/901677/building-tx1-kernel-from-source/)を参考にしながら、エラーを潰していきましょう。

`error: r7 cannot be used in asm here`と言われる問題については
`Makefile`の379行目辺りに
`KBUILD_CFLAGS_KERNEL :=` と書いてあるので
`KBUILD_CFLAGS_KERNEL := -fomit-frame-pointer` と書き足します。

`logical not is only applied to the left hand side of comparison`と言われる問題については
`drivers/platform/tegra/tegra21_clocks.c`の1065行目辺りに
`c->state = (!is_lp_cluster() == (c->u.cpu.mode == MODE_G)) ? ON : OFF;` と書いてあるので
`c->state = ((!is_lp_cluster()) == (c->u.cpu.mode == MODE_G)) ? ON : OFF;` と修正します。（括弧を追加）

そうするとコンパイルが通るようになるので、続けてコマンドをポチポチと……
`make O=$TEGRA_KERNEL_OUT dtbs`
`make O=$TEGRA_KERNEL_OUT modules`
`make O=$TEGRA_KERNEL_OUT modules_install INSTALL_MOD_PATH=<your_destination>`
`<your_destination>`というのはよく分からなかったので、とりあえずKERNEL_OUTで指定したフォルダの隣に「modules_out」というフォルダを作成

再ビルドする場合は、一旦cleanしろと言われるので以下のコマンドを打ちます。
`make mrproper`
`make O=$TEGRA_KERNEL_OUT mrproper`

#ビルド完了……？
以上の処理が終わる頃には、`TEGRA_KERNEL_OUT`に指定したフォルダ内に、いろんなファイルが出来あがります。
んだけど、次の手順が
`6. Copy both the uncompressed (Image) and compressed (zImage) kernel images over the ones present in the ‘kernel’ directory of the release.`
ｱｲｴｴ!? Image? zImageﾄﾞｺ!?
見当たらないので、`find`コマンドで探しますと、`arch/arm64/boot/`にImageとzImageが見つかりました。
コレを`Linux_for_Tegra/kernel/`に上書きして再度`./flash.sh`スクリプトを走らせれば良いのでしょうか？
デバイスツリー（`dtb`フォルダ）も上書きする必要があると思うんですがどうなんでしょう？
キャベツ（`make modules_install`の出力ファイル）はどうした！？

`7. Archive the kernel modules created in Step 4 using the tar command and the filename that is used for the kernel modules TAR file in the same kernel directory of the release. When both of those TAR files are present, you can follow the instructions provided in this document to flash and load your newly built kernel.`
↑この手順にある「Step 4」は「Step 5」の誤植なんでしょうか？

指南書通りにコマンド打ち込んでるだけなので何が起きてるのかは全く理解できていませんが
ひとまず「何かビルドできたっぽい」ところまで進みました。続きはまた明日！！