4.2.4.5 割り込み/例外処理ハンドラ

CC-RHでは,C言語で“割り込み”や“例外”が発生したときに呼ばれる“割り込みハンドラ”,“例外ハンドラ”を記述することができます。ここでは,その記述方法などについて説明します。

(1)

割り込み/例外の発生

RH850ファミリでは,割り込みや例外が発生すると,その割り込みや例外に対応したハンドラ・アドレスにジャンプします。

なお,ハンドラ・アドレスの並びや,搭載している割り込みは,RH850の品種ごとに異なります。詳細は,使用する各デバイスのユーザーズ・マニュアルを参照してください。

具体的な記述方法は「(3) 割り込み/例外ハンドラの記述方法」で説明します。

(2)

割り込み/例外発生時に行う必要のある処理

関数実行時に割り込み/例外が入ると,即座に割り込み/例外処理を行う必要があります。そして割り込み/例外処理が終わると,割り込みが入った時点の関数に戻る必要があります。

したがって,割り込み/例外発生時には,そのときのレジスタ情報を保存し,割り込み/例外処理が終わった後は,そのレジスタ情報を復帰する必要があります。

(3)

割り込み/例外ハンドラの記述方法

割り込み/例外ハンドラの記述上の形態は,通常のC言語関数と変わりませんが,C言語で記述した関数を,CC-RHに対して“割り込み/例外ハンドラ”として認識させる必要があります。CC-RHでは,割り込み/例外ハンドラの指定を“#pragma interrupt指令”で行います。

#pragma interrupt ( 関数指定 [, 関数指定]... ) 
  関数指定 : 関数名 [(割り込み仕様 [, 割り込み仕様]...)]

外側のかっこは省略可能です。

 

関数名は,C言語記述の関数名を記述してください。たとえば,"void func1 ( ) { }"という関数であれば"func1"と指定します。

割り込み関数の戻り型は,常にvoidとしてください。

割り込み関数は,関数の出口コードが通常関数と異なるため,通常関数のように呼び出さないでください。

(a)

割り込み関数定義

割り込み関数定義は,引数なし,または引数1 個のみ使用できます。

例 1.

引数なしの場合

void i_func(void)
{
        :
}

例 2.

引数1 個の場合

void i_func(unsigned long dummy)
{
        :
}

(b)

割り込み仕様

割り込み仕様には,以下のものを指定できます。

enable=

多重割込の可否を指定します。true/false/manualが記載できます。

-

true

ei/diを出力します。

eipc/eipswの退避/復帰コードを出力します。

-

false(デフォルト)

ei/diを出力しません。

eipc/eipswの退避/復帰コードを出力しません。

-

manual

ei/diを出力しません。

eipc/eipswの退避/復帰コードを出力します。

priority=

channel=

priority,またはchannel のどちらか一方のみ記述可能です(両方書いた場合は,コンパイル・エラーとなります)。

-

priority=

例外発生要因を指定します。以下の字句から1個のみを書くことができます。

SYSERR/FETRAP/TRAP0/TRAP1/RIE/FPP注1/FPI注1/FPINT注2/UCPOP/MIP/MDP/PIE/MAE/FENMI/FEINT/EIINT_PRIORITYX(X は0から15)

-

channel=

割込発生チャネルを指定します。割り込みの「拡張仕様」を使う場合に選択してください。

EI ハンドラと判断してコードを生成します。

priority,またはchannel を記載しなかった場合は,EIINTと判断します。

fpu=

fpuのコンテキストfpepc/fpsrを退避/復帰するか指定します。true/false/autoが記載できます。

-

true

fpepc/fpsrを退避/復帰します。

-

false

fpepc/fpsrを退避/復帰しません。

-

auto(デフォルト)

-Xfloat=fpuオプションが指定されている場合は,trueを指定したとみなします。

-Xfloat=softの場合は,falseを指定したとみなします。

callt=

calltのコンテキストctpc/ctpswを退避/復帰するか指定します。true/falseが記載できます。

-

true(デフォルト)

ctpc/ctpswを退避/復帰します。

-

false

ctpc/ctpswを退避/復帰しません。

注 1.

-Xcpu=g3mh指定時は使用できません。使用した場合はエラーになります。

注 2.

-Xcpu=g3mh指定時のみ使用できます。それ以外で使用した場合はエラーになります。

 

割り込み仕様を書く場合は,必ず=の右項を必要とします。

たとえば,“enable=”だけを書くとコンパイル・エラーとなります。割り込み仕様のデフォルトとは,個々の割り込み仕様を書かない場合の動作を意味します。

(c)

EIレベル例外の出力コード内容

EIレベル例外の割り込み関数に対して,コンパイラが入口/出口に挿入する命令列を以下に示します。主に,EIINTやFPI等がこれに該当します。
ただし,これらをすべての割り込み関数に挿入するわけではなく,ユーザの#pragma記述やコンパイル・オプション等に応じて必要な処理が出力されます。

<1>

[割り込み関数の入口コード]

(1)コンテキストの退避に使用するスタック領域を確保

(2)割り込み関数中で使用する関数呼び出し前後で内容が保証されないレジスタを退避

(3)EIPC,EIPSWを退避

(4)仮引数を記述した関数の場合,EIICをR6に設定

(5)多重割り込みを許可

(6)CTPC,CTPSWを退避

(7)FPEPC,FPSRを退避

<2>

[割り込み関数の出口コード]

(8)インプレサイス割り込み待ちを設定

(9)FPEPC,FPSRを復帰

(10)CTPC,CTPSWを復帰

(11)多重割り込みを禁止

(12)EIPC,EIPSWを復帰

(13)割り込み関数中で使用した関数呼び出し前後で内容が保証されないレジスタを復帰

(14)コンテキストの退避に使用したスタック領域を解放

(15)eiret

 

次に,具体的な出力コード例を示します。コード例中の番号(1)〜(15)は,上記の各処理に記載された番号と対応しています。

なお,必ず出力コード例のとおりの命令が出力されるわけではありません。使用する命令や汎用レジスタ等は,コード例とは異なる場合があります。

例 1.

EIレベル例外の出力例1

#pragma interrupt func1(enable=true, callt=true, fpu=true)
void func1(unsigned long eiic)
{
        ユーザ記述の処理;
}

 

例 2.

EIレベル例外の出力例2
仮引数なし,割り込みの多重化は手動(enable=manual)の場合

#pragma interrupt func1(enable=true, callt=true, fpu=true)
void func1(unsigned long eiic)
 {
        ユーザ記述の処理;
}

 

(d)

FEレベル例外の出力コード内容

FEレベル例外の割り込み関数に対して,コンパイラが入口/出口に挿入する命令列を以下に示します。主に,FEINTやPIE等がこれに該当します。
ただし,これらをすべての割り込み関数に挿入するわけではなく,ユーザの#pragma記述やコンパイル・オプション等に応じて必要な処理が出力されます。

<1>

[割り込み関数の入口コード]

(1)コンテキストの退避に使用するスタック領域を確保

(2)割り込み関数中で使用する関数呼び出し前後で内容が保証されないレジスタすべてを退避

(3)仮引数を記述した関数の場合,FEICをR6に設定

(4)CTPC,CTPSWを退避

(5)FPEPC,FPSRを退避

<2>

[割り込み関数の出口コード]

(6)FPEPC,FPSRを復帰

(7)CTPC,CTPSWを復帰

(8)割り込み関数中で使用する関数呼び出し前後で内容が保証されないレジスタすべてを復帰

(9)コンテキストの退避に使用したスタック領域を解放

(10)feret

 

次に,具体的な出力コード例を示します。コード例中の番号(1)〜(10)は,上記の各処理に記載された番号と対応しています。

なお,必ず出力コード例のとおりの命令が出力されるわけではありません。使用する命令や汎用レジスタ等は,コード例とは異なる場合があります。

FEレベル例外の出力例

#pragma interrupt func1(priority=feint, callt=true, fpu=true)
void func1(unsigned long feic)
{
        ユーザ記述の処理;
}

 

(e)

FEレベル例外(復帰/回復不可)の出力コード内容

FEレベル例外(復帰/回復不可)の割り込み関数に対して,コンパイラが入口/出口に挿入する命令列を以下に示します。主に,FENMIやSYSERR等がこれに該当します。

<1>

[割り込み関数の入口コード]

(1)仮引数を記述した関数の場合,FEICをR6に設定

仮引数を記述しない場合は,何も出力されません。

<2>

[割り込み関数の出口コード]

なし

備考

コンテキストの退避/復帰は一切出力されません。
関数呼び出し前後で内容が保証されるレジスタの退避/復帰も出力されません。
関数内で abort() を呼び出してプログラムを終了させるなど,ユーザ・プログラムで適切に処置してください。

 

次に,具体的な出力コード例を示します。コード例中の番号(1)は,上記の各処理に記載された番号と対応しています。

FEレベル例外(復帰/回復不可)の出力例

#pragma interrupt func1(priority=fenmi)
void func1(unsigned long feic)
{
        ユーザ記述の処理;
}

 

(4)

割り込み/例外ハンドラの記述時の注意事項

-

#pragma interruptは,次の#pragma指令とは同時に指定できません。

#pragma inline_asm,#pragma inline,#pragma noinline,#pragma interrupt,

#pragma block_interrupt