Raspberry Piのデバイスドライバの開発環境を構築します。imageには、カーネルのヘッダが入っていないので、このままでは、作成した、Raspberry Piのドライバのコンパイルができません。このため、Raspbian “wheezy”のソースコードをダウンロードします。

最初に、root権限で作業するので、rootでログインできるように「sudo passwd root」でrootのパスワードを設定します。

pi@raspberrypi:~$ sudo passwd root
Enter new UNIX password:

rootになります。

pi@raspberrypi:~$ su –

デバイスドライバ開発のためのヘッダファイルの設定

まず、コンパイルするための開発環境をインストールします。

root@raspberrypi:~# apt-get install build-essential

git(ソースコードのダウンロードツール)をインストールします。

root@raspberrypi:~# apt-get install git

※既に最新パッケージが入っている場合は、インストールは行われません。

ソースコードの作業用ディレクトリに移動します。

root@raspberrypi:~# cd /usr/src
root@raspberrypi:/usr/src#

Raspbian “wheezy”のソースコードをダウンロードします。

root@raspberrypi:/usr/src# sudo apt-get install linux-image-rpi-rpfv linux-headers-rpi-rpfv

「/usr/src」と「/lib/modules/」にダウンロードされたファイルを確認します。

root@raspberrypi:/usr/src# ls
linux-headers-3.12-1-common  linux-headers-3.12-1-rpi  linux-kbuild-3.12

root@raspberrypi:/usr/src# cd /lib/modules/
root@raspberrypi:/lib/modules# ls
3.12-1-rpi

新規のカーネルをブート時にロードするために、/boot/config.txtの最後の行に次のラインを追加します。

# Parameters to boot on raspbian kernel (linux-image-rpi-rpfv package)
kernel=vmlinuz-3.12-1-rpi
initramfs initrd.img-3.12-1-rpi followkernel

再起動します

root@raspberrypi:/usr/src# sudo reboot

カーネルのバージョンを調べます。

pi@raspberrypi ~ $  uname -a
Linux raspberrypi 3.12-1-rpi #1 Debian 3.12.9-1+rpi2 (2014-12-14) armv6l GNU/Linux

テスト用デバイスドライバのソースコード

テスト用に次のCコードを作ります。作成したテスト用のプログラムは、ディレクトリ「/home/pi/hello-module」を作成して保存します。

hellow-1.c

/*  
 *  hello-1.c - The simplest kernel module.
 */
#include <linux/module.h>   /* Needed by all modules */
#include <linux/kernel.h>   /* Needed for KERN_INFO */

int init_module(void)
{
    printk(KERN_INFO "Hello world 1.\n");

    /* 
     * A non 0 return means init_module failed; module can't be loaded. 
     */
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye world 1.\n");
}


makeファイルは次のようにします。作成したmakeファイルは、ディレクトリ「/home/pi/hello-module」に保存します。

Makefile

KERNEL_HEADERS=/lib/modules/$(shell uname -r)/build
obj-m := hellow-1.o
all:
   $(MAKE) -C $(KERNEL_HEADERS) M=$(PWD) modules
clean:
   $(MAKE) -C $(KERNEL_HEADERS) M=$(PWD) clean
obj-m
ローダブルモジュール(.ko)を作成する場合です。insmod コマンドでロードする場合です。obj-yは、カーネル起動時にロードする場合です。zImageやuImageに含める場合です。
makeコマンドのCオプション
makeは指定したディレクトリに移動してから処理を開始します。KERNEL_HEADERS変数であらかじめカーネルソースコードへのパスを指定しています。
makeコマンドの「M=パス」
modulesターゲットを作成する前に,モジュールのソースディレクトリにあるMakefileに戻ることを表します。
$(MAKE)、$(PWD)
あらかじめ定義されている変数を示します。また、特殊変数は、ターゲットと依存ファイルの関係を示す値を格納します。例えば次のようなものがあります。

  • 「$@」は依存行のターゲットファイル名を示します。
  • 「$^」は依存行のすべての依存ファイル名を示します。


コマンドの前にはタブを挿入します。スペースを入れると次のエラーメッセージが発生します。
Makefile:6: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.

makefileの構成

makefileの構成は次のようになっています。

ターゲットファイル : 依存ファイル
(タブ)コマンド
(空行)
(上記設定の繰り返し。)

デバイスドライバ開発環境の確認

rootになり、/home/pi/hello-moduleに移動して、次のmakeコマンドを実行します。。

root@raspberrypi:/home/pi/hello-module# make
make -C /lib/modules/3.12-1-rpi/build M=/home/pi/hello-module modules
make[1]: Entering directory `/usr/src/linux-headers-3.12-1-rpi’
  CC [M]  /home/pi/hello-module/hello-1.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/pi/hello-module/hello-1.mod.o
  LD [M]  /home/pi/hello-module/hello-1.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.12-1-rpi’
root@raspberrypi:/home/pi/hello-module#

次のファイルが作成されています。

root@raspberrypi:/home/pi/hello-module# ls
hellow-1.c   hellow-1.mod.c  hellow-1.o  modules.order
hellow-1.ko  hellow-1.mod.o  Makefile    Module.symvers

insmod コマンドと、rmmodコマンドで登録して削除してみます。syslogを見ると正常に実行されていることが確認できできます。

root@raspberrypi:/home/pi/hello-module# sudo insmod hellow-1.ko
root@raspberrypi:/home/pi/hello-module#  tail -1 /var/log/syslog
Dec 20 16:02:36 raspberrypi kernel: [  110.341449] Hello world 1.
root@raspberrypi:/home/pi/hello-module# sudo rmmod hellow-1.ko
root@raspberrypi:/home/pi/hello-module# tail -1 /var/log/syslog
Dec 20 16:02:59 raspberrypi kernel: [  133.035910] Goodbye world 1.

「Invalid module format」エラー

出来上がったドライバプログラムをinsmodコマンドで実行すると、次のような、「Invalid module format」エラーがでることがあります。カーネルのバージョンと コンパイルしたドライバのバージョンが異なるのが原因のようです。この時は、/boot/config.txtに追加したコードをもう一度確認してみてください。

root@raspberrypi:/home/pi/hello-module# sudo insmod hello-1.ko
Error: could not insert module hello-1.ko: Invalid module format