Windows版 iTRONサービスコールの作成 (割り込み管理機能)
(その1)
組み込みソフトウェアで利用されているOS「iTRON」のサービスコールをWindows上で動作させるためのライブラリです。
『割り込み管理機能』の実装を説明します。
割り込みハンドラの登録と割り込みの禁止/許可を実装します。
Ver4.0で定義されている割り込みサービス・ルーチンの実装は行いません。
割り込みハンドラはライブラリの外部から呼び出せる仕組みを作りましたので、擬似的な割り込み処理の確認が行えます。
・Ver3.0の割り込み管理機能で提供されるサービスコールは以下のとおりです。
サービスコール名 | 説明 |
---|---|
def_int | 割り込みハンドラを登録します。 |
dis_int | 割り込みを禁止します。 |
ena_int | 割り込みを許可します。 |
ret_int | 割り込みハンドラから復帰します。 |
ret_wup | 割り込みハンドラから復帰して、指定したタスクを起床します。 |
loc_cpu | CPUをロック状態に移行します。 |
unl_cpu | CPUのロック状態を解除します。 |
・Ver4.0の割り込み管理機能で提供されるサービスコールは以下のとおりです。
サービスコール名 | 説明 |
---|---|
def_inh | 割り込みハンドラを登録します。 |
cre_isr / acre_isr | 割り込みサービス・ルーチンを生成します。 |
del_isr | 割り込みサービス・ルーチンを削除します。 |
ref_isr | 割り込みサービス・ルーチンの状態を参照します。 |
dis_int | 割り込みを禁止します。 |
ena_int | 割り込みを許可します。 |
loc_cpu | CPUをロック状態に移行します。 |
unl_cpu | CPUのロック状態を解除します。 |
ライブラリの外部から割り込みハンドラを呼び出す為に以下の関数を用意しました。
void request_interrupt( UINT num )
引数 | 説明 |
---|---|
num | 割り込みハンドラ番号。 |
処理としては、割り込みハンドラを呼び出すスレッドに対して、呼び出す割り込みハンドラの番号をメッセージで通知するだけですので、すぐに制御を戻します。
割り込みハンドラの呼び出し用にスレッドを最上位の優先度(THREAD_PRIORITY_HIGHEST)で立ち上げます。
別スレッドからの割り込みハンドラ呼び出し要求を受けると、該当する割り込みハンドラが登録されていれば呼び出します。
dis_int()およびloc_cpu()にて該当する割り込みが禁止されている場合は割り込み要求の保留され、ena_int()またはunl_cpu()にて割り込みが許可されたときに割り込みハンドラを呼び出します。
/****************************************************************************/
/*!
* @brief 割り込みタスク.
*
* @param [in] arg タスクリソース構造体のポインタ.
*
* @retval 常に0を返す.
*/
static unsigned __stdcall IntrTask( void* arg )
{
MSG msg;
//! スレッド識別子を取得する.
IntrTid = GetCurrentThreadId();
//! メッセージループ.
while( GetMessage( &msg, NULL, 0, 0 ) ){
//! システムの終了の場合はメッセージループを抜ける.
if( msg.message == WM_SYSTEM_EXIT ){
break;
}
switch( msg.message ){
case WM_INTRRUPT_REQ:
CallIntrruptHandler( (INT)msg.wParam );
break;
}
}
_endthreadex( 0 );
return 0;
}
/****************************************************************************/
/*!
* @brief 割り込みハンドラを呼び出す.
*
* @param [in] no 割り込みハンドラ番号.
*
* @retval なし.
*/
static void CallIntrruptHandler( INT no )
{
wi_CommonLock();
do {
FP intr_adr;
ER ercd;
WIINTOBJ *p;
//! 割り込みハンドラ構造体を取り出す.
p = (WIINTOBJ *)wi_FindObject( no, TMAX_MAXINT, ObjList, &ercd );
if( !p ){
break;
}
//! 割り込みエントリ・アドレスがない場合は呼び出さない.
if( !p->IntrAdr ){
break;
}
//! 割り込み禁止の場合は呼び出さない.
if( !p->Enabled || wi_IsCPULock() ){
p->IntrCnt++;
break;
}
p->IntrCnt = 0;
intr_adr = p->IntrAdr;
wi_CommonUnlock();
//! 割り込みハンドラを呼び出す.
intr_adr();
return;
} while( FALSE );
wi_CommonUnlock();
}
割り込みハンドラが登録されていない場合は処理を行いません。
また、割り込みハンドラが登録されていても、割り込みハンドラのエントリ・アドレスがない場合も処理を行いません。
割り込みが禁止されている場合は割り込み要求があったことをカウントして、処理を終了します。
(割り込み要求をカウントアップしていますが、割り込み禁止中に何回割り込み要求が発生しても、割り込み許可後には一度しか呼び出しません。)