RaspberryPi kernelとDriverのクロスコンパイル方法
ARMv8 32bit/64bitのクロスコンパイルの方法についてまとめました。
https://www.raspberrypi.org/documentation/linux/kernel/building.md
基本的にはRaspberryPi公式の方法に則ってやっていきます。(公式では32bit版しか載っていません。)クロスコンパイルに使ったのはVirtualBoxとubuntu 18.4LTSの組み合わせです。
見た目はこんな感じで、普段のWindowsと変わらない操作感です。ホストOS-ゲストOS間のコピペも自在ですし、USBメモリやSDカードをゲストOSに直接マウントすることもできて便利です。ただし、ホストのストレージは喰うので256GB以下の小容量SSDなパソコンにはあまりお薦めできません。
ubuntu 18.4LTS(PC-Linux)上での作業
ツールチェーン用にディレクトリを作成してその中に入れていきます。
mkdir raspi-dev
cd raspi-dev
sudo apt-get update
sudo apt-get -y install git build-essential libncurses5-dev bc bison flex libssl-dev
続いてツールチェーンのダウンロード
git clone https://github.com/raspberrypi/tools.git
準備完了です。※ここで導入できるのはARMv7(32bit)用のクロスコンパイラ一式です。
この後、公式サイト通りに進めると最新版のカーネルソースを取得していきますが、現在、起動しているラズパイがあるのでしたら、そのカーネルと同じソースを取得した方がドライバ作成には好都合です。カーネルバージョンが完全一致しないとドライバモジュールを取り込まないセキュリティになっているからです。
という訳で、ラズパイ側でも作業します。
64bitモードで起動しているのか、32bitモードで起動しているのか把握しておく必要があります。普通にRaspbianを起動すると32bitモードです。(2020年2月時点)
ラズパイでの作業
sshでラズパイにリモートログインします。
Raspbianなら、ユーザー名:pi パスワード:raspberry
sudo apt-get update
apt-get install bc bison flex libssl-dev libncurses5-dev
sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source
sudo chmod +x /usr/bin/rpi-source
sudo /usr/bin/rpi-source -q --tag-update
sudo rpi-source --skip-gcc -d /home/pi/
*** SoC: BCM2711
*** Using: /usr/share/doc/raspberrypi-bootloader/changelog.Debian.gz
*** Latest firmware revision: 01508e81ec1e918448227ca864616d56c430b46d
*** Linux source commit: 6d8bf28fa4b1ca0a35c0cd1dcb267fb216daf720
*** Download kernel source
--2020-01-27 12:33:16-- https://github.com/raspberrypi/linux/archive/6d8bf28fa4b1ca0a35c0cd1dcb267fb216daf720.tar.gz
Resolving github.com (github.com)... 52.192.72.89
Connecting to github.com (github.com)|52.192.72.89|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/raspberrypi/linux/tar.gz/6d8bf28fa4b1ca0a35c0cd1dcb267fb216daf720 [following]
--2020-01-27 12:33:17-- https://codeload.github.com/raspberrypi/linux/tar.gz/6d8bf28fa4b1ca0a35c0cd1dcb267fb216daf720
Resolving codeload.github.com (codeload.github.com)... 52.193.111.178
Connecting to codeload.github.com (codeload.github.com)|52.193.111.178|:443... connected.
HTTP request sent, awaiting response... 200 OK
・・・・・・・・・・・・・・・・・・
このあとも続いていますが、必要な情報としては、Download kernel source
と出たところのhttps://github.com/raspberrypi/*********.tar.gzがソースコード一式です。(上ではブラウザによって見切れているかも)
このURLのソース一式をPC-linux側でも使うのでダウンロードします。ここではURLだけ覚えておいてください。
続けて、実行中のconfigを取得します。ファイルとして存在するディストリビューションもあるのですが、Raspbianでは以下のようにして取り出します。
cd ./linux
sudo modprobe configs
sudo zcat /proc/config.gz > .config
sudo cp .config /boot/config.pi4.txt
/boot はSDカードをPCに挿したときに見えるディレクトリですので、分かりやすい名称にして保存しておきます。
ラズパイでの作業はここまで。
ubuntu 18.4LTS(PC-Linux)に戻って作業
先ほどのURLのカーネルソース一式のファイルを落としてきます。
wget https://github.com/raspberrypi/linux/archive/6d8bf28fa4b1ca0a35c0cd1dcb267fb216daf720.tar.gz
(ブラウザによって見切れているかも ******.tar.gz まであります。)
解凍します。
tar -xvf 6d8bf28fa4b1ca0a35c0cd1dcb267fb216daf720.tar.gz
cd linux-6d8bf28fa4b1ca0a35c0cd1dcb267fb216daf720
ここに、先ほどラズパイで取得したconfig.pi4.txtを .configとしてコピーしてきます。
virtualBoxではホスト-ゲスト間でドラッグ&ドロップでファイルをコピーできますし、Raspberryのストレージからscpで直接持ってきても良いです。
下はssh://moode.local としてネットワーク接続した例です。
< winSCPのようにLinux-PCもラズパイのストレージに接続できる >
さて、ラズパイを32bitモードで起動しているなら
32bitOS Raspberry Pi 2, Pi 3用
CCPREFIX=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
KERNEL=kernel7
make ARCH=arm CROSS_COMPILE=$CCPREFIX oldconfig
make -j10 ARCH=arm CROSS_COMPILE=$CCPREFIX zImage modules dtbs
32bitOS Raspberry Pi 4用
CCPREFIX=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
KERNEL=kernel7l
make ARCH=arm CROSS_COMPILE=$CCPREFIX oldconfig
make -j10 ARCH=arm CROSS_COMPILE=$CCPREFIX zImage modules dtbs
ラズパイを64bitモードで起動しているなら
64bitOS Raspberry Pi 3, Pi 4用
sudo apt-get install binutils-aarch64-linux-gnu
とaarch64用のクロスコンパイラをインストールしてから
KERNEL=kernel8
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- oldconfig
make -j10 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- Image modules dtbs
です。
これで、カーネルをビルドできました。-j10 のところは、cpu数の1.5倍くらいにしておくと高速にビルドできると言われています。
modules と dtbsは、外部ドライバをコンパイルするという目的なら必要ありません。ビルドしたカーネルを起動するなら必要です。SDカードに転送したりする部分は公式サイトをご覧ください。
昨年組んだ新しいPCを使っているので、非常に高速にkernelをビルドすることができました。一番上の画像に載っている通り1分48秒でzImageが出来てます。Pi4のセルフビルドで約1時間と速くなったな~なんて思っていたのですが、さすがx86系CPUの上位モデルは違いますね。仮想環境でもこの速度。
ようやくカーネルソース外のドライバをコンパイルする環境が整いました。
■ 外部ドライバをコンパイル
引き続きPC-linux上での作業です。
という具合にドライバソースを入れたディレクトリを配置してそのディレクトリに移動します。
Makefileの中でカーネルソースやDTCを指定しているときは変更します。
KERNEL_SRC = ../linux-*********/
DTC_DIR = $(KERNEL_SRC)/scripts/dtc/
ラズパイが32bitモードなら
CCPREFIX=../tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-
make ARCH=arm CROSS_COMPILE=$CCPREFIX
ラズパイが64bitモードなら
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-
以上でドライバのコンパイルが出来ました。
あとは、ラズパイ本体に入れて動作をみてみるだけです。
64bit版moodeAudio用のSabreberry32ドライバはこうやって作りました。
参考になれば幸いです。
そもそもの話
そもそも、なぜドライバをコンパイルするために先にカーネル本体をビルドしなければいけないのか?疑問に思う人もいると思います。
カーネルとドライバモジュールとのバージョン整合性を持たせる仕組みに Module.symvers というファイルが使われています。
カーネルソースとビルドの設定(.config)の組み合わせでシンボルのプロトタイプをCRCハッシュ計算したものをModule.symvers に保存しています。カーネルソースが同じでも.configが違うとModule.symversの内容が違ってくることに注意が必要です。
Module.symversはカーネルをビルドすると生成されます。
ドライバは、そのModule.symversを参照して、組み込み先のカーネルに拒絶されないようにコンパイルされます。
Module.symversの中身はめっちゃ長いのですが、おそらく
0xb1adfa60 module_layout vmlinux EXPORT_SYMBOL
というシンボルが外部ドライバでは共通で使われます。この例だと0xb1adfa60という数値がハッシュ値です。
modprobe --dump-modversions *****.ko
でコンパイルしたドライバのmodule_layout のハッシュ値を確認することができます。完全一致していないとカーネルに取り込めません。変な仕組みですが、セキュリティのため。未検証で外部ドライバをカーネルに取り込むと、そこからデータを抜かれてしまう、というのを防ぐのだと思います。
話は戻って、
rpi-source スクリプトは、Raspbian公式のgithubからカーネルソースとModule.symversもダウンロードしてくるため、カーネル本体をビルドすることなくドライバをコンパイルすることが出来るようになります。正式にリリースされたRaspbianのModule.symversがgithubにUPされているようなので、独自に.configをいじったりすると使えなくなります。
https://raw.githubusercontent.com/raspberrypi/firmware/${FIRMWARE_REV}/extra/Module.symvers
からダウンロードできます。
FIRMWARE_REV は、rpi-sourceで最初の方に表示される(上の例だと)
*** Latest firmware revision: 01508e81ec1e918448227ca864616d56c430b46d
の長い数字の部分です。
firmware revisionは /boot/.firmware_revision に保存されている場合もあるようです。(apt-get upgradeしたときなど)
まあ、現時点ではARM64bit版のgcc、glibが提供されていないので、64bit版のドライバを作るにはクロスコンパイルするしか手段はありません。(64bit版のgcc、glibをコンパイルして作ればよいという話もありますが。。。)
にほんブログ村
ブログランキングに参加中です。 めざせ1位!
もしよろしければ「ぽちっと」お願いします。
« ついに64bit版 Moode Audio R6.4.1用のSabreberry32ドライバリリース | トップページ | RaspberryPiのCPU比較 どれが64bitで動くの? »
「Raspberry Pi」カテゴリの記事
- 2022年版のRaspberry Pi OSではユーザー、パスワード設定が必須に(2022.05.05)
- あのオーディオデザインさんがラズパイオーディオを発売(2022.04.18)
- Volumio/MoodAudioに秋月電子のI2CタイプOLEDを接続して曲名などを表示するPython3版(2022.03.26)
- reTerminal(Raspberry Pi CM4)でMoodeAudioを動かそう(2022.02.20)
- MoodeAudio 7.3をPi4でUSB3.0接続SSDから起動する方法(2021.09.24)
« ついに64bit版 Moode Audio R6.4.1用のSabreberry32ドライバリリース | トップページ | RaspberryPiのCPU比較 どれが64bitで動くの? »
コメント