GPIOをソフトウェアから制御する
72. SDKが動いてHello Worldが出たら、アプリケーションを自分用に書き換えてあげましょう。
プロジェクトの中にあるhellow.cは次のようになっています。
#include#include "platform.h" void print(char *str); int main() { init_platform(); print("Hello World¥n¥r"); return 0; }
このincludeに、xparameters.hと、xgpio.hを追加します。
73. ポートから値を出力するには次のようにします。
#include "xparameters.h" #include "xgpio.h" int main(){ ・・・ XGpio xgpout; // ハンドルの生成 XGpio_Config xcfg_out; xcfg_out.DeviceId = XPAR_LEDS_DEVICE_ID; XGpio_CfgInitialize(&xgpout, &xcfg_out, XPAR_LEDS_BASEADDR); // 初期化 XGpio_SetDataDirection(&xgpout, 1, 0); // 方向の設定 チャネル1 方向0(出力) XGpio_DiscreteWrite(&xgpout,1,0x55); // 値の出力 チャネル1に0x55
XPAR_LEDS_BASEADDRというのは、xparameters.h中でdefineで定義されている値です。
このマクロを使えばよいので、GPIOを操作するときに、レジスタのアドレスはどこだろう・・などと調べる必要はありません。xparameters.hをインクルードすればすべて解決します。
xgpoutという変数はハンドルみたいなものです。xcfg_outはDeviceIdを設定するためだけに使われるようで、しかもこの値は結局参照されていないようなのですが、上のリストのようにXPAR_LEDS_DEVICE_IDでマクロ定義された値を設定します。そして、XGpio_CfgInitializeでGPIOの特定のポートを初期化します。ここで与えるアドレスはGPIOの実効アドレスなのですが、これもXPAR_LEDS_BASEADDRというマクロで定義されています。(実際の値は0x40000000)
XGpio_SetDataDirectionはGPIOの方向を指定する関数ですが、第一引数は先のハンドルを指定します。第二引数はチャネル番号で、通常は1です。最後の0は全ポート出力を意味します。(各ビットが1だと入力になる)
実際に値を出力するのは、XGpio_DiscreteWriteという関数です。第一引数は先のハンドルを指定します。第二引数はチャネル番号でこれも1です。第三引数に出力したい値を指定します。
たかがGPIOからの出力のためにわざわざハンドルを作らなければならないのが面倒ですが、このようにしてソフトウェアからFPGA部分に任意の値を送り込むことができます。
74. ポートから値を入力する場合は次のようにします。
GPOUTとは逆にやればよいので、それほど難しくはないはずです。
XGpio xgpin; // ハンドルの生成 XGpio_Config xcfg_in; xcfg_in.DeviceId = XPAR_AXI_GPIN_DEVICE_ID; XGpio_CfgInitialize(&xgpin, &xcfg_in, XPAR_AXI_GPIN_BASEADDR); // 初期化 XGpio_SetDataDirection(&xgpin, 1, 1); // 方向の設定 チャネル1 方向1(入力) xil_print("%4d ", XGpio_DiscreteRead(&xgpin,1));// 値の出力 チャネル1
※ このプログラムをビルドするには、ステップ18のXPSメイン画面で、AXI GPIOを追加して、汎用の入力ポートを作っておくこと。