- ベストアンサー
割り込みベクタに飛んだ場合必ず”OSIntEnter();”という関数は使わないといけない?
今、H8S2368のために書かれたプログラムを見ているのですが、このプログラムではuC/OSというプログラムの関数である"OSIntEnter();"という関数が出てくることがわかりました。それで、OSIntEnter()関数というのが現在のソースプログラムの中でどのように使われているのかを、全ソースに対して検索をかけてみたところ、必ずと言っていいほど割り込みベクタのプログラムである下記のようなプログラムで使われていることがわかりました。 __interrupt(vect=22) void INT_IRQ6(void) { OSIntEnter(); OSSemPost(CmxInt); OSIntExit(); } たぶん、割り込みが発生して、その割り込みの種類の割り込みベクタに飛ぶときにこの”OSIntEnter()”というのを使わなければならないのだろうと推測しているのですが、 もし、割り込みベクタで”OSIntEnter()”を使わなかった場合、どのような問題がおきるのでしょうか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
以下参考まで、 指定マニュアルにレジスタ保存は別途記載があるか、コンパイラがやっているので 記載がない のどちらかと思います。 1.タスク状態以外からの呼び出しに限る。 -->つまりハンドラ等ということなんでしょう。 2.安全に割込みネストカウンターを更新します。 --> このOSでは多重割込みを許可しているものです。多重割込みの回数を カウンターで把握しています。なので出るときにもデクリメントしている のでしょう。 また安全な更新は、割込不可状態で実施する必要があり、 なので、通常割込みハンドラの入り口では割込み禁止状態なので まずカウンターをインクリメントし、そのあと割込み許可(ただし、レベル管理 が可能なCPUの場合は、その割込み優先以下はマスク) までしてぬけるんじゃないかと思います。 3. 割込みネスト数は最大255まで --> たぶん8bitでカウンターを持っているのが理由で、まぁ255もあれば十分 ですので、実際そこまでいくと、先にスタックが不足しますから なぜ、割込みネストカウンターが必要なのかは、0になったときにスケジューラの 起動が必要だからでしょう。これをμITRONでは遅延ディスパッチといいます。
その他の回答 (2)
- 松延 英樹(@maznobu)
- ベストアンサー率46% (80/171)
こんにちは。 割り込みベクタのエントリは、必ずコンテキスト(context)を保存します。 コンテキストというのは、ここではCPUのレジスタ情報です。 どのCPUであっても、既存の何らかの処理が動いているときに、割り込みによって最優先処理を動かすわけですよね。そして、割り込み処理が終わったら、元の処理が何事も無かったように動くことを保証してあげなければなりませんよね? そのために、コンテキストを保存するのです。 この仕組みは、あらゆるCPUで全て同じです。H8でもH330でも、Z80、i8086、PentiumとかTurionであれ皆同じです。そして、戻るときの OSIntExit() はそのコンテキストを復元する処理なのです。 一般的に割り込みベクタのエントリでは、多重割り込みを禁止するためにフラグを操作してから割り込みコンテキストを保存して、何らかの処理をできるだけ早く処理するようにして、終わったらコンテキストを復元しつつ割り込みを許可してリターンします。コンテキストの保存は、大抵はスタックにレジスタを保存するアセンブラ命令とかを実行しているはずです。復元は同じくスタックからレジスタにロードするアセンブラ命令があります。 なお、同じ処理が書ければいいのですから、同じ関数である必要はありません。 でも、普通は、セオリー通りに同じ関数を呼んだほうがトラブルが少ないと思います。
お礼
回答頂きありがとうございます。 たくさんの情報頂きありがとうございました。私のRTOSに関する知識が不足しているのが原因なので、RTOSに関して今後もご協力お願いたします。
- R32C
- ベストアンサー率39% (115/290)
使わなかった場合にどんな現象がおこるかは、uC/OSの振る舞いによる。といいますか uC/OSのマニュアル等を参照してみてください としかいえませんね。 そう書いてください とかしかマニュアルに記載がない場合もあるかもしれません。 以下、想定での回答なのであまり期待しないでほしいのですが、 いわゆる割り込みハンドラの中で、uC/OSの動作に関係する操作はまずできない というのが ひとつあると思います。 μITRONの場合を考えると、割り込みハンドラに入るときに同様に入り口で同じように 指定の関数をコールする決まりがある実装としてMISPOのNortiとかあります。 実際にNortiの場合にそれを書かなかったばかりにうまく動作しないというQ&Aはみかける ことがあるので、同様の問題が発生するように思います。 なぜ、そういったOSを利用するときにまじないのように指定関数のコールが必要か というと、Nortiのマニュアルにも動作内容の概要がかかれていますが、 ひとつはレジスタ退避、もうひとつは、割り込みマスクの変更のようです。 レジスタ退避は、OSを使わない場合でも同様に必要性がありますが、Nortiは多数のMPUで同様の 対応をしているため、やっているのだと思います。割り込みマスクの変更は、通常は多重割り込みを 受け付けるための変更を行っているでしょう。 さらにuC/OSのまじないとして、割り込みハンドラの終わりにOSIntExit();が必要なはずです。 OSIntEnter(); OSSemPost(CmxInt); OSIntExit(); これはたぶん、あるデバイスかなにかの割り込みが発生したら、セマフォーで知らせるという 動作かと 思います。 セマフォ待ちのタスクはここで待ち状態からレディ状態になるでしょう。 OSIntEnt()は多重割り込みだった場合は割り込んだ元に戻りますが、タスク実行中に 割り込んだ場合は、タスクスケジューラに行き、そのときの最適な(たぶん最優先度の)タスクに切り替わる ために呼ばないといけないルーチンかと思います。 OSSemPost(CmxInt);によってレディになるタスクが増える場合があり、その結果割り込まれたタスクよりも 優先度の高いタスクがレディになった場合にタスク切り替えが必要になるからです。 OSIntExit();を書かないとセマフォ待ちのタスクに切り替わらないという現象が現れるかもしれませんが、 スタック退避や割り込みマスクの処理の不整合があってそこまで動かないように思います。
お礼
回答頂きありがとうございました。 確かに現在H8S2368マイコンで使用しているOSというのはuC/OSというのを搭載しているとのことです。 それで、”OSIntEnter();”というのをuC/OSのマニュアルを下記のURL http://www.scribd.com/doc/7046520/Ucos-II-Refman このサイトでダウンロードできることがわかったので、pdfファイルをダウンロードしてみ説明を見てみたところ このような説明があったので、yahoo翻訳で調べて読んでみました。 なんとなく使い方がわかったような気がしています。 OSIntEnter 1. This function must not be called by task-level code. 2. You can increment the interrupt-nesting counter (OSIntNesting) directly in your ISR to avoid the overhead of the function call/return. It’s safe to increment OSIntNesting in your ISR because interrupts are assumed to be disabled when OSIntNesting needs to be incremented. 3. You are allowed to nest interrupts up to 255 levels deep.
お礼
回答頂きありがとうございます。 たくさんの情報頂きありがとうございました。私のRTOSに関する知識が不足しているのが原因なので、RTOSに関して今後もご協力お願いたします。