2016/09/03

Raspberry Piドライバ作成 クロスビルド環境構築

Raspberry Piで色々デバイスを制御したところ、USBで接続したほうが扱いやすい例があった。
いくつかの電子部品ではドライバの作成が必要になる例もあったので、色々試行錯誤した内容を説明する。

対象は「RaspbianをインストールしたRaspberry Pi3」とする。


目標


ある特殊な環境で動作するプログラムを作成する場合、その実行環境上で開発環境もインストールした方が楽だが、そうしたくない場合もある。
例えば
  1. 実行環境に作成環境をインストールしたくない。(余計なものは入れたくない)
  2. 実行環境では動かない、慣れた開発ツールを使用したい。
  3. 実行環境がコンパイルなどに使用するにはスペックが高くない。
などの理由がある。
Raspberry Piの場合、3などが当てはまることが多いのではないだろうか。

規模が大きくなるとコンパイル時間は無視できないので、クロスコンパイル環境で作成することを目的に、環境構築を行った。


制作環境考


とはいえ、RaspbianはLinux系OSで、クロス開発用ビルドツールもLinuxのものしか用意されていないので、WindowsやMac上で直接のクロス制作環境の作成は果てしない道というもの。
Linux上にクロス制作環境を作る。
Ubuntuを使い慣れているのでこれを使用したが、正直別のディストリビューションでも可能かと思われる。
普段がMac使いなので仮想環境でLinux環境を用意した。


結果として、Mac OSX上にVMWare FusionでUbuntu Linux 16.04をインストールして、そこにビルド環境を構築した。


仮想環境の作り方なんかは、Web上にいくらでも記事があるので省略する。
今後ドライバのビルド環境になると思うので、できるだけ快適に作っておくといいかも。


環境構築


構築は以下の手順で行う。
  1. クロスビルド環境の構築
  2. カーネルのソースコード入手とビルド
  3. ドライバのソースコード、Makefileの作成

1はRaspberry PiのGithubにカーネルが公開されているので、これを使用する。
2も公式のクロス開発用ツールがGithubに公開されている。
3のソースコードはLinux上のドライバ作成と変わらないが、Makefileは独自の設定を行う。


前提

ディレクトリはユーザホーム内に作成環境を構築する。
$ mkdir ~/pi
ここにはドライバのプロジェクト以外に、raspbianのカーネルソースコードやクロスビルドツールなど一式も入れる。


クロスビルド環境の構築


いろいろGithubで公開されているので、とりあえずgitをインストールする。
あと、一般的なビルドツールをついでにインストールする。
$ sudo apt-get install git
$ sudo apt-get install build-essential
build-essentialはインストール済みかも。
他のディストリビューションではbuild-essentialのあたりは工夫してね。まあ、makeとかが動けばいいかと。
次にGithubからクロスビルドツールをゲットする。
$ cd ~/pi
$ git clone --depth=1 https://github.com/raspberrypi/tools

次に、クロスビルドツールのパスを環境変数に追加する。
$ gedit ~/.bashrc
エディタはなんでもいい。ここではgeditを使う。
.bashrcはbashの設定ファイルなので、これを編集して環境変数にパスを追加する。
最終部分に次の二行を追加して、環境変数PATHにtools内のパスを追加する。
PATH="$PATH":~/pi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian
PATH="$PATH":~/pi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin
bashを再起動すると、これが反映される。確認は
$ echo $PATH
で環境変数PATHの中身が確認できる。


64bitのOSの場合、32bit用実行環境がないと、クロス用コマンドを実行できない。これもインストールしておく。
$ sudo dpkg --add-architecture i386
$ sudo apt-get update
$ sudo apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386

あと、ビルドに足らない32bitライブラリをインストールしておく。
$ sudo apt-get install lib32z1


カーネルのソースコード入手とビルド


Githubからカーネルのソースコードをゲットする。
$ cd ~/pi
$ git clone --depth=1 https://github.com/raspberrypi/linux

いよいよカーネルのビルドを行う。
$ cd ~/pi/linux
$ KERNEL=kernel7
$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
$ time make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
これでビルド完了。仮想環境で1時間弱くらいかかった。


ドライバのソースコード、Makefileの作成


これでビルド環境は整った。あとはソースコードのサンプルとMakefileの書き方が少し特殊なので、これを説明する。

ソースコードのサンプルは最小のドライバ実装とする。
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("Dual MIT/GPL");
MODULE_DESCRIPTION("Hello Driver");

static int mod_init(void)
{
 printk(KERN_ALERT "driver loaded\n");
 return 0;
}

static void mod_exit(void)
{
 printk(KERN_ALERT "driver unloaded\n");
}

module_init(mod_init);
module_exit(mod_exit);
最小構成。
モジュールのロード時とアンロード時に、dmesgにメッセージを出力する。

MODULE_XXXXXのマクロは、modinfoした時に表示される情報を設定する。
printkはdmesgに文字を出力する関数。

module_initとmodule_exitはそれぞれロード時とアンロード時のハンドラを設定する。

Makefileは以下のとおり
KSRC = ~/pi/linux
ARCH = arm
CROSS_COMPILE = arm-linux-gnueabihf-
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
KVER = 4.4.19

obj-m := hello.o

all:
 make -C $(KSRC) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules

clean:
 make -C $(KSRC) M=$(PWD) clean

KVERに関しては、raspbianのカーネルのバージョンを記載する。
あと、Makefile内のmakeの前をタブにしないとエラーが出ることがあるので注意。

このhello.cとMakefileを同じディレクトリに置いて、そのディレクトリ内で
$ make
とすると、ビルドが始まる。
同じディレクトリ内に
module.symvers, hello.ko, hello.mod.c, hello.mod.o, hello.o, modules.order
が出来上がるとビルド成功。

このhello.koがドライバになる。


インストールテスト


このhello.koをRaspberry Piに入れる。
今回はホームディレクトリに入れた。

insmodとrmmodコマンドで、ロード、アンロードを行ってみる。
まずはロード。
$ cd ~
$ sudo insmod hello.ko
$ dmesg
dmesgで"driver loaded"と表示されたうまくいっている。
次にアンロード。
$ cd ~
$ sudo rmmod hello
$ dmesg
dmesgで"driver unloaded"と表示されたOK。


とりあえずはRaspberry Piにインストールできるドライバモジュールを作成するクロス環境の構築はできた。
あとは、基本的にLinuxドライバの作成と同じなので、それは別シリーズで説明したい。

0 件のコメント:

コメントを投稿