2019/04/30

GPIO操作のPCテスト環境について考える

GPIO操作のテスト環境は、ほぼ実機でのテストしかできません。
(と思ってるけど、実はあるのだろうか・・)

例えば、GPIO23に出力するとき、コンソールで以下のようにします。
> echo 23 > /sys/class/gpio/export
> echo "out" > /sys/class/gpio/gpio23/direction
> echo 1 > /sys/class/gpio/gpio23/value

この操作を、実機ではなくPC上で行おうとすると、
最初の exportへ23を書き込む ところで、引数エラーになります。
> echo 23 > /sys/class/gpio/export
echo: 書き込みエラー: 無効な引数です

dmesgで見ると、以下のメッセージが出力されています。
> dmesg
    ~省略~
[  955.6530668] export_store: invalid GPIO 23

これを出してるのは、linux v4.18.0 のカーネルソースを見ると、
以下の場所で出力しているようです。
/drivers/gpio/gpiolib-sysfs.c
453 static ssize_t export_store(struct class *class,
454    struct class_attribute *attr,
455    const char *buf, size_t len)
456 {
    ~省略~
465     desc = gpio_to_desc(gpio);
466     /* reject invalid GPIOs */
467     if (!desc) {
468         pr_warn("%s: invalid GPIO %ld\n", __func__, gpio);
469         return -EINVAL;
470     }

エラーになってるのはgpio_to_desc関数で、引数gpioに対応する
ディスクリプタを返すが、このディスクリプタはカーネルソース内で
チップ情報によって作成されています。つまり、この動作を変えるには、
カーネルソースの再ビルドが必要となりそうです。

なので、GPIO操作のテストには実機が必要だが、現場では数人で
実機を共有しているので、気軽にテストできません。
ようやく実機使えてテストしたら、「不等号の向き間違えた」なんかの
つまらないバグが出ると、時間の無駄だし、気が滅入ってきます。
なので、PC上でコーディングミスレベルの不具合は潰しておきたい。

PC上での方法を考えると、デバッグ時は/sys/class/gpio/gpioN/value を
mkfifo で作ったパイプで代替する方法をしている人が、私の職場でいました。
しかし、これは、書き込み側は動作は変わらないが、読み出し側がパイプを
readしたときに書き込みがあるまで関数がブロックしてしまいます。
また、読み出しが遅い場合、書き込みを、例えば2回1を書き込んだ場合、
読み出すと11になるので、一文字ずつ処理するなど、実機の場合には
不要な処理を足さなくてはならないので面倒です。

カーネルソースのgpiolib-sysfs.cを見ていると、実ポートには出力せず、
メモリ上の値を読み書きするだけの、GPIOの動作を模擬できる
仮想GPIOドライバが作れそうです。

というわけで、このゴールデンウィーク中に仮想GPIOドライバを
作ってみることにしました。