Raspberry Pi Zeroを5GHzの無線LANに参加させたいのですが、2015/11/21にリリースされたJessieだと、手持ちのWifiアダプタGW-450Sは使用できませんでした。githubにあるドライバ (https://github.com/gnab/rtl8812au) をカーネルモジュールとしてコンパイルする必要があるようです。
本稿では、他のマシンでRaspberry Pi Zero用のカーネルをクロスコンパイルする手順と、今回のGW-450Sを例に外部ドライバをカーネルモジュールとして導入する手順を紹介したいと思います。
※カーネルのコンパイルをRaspberry Pi Zeroでも行えますが、Raspberry Pi Zeroのカーネルイメージにデフォルトで使われている.configを用いたところ、14時間かかりました。。。作成モジュールが相当多いため、時間がかかるようです。
2017/2追記
Raspberry Pi Zero上で同一バージョンのカーネルソースを取得し、モジュールのみコンパイル、という方法で短時間で達成できます。
参考
https://www.max2play.com/en/forums/topic/howto-raspberry-pi-3-realtek-802-11ac-rtl8812au/
こちらの方がオススメです。
環境はUbuntu 14.04 LTSです。以下、64bitマシンで作業する前提で記述します。
カーネルのクロスコンパイル
「石を売る」さんの「Raspberry Pi2のカーネルの再構築とGW-450Dを使えるようにする。」を参考にさせていただきました。
作業フォルダの作成
$ mkdir -p $HOME/src/Raspberry_Pi_Zero
$ cd $HOME/src/Raspberry_Pi_Zero
必要なパッケージのインストール
たまたまIntel Edisonのカーネルビルドも行っていたので、インストールが必要なパッケージはありませんでしたが、以下のパッケージが必要になります。
$ sudo aptitude install build-essential git openssh-server ncurses-dev
toolchainとkernel sourceのダウンロード
クロスコンパイルに必要なツールと、Raspberry Piのカーネルソースをダウンロードします。
$ git clone --depth=1 git://github.com/raspberrypi/tools.git
$ git clone --depth=1 git://github.com/raspberrypi/linux.git
環境変数の設定
$ ls tools/arm-bcm2708
$ export PATH=`pwd`/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH
$ export ARCH=arm
$ export CROSS_COMPILE=arm-linux-gnueabihf-
クロスコンパイラが使えるか確認します。
$ arm-linux-gnueabihf-gcc -v
Raspberry Pi Zeroより.config取得
Raspberry Pi Zeroから取得します。
$ cd linux
$ ssh pi@(Raspberry Pi Zeroのアドレス) 'sudo modprobe configs'
$ ssh pi@(Raspberry Pi Zeroのアドレス) 'zcat /proc/config.gz' > config-pizero
$ mv config-pizero .config
カーネルに命名
Makefile内の EXTRAVERSION を指定すると、カーネル名の後ろに名前がつけられます。今回は mod としました。カーネルのバージョンが4.1.15だったので、4.1.15-modになります。(後でカーネル名やフォルダ名としてまた出てきます)
$ vim Makefile
EXTRAVERSION = -mod
menuconfigの実行
別途、使用したいデバイス等があれば設定します。menuconfigのお作法に倣って設定、保存をしてください。
$ make menuconfig
カーネルのビルド
$ make -j 4
-jの後の数字はCPUコア数に応じて変えます。2倍程度が一般的です。
Core2 Duo T7600(2.33GHz)のデュアルコアなマシンで30分弱で終わりました。
モジュールとカーネルをまとめる
$ cat include/config/kernel.release
4.1.15-mod+
$ export KERNEL_RELEASE=`cat include/config/kernel.release`
$ export INSTALL_MOD_PATH=../$KERNEL_RELEASE
$ mkdir -p $INSTALL_MOD_PATH
$ mkdir -p ../$KERNEL_RELEASE/boot
$ make modules
$ make modules_install
$ cp arch/arm/boot/Image ../$KERNEL_RELEASE/boot/kernel-$KERNEL_RELEASE.img
$ cd ..
Raspberry Pi Zeroで一度動作確認
出来上がったカーネルが動作するか確認します。
$ cd $KERNEL_RELEASE
$ tar zcvf $KERNEL_RELEASE.tar.gz boot lib
$ scp $KERNEL_RELEASE.tar.gz pi@(Raspberry Pi ZeroのIPアドレス):/home/pi/
$ ssh pi@(Raspberry Pi ZeroのIPアドレス)
ログイン後
$ sudo tar zxC / -f 4.1.15-mod+.tar.gz
$ ls /boot
(今回作成したkernel-4.1.15-mod+.imgがあることを確認)
$ sudo vim /boot/config.txt
末尾に以下を追加
kernel=kernel-4.1.15-mod+.img
Raspberry Pi Zeroを再起動します。uname -a
で今回設定したカーネル名が表示されるか確認してください。
起動に失敗した場合、SDカードを取り出して、先ほどのconfig.txtを元に戻せば修正前の状態で起動できます。
rtl8812モジュールのビルド
前項の「カーネルのクロスコンパイル」を実施済みが前提になります。このパートのみ再度行う場合は、前項中にある「環境変数の設定」を実施して、クロスコンパイラが使用できる状態にしてください。
githubにあるドライバのページ(https://github.com/gnab/rtl8812au) にある手順に従います。
ドライバソースのダウンロード
$ cd $HOME/src/Raspberry_Pi_Zero
$ git clone https://github.com/gnab/rtl8812au
設定の変更
$ vim Makefile
ターゲットをI386_PCからARM_RPIに変更します。
(変更前)
CONFIG_PLATFORM_I386_PC = y
...
CONFIG_PLATFORM_ARM_RPI = n
(変更後)
CONFIG_PLATFORM_I386_PC = n
...
CONFIG_PLATFORM_ARM_RPI = y
続いて、クロスコンパイラ(CROSS_COMPILE)、カーネルバージョン(KVER)とこれに付随して指定されるディレクトリ(KSRC, MODDESTDIR)を変更します。ディレクトリは絶対参照から相対参照に切り替えています。
カーネルバージョンは「4.1.15-mod+」を決め打ちしていますので、適宜変更してください。(以後も登場します)
(変更前)
ifeq ($(CONFIG_PLATFORM_ARM_RPI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE :=
KVER := $(shell uname -r)
KSRC ?= /lib/modules/$(KVER)/build
MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
endif
(変更後)
ifeq ($(CONFIG_PLATFORM_ARM_RPI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
ARCH := arm
CROSS_COMPILE := arm-linux-gnueabihf-
KVER := 4.1.15-mod+
KSRC := ../$(KVER)/lib/modules/$(KVER)/build
MODDESTDIR := ../$(KVER)/lib/modules/$(KVER)/kernel/drivers/net/wireless/
endif
ドライバモジュールのビルド
$ make
ドライバのコピー
$ cp 8812au.ko ../4.1.15-mod+/lib/modules/4.1.15-mod+/kernel/drivers/net/wireless
Raspberry Pi Zeroへの転送
前項「Raspberry Pi Zero側で一度動作確認」を実施して、カーネルイメージを再送、再起動してください。
再起動後
$ sudo depmod
このあと、GW-450SをUSBポートに刺すと無事使えるようになるはずです。
おまけ
カーネルコンパイルをRaspberry Pi Zero上で行いたい場合
いばらの道です。
$ cd $HOME
$ bash -c "$(curl -fsSSL https://raw.githubusercontent.com/moutend/raspi-kernel/master/raspi-kernel)"
$ cd /usr/src/linux-...
$ sudo modprobe configs
$ zcat /proc/config.gz > .config
$ time make
real 742m7.551s
user 700m51.830s
sys 29m42.700s
$ make modules
$ make modules_install
現在使用中のカーネルからconfigを取得
configを取得できるカーネルコンフィグがあることを初めて知りました。
CONFIG_IKCONFIG=m
CONFIG_IKCONFIG_PROC=y
このオプションが組み込まれたカーネルで、以下を実行します。
$ sudo modprobe configs
$ zcat /proc/config.gz > .config
Todo
最初のインストールイメージに対して更新したい。
PiTFTの変更を反映したい(本稿で作成するGW-450S等のモジュールと一緒に用いたい)