撤退

参加報告を記します.

簡単なデバイスドライバを作る

簡単なデバイスドライバを作る

間が空いてしまいましたが,セキュリティキャンプ九州にて小出先生のテキストで消化できなかった部分を32GBのSDカードをようやく買ったのでやってみました.

環境準備

とりあえず先生から頂いた環境でHello, World!ドライバを作ろうと,

#include <linux/module.h>
#include <linux/kernel.h>

MODULE_AUTHOR("hoge");
MODULE_DESCRIPTION("dummy driver");
MODULE_LICENSE("GPL");

int init_module(void)
{
    printk(KERN_INFO "Hello World!");
    return 0;
}

void cleanup_module(void)
{
    printk(KERN_INFO "Goodbye World!");
}

をhello.cとして,とりあえず頭空っぽにして sudo make すると

make -C *** /lib/modules/4.1.4-v7+/build: No such file or directory.

となるので,kernel-headersが必要とわかりsudo apt-get install linux-headers-$(uname -r) でkernel headerを落とそうとするもパッケージが見つからなくて失敗. update, upgradeしてもだめだったので4.1.4-v7+のlinux-headerのdebファイルを持ってきてインストールしました.

sudo makeできるようになったので,sudo insmod hello.koでドライバを組み込みます.lsmodで組み込まれているドライバを確認すると

$ lsmod
Module                  Size  Used by
hello                    683  0

となり組み込めていることが確認できます. その後,sudo rmmod hello を行いドライバを外しました. tailコマンドを使って正常にドライバが動作したかを確認.

$ tail -n 2 /var/log/syslog
Sep 18 14:39:16 raspi000 kernel: [10449.520157] Hello world
Sep 18 14:41:19 raspi000 kernel: [10571.904216] Goodbye world

ちゃんと表示されてるので大丈夫だと認識しました.

ドライバでgpio制御をする

とりあえずbuild

https://github.com/wendlers/rpi-kmod-samples を利用して作ろうとのことなので,ちょいちょいとコードをいじってみました.

この中でもkmod-gpio_outptimerを用いて,LEDをチカチカさせてみようと思います. はじめはコードをそのまんまでbuildしてLEDをチカチカさせました.

ちなみにこの時のraspiと周りの回路の関係は下の図のようになっています.

f:id:turn_up:20150918151249j:plain

スイッチも制御しよう

せっかくスイッチも回路に組み込んであるし,スイッチを押したら点滅するようにしてみます. 先生のテキストによると,init_moduleでGPIOの初期化及びタイマの設定. blink_timer_funcでLEDの点滅,タイマの設定.とのことなので,

#define SWITCH1 21

を追加しました.

init_moduleではGPIOの初期化が必要なので,

  ret = gpio_request_one(SWITCH1, GPIOF_IN, "switch1");

  if (ret) {
    printk(KERN_ERR "Unable to request GPIOs: %d\n", ret);
    return ret;
  }

を追加し,またLEDの初期化では最初がオフになるように

ret = gpio_request_one(LED1, GPIOF_OUT_INIT_LOW, "led1")

...

blink_timer.data = 0L;

としました.

その後,blink_timer_funcにスイッチの値によってLEDの値を決まるようにする条件分岐を追加しました.

  int value = 0;
  value = gpio_get_value(SWITCH1);
  if (value) blink_timer.data = !data;
  else blink_timer.data = 0L;

これで動かしてみたのが次の動画です.

ドライバの組み込みに成功したので,sudo rmmod gpiomod_outptimerして時間間隔をちょっといじってみたあとsudo makeして,再度sudo insmod gpiomod_outptimer.koしようとすると,

Error: could not insert module gpiomod_outptimer.ko: Device or resource busy

となります.

藤原竜也の真似をする某人ばりになんでだよおおって言ったあとにcleanup_moduleでGPIOを解放していないことに気がついたので,以下の文をcleanup_moduleに追加しました.

  gpio_free(SWITCH1);

これで無事普通に動くようになったと思います. tailの結果も

$ tail -n 2 /var/log/syslog
Sep 18 15:10:10 raspi000 kernel: [12302.915460] gpiomod_init
Sep 18 15:10:16 raspi000 kernel: [12308.776421] gpiomod_exit

となり,問題なさそうです.

まとめ

LチカをLinuxカーネルモジュールとして作成しました.

今回少しハマったポイントはドライバ作成環境構築でのkernel-headersのインストールと GPIOの初期化,GPIOの解放をドライバの組み込み,取り外しに際してそれぞれ行うことを忘れたことでした.

感想

簡単ながらデバイスドライバを作成したということで作成経験を主張していこうと思います.

小出先生の講義はどれもraspi活用法の入り口として面白かったのでこういう風に作ってみました. 今後はこれを応用してGPIO制御をユーザ空間,カーネル空間使い分けて電子工作を行っていきたいと思います.