Raspberry Pi 3にCentOS7をインストールした場合のI/Oへのアクセス方法をまとめました。
Rasbianでは、各種の方法が提供されているようですが、CentOSの対応状況が不明です。そのため、調べた結果をメモします。
聞き慣れない用語ですが、I/Oアクセスに関する記事を検索すると、よく見かけます。
結局のところ、ARM Linux 用のプロパティ情報を記述した設定ファイルのことらしい。
Device Treeの仕組みはOpen Firmwareを原点にしており、デバイスのベースアドレスや、クロック、割り込み番号といった、ハードウェア固有のプロパティをカーネルから分離しデバイスドライバの再利用性を高めることが目的としている。結局、ドライバはこの情報を元に、アクセスする。
Device Treeは2.6.38 以前のLinuxカーネルには存在しない。(2.6.38の開発の際に問題となり、対策としてこの手法が以降導入されたらしい)
Linux コミュニティとしては Device Tree 非対応のデバイスドライバのパッチ受け付けはしない決まりになったとのことです。
サポートされていると「/proc/device-tree/」で情報を取得できるようなので、調べてみます。
# ls /proc/device-tree/ #address-cells __symbols__ chosen cpus memreserve soc #size-cells aliases clocks interrupt-parent model system __overrides__ axi compatible memory name #サポートはしているようです。新しいカーネルなので、当たり前といえば当たり前ですが。
実際にどのようなドライバーがインストールされているかを調べます。
モジュールの一覧を調べます。
# lsmod Module Size Used by brcmfmac 186339 0 brcmutil 5661 1 brcmfmac cfg80211 427855 1 brcmfmac rfkill 16037 1 cfg80211 bcm2835_gpiomem 3040 0 bcm2835_wdt 3225 0 uio_pdrv_genirq 3164 0 uio 8000 1 uio_pdrv_genirq ip_tables 11445 0 x_tables 13165 1 ip_tables ipv6 347466 33 #この中で、それらしいのを調べて見ます。
たぶんGPIO用のドライバの用です。まずは、調べてみます。
WiringPiによると bcm2835_gpiomem により /dev/gpiomem interface が使用できるようになるということで、GPIOについてはRasbianと同様のことができることが期待できます。
有効ならば、「gpiomem」ができるようです。# ll /dev/gpiomem crw------- 1 root root 244, 0 1月 1 1970 /dev/gpiomem #
ありました。
次に、rasbianでは、「/sys/class/gpio/」以下に生成されるファイルによりGPI/Oへのアクセスが可能となりますので、あるか調べます。
# ll /sys/class/gpio/ 合計 0 --w------- 1 root root 4096 9月 22 21:30 export lrwxrwxrwx 1 root root 0 9月 22 21:30 gpiochip0 -> ../../devices/platform/soc/3f200000.gpio/gpio/gpiochip0 lrwxrwxrwx 1 root root 0 9月 22 21:30 gpiochip100 -> ../../devices/platform/soc/soc:virtgpio/gpio/gpiochip100 --w------- 1 root root 4096 9月 22 21:30 unexport #ありました。
これらは、以下のudev ruleが設定されていると動作するらしいです。SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio", MODE="0660" SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'" SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"
その他のドライバはデフォルトでは、サポートしていないようで、別途インストールが必要な予感です。
では実際にアクセスできるかテストします。
# echo 21 > /sys/class/gpio/export # ls /sys/class/gpio/ export gpio21 gpiochip0 gpiochip100 unexport # ls /sys/class/gpio/gpio21/ active_low device direction edge power subsystem uevent value # echo out > /sys/class/gpio/gpio21/direction # echo 1 > /sys/class/gpio/gpio21/value # echo 0 > /sys/class/gpio/gpio21/value # echo 21 > /sys/class/gpio/unexport # ls /sys/class/gpio/ export gpiochip0 gpiochip100 unexport #
まずは、GPIOには簡単にアクセスできる方法は用意されていました。
では、C等でGPIO/IIC/SPIなどのインタフェースはどうすればいいのかを調べました。Rasbianでは、ドライバーが用意されているようですが、CentOS7は上記の状況です。
検索してみたところ、「BCM 2835」という、CのRaspberry Pi 用のIOライブラリがありました。早速ダウンロードしてコードを見ると、IOアドレス空間を直接アクセスしています。
ぎょっとしましたが、Linux Kernel 2.6.23-rc1からUIOがマージされて、このようなことが可能になったようです。
コードでは、/dev/memをmmapし、メモリ空間をアクセスしています。また、DeviceTree?にも対応しています。
早速、CentOSでも調べてみます。# ll /dev/mem crw-r----- 1 root kmem 1, 1 1月 1 1970 /dev/mem #ありました。これでイケルようです。
Raspberry Pi用のCライブラリで、
This is a C library for Raspberry Pi (RPi). It provides access to GPIO and other IO functions on the Broadcom BCM 2835 chip, allowing access to the GPIO pins on the 26 pin IDE plug on the RPi board so you can control and interface with various external devices.
It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, and for accessing the system timers. Pin event detection is supported by polling (interrupts are not supported).
It is C++ compatible, and installs as a header file and non-shared library on any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with BCM 2835).
とありますので、割り込み以外は、おおよそ何でもできそうです。
早速ビルドしてみます。
# cd /opt/ # mkdir bcm2835 # cd bcm2835/ # curl http://www.airspayce.com/mikem/bcm2835/bcm2835-1.50.tar.gz -O # tar zxvf bcm2835-1.50.tar.gz # ls bcm2835-1.50 bcm2835-1.50.tar.gz # cd bcm2835-1.50 # ./configure # make # make install
以下のファイルがインストールされます。
種別 ファイル Lib /usr/local/lib/libbcm2835.a Header /usr/local/include/bcm2835.h Document ?
Kernelをアップデートするたびにmakeしなくてよさそうなのがありがたい。
サンプルのLEDチカチカがありますので、テストします。
LEDはGPIO-17(コネクタP1の11)に接続し、1秒間隔で点滅(ON:500ms、OFF:500ms)します。# cd examples/ # cd blink/ # gcc blink.c -o blink_led -l rt -l bcm2835 # ./blink_led
※-l rt はreal-time extensionsです。(RTカーネルではないので、意味ないかもしれませんが)
お疲れ様でした。