はじめに †
Raspberry Pi 3にCentOS7をインストールした場合のI/Oへのアクセス方法をまとめました。
Rasbianでは、各種の方法が提供されているようですが、CentOSの対応状況が不明です。
そのため、調べた結果をメモします。
デバイスツリーサポート状況 †
デバイスツリー(Device Tree)とは †
聞き慣れない用語ですが、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'"
その他のドライバはデフォルトでは、サポートしていないようで、別途インストールが必要な予感です。
GPIOへのアクセステスト †
では実際にアクセスできるかテストします。
# 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には簡単にアクセスできる方法は用意されていました。
IIC †
IIC(I2C)へのアクセスについても、ドライバーレベルでサポートされるようです。
インストールデフォルトでは、ドライバーがイネーブルにならないようで /boot/config.txt にドライバを読み込む設定が必要です。
以下の2行を追加します。
dtparam=i2c_arm=on
dtparam=i2c1=on
これにより、起動時にドライバーを読み込んでくれるようになります。
# lsmod
(中略)
i2c_dev 6913 0
i2c_bcm2708 5994 0
(以下省略)
# ll /sys/class/i2c-dev
合計 0
lrwxrwxrwx 1 root root 0 8月 12 09:28 i2c-1 -> ../../devices/platform/soc/3f804000.i2c/i2c-1/i2c-dev/i2c-1
#
そのほか †
検索してみたところ、「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).
とありますので、UART、割り込み以外は、おおよそ何でもできそうです。
ライブラリのビルド †
開発ツールはインストール済みの前提です。
早速ビルドしてみます。
# 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カーネルではないので、意味ないかもしれませんが)
お疲れ様でした。