Everything

ハードウェア割り込みハンドラ(#pragma interrupt)


ハードウェア割り込みに対応したオブジェクト・コードを出力します。

[機能]

-

割り込みベクタが生成されます。

-

対象の関数定義をハードウェア割り込みハンドラとして,RETIによる復帰コードが生成されます。

-

汎用レジスタの退避領域としてスタック,またはレジスタ・バンクが指定できます。

-

割り込みハンドラ定義は通常関数同様に,.textセクション,または.textfセクションに出力されます。セクション名は,#pragma sectionにより変更可能です。
ただし,ベクタテーブルを指定した場合は,割り込みハンドラの先頭アドレスは16ビットでアドレッシングできなければなりません。

-

ベクタテーブルを指定した場合,明示的,暗黙問わず__farを指定しても強制的に__near指定となります。
警告は出力しません。

-

ベクタテーブルを指定しなかった場合,明示的,暗黙問わず関数の__near/__far指定に従います。

[効果]

-

Cソース・レベルで割り込みハンドラの記述が可能となります。

[方法]

-

#pragma指令に関数名,割り込み仕様を指定します。

-

#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.

割り込みハンドラを呼び出す前に使用しているレジスタ・バンクとは,異なるレジスタ・バンクを指定してください。同じレジスタ・バンクが指定された場合には,退避したレジスタの内容を復帰できなくなります。

注 2.

割り込み時のレジスタ退避やスタックフレームの詳細は「9.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に定数値を設定するなどのレジスタを使わない命令のみが出力される場合

[使用例]

(1)

割り込みハンドラ中に関数呼び出しがない場合

(a)

デフォルト指定の場合

【入力プログラム】

#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

(b)

レジスタ・バンク指定がある場合

【入力プログラム】

#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宣言された関数の関数呼び出しを含む)がある場合

(a)

デフォルト指定の場合

【入力プログラム】

#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

(b)

レジスタ・バンク指定がある場合

【入力プログラム】

#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