ハードウェア割り込みハンドラ(#pragma interrupt)
|
ハードウェア割り込みに対応したオブジェクト・コードを出力します。
[機能]
- | 対象の関数定義をハードウェア割り込みハンドラとして,RETIによる復帰コードが生成されます。 |
- | 汎用レジスタの退避領域としてスタック,またはレジスタ・バンクが指定できます。 |
- | 割り込みハンドラ定義は通常関数同様に,.textセクション,または.textfセクションに出力されます。セクション名は,#pragma sectionにより変更可能です。
ただし,ベクタテーブルを指定した場合は,割り込みハンドラの先頭アドレスは16ビットでアドレッシングできなければなりません。 |
- | ベクタテーブルを指定した場合,明示的,暗黙問わず__farを指定しても強制的に__near指定となります。
警告は出力しません。 |
- | ベクタテーブルを指定しなかった場合,明示的,暗黙問わず関数の__near/__far指定に従います。 |
[効果]
- | Cソース・レベルで割り込みハンドラの記述が可能となります。 |
[方法]
- | #pragma指令に関数名,割り込み仕様を指定します。 |
#pragma interrupt [(]割り込みハンドラ名[(割り込み仕様 [,...])][)]
|
割り込み仕様には,以下のものを指定できます。
|
|
|
ベクタテーブル指定
|
vect=アドレス
|
割り込みハンドラの先頭アドレスを格納するベクタテーブルのアドレス。
省略時はベクタテーブルを生成しません。
アドレス: 2,8,10または16進数定数
0x0~0x7cの偶数のみ(範囲外はエラーとする)
|
レジスタ・バンク指定
|
bank={RB0|RB1|RB2|RB3}
|
割り込みハンドラ内で使用するレジスタ・バンク。注1
割込みハンドラの実行に指定のバンク中のレジスタを使います。
ESとCSはスタックに退避します。
汎用レジスタの退避および復帰をレジスタ・バンクを切り替えるSEL命令で実現するため,コードサイズを小さくすることができます。
本指定を省略した場合,汎用レジスタはスタックに退避します。注2
|
多重割り込み許可指定
|
enable={true|false}
|
true: 関数入口での多重割り込みを可能とします。
すなわち,レジスタの退避処理よりも前にEIを生成します。
false: EIを生成しません。enableを省略した場合は,EIを生成しません。
|
注 1. | 割り込みハンドラを呼び出す前に使用しているレジスタ・バンクとは,異なるレジスタ・バンクを指定してください。同じレジスタ・バンクが指定された場合には,退避したレジスタの内容を復帰できなくなります。 |
同一の項目を,同時に複数回書く場合はコンパイル・エラーとなります。
ただし,ベクタテーブルの指定は,アドレスが重複しなければ複数記述可能とします。【V1.06以降】
#pragma interrupt func(vect=2,vect=2) // エラー
|
#pragma interrupt func(vect=2,vect=8) // OK
|
#pragma interrupt func(vect=2)
#pragma interrupt func(vect=8) // OK
|
「vect=アドレス」指定がある場合はベクタテーブルを生成します。このため,スタートアップ・ルーチンなどにアセンブリ言語のセクション定義疑似命令でベクタテーブルを定義すると,リンク時にエラーとなります。
「vect=アドレス」指定を記述した場合,それ以外にアセンブリ言語でベクタテーブルを記述するには,セクション定義疑似命令ではなく.VECTOR疑似命令で記述してください。
[制限]
- | 割り込みハンドラを通常関数のように呼び出すと,コンパイル・エラーとなります。 |
- | __inline,__callt,および他の#pragma を指定すると,コンパイル・エラーとなります。 |
- | 割り込みハンドラは,引数,戻り型ともにvoid型で宣言しなければなりません(例:void func (void);)。
void型でない場合はコンパイル・エラーとなります。 |
- | 割り込みハンドラ中にレジスタ利用や関数呼び出しがない場合,#pragma interruptでレジスタ・バンク切り替え指定をしてもレジスタ・バンク切り替え命令は出力しません。
これが発生する例として以下があります。 |
- | 割り込みハンドラ中に,SFRに定数値を設定するなどのレジスタを使わない命令のみが出力される場合 |
[使用例]
【入力プログラム】
#include “iodefine.h” /*iodefine.hをインクルードすると*/
#pragma interrupt inter (vect=INTP0) /*vect指定に割り込み要因名が使える*/
void inter ( void ) {
/*割り込み処理(AX,HL,ESのみ使用)*/
}
|
【出力プログラム】
_inter .vector 0x0008 ;INTP0
.section .text, TEXT ;ベクタテーブル指定があるため__near指定とみなす
_inter:
push AX ;使用する汎用レジスタの,スタックへの退避コード
push HL
mov A, ES
push AX
;INTP0端子入力に対する割り込み処理(関数本体。AX,HL,ESのみ使用)
pop AX ;使用する汎用レジスタの,スタックからの復帰コード
mov ES, A
pop HL
pop AX
reti
|
【入力プログラム】
#pragma interrupt inter (vect=INTP0, bank=RB1)
void inter ( void ) {
/*割り込み処理(ESは使用,CSは使用しない)*/
}
|
【出力プログラム】
_inter .vector 0x0008 ;INTP0
.section .text, TEXT ;ベクタテーブル指定があるため__near指定とみなす
_inter:
sel RB1 ;レジスタ・バンクの切り替えコード
mov A, ES ;使用するES,CSレジスタのスタックへの退避コード
push AX
;INTP0端子入力に対する割り込み処理(関数本体。ESは使用,CSは使用しない)
pop AX ;使用するES,CSレジスタのスタックからの復帰コード
mov ES, A
reti
|
(2) | 割り込みハンドラ中に関数呼び出し(#pragma inline_asm宣言された関数の関数呼び出しを含む)がある場合 |
【入力プログラム】
#pragma interrupt inter (vect=INTP0)
void inter ( void ) {
/*割り込み処理*/
}
|
【出力プログラム】
_inter .vector 0x0008 ;INTP0
.section .text, TEXT ;ベクタテーブル指定があるため__near指定とみなす
_inter:
push AX
push BC
push DE
push HL
mov A, ES ;ES,CS,および全汎用レジスタのスタックへの退避コード
mov X, A
mov A, CS
push AX
;INTP0端子入力に対する割り込み処理(関数本体)
pop AX ;ES,CS,および全汎用レジスタのスタックからの復帰コード
mov CS, A
mov A, X
mov ES, A
pop HL
pop DE
pop BC
pop AX
reti
|
【入力プログラム】
#pragma interrupt inter (vect=INTP0, bank=RB1)
void inter ( void ) {
/*割り込み処理*/
}
|
【出力プログラム】
_inter .vector 0x0008 ;INTP0
.section .text, TEXT ;ベクタテーブル指定があるため__near指定とみなす
_inter:
sel RB1 ;レジスタ・バンクの切り替えコード
mov A, ES ;ES,CSレジスタのスタックへの退避コード
mov X, A
mov A, CS
push AX
;INTP0端子入力に対する割り込み処理(関数本体)
pop AX ;ES,CSレジスタのスタックからの復帰コード
mov CS, A
mov A, X
mov ES, A
reti
|