2191は同じ優先順位の割り込みに複数の内蔵ペリフェラルを割り当てることが出来ます。この場合、割り込みがかかったらどのペリフェラルからの割り込みなのかソフトウェアで調べてやる必要があります。
INTRDxはこのためのレジスタです。割り込みが発生した後にINTRDxを読むことによって、どのペリフェラルから割り込みが行われたかを知ることが出来ます。
では、早速例題を見ながらこの方法を考えてみましょう。お題は次のようなものです。
プログラムを下に例示します。mainプログラムは前回とほんの少し違います。
2番目の作業はMASKBSレジスタへの書き込みで行っています。デフォルトの状態では2191はPF割り込みAとBを同じSIG_INT15に割り当てます。したがってハンドラは一つだけです。
ハンドラの中身は大きく様変わりしています。ここでは、割り込みを受けるとどちらのPF割り込みA/Bのどちらであるかを判断した後、それにあわせて処理をします。具体的にはAならばインクリメント、Bならばデクリメントします。
どちらの割り込みがかかったかを調べるには、INTRDxを読みます。今回はSIG_INT15ですので、読み出すのはINTRD11です。これは、INTRD11の11がペリフェラル割り込み順位をであるのに対し、SIG_INT15の15はコア割り込み順位だからです。この点は別文書を参照してください。
INTRD11を読み出せば、そのビットマップの状態でどの割り込みが処理待ちであるかわかります。後は発生した割り込みにあわせてインクリメントかデクリメントを行い、割り込みをクリアするだけです。
割り込みのクリアに気をつけてください。割り込みのクリアは処理した割り込みだけしか行ってはいけません。今回で言えば、FLAGSに0x30を書いてはいけません。なぜならif..else..で処理できるのは片方だけだからです。どうしても両方同時にクリアしたければ、if.. if.. のように変更してA,B両方が同時に割り込みを掛けても処理できるようにしておかなければなりません。
#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, 0x30 ); // set PF4,5 to edge sense. io_space_write( FSBER, 0x00 ); // set PF4,5 to one dege. io_space_write( MASKAS, 0x10 ); // set PF4 to PF interrupt A io_space_write( MASKBS, 0x20 ); // set PF5 to PF interrupt B interrupt( SIG_INT15, &intHandler ); enable_interrupts(); // set GIE while (1) ; } int count = 0; void intHandler( int sig ) { int intrd; sysreg_write( sysreg_IOPG, Interrupt_Controller_Page ); intrd = io_space_read( INTRD11 ); sysreg_write( sysreg_IOPG, General_Purpose_IO ); if ( intrd & 0x1000 ) // PF interrupt A? { io_space_write( FLAGC, 0x10 ); // clear interrupt count ++; } else // PF interrupt B { io_space_write( FLAGC, 0x20 ); // clear interrupt count --; } io_space_write( FLAGS, 0x0f & count ); // set singal to LED io_space_write( FLAGC, 0x0f & ~count ); // clear the 0 LED. }
⇒次はIPRxを使おう