2015年7月29日水曜日

ZYNQのMIO GPIOをLinuxから使う

ZYNQのMIOピンは、わりと制限事項があって割り振り自由度もそう高くないので、だんだんPL部が高機能になってくると最終的にはMIOのどうでもいいピンがデバッグ用に残ったりします。

ZYBOだとMIO7にLEDと、MIO50,51にスイッチが着いてます。

で、このMIO7のLEDをGPIOとして光らそうと思ってえらく苦労したのでメモを残します。



まず、日本人ならほとんどの zynq ユーザーが参考にしてそうな marsee さんの以下の記事
http://marsee101.blog19.fc2.com/blog-entry-2203.html

によると、ベースアドレス0xE000A000以降に必要なレジスタが割り振ってあって、方向指定、アウトイネーブルを1にしたあと出力レジスタのビットを1にすれば良さそうです。
んが、この通りにやっても反応がありませんでした。読み出し方向も全く反応が無く、全レジスタ0が読めるだけです。

Linuxからだと上位1Gの空間にアクセスするのに制限があるのか? とか勘違い迷宮にはまり込んで、LEDドライバを流用したカーネル空間からあれこれトライするも、やっぱりダメです。



ベアメタルでMIOのGPIOを使うサンプルはxilinxにもいろいろあるので、ためしにFSBLのカスタマイズ部分  ( fsbl_hooks.c の FsblHookBeforeHandoff の中 ) に、marseeさんと同じ書き方で
volatile unsigned int* mio_base;
mio_base = 0xe000a000;
*(mio_base + 0x81) = 0x80;
*(mio_base + 0x82) = 0x80;
*(mio_base + 0x10) = 0x80;
と書いてみると、みごとにMIO7のLEDが光ります。


つまりPLのコンフィギュレーションやレジスタの使い方は合っていて、Linuxが起動しちゃうと動作しないわけですから、上記のレジスタ以外の上位概念のせいで動作しなくなっているようです。

テクニカルマニュアル
http://japan.xilinx.com/support/documentation/user_guides/j_ug585-Zynq-7000-TRM.pdf
のgpioセクションをきれいな心で読み返してみると、上位概念は
  • モジュール単位のリセット
  • モジュール単位のクロック
  • 出力ピンのトライステート指定
の3つがあるようです。

今困ってる現象では読み出しもまったく機能せずレジスタが0に見えているので、Linuxがリセットかクロックのどちらかを操作してGPIOモジュールを止めたままにしてるんではないかと思います。



強制的に slcr を操作してモジュールを動かすこともできるかもしれませんが、Linux流のやりかたはLinuxにちゃんと用意されてる gpio-zynq ドライバで初期化する、という方法だと思います。


xilinxドライバ参考資料
http://www.wiki.xilinx.com/Linux+GPIO+Driver
これに加えてxilinx ZYNQ用のGPIOドライバ( gpio-zynq.c )をmenuConfigで有効にしておきます。

dtsにはzynq用ものなら最初からgpioについて書かれてるのでそのままでOKです。


起動すると、特にdmesgにgpioドライバのメッセージはありませんが、なんとなく起動してるっぽくて /sys/class/gpioを見ると gpiochip906 というフォルダが増えました。

が、使い方がよくわからないまま、xilinxの参考資料のとおりに
  >echo 240 > /sys/class/gpio/export
とかやっても特に制御用のgpio204フォルダが出現するわけでもなく、正しく動いてるのかどうかわかりません。

まあ、ドライバは起動してるんだから行けるかな、と思ってここで冒頭のmarseeさんの記事にあったコードを (MIO10ピンを意味する0x400はMIO7相当の0x80に変更して) 実行しても、やっぱり無反応のまま…というところでまた途方にくれていました。



が! その後しばらくぐぐっていたら、xilinxフォーラムに
http://forums.xilinx.com/t5/Embedded-Linux/Zynq-Petalinux-hangs-on-GPIO-access/td-p/645008
という記事があり、一番下の方のデバッグ出力を見ると
GPIOs 906-1023, platform/e000a000.gpio, zynq_gpio:
という箇所があるのを見つけました。906って、さっき出現したgpiochip906と同じです。
つーことは、zynqのmio/emio用gpioモジュールは、ドライバ内ではピン番号906~にマップされてる、てことみたいですね。


それなら! というわけで、MIO7相当の
  >echo 913 > /sys/class/gpio/export
とやってみると、見事にgpio913というフォルダが出現し、その中のdirectionやvalueに1を書き込むとMIO7のLEDが点灯しました。


また、一度このexport操作をすると、後はmarseeさんのコードの通りにレジスタを操作する方法でもLEDのON/OFFが可能でした。

つまり、906以降のどこかのピンに対して最初にexportをしたときにgpioモジュールのクロック供給が開始されてる、てことみたいです。

これでやっと、MIOピンを無駄にせずLinuxからIOとして使えるようになりました。

0 件のコメント:

コメントを投稿