今回は BeagleBone (Angstrom) での GPIO 入力について。サンプルを探すと https://github.com/joelagnel/validation-scripts/tree/master/bone-tester/lib に led.sh とか util.sh があった。これを元に GPIO1_6 (拡張ヘッダ P8-3)の状態を取得してみる。
こんな具合に期待通り入力状態が得られる。38 というのは GPIO1_6 に対応するシステム上の識別番号で、とりあえずは cloud9 IDE サンプルの bonescript/index.js を見れば判る。# echo 38 > /sys/class/gpio/export # cat /sys/class/gpio/gpio38/value 1 --- ここで P8-1(GND) と P8-3 をショートさせる。 --- # cat /sys/class/gpio/gpio38/value 0 #
これをもう少し詳しく見てみる。最初に # echo 38 > /sys/class/gpio/export
を実行する前には /sys/class/gpio/gpio38 ディレクトリは存在していない。そして
# echo 38 > /sys/class/gpio/unexport で消える。これは GPIO 操作をユーザスペースからおこなうための手続きで、こうしたことについては Linux Kernel の GPIO Interface のドキュメント(http://www.kernel.org/doc/Documentation/gpio.txt)に書かれていて、/sys/class/gpio/gpioN 以下については次のような属性のエントリができる。
ここで振り返って bonescript/index.js
を見ると pinMode
でなにやら /sys/kernel/debug/omap_mux/*
を操作している。この辺りの事情は先ほどのドキュメントには書かれていないが、mux と言う名前から MCU のピンの役割選択であることだと予想が付く。
/sys/kernel/debug/omap_mux/ ディレクトリには信号ピンの MODE0 での名称が並んでいる。BeagleBone 付属のリファレンスマニュアルの Table 9 および 10 で P8 の各ピンのモードについてみると GPIO1_6 は MODE7 で、MODE0 は gpmc_ad6 となっているから、これを見てみる。# ls /sys/kernel/debug/omap_mux/ ain0 gpmc_ad3 lcd_data3 mii1_txd1 ain1 gpmc_ad4 lcd_data4 mii1_txd2 ain2 gpmc_ad5 lcd_data5 mii1_txd3 ain3 gpmc_ad6 lcd_data6 mii1_txen ain4 gpmc_ad7 lcd_data7 mmc0_clk ain5 gpmc_ad8 lcd_data8 mmc0_cmd ain6 gpmc_ad9 lcd_data9 mmc0_dat0 ain7 gpmc_advn_ale lcd_hsync mmc0_dat1 board gpmc_ben0_cle lcd_pclk mmc0_dat2 ecap0_in_pwm0_out gpmc_ben1 lcd_vsync mmc0_dat3 gpmc_a0 gpmc_clk mcasp0_aclkr rmii1_refclk gpmc_a1 gpmc_csn0 mcasp0_aclkx spi0_cs0 gpmc_a10 gpmc_csn1 mcasp0_ahclkr spi0_cs1 gpmc_a11 gpmc_csn2 mcasp0_ahclkx spi0_d0 gpmc_a2 gpmc_csn3 mcasp0_axr0 spi0_d1 gpmc_a3 gpmc_oen_ren mcasp0_axr1 spi0_sclk gpmc_a4 gpmc_wait0 mcasp0_fsr uart0_rtsn gpmc_a5 gpmc_wen mcasp0_fsx uart0_rxd gpmc_a6 gpmc_wpn mdio_clk uart0_txd gpmc_a7 i2c0_scl mdio_data uart1_ctsn gpmc_a8 i2c0_sda mii1_col uart1_rtsn gpmc_a9 lcd_ac_bias_en mii1_crs uart1_rxd gpmc_ad0 lcd_data0 mii1_rxclk uart1_txd gpmc_ad1 lcd_data1 mii1_rxd0 uatr0_ctsn gpmc_ad10 lcd_data10 mii1_rxd1 usb0_drvvbus gpmc_ad11 lcd_data11 mii1_rxd2 usb1_drvvbus gpmc_ad12 lcd_data12 mii1_rxd3 vrefn gpmc_ad13 lcd_data13 mii1_rxdv vrefp gpmc_ad14 lcd_data14 mii1_rxerr xdma_event_intr0 gpmc_ad15 lcd_data15 mii1_txclk xdma_event_intr1 gpmc_ad2 lcd_data2 mii1_txd0
なにやらレジスタっぽい値が表示されたから、AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference Manual を参照して調べると "9. Control Module" に解説がある。# cat /sys/kernel/debug/omap_mux/gpmc_ad6 name: gpmc_ad6.gpio1_6 (0x44e10818/0x818 = 0x0037), b NA, t NA mode: OMAP_PIN_OUTPUT | OMAP_MUX_MODE7 signals: gpmc_ad6 | mmc1_dat6 | NA | NA | NA | NA | NA | gpio1_6 #
bonescript/index.js
での pinMode
ではこれを 0x37 ではなく 0x07 に設定しているから、Receiver disabled となって入力動作ができなくなるらしい。試してみた限り 0x37 の状態から echo out > /sys/class/gpio/gpio38/derection
と出力モードにしても /sys/kernel/debug/omap_mux/gpmc_ad6
の値も OMAP_PIN_OUTPUT の表示も変わらない。詳細は kernel のソースコードを追わないと判らなさそうだが、おそらく BeagleBone の AM335x への対応が不十分なのだと思われる。
BeagleBone でのデフォルトはリファレンスマニュアルのピン名で、MODE7 の GPIO となっているとは限らないために MODE7 指定をしているのだろうが、0x37 ではなく 0x07 である意味はよく判らない。どうやらこれは BeagleBoard の AM35x プロセッサの名残りらしい。AM35x では GPIO の入出力の設定は bit 8 だったものが BeagleBone の AM335x では bit 5 になっている。bit 5-7 は AM35x では reserved となっていて使用されていない。
[追記]
ソースコードを見ると arch/arm/mach-omap2/mux.h で
# define OMAP_INPUT_EN (1 << 8)
となっている。これを (1 << 5) とすれば良さそうだが、変更するのはちょっと怖い。まとめ。基本は Linux スタイル GPIO。pinmux については /sys/kernel/debug/omap_mux/* で操作する。digitalRead = exports.digitalRead = function(pin) { var s = fs.readFileSync(gpio[pin.gpio].path, 'ascii'); s.split('\s+'); return s[0]; }
続く、かも。
Posted by masato at 10:01 PMおそらく携帯電話等からは投稿できません。日本語文字列を含まないコメントやトラックバック、および当サイトへの言及を含まないトラックバックは御遠慮いただいております。また、90日以上経過した記事へのコメントはできません。