PF出力を使おう

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ピンは変化しません。

これはビット単位でセット・クリアを行うような制御では大変重宝します。と、いうのはプログラム側で読んでマスクをかけて修正するような手間が不要だからです。逆にビットフィールドにビットパターンをセットするような処理は手間が増えて不便です。

IOマップドIO

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で定義されています。

IOページ

さて、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で遊ぶサイトですから何か動かしてみましょう。

以下のプログラムは次のような動作をします

  1. PF0-PF3を出力にする
  2. PF0-PF3に1を出力する
  3. PF0とPF2に0を出力する

その結果、ステップ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++で開いた後、メニューバーProjectUpdage Dependenciesを実行してください。プロジェクトを作成場所から移動させた場合にはこれが必要です。

⇒次はPF入力を使おう

2191空挺団 | プログラム | EZ-KIT | こぼれ話 | アーキテクチャー | 命令 | レジスタ | DSP掲示板 | FAQ |