Forums: Open Discussion (Thread #30244)

割り込みハンドラの出口処理について (2011-08-30 18:29 by easygo #59351)

http://sourceforge.jp/forum/message.php?msg_id=59256

上記の話題に関連しますが(再度蒸し返すようで申し訳ありません)
割り込みハンドラの出口処理(kernel_end_int)にてタスクが切り替わった場合
そのタスクは実質的に割り込み処理内で動作することになってしまうと思います。
(割り込みハンドラの最後のretiやrteに到達しないと割り込み処理が終了しない為)

他のμitron OSのソースを解析したところ、出口処理に工夫が施されており
割り込み処理を抜けた後にディスパッチャを起動するようになっていました。

μitronの仕様書を参照しましたが、実装方法についての記載はないようですので
実装依存なのかもしれませんが、一般的には下記のどちらになるのでしょうか?
①割り込み処理内でディスパッチ(タスクは割り込み処理内で動作)
②割り込み処理を抜けた後でディスパッチ

ご意見を頂けると幸いです。

RE: 割り込みハンドラの出口処理について (2011-08-30 23:06 by ryuz #59356)

お世話になります。Ryuzです。

あくまでITRONでの一般論になりますが、簡単にコメントいたします。

easygo様のおっしゃる「割り込み処理」の定義があいまいではありますが、ITRON仕様としては、割込みサービスルーチンなどで起床された、タスクへのスイッチタイミングは割込み終了時です。

しかしながら当然、タスクにリターンしてしまうとスイッチできなくなってしまうので、「リターンすることなく、割込み状態を終了させる」という事が求められてきます。

プロセッサの多くは割込み発生と同時に、プロセッサ(や周辺デバイス)のハードウェア的な状態を割込み処理状態として何らかのモード変更を行うものが大半です。
この状態だけ復帰させて、処理はリターンせずにスイッチに向かうというのが肝でして、プロセッサ毎にやり方が変わってきますし、しばしバグの巣窟になります。

単にステータスレジスタをいじるだけ(下手すると何もしなくてよい)というプロセッサから、非常にトリッキーなコードを書く必要のあるプロセッサまでさまざまです。

HOSの場合、kernel_end_int 呼び出し前にこのような処理が必要です。kernel_end_intを呼ばれたときは、プロセッサ的にもソフト的にも割込み処理状態を解除されており、通常のAPIの中と同様にただ割り込みだけが禁止された状態で呼ばれることが求められます。

タスクスイッチが行われた場合は、kernel_end_int 内でタスクスイッチが行われ、スイッチ先で割り込みが解除されてタスクが進行します。
また、再び、何らかのタスクスイッチで元のタスクに制御が戻った場合、何事も無かったように kernel_end_int から復帰し、レジスタを復帰させてタスクにリターンして再開が行われます。

以上、ITRONとしてもなかなか難しい部分ではあるのですが、理解の参考になれば幸いです。



Reply to #59351

RE: 割り込みハンドラの出口処理について (2011-08-31 05:39 by easygo #59359)

Ryuz様、お世話になります。

>しかしながら当然、タスクにリターンしてしまうとスイッチできなくなってしまうので
>「リターンすることなく、割込み状態を終了させる」という事が求められてきます。

やはりそういうことなんですね。
私が考えていた「割り込み処理の終了」とは上記の「割り込み状態の終了」でした。
これですっきりいたしました。

実は使用させて頂いているV850ES版は割り込み状態を終了する前にkernel_end_intが呼ばれていたため
(割り込み状態のままタスクスイッチしまう)本来の動作を質問させていただきました。

上記の問題は、割り込みハンドラを改造してなんとか対応できそうです。
ありがとうございました。
Reply to #59356

RE: 割り込みハンドラの出口処理について (2011-09-27 17:14 by easygo #59788)

改造後、暫く動作を確認していましたが問題なさそうでしたので
修正内容をお知らせします。

src/v850es/v850es_ca850/pacint.sの45~49行目をコメントアウトし

# # 割り込み終了処理呼び出し
# jarl _kernel_end_int, lp
# # レジスタ復帰
# popall
# reti

下記の処理を追加しました

# 割込み状態を終了した際(reti実行時)に_ret_intへ飛ぶように細工する
mov _ret_int, r10
ldsr r10, eipc -- 割込み時状態退避レジスタ
reti

_ret_int:
# 割込み状態を終了した時点(reti実行時)に呼ばれる為、割込禁止にする
di
jarl _kernel_end_int, lp
# レジスタ復帰
popall
reti
Reply to #59359