ADSP-2191にはPF( Programmable Flag )入出力と呼ばれる機能があります。いわゆるGPIOなのですが、2191には都合16本のPF入出力があります。16本のPFピンにはPF0からPF15までの名前がついており、EZ-KIT Lite 2191ではこのうちPF0からPF3までをLED出力、PF4とPF5をボタンスイッチ入力として使っています(下の表)。
PF0 | PF1 | PF2 | PF3 | PF4 | PF5 |
---|---|---|---|---|---|
LED8 | LED9 | LED10 | LED11 | SW3 | SW2 |
今回はこれらのうちPF0からPF3までを出力として使い、LEDの点灯と消灯を制御します。
PFピンはプログラマブルですので極性や方向を自由に変えることが出来ます。これらの変更は制御レジスタで行いますが、どのレジスタもレジスタ内部のビットとPFピンが一対一対応しています。つまり、ビット0がPF0、ビット1がPF1に対応しています。
入出力の方向を決めるIOレジスタはDIRレジスタです。このレジスタの任意のビットを1にすると対応するPFピンが出力になります。逆に任意のビットを0にすると対応するPFピンが入力になります。
方向をDIRレジスタで決めた後は、データを出力します。出力データはFLAGSレジスタとFLAGCレジスタを使って書き込みます。この方法は少し注意が必要です。
例を使って説明しましょう。FLAGSレジスタに0x0005を書き込んだとします。このとき、PF0とPF2が1になり、その他のピンの状態は変わりません。次にFLAGCレジスタに0x0005を書き込んだとします。このとき、PF0とPF2が0になり、その他のピンの状態は変わりません。
つまり、FLAGSとFLAGCはそれぞれ書き込んだデータの1に対応するPFピンをセットあるいはクリアします。書き込んだデータの0に対応するPFピンは変化しません。
これはビット単位でセット・クリアを行うような制御では大変重宝します。と、いうのはプログラム側で読んでマスクをかけて修正するような手間が不要だからです。逆にビットフィールドにビットパターンをセットするような処理は手間が増えて不便です。
DIR、FLAGC、FLAGSといったレジスタはどのようにしてアクセスするのでしょうか。また、それはC言語から可能でしょうか。結論から言うとレジスタはIO空間にマップされており、標準のC言語からアクセスすることは出来ません。
IO空間はアドレスを持っていますが、通常のメモリー空間とは独立しているため、専用のアクセス命令を使います。このようなメモリーアクセス方法をIOマップドIOと呼びます。ADSP-2191はこのIO空間をアクセスする専用命令を持っていますが、当然この命令は標準C言語から扱うことはできません。そこでアナログデバイセズのCコンパイラは特殊な拡張を行ってIO空間にアクセスします。
IO空間のレジスタをアクセスするには、最初にsysreg.hをインクルードしてください。このヘッダーファイルにはアクセスに必要なマクロやプロトタイプが用意されています。
C言語からIOレジスタに書き込むときには次のように書きます。
io_space_write( レジスタアドレス, 値 );
レジスタアドレスで示されるレジスタに値が書き込まれます。例えば、FLAGCに値0x05を書き込むには次のようにします。
io_space_write( FLAGC, 0x05 );
ここでFLAGCはこのレジスタのアドレスを表すマクロです。このマクロはVisualDSP++のヘッダーファイルdef2191.hで定義されています。
さて、ADSP-2191のIOは困ったことにもうひとひねりあります。それはIOマップドIOかつ、セグメント・アドレスなのです。つまり、IOアドレスはセグメント+オフセットであらわされます。アナログデバイセズはこのセグメントのことをIOページと呼んでいます。
言葉を変えて言うと、DIRCに書き込みたければ漫然とDIRCに書くだけではだめで、事前にIOページを正しいものにセットしなければなりません。IOページはIOPGレジスタに書き込むことでセットできます。うんざりするような話ですがそうなっているものは仕方ありません。レジスタとIOページの関係はADSP-219x/2191 DSP Hardware ReferenceのテーブルB-1に定義されています。このマニュアルはVisualDSP\doc\2191_hwr\にPDFとして納められています。
IOPGに設定するべき値をもっと簡単に知るにはdef2191.hを見るのが一番です。ここには各IOペリフェラルごとにIOページの値が書いてあります。結論から言うとDIRやFLAGCのIOページは General_Purpose_IO です
私はこれもバグじゃないかとにらんでます。正しい名前はGenral_Purpose_IO_Page じゃないでしょうか (¬_¬)アヤシイさて、脱線が相次ぎましたが、IOPGをC言語からセットするにはsysreg_writeを使います。次の例はIOPGをセットしてPF関連レジスタにアクセスできるようにしています。
sysreg_write( sysreg_IOPG, General_Purpose_IO );
さて、理屈ばかりで退屈でしたでしょうか。せっかくEZ-KIT Liteで遊ぶサイトですから何か動かしてみましょう。
以下のプログラムは次のような動作をします
その結果、ステップ2でLED8からLED10が全点灯し、次にLED8とLED10が消灯します。特別な制御はしていませんので、上の説明を読めば下のプログラムは自明だと思います。
#include <def2191.h> #include <sysreg.h> int main(void) { sysreg_write( sysreg_IOPG, General_Purpose_IO ); io_space_write( DIR, 0xf ); io_space_write( FLAGS, 0xf ); io_space_write( FLAGC, 0x5 ); }
なお、プロジェクトを丸ごと圧縮したものを用意しました。興味がある方はダウンロードして使ってください(7.5KB)。使用するにはVisualDSP++で開いた後、メニューバー⇒Project⇒Updage Dependenciesを実行してください。プロジェクトを作成場所から移動させた場合にはこれが必要です。
⇒次はPF入力を使おう