R8Cの割り込み

割り込みというのは、CPUが実行中の処理に関係なく、何らかの条件を満たすと現在の処理を中断し、特定の処理を実行させることの出来る、CPUの機能です。処理中の内容に一時的に割り込んで、別の処理を実行するため、割り込みと呼ばれます。

R8Cの割り込みは、何通りかの分け方でいくつかに分類できますが、その分類のしかたの1つに、ノンマスカブル割り込みとマスカブル割り込みがあります。

ここで、Iフラグと割り込み優先レベルについて説明します。

R8Cでの作品の作成時に頻繁に使用したくなる割り込みは、本格的な製品に使用する本気のソフトでもない限り、殆どが周辺機能を使うためのマスカブル割り込みだと思うので、ここではそれについて解説します。


周辺機能割り込み

R8Cで周辺機能の割り込み使うのには、周辺機能の設定の他に下の設定が必要です。

Iフラグ

Iフラグは、アセンブリの、fsetとfclrを使って操作するのがいいでしょう。 C言語のインラインアセンブリで書く場合、こんな感じ。

割り込み制御レジスタ

各マスカブル割り込みに付き1つ、メモリ上に割り込み制御レジスタがあります。すべての割り込み制御レジスタは、以下のようなフォーマットです。
ビット 名前 機能 説明
0 ILVL0 割り込み優先レベル 割り込み優先レベルを0から7で設定する。0にすると、割り込みが発生しなくなる。
1 ILVL1
2 ILVL2
3 IR 割り込み要求ビット 割り込み要求発生時に1になり、割り込み発生時に0に戻る。書く場合は0を書くこと。
4-5 特殊な場合を除き、なにも配置されない。書く場合の値は0。読んだ場合、値は不定。

可変ベクタテーブル

マスカブル割り込みの割り込み番地(割り込み発生時に実行する処理が書いてある番地)は、すべて可変ベクタテーブルに配置されます。ベクタテーブルとは、この場合割り込み番地が列挙されているものです。可変ベクタテーブルはCPUのINTBレジスタで位置を指定するものですが、この設定はスタートアッププログラムがやってくれるので、C言語のプログラマがやるべきことは、自分の作った割り込み関数を可変ベクタテーブルに登録するだけです。Renesasのコンパイラパッケージを利用する場合、これは#pragmaで可能です。次の例のように、割り込み関数の定義の隣に#pragmaを置いておきます。これによって、関数は自動で割り込み関数になり、適切に処理されます。
#pragma INTERRUPT 割り込み関数名(vect=割り込み番号)
void 割り込み関数名(void){
    処理;
}
割り込み処理中の、より優先順位の高い割り込みを許可する(多重割り込み)場合は、次のように書きます。
#pragma INTERRUPT /E 割り込み関数名(vect=割り込み番号)
void 割り込み関数名(void){
    処理;
}
この#pragmaの前には、対象の割り込み関数のプロトタイプ宣言をしてはいけません。

割り込み番号

可変ベクタテーブルに配置される割り込みには、全て割り込み番号があります。割り込み番号の割り当てはモデルによって違うので、データシートを見てください。R8C/1A,1Bのデータシートでは、12章の表12.2のソフトウェア割り込み番号がそれです。

こまごましたこと

割り込み発生時にIフラグなどで禁止されていた割り込みは、IRビットが設定されたままになり、割り込み発生の条件が満たされてから実行されます。また、複数の割り込みが同時に発生した場合、優先順位が高い割り込みが先に発生し、後で優先順位の低いものが実行されます。