Wed 01/18, 2012

GPIO input on BeagleBone [Electronics ]

今回は BeagleBone (Angstrom) での GPIO 入力について。サンプルを探すと https://github.com/joelagnel/validation-scripts/tree/master/bone-tester/lib に led.sh とか util.sh があった。これを元に GPIO1_6 (拡張ヘッダ P8-3)の状態を取得してみる。

# 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
#
こんな具合に期待通り入力状態が得られる。38 というのは GPIO1_6 に対応するシステム上の識別番号で、とりあえずは cloud9 IDE サンプルの bonescript/index.js を見れば判る。

これをもう少し詳しく見てみる。最初に # 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 以下については次のような属性のエントリができる。

  • direction - in または out で示される入出力方向。read で現在値が得られ、write で変更できる。
  • value - direction=in の場合には read で GPIO の値(1 または 0)が得られ、direction=out の場合には、これに write することで 0 または 1(0以外の場合)を出力する。
  • edge - direction=in での読み取りタイミングと、その指定。"none", "rising", "falling", "both" のいずれか。
  • active_low - 論理値の反転。
ここで振り返って bonescript/index.js を見ると pinMode でなにやら /sys/kernel/debug/omap_mux/* を操作している。この辺りの事情は先ほどのドキュメントには書かれていないが、mux と言う名前から MCU のピンの役割選択であることだと予想が付く。

# 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
/sys/kernel/debug/omap_mux/ ディレクトリには信号ピンの MODE0 での名称が並んでいる。BeagleBone 付属のリファレンスマニュアルの Table 9 および 10 で P8 の各ピンのモードについてみると GPIO1_6 は MODE7 で、MODE0 は gpmc_ad6 となっているから、これを見てみる。
# 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
# 
なにやらレジスタっぽい値が表示されたから、AM335x ARM® Cortex™-A8 Microprocessors (MPUs) Technical Reference Manual を参照して調べると "9. Control Module" に解説がある。
  • Table 2-2. L4_WKUP Peripheral Memory Map
    Control Module 0x44E1_0000-0x44E1_1FFF 128KB Control Module Registers
  • Table 9-8. CONTROL_MODULE REGISTERS
    818h conf_gpmc_ad6
  • 9.3.1.50 conf_<module>_<pin> Register (offset = 800h)
  • Table 9-58. conf_<module>_<pin> Register Field Descriptions
つまり、0x0037 という値は MODE7/Receiver enabled/プルアップ/Fast と言うことになる。 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) とすれば良さそうだが、変更するのはちょっと怖い。
[追記ここまで]

と言うことで、とりあえず bonescript/index.js では bone の定義で mux を外すか 7 を 0x37 とすれば入力も取れる。digitalRead() はこんな感じで 0 または 1 が得られる。
digitalRead = exports.digitalRead = function(pin)
{
  var s = fs.readFileSync(gpio[pin.gpio].path, 'ascii');
  s.split('\s+');
  return s[0];
}
まとめ。基本は Linux スタイル GPIO。pinmux については /sys/kernel/debug/omap_mux/* で操作する。

続く、かも。

Posted by masato at 10:01 PM
このエントリーのトラックバックURL: http://bird.dip.jp/cgi-bin/mt/mt-tb.cgi/1817
コメントする

おそらく携帯電話等からは投稿できません。日本語文字列を含まないコメントやトラックバック、および当サイトへの言及を含まないトラックバックは御遠慮いただいております。また、90日以上経過した記事へのコメントはできません。










名前、アドレスを登録しますか?