はじめに
「お手軽ARMコンピュータ ラズベリー・パイでI/O」(インターフェース増刊 2013 CQ出版社)の「第4章 コマンド入力で外付け回路を動かしてみる」の桑野氏の記事の内容を、2020年秋になってUbuntu 18.04
で動作確認しました1。記事の内容はとても理解しやすく説明も丁寧でわかりやすいのですが、2013年当時の記事でraspbian
の利用が前提なので、Ubuntu
上で動かすにはGPIO上のSPI設定を無効にする作業や、紹介されている回路設計にも一部変更の必要があり、その作業内容や変更点のメモを自分の理解の整理を兼ねて記事にします。
##実験環境
- Raspberry Pi 3B+
- Ubuntu 18.04 LTS
##GPIOテスト用の回路
以下に参考の回路図2へのリンクと実際に作ったデバイスの写真3を示します。
- ONE SEGMENT 7-DIGIT LED TEST BOARDの「回路図」
##確認作業
まず、/sys
ディレクトリのGPIOインターフェースは、初期設定のままで既に存在します。
~$ ls -l /sys/class/gpio/
total 0
--w------- 1 root root 4096 Jan 1 1970 export
lrwxrwxrwx 1 root root 0 Jan 1 1970 gpiochip0 ->
../../devices/platform/soc/3f200000.gpio/gpio/gpiochip0
lrwxrwxrwx 1 root root 0 Jan 1 1970 gpiochip504 -> ../../devices/platform/soc/soc:firmware/soc:firmware:expgpio/gpio/gpiochip504
--w------- 1 root root 4096 Jan 1 1970 unexport
でも、GPIO7
のピンのシンボリックリンクを作成しようとすると、「デバイスかリソースがビジーで、echoでの書き込みエラー」と叱られます。
~$ sudo -s
~# echo 7 >/sys/class/gpio/export
bash: echo: write error: Device or resource busy
デフォルトでGPIO7
とGPIO8
のピンがSPI用に設定されていました4。
~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-53, parent: platform/3f200000.gpio, pinctrl-bcm2835:
gpio-7 ( |spi0 CS1 ) out hi ACTIVE LOW
gpio-8 ( |spi0 CS0 ) out hi ACTIVE LOW
gpio-29 ( |led0 ) out lo
~# exit
##raspi-config のインストール
GPIOの機能設定には、raspi-configを使用しました。raspbian専用の設定変更ツールなのですが、ubuntuでも以下のURLで動作することが紹介されていたので、その紹介されている手順どおりに作業しました。
sudo echo "deb http://archive.raspberrypi.org/debian/ jessie main" >> /etc/apt/sources.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 7FA3303E
sudo apt-get update
sudo apt-get install raspi-config
sudo mount /dev/mmcblk0p1 /boot
これで、普通にraspi-configのGUIのメニュー画面を立ち上げることができます。
~$ sudo rapsi-config
rapsi-configのトップメニュー画面から「5 Interfacing Options Configure connections to peripherals」>「P4 SPI Enable/Disable automatic loading of SPI kernel module」を選択します。あとは、「Would you like the SPI interface to be enabled?」で「No」を選択すると「The SPI interface is disabled」のメッセージで「Ok」を押すとトップ画面に戻りますので、最後に「Finish」で変更を保存するだけです。
~$ sudo reboot -h now
設定変更を読み込むためにリブートしたら、もう一度GPIOの設定状況を確認します。
~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-53, parent: platform/3f200000.gpio, pinctrl-bcm2835:
gpio-29 ( |led0 ) out lo
gpiochip1: GPIOs 504-511, parent: platform/soc:firmware:expgpio, raspberrypi-exp-gpio, can sleep:
gpio-506 ( |led1 ) out lo ACTIVE LOW
GPIO7と8がリストから消えていたら成功です。ここでうまくいかなかった場合、raspi-config
の変更設定が保存されていないことが考えられます。
##参考
今回の作業の目的は、自作のGPIOデバイスドライバ学習用デバイスの回路テストの実行環境の構築です。つまり、実際に以下のシェルスクリプトのコードを動かして回路上の配線ミスがないかなどを最終チェックすることでした。
コマンドラインでエラーも出ず、実機テストでも、スクリプトの仕様通り、ドットが2回点滅した後に7セグLEDに0から9までの数字が表示されて再度ドットが2回点滅した後に終了しました。
プッシュボタンを開放した状態ではコンソール画面に1
が表示され、ボタンを押すと0
が表示されます。
なお、「ラズベリーパイでI/O」当時から、GPIO番号の配置が少し変更になっています。今回の実験用回路では、プッシュスイッチの物理的なピン位置を従来のまま3番と5番を使っているので、GPIO番号を「0
と1
」の組み合わせから「2
と3
」の組み合わせにプログラム上で変更しています。
echo gpio export pin seting ...
echo 2 > /sys/class/gpio/export
echo 3 > /sys/class/gpio/export
echo 7 > /sys/class/gpio/export
echo 8 > /sys/class/gpio/export
echo 9 > /sys/class/gpio/export
echo 10 > /sys/class/gpio/export
echo 11 > /sys/class/gpio/export
echo gpio pin direction seting ...
echo in > /sys/class/gpio/gpio2/direction
echo in > /sys/class/gpio/gpio3/direction
echo out > /sys/class/gpio/gpio7/direction
echo out > /sys/class/gpio/gpio8/direction
echo out > /sys/class/gpio/gpio9/direction
echo out > /sys/class/gpio/gpio10/direction
echo out > /sys/class/gpio/gpio11/direction
echo gpio test start...
echo 1 > /sys/class/gpio/gpio7/value
echo 1 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 1 > /sys/class/gpio/gpio10/value
echo 1 > /sys/class/gpio/gpio11/value
echo 1 > /sys/class/gpio/gpio11/value
sleep 1
echo 0 > /sys/class/gpio/gpio11/value
sleep 1
echo 1 > /sys/class/gpio/gpio11/value
sleep 1
echo 0 > /sys/class/gpio/gpio11/value
sleep 1
echo 0 > /sys/class/gpio/gpio7/value
echo 0 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 0
sleep 1
echo 1 > /sys/class/gpio/gpio7/value
echo 0 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 1
sleep 1
echo 0 > /sys/class/gpio/gpio7/value
echo 1 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 2
sleep 1
echo 1 > /sys/class/gpio/gpio7/value
echo 1 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 3
sleep 1
echo 0 > /sys/class/gpio/gpio7/value
echo 0 > /sys/class/gpio/gpio8/value
echo 1 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 4
sleep 1
echo 1 > /sys/class/gpio/gpio7/value
echo 0 > /sys/class/gpio/gpio8/value
echo 1 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 5
sleep 1
echo 0 > /sys/class/gpio/gpio7/value
echo 1 > /sys/class/gpio/gpio8/value
echo 1 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 6
sleep 1
echo 1 > /sys/class/gpio/gpio7/value
echo 1 > /sys/class/gpio/gpio8/value
echo 1 > /sys/class/gpio/gpio9/value
echo 0 > /sys/class/gpio/gpio10/value
echo 7
sleep 1
echo 0 > /sys/class/gpio/gpio7/value
echo 0 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 1 > /sys/class/gpio/gpio10/value
echo 8
sleep 1
echo 1 > /sys/class/gpio/gpio7/value
echo 0 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 1 > /sys/class/gpio/gpio10/value
echo 9
sleep 1
echo 0 > /sys/class/gpio/gpio7/value
echo 1 > /sys/class/gpio/gpio8/value
echo 0 > /sys/class/gpio/gpio9/value
echo 1 > /sys/class/gpio/gpio10/value
echo 1 > /sys/class/gpio/gpio11/value
echo dot
sleep 1
echo 0 > /sys/class/gpio/gpio11/value
sleep 1
echo 1 > /sys/class/gpio/gpio11/value
sleep 1
echo 0 > /sys/class/gpio/gpio11/value
sleep 1
echo 1 > /sys/class/gpio/gpio11/value
cat /sys/class/gpio/gpio2/value
cat /sys/class/gpio/gpio3/value
echo test exiting...
echo 2 > /sys/class/gpio/unexport
echo 3 > /sys/class/gpio/unexport
echo 7 > /sys/class/gpio/unexport
echo 8 > /sys/class/gpio/unexport
echo 9 > /sys/class/gpio/unexport
echo 10 > /sys/class/gpio/unexport
echo 11 > /sys/class/gpio/unexport
echo end
##おわりに
デバイスドライバの作成の実験のための準備で、できるだけ単純な動作確認のためraspi-configの導入を行いました。/sys/kernel/debug/gpio
ファイルの中に、gpiochip0: GPIOs 0-53, parent: platform/3f200000.gpio, pinctrl-bcm2835
と表記されており、SOCのGPIOアドレスが3f200000からであることがこんなところにも記載されていることを知り、単純な実験ですがLinuxがまた更に身近に感じられるようになりました。
次は、C言語でGPIOデバイス・ドライバでの使い方と、レジスタを直接たたく方法を実験したいと思います。
-
私個人が将来的に
ROS
の学習を予定しているので、ROS
のインストールが楽なubuntu
をOSとして選んだ結果として発生した作業なので、もちろん、raspbian
なら最新バージョンでもraspi-config
は初期設定に入っているので利用するのに必要な作業はありません。 ↩ -
実際に作ったデバイスの回路は、「Raspberry Piで学ぶ ARM デバイスドライバー プログラミング」(米田聡著 2014 ソシム)P.47の7セグLEDと74HC4511を使った設計を少しだけ修正したものです。修正点は、DP端子用を抵抗(510Ω)を介してGPIO11に直接接続してコントロールしている点と、「ラズベリーパイでI/O」の回路のとおり、10kオームのプルアップ抵抗を使用したプッシュスイッチ2個を追加している点だけです。スイッチのコントロールのためのGPIOへの接続は、
J8 GPIO
のGPIO2
とGPIO3
を使用しています。 ↩ -
ICとユニバーサル基板以外は、ほとんど自宅にあった廃材を再利用しているのと、配線を間違えて配線を何度もつけたり外したりしたので配線も作りも雑ですが、とりあえずは指示通りに動いてくれています。 ↩
-
上のデバイスの写真にあるとおり、電源を入れると自動的に数字の
3
が表示されます。74HC3411
で3
が表示されるのは、回路図からGPIO7
とGPIO8
がH
になっているからなので、GPIOに回路をつなげた段階でSPIが初期設定で使えるようになっていることの想像はできますが、コマンドでも調べられると大変便利です。 ↩