割り込みハンドラを直接呼んではいけないわけ
RL78の話。他のCPUは大丈夫かもしれない。
割り込みハンドラをCで実装する場合は、attributeやpragmaでinterrupt指定します。
void INT_WDTI(void) __attribute__ ((interrupt)); // GCC
#pragma interrupt r_tau0_channel0_interrupt(vect=INTTM00) // CCRL
割り込みが発生すると自動的に呼ばれるもので、明示的に呼び出す必要はありません。
見た目は普通の関数ですが、わざわざこのような指定をするということは普通の関数ではないわけで、具体的にはRETI命令でリターンする"関数"になります。
何か処理の共通化のために、タスクの中から呼び出したくなることもあるかもしれませんが
void task(void)
{
r_tau0_channel0_interrup(); // タイマー処理を実行
}
実際、コンパイルエラーになるわけでもなく普通に実行できてしまいますが、裏ではよくないことが起こっています。
RET命令とRETI命令はスタックから戻りアドレスを取得してそのアドレスにジャンプするところは同じですが、RETIではさらにPSW(プログラムステータスワード)の復元も行われます。
PSWの退避は割り込み発生時に自動的に行われるのですが、CALL命令でジャンプした場合は、この退避が行われません。その結果、不定値が"復元"されてしまいます。
PSWはCPUの状態を表すもので、割り込み許可フラグなどがあります。これが0になると割り込み禁止になるので、一見普通に動いていて「あれ?割り込みが入らない??」という事態になります。非常に見つけにくい不具合になります。
関数コールでもPSWを退避してくれるようなCPUなら問題ないですが、そういうところでCPU依存なプログラムは避けるのが無難です。
Author And Source
この問題について(割り込みハンドラを直接呼んではいけないわけ), 我々は、より多くの情報をここで見つけました https://qiita.com/shirokumaneko/items/6f58f21f7fd924377e15著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .