PFピンはProgrammableと名乗るだけあって機能が豊富です。当然割り込み源としても使えます。そこで今回はPFピンを割り込み源として使ってみましょう。例題として作るのは次のようなプログラムです
つまりPF4を割込み源とするプログラムです。では、まずはいつもの通り関連レジスタの説明を。FSPRについては前回をご覧下さい。
FSSR (Flag Source Sensetivity Register)は割り込み入力にしたフラグがエッジ・センスかレベル・センスかを決定します(HR B-90)。あるビットが1ならば、対応するPF割り込み入力がエッジ・センスになります。0ならばレベルセンスです。
FSBER (Flag Set on Both Edge Register )は割り込み入力にしたフラグがシングル・エッジ割り込みかダブル・エッジ割り込みかを決めます(HR B-91)。あるビットが1ならば、対応するPF割り込み入力がダブル・エッジになります。0ならばシングルエッジ割り込みです。
制御レジスタ | PFピンの状態 | |||||
---|---|---|---|---|---|---|
FSBER | FSSR | FSPR | H | L | ↑ | ↓ |
0 | 0 | 0 | x | x | 〇 | - |
0 | 0 | 1 | x | x | - | 〇 |
0 | 1 | 0 | 〇 | - | x | x |
0 | 1 | 1 | - | 〇 | x | x |
1 | 0 | 0 | x | x | 〇 | 〇 |
1 | 0 | 1 | x | x | 〇 | 〇 |
1 | 1 | 0 | 〇 | - | x | x |
1 | 1 | 1 | - | 〇 | x | x |
表に各レジスタの設定と、対応するPFピンの状態を元にした割り込みの発生条件を示します
PFは2種類の割り込みを起こすことが出来ます。一つはPF割り込みAと呼ばれ、もう一つはPF割り込みBと呼ばれます。両者は同じ機能をもっており、単に複数あるPF入力割り込みを二系統に分類するというだけです。必要なければ無理に分類する必要はありません。
分類はMASKAS, MASKACによって行います(HR B-89)。MASKASにある値を代入すると、1を与えられたビットに対応するPFはPF割り込みAを発生します。0を与えられたビットに対応するPFの割り込みに関する設定は変わりません。MASKACにある値を代入すると、1を与えられたビットに対応するPFはPF割り込みAを発生しなくなります。0を与えられたビット非対応する設定は変わりません。
同様のレジスタとしてMASKBS、MASKBCがあります。これらはPF割り込みBに関するものです。一つのPFからA、B二つの割り込みを発生させることも出来ます。
219xコアへの割り込み入力はすべてレベル入力になっています。つまり、エッジ割り込みでなんであれ、誰かがラッチして219xコアに入力しているのです。そうなると、割り込み処理終了後にこれをクリアしなければなりません。それが、FLAGCレジスタへの書き込みです(HR B-89)。
FLAGCレジスタには、割り込みソースになっているPFに1を書き込むと、そのソースからの割り込みをクリアする機能があります。出力だけじゃないんですね。間違えやすそうです。
以上の他、HR 14-43からPFに関する詳しい説明がありますので読んでおいてください。特にHR 14-44にはレジスタ変更とレイテンシの話がありますので重要です。
さてプログラムです。例によってLED、スイッチ、PFの関係を再掲します。
PF0 | PF1 | PF2 | PF3 | PF4 | PF5 |
---|---|---|---|---|---|
LED8 | LED9 | LED10 | LED11 | SW3 | SW2 |
EZ-KIT Liteでは、SWを押すとPFがHになり、PFにHを出力するとLEDが点灯します。わかりやすいですね。
以下、プログラムを見ていきましょう。
実行プログラム1行目ではIOPGを General_Purpose_IO にして、以下のIOアクセスをすべてフラグIOにします。2行目ではPF0-3を出力とし、他のPFを入力としています。3行目では入力の極性をすべて正論理としています。
今回新しいのは4行目のFSSRの設定からです。ここではPF4(SW3)をエッジ・センスに指定しています。5行目ではFSBERを使ってシングル・エッジでの割り込みとしています。前出の表と見合わせて、ボタンを押した瞬間に割り込みが入るとわかります。
6行目のMASKASで、PF4(SW3)をPF割り込みAに割り当てています。
8行目のinterrupt()で割り込みハンドラを登録しています。登録しているのはSGI_INT15で、これはPF割り込みAがデフォルトで割り当てられる割り込み優先順位です。
次にintHandler()の説明です。2行目と3行目でフラグにカウンタの値を出力しています。このとき、代入一回でフラグのすべてのビットに任意の値をセットすることが出来ないため、1にするビットと0にするビットに分けて制御しています。面倒な部分です。
さて、今回一番重要な部分がintHandler()実行部の4行目です。ここは単にフラグのクリアに見えますが、そうではなくて割り込みのクリアです。もし、これを怠ると割り込みから帰っても即割り込みがかかるため、延々と割り込みハンドラが呼ばれることになります。
説明が長くなりました。動かしてみましょうか。
#include <def2191.h> #include <sysreg.h> #include <signal.h> void intHandler( int ); int main(void) { sysreg_write( sysreg_IOPG, General_Purpose_IO ); io_space_write( DIR, 0x0f ); // set PF0-3 to output io_space_write( FSPR, 0x00 ); // Source polarity is positive. io_space_write( FSSR, 0x10 ); // set PF4 to edge sense. io_space_write( FSBER, 0x00 ); // set PF4 to one dege. io_space_write( MASKAS, 0x10 ); // set PF4 to PF interrupt A interrupt( SIG_INT15, &intHandler ); enable_interrupts(); // set GIE while (1) ; } int count = 0; void intHandler( int sig ) { count ++; io_space_write( FLAGS, 0xf & count ); // set singal to LED io_space_write( FLAGC, 0xf & ~count ); // clear the 0 LED. io_space_write( FLAGC, 0x10 ); // clear the interrupt }
SW3を押下すると、そのたびにLEDの値がカウントアップしていきます。今回は単純な割には設定が面倒でしたが、そのご褒美(?)にいろいろ遊べます。DSPR、FSSR、FSBERのビット4の値をいろいろ変えてみましょう。前述の割り込み設定と条件の表を眺めながらLEDの動きを見ると楽しいですよ。
割り込みハンドラの動きを捕まえたいときにはブレークポイントを使います。ブレークポイントを掛けたい行で右クリック⇒Insert Breakpointを実行してください。
⇒次はINTRDxを使おう