「Raspbian OS」という名前が「Raspberry Pi OS」という名前に変更になりました。
また、クロスコンパイルするためのモジュールについても、Debian系の標準のものを使用するようになった感じになりました。
以上を踏まえて、ラズパイのカーネルに再構築(リビルド)する手順について説明していこうと思います。
既にビルドされたRaspberry Pi OS (旧RaspbianOS)のイメージをインストールして起動することは簡単にできますが、
カーネルソースからビルドしてイメージを作成するのは以外と手間がかかります。
しかし、自分で作成したデバイスドライバをカーネルイメージ内に組み込むために必要なので、
組み込み系の勉強をしたい方にとっては、カーネルビルドは始めの第一歩目の勉強になります。
基本的な流れは、GitでRaspberry Pi OSのカーネルソースをダウンロードして、
クロスコンパイルするための環境設定後、 カーネルをビルドします。
このやり方は、 Kernel building - Raspberry Pi Documentationに書かれているのですが、
Linuxのカーネルビルドをしたことがない方はハマると思います。
私も久しぶりにカーネルビルドをしましたので、少しハマりました。
それでは、Raspberry Pi OSのカーネルをビルドしてラズパイで起動確認するまでの手順を書いていきたいと思います。
1.ビルドマシンなどの使用環境
私がビルドに使ったマシンやラズパイなどの環境は、下記になります。
・ビルドPCのスペック:デスクトップ型、CPUはCore i7-2600 3.8GHz、RAMは8GB
・ビルドPCのOS : Ubuntu 20.04.1 LTS
・ラズパイバージョン : 4B、3B+
・MicroSDカードの中身:既にOSが起動できる状態になっている
上記のスペックでの実際のビルド時間は、約20分程でした。
ビルドPCは、デスクトップで高スペックの方がビルド時間が短くなります。
あと、ノートパソコンでビルドするのはやめておいた方が良いです。
今回のビルドはノートパソコンでやっていませんが、経験的にかなり時間がかかると思います。
(おそらく十数時間ぐらい。。)
とりあえず、目安として私が使用したマシン環境を書きました。
また、既にRasberry Pi OSが動作しているMicroSDカードに対して、
カーネルやdtbファイル(ドライバ等の初期組み込み設定やその初期設定)を上書きしますので、
上書きしても良いMicroSDカードを準備してください。
もし、以前の状態をそのままの状態で残しておきたい場合には、
MIcroSDの中身をイメージファイルとしてバックアップすることで残しておくことができます。
2.Raspberry Pi OSのカーネルソース取得
カーネルソースを取得するには、gitコマンドを使用します。
またその他、ビルドに必要なモジュールをインストールしていない場合は、
$ sudo apt install git bc bison flex libssl-dev make
で、インストールします。
私のUbuntu環境では、ある程度ビルドするためのモジュールが入っていますので、
上記のインストールだけでは不十分かもしれません。
もし不足している場合は、カーネルビルド時にエラーが出ますので、随時、エラーになったモジュールをインストールしてください。
Raspberry Pi OSカーネルソースの取得は、
$ git clone --depth=1 https://github.com/raspberrypi/linux
で行います。
取得すると、linuxフォルダが生成され、そのフォルダ内にソース一式が格納されます。
例えば、私のユーザーディレクトリである/home/mantaで上記コマンドを実行すると、
カーネルソースは、/home/manta/linuxになります。
このカーネルソース一式には、全てのラズパイのバージョンが含まれており、
クロスコンパイル時に、次章での環境変数を切り替えることで使用したいバージョンでビルドすることができます。
3.環境変数の設定
クロスコンパイルするためには、事前に環境変数の設定をする必要があります。
ラズパイのどのバージョンのイメージを作るかの環境設定を行います。
ここでは私が持っているラズパイ4Bと3B+の設定を記述します。
<ラズパイ4Bの場合>
$ export ARCH=arm $ export KERNEL=kernel7l $ export CROSS_COMPILE=arm-linux-gnueabihf-
<ラズパイ3B+の場合>
$ export ARCH=arm $ export KERNEL=kernel7 $ export CROSS_COMPILE=arm-linux-gnueabihf-
その他のバージョンについては、冒頭で参考にしたラズパイのカーネルビルドのサイトを参考にしてください。
また、これらの環境設定を毎回するのは面倒ですので、.bashrcに記述しておくと楽です。
4.クロスコンパイルの手順
ラズパイのCPUであるARM用のイメージを作成するためにクロスコンパイル環境が必要になります。
ラズパイのサイトに記載されているcrossbuild-essentialをインストールしても、
arm-linux-gnueabihf-gccがインストールされませんでした。
パッケージがインストールされているかapt searchで確認すると、
パッケージが表示されてインストールされているのですが、肝心のクロスコンパイルコマンドがありませんでした。
以前は、Gitからクロスコンパイル環境をダウンロードできていましたができなくなりました。
なので、これを解決するために、クロスコンパイラコマンド名のパッケージをインストールします。
$ sudo apt install g++-arm-linux-gnueabihf
gccではなく、g++のパッケージをインストールする理由は、
単にgccだとC++がビルドできないからで、将来的にC++も使用したいからです。
C++を使用しないとしても、g++のパッケージをインストールしておく方が良いです。
次に、クロスコンパイルのやり方ですが、まず3章で行った環境変数が設定されているか確認します。
ここでは、ラズパイ4Bのカーネルビルドを行います。
クロスコンパイルの手順は、以下です。
$ make bcm2711_defconfig $ make -j4 zImage modules dtbs $ sudo make modules_install
簡単に説明すると、
・1行目では、.configファイルが作成されます。
Gitコマンドでカーネルソース取得した時点では、.configファイルは存在していません。
このファイルが無いと、どのモジュールをビルドしたら良いかコンパイラがわからないため、
.configファイルを作成するために実行します。
・2行目では、1行目で生成された.configファイルを参照して、カーネルモジュールのビルドやdtbファイルの生成を行います。
私のマシンスペックで約20分程でしたが、マシンスペックにより数時間かかる場合もあります。
・3行目では、2行目で生成されたカーネルモジュールを/lib/modules配下にコピーします。
完了後に、上記のDEPMODの行でビルドしたカーネルバージョンのフォルダ名がでますので、
Ubuntuマシン上の/lib/modules配下にそのフォルダが生成されているかどうか確認します。
とりあえずここでは、エラーが出ず成功するかどうかを確認してください。
注意点:カーネルクリーンはしないこと
カーネルのビルドを失敗した場合に、カーネルビルドを行ったことがある方は、make cleanで、中途半端に生成されたモジュールをクリーンしたくなりますが、これをすると少し面倒になります。
クリーンすると次の再ビルド時にカーネルコンフィグ設定に対して、
どのモジュールをカーネルに組み込むかどうかの選択が対話形式で始まります。
これを一つづYes/Noを入れていくと非常に時間がかかりますし、
面倒だからと言ってずっとエンターキーを押しているとエラーになることもあります。
なので、クリーンをするなら、もう一度Gitからカーネルソースを再取得してやり直す方が良いです。
5.ビルドしたイメージをMicroSDカードに上書き
4.でビルドしたカーネルイメージやモジュールを既にRaspberry Pi OSが起動しているMicroSDカードに上書きします。
上書きの作業は、Ubuntuパソコン上で行いますので、
Raspberry Pi OSインストール済みのMicroSDカードをUbuntuパソコンに認識させておいてください。
5.1 MicroSDカードのパーティション構造
まず、MicroSDカードのパーティションとその中身を把握しておきます。
dfコマンドでみるとこんな感じです。(対象だけ抜粋)
ビルドしたイメージは、sdc6のbootフォルダとsdc7のrootフォルダに上書きしていきます。
bootフォルダは、この中にカーネルイメージやdtbなどラズパイ起動に必要なファイルが格納されています。
rootフォルダは、Raspberry Pi OSのルートファイルシステムになります。
(上記の/media/mantaの部分は、私のユーザー名のものなので、自分のものと置き換えてください。)
5.2 MicroSDカードにビルドしたイメージの上書き手順
MicroSDカード内のbootフォルダとrootフォルダに、4で作成したイメージを上書きする手順は、下記のようにします。
$ sudo cp arch/arm/boot/zImage /media/manta/boot/($KERNEL).img $ sudo cp arch/arm/boot/dts/*.dtb /media/manta/boot $ sudo cp arch/arm/boot/dts/overlays/*.dtb* /media/manta/boot/overlays $ sudo cp -r /lib/modules/5.4.74-v7l+ /media/manta/root/lib/modules
・1行目で、ビルドで生成されたzImageファイルをリネームして、MicroSDカードのbootフォルダ直下に上書きしています。$KERNELは、環境設定で設定した名前になります。
・2行目は、ビルドで生成されたdtbファイルを、MicroSDカードのbootフォルダ直下に上書きしています。
・3行目は、ビルドで生成されたoverlaysフォルダ内のdtboなどのファイルをMicroSDカードの
/boot/overlaysフォルダに上書きしています。
・4行目は、ビルドで生成されたモジュールをMicroSDカードの/root/lib/modulesフォルダにコピーしています。
この行は、ラズパイのサイトに記載されていませんが、これをしないとカーネルバージョンとモジュールバージョンの整合性が取れなくなり、ラズパイ起動時にモジュールロードエラーが出て、起動できたとしても正常に動作できていませんでした。
これでカーネルイメージとdtb関連ファイル、カーネルモジュールの上書きとコピーは完了です。
カーネルモジュールのコピーですが、4.で行った、
$ sudo make modules_install
を
$ sudo make INSTALL_MOD_PATH=/media/manta/root/ modules_install
にすることで直接MicroSDカードの/lib/modulesにコピーすることもできます。
環境変数としてINSTALL_MOD_PATHを.bashrcに設定して、
$ sudo make modules_install
で、MicroSDカードの/lib/modules配下にコピーされるのかと思ったのですが、できませんでした。
何故だかまだわかっていませんが、まあ良しとします。
とりあえず、これでMicroSDカードにこれまで作成したイメージの上書きが完了しました。
6.Raspberry Pi OSの起動確認
起動確認は簡単です。 イメージを上書きしたMicroSDカードをラズパイに挿入して電源を入れるだけです。
起動中のメッセージでエラーが出ていないことを確認しながら、デスクトップ画面が表示されるのを待ちます。
表示後、ビルドしたカーネルイメージで本当に起動しているかを端末から「uname -r」で確認します。
カーネルのバージョンは、make modules_installで生成されたフォルダ名になっているはずです。
7.最後に
Raspberry Pi OSのカーネルビルドができるようになると、
自分で作成したデバイスドライバを組み込んだり、ラズパイで使用しているデバイスドライバを特定でき、
そのデバイスドライバの動きを理解することができます。
そういった組み込みの知識を勉強したい方には、このカーネルのビルドを是非やってみてください。
<関連・おすすめ記事>
簡単にできるWindowsからラズパイ3B+にリモートアクセス(VNC,SSH)する手順 - 水瓶座列車
Wake ON LAN(WOL)でUbuntu18.04マシンを起動する手順 - 水瓶座列車
Raspberry Pi (ラズパイ)で役に立つ書籍のおすすめランキングベスト5 - 水瓶座列車
Sambaサーバーの設定手順(Ubuntu18.04)とWindowsからのアクセス方法 - 水瓶座列車