割り込みは普通のC言語のスタイルにうまく乗せにくいのですが、VisualDSP++のC言語はANSI標準の範疇でうまいこと割り込みをさばいています。219xの割り込みについては別ページを見てもらうとしてここでは219xの割り込みをC言語で取り扱う方法を紹介します。
VisualDSP++のC言語は、割り込みハンドラをC言語で書くことが出来るようになっています。void func( int );型の関数として記述したハンドラはinterrupt()関数でシステムに登録します。
interrupt()関数は二つの引数を受け取ります。最初の引数はハンドラを登録する割り込みを指定します。ここでの割り込みとは219xの割り込みベクトル番号であり、SIG_で始まるマクロです。このマクロはsignal.hに定義されています。このマクロ名と219xのベクトルの対応については別表をご覧下さい。
二番目の引数は割り込みハンドラへのポインタです。ここにポインタでなくSIG_IGNを与えると、その割り込みを禁止できます。
Compiler patch 6.1.2から、interrupt()関数の挙動がかわっていますので注意してください。これまでinterrupt()関数を使ってハンドラを登録すると自動的にICNTLのGIEをセットしてグローバル割り込みを有効にしていました。しかし6.1.2では変化しなくなりました。これはバグではなく、今後はこのようにするとのことです。したがって、今後はプログラマが明示的にGIEをセットしなければなりません。具体的にはsysreg.hのenable_interrupts()関数を呼びます。
割り込みは本来外部ハードウェアが起こすものですが、raise()関数を使ってソフトウェアから起こすことも出来ます。今回はとりあえず割り込みがどんなものか見たいだけなのでraise()関数を使ってみました。
raise()関数の引数は割り込み番号です。
下にプログラムを例示します。このプログラムは本体でLED8-11を出力に設定します。割り込みが入るとハンドラの中でLEDを点灯します。本体ではLEDを消灯します。本体ではraise()関数とLED消灯を交互に実行します。
while()文以下をステップ実行すると、LEDが点灯と消灯を繰り返します。本文内部ではraise()を実行するたびに割り込みハンドラであるintHandler()が呼ばれているため、このような動きになります。
LEDが表示するのは割り込みハンドラに渡された引数の値です。この引数はハンドラを呼び出した割り込み番号です。今回はSIG_INT10にハンドラを登録しているので、LEDが表示するのは10進の10、すなわち2進の1010です。
#include <def2191.h> #include <sysreg.h> #include <signal.h> void intHandler( int ); int main(void) { sysreg_write( sysreg_IOPG, General_Purpose_IO ); // 汎用IOページを選ぶ io_space_write( DIR, 0xf ); // 下位4ビットを出力に設定 interrupt( SIG_INT10, &intHandler ); // INT10割り込みのハンドラとしてintHandlerを登録 enable_interrupts(); // 割り込みを有効にする while (1) { raise( SIG_INT10 ); // 割り込みを強制的に起こす io_space_write( FLAGC, 0xf ); // LEDを消す } } void intHandler( int sig ) { io_space_write( FLAGS, sig ); // シグナル番号をLEDに出力 }
このプログラムの本体は無限ループであるため、メニューバー⇒Debug⇒Runを実行すると制御が帰ってきません。この場合メニューバー⇒Debug⇒Haltで停止させてください。
⇒次はPF割り込みを使おう