H8/3052Fには、様々なハードウエアが組み込まれている。この中で、割り込みを発生する周辺装置(デバイスという)は、以下のように複数ある。
CPUは、これらの周辺デバイスが発生する割り込みを識別して、それぞれに合った処理(割り込みハンドラ)を行う必要がある。このために、それぞれの割り込みに対して、処理する割り込みハンドラを対応付けする必要がある。これを行うのが、割り込みベクタと呼ばれる表で、メモリの特定のアドレスに、割り込みベクタを配置している。(セクションのCVECTBLで、0xFE110から始まる256Byteの領域で、monitor.hの VectorTable配列として定義している。)
この場合、ベクタ番号は配列の添字に相当する。
ベクタ番号 | アドレス | 種類 | 説明 |
0 | FFE110 | リセット | 電源投入/リセット入力時 |
1 | FFE114 | 予約 | |
2 | FFE118 | 予約 | |
3 | FFE11C | 予約 | |
4 | FFE120 | 予約 | |
5 | FFE124 | 予約 | |
6 | FFE128 | 予約 | |
7 | FFE12C | NMI | マスク不能割り込み(緊急時に利用) |
8 | FFE130 | TRAP0 | トラップ命令により発生 |
9 | FFE134 | TRAP1 | 〃 |
10 | FFE138 | TRAP2 | 〃 |
11 | FFE13C | TRAP3 | 〃 |
12 | FFE140 | IRQ0 | 外部割り込み |
13 | FFE144 | IRQ1 | 〃 |
14 | FFE148 | IRQ2 | 〃 |
15 | FFE14C | IRQ3 | 〃 |
16 | FFE150 | IRQ4 | 〃 |
17 | FFE154 | IRQ5 | 〃 |
18 | FFE158 | 予約 | |
19 | FFE15C | 予約 | |
20 | FFE160 | WOVI | ウォッチドッグ(番犬)タイマ。システムの誤動作検出に使用 |
21 | FFE164 | CMI | リフレッシュコントローラ(DRAM接続時に使用) |
22 | FFE168 | 予約 | |
23 | FFE16C | 予約 | |
24 | FFE170 | IMIA0 | ITUチャネル0 (コンペアマッチ/インプットキャプチャA0) |
25 | FFE174 | IMIB0 | ITUチャネル0 (コンペアマッチ/インプットキャプチャB0) |
26 | FFE178 | OVI0 | ITUチャネル0 (オーバフロー0) |
27 | FFE17C | 予約 | |
28 | FFE180 | IMIA1 | ITUチャネル1 (コンペアマッチ/インプットキャプチャA1) |
29 | FFE184 | IMIB1 | ITUチャネル1 (コンペアマッチ/インプットキャプチャB1) |
30 | FFE188 | OVI1 | ITUチャネル1 (オーバフロー1) |
31 | FFE18C | 予約 | |
32 | FFE190 | IMIA2 | ITUチャネル2 (コンペアマッチ/インプットキャプチャA2) |
33 | FFE194 | IMIB2 | ITUチャネル2 (コンペアマッチ/インプットキャプチャB2) |
34 | FFE198 | OVI2 | ITUチャネル2 (オーバフロー2) |
35 | FFE19C | 予約 | |
36 | FFE1A0 | IMIA3 | ITUチャネル3 (コンペアマッチ/インプットキャプチャA3) |
37 | FFE1A4 | IMIB3 | ITUチャネル3 (コンペアマッチ/インプットキャプチャB3) |
38 | FFE1A8 | OVI3 | ITUチャネル3 (オーバフロー3) |
39 | FFE1AC | 予約 | |
40 | FFE1B0 | IMIA4 | ITUチャネル4 (コンペアマッチ/インプットキャプチャA4) |
41 | FFE1B4 | IMIB4 | ITUチャネル4 (コンペアマッチ/インプットキャプチャB4) |
42 | FFE1B8 | OVI4 | ITUチャネル4 (オーバフロー4) |
43 | FFE1BC | 予約 | |
44 | FFE1C0 | DEND0A | DMAC |
45 | FFE1C4 | DEND0B | 〃 |
46 | FFE1C8 | DEND1A | 〃 |
47 | FFE1CC | DEND1B | 〃 |
48 | FFE1D0 | 予約 | |
49 | FFE1D4 | 予約 | |
50 | FFE1D8 | 予約 | |
51 | FFE1DC | 予約 | |
52 | FFE1E0 | ERI0 | SCI0 受信エラー0 |
53 | FFE1E4 | RXI0 | SCI0 受信データ・フル0 |
54 | FFE1E8 | TXI0 | SCI0 送信データエンプティ0 |
55 | FFE1EC | TEI0 | SCI0 送信終了0 |
56 | FFE1F0 | ERI1 | SCI1 受信エラー1 |
57 | FFE1F4 | RXI1 | SCI1 受信データ・フル1 |
58 | FFE1F8 | TXI1 | SCI1 送信データエンプティ1 |
59 | FFE1FC | TEI1 | SCI1 送信終了1 |
60 | FFE200 | ADI | AD変換終了 |
H8/3052Fの割り込みベクタ
■実際のプログラミング
(1)割り込みハンドラの定義
割り込みハンドラというと、特別な関数のように聞こえるかもしれないが、書き方は通常の関数と同じ。ただ、関数の宣言の前に
#pragma interrupt(割り込みハンドラの関数名) |
を記述しておくこと。
(2)割り込みハンドラをベクタテーブルに登録
monitor.hに定義されているベクタテーブルに、割り込みハンドラの関数名を記述する。
(3)割り込みマスクと優先順位に関する設定を行う。
SYSCRのI ビットを制御するには、
set_imask_ccr(1); // SYSCRのI ビットを1に設定し、全割り込みを不許可にする。 |
もしくは、
set_imask_ccr(0); // SYSCRのI ビットを0に設定し、全割り込みを許可する。 |
とする。
【注意】
set_imask_ccr関数を呼び出すには、monitor.hの先頭付近に
#include <machine.h> |
を入れておくこと。... でないと、コンパイルエラーが発生する。
以下のように示すように、IERの各ビットが、IRQの信号線に対応している。(IRQxEが、IRQx信号線に対応)
bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
IRQ名 | IRQ5E | IRQ4E | IRQ3E | IRQ2E | IRQ1E | IRQ0E | ||
初期値 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
IRQxEの値を1にすれば、該当するIRQx信号線による割り込みが有効になる。
以下は、外部割り込み信号線(IRQ0)にイベント(信号の立下り:エッジトリガ)が発生した時に、割り込みハンドラirq0_handlerを呼び出すプログラムの例。
main関数と割り込みハンドラの記述、およびベクタテーブルへの割り込みハンドラの登録例を示したもの。
(割り込みに関連する記述を赤字で示した。)
※ 外部割り込み信号線と、マイコンボード上の端子との関係は、回路図を参照のこと。
#include "monitor.h" #define PB_DDR (*(volatile unsigned char *)0xFFFFD4) #define PA_DDR (*(volatile unsigned char *)0xFFFFD1) #define ISCR (*(volatile unsigned char *)0xFFFFF4) |
割り込みハンドラとmain関数の記述例
#define printf ((int (*)(const char *,...))0x00002b52) #pragma section VECTBL void PowerON_Reset(); void irq0_handler();
// 割り込みハンドラのプロトタイプ宣言 typedef void (*fp)(void); const fp VectorTable[] = //
ベクタテーブルの定義 int main(void); __entry void PowerON_Reset(void) |
monitor.hの内容とベクタテーブルの定義
多重割り込み
H8/3052Fの割り込み処理では、割り込みハンドラ内部では、デフォルトで他の割り込みは禁止されている。(set_imask_ccr(1)の状態)従って、割り込みハンドラの処理中に、その他の割り込みイベントが発生しても、割り込みハンドラが新たに起動されることは無い。(つまり、多重割り込み禁止の状態)
現実のプログラミングでは、ある割り込みハンドラ(例えばIRQ0)実行時に、他の割り込み処理(例えばIRQ1)を受け付けたい場合も存在する。(つまり、割り込み処理実行中に、他の割り込み処理を受け付ける事。同じ割り込みでも良い)こういうのを多重割り込みと呼ぶ。
多重割り込みを受け付けるには、割り込みハンドラ内で、
set_imask_ccr(0) |
を実行すればよい。
多重割り込みとリエントラント