# OS_WaitIrq

## 構文

  `#include <nitro/os.h>`
  `void OS_WaitIrq( BOOL clear, OSIrqMask irqFlags );`

## 引数

clear | チェックフラグをクリアするかどうか
irqFlags | 発生を待つ割り込みのマスク値。論理和で複数を指定可能

## 返り値

なし。

## 説明

指定のIRQ割り込み要因の発生を待ちます。

irqFlags には複数の割り込み要因をマスク値の論理和で指定することが出来ます。この中のいずれかの割り込みが発生したときに関数から戻ります。割り込みの種類は以下を参照してください。

→ 割り込みの種類

> `(例) VBLANK と TIMER0 のどちらかを待ちます。`
> `OS_WaitIrq( TRUE, OS_IE_V_BLANK | OS_IE_TIMER0 );`

割り込みが発生したかどうかは、割り込みチェックフラグがセットされているかどうかを見て判断しています。このフラグは割り込みハンドラの中でユーザが明示的に `OS_SetIrqCheckFlag()` を呼んでセットする必要があります。

clear を TRUE にすると、割り込み発生待ちを行う前に、irqFlags で指定された割り込みチェックフラグをリセットします。FALSE ならリセットしません。リセットしない場合は、この関数に入った時点で待ちを行いたいチェックフラグがセットされているとすぐに関数から戻ることになります。

###
`OS_WaitInterrupt()` と `OS_WaitIrq()` との違い

`OS_WaitInterrupt()` と `OS_WaitIrq()` との違いは、`OS_WaitInterrupt()` は割り込み要因を待つ間 `OS_Halt()` で停止しますが、`OS_WaitIrq()` は割り込み要因を待つ間は他のスレッドに処理を移し、割り込みが発生した後に動作を再開する、というものです。スレッドを使用しない場合は、両者は同じ動作をする関数となります。

###
複数のスレッドが同じ割り込みを待つ場合

複数のスレッドが同じ割り込みを待つ場合には注意が必要です。一方のスレッドだけが実行され、他方が実行されないという状況が起こりえます。

例えば、以下のようなプログラムを考えます。

> `void TwlMain(void)
> {
> :
> OS_CreateThread( &thread1, proc1, ..., 10 );
> OS_CreateThread( &thread2, proc2, ..., 11 );
> :
> }
> //---- Thread1
> void proc1(void* arg)
> {
> while(1)
> {
> OS_WaitIrq( TRUE, OS_IE_V_BLANK );
> OS_Printf("proc1\n");
> }
> }
> //---- Thread2
> void proc2(void* arg)
> {
> while(1)
> {
> OS_WaitIrq( TRUE, OS_IE_V_BLANK );
> OS_Printf("proc2\n");
> }
> }
> //---- VBlank interrupt handler
> void VBlankHandler( void )
> {
> OS_SetIrqCheckFlag( OS_IE_V_BLANK );
> }`

スレッド1 と スレッド2 が Vブランクを待ちます。Vブランクが発生するとハンドラ内で Vブランクの割り込みチェックフラグをセットしています。そして スレッド1 と スレッド2 が実行可能状態になりますが、スレッドの優先順から、スレッド1 が先に起きます。スレッド 1 では 「`proc1`」と表示した後再び `OS_WaitIrq()` に入り、Vブランク待ちを行います。この際、第一引数が TRUE なので、Vブランクの割り込みチェックフラグをリセットしてからスリープします。次にスレッド2 に実行権が移されますが、すでにVブランクの割り込みチェックフラグがクリアされているので `OS_WaitIrq()` から戻ることなく再びスリープします。次のVブランクでもこの繰り返しとなります。つまり、このプログラムはずっと「`proc1`」 が表示されるだけで 「`proc2`」と表示されることはありません。

かといって、`OS_WaitIrq()` の第一引数を FALSE にすることは出来ません。もし FALSE にすれば、Vブランクが発生した後にいくら `OS_WaitIrq()` を呼んでも、すぐに戻ることになるからです。

## 参照

`OS_SetIrqCheckFlag, OS_WaitInterrupt, OS_WaitAnyIrq
`

## 履歴

2008/07/01 複数スレッドからの呼び出しの注意を追記
2005/03/08 用語統一 [割込み] → [割り込み]
2004/05/24 `OS_WaitInterrupt()` との違いを明記
2004/05/01 初版