CentOSからI/Oをアクセス

はじめに

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には簡単にアクセスできる方法は用意されていました。

その他のアクセス方法

では、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
#

ありました。これでイケルようです。

BCM 2835

概要

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カーネルではないので、意味ないかもしれませんが)

お疲れ様でした。


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS