Windows版 iTRONサービスコールの作成 (データキュー)
(その6)
データキューからデータを受信するサービスコールは以下のとおりです。
サービスコール名 | 説明 |
---|---|
rcv_dtq | タイムアウトなしでデータキューからデータを受信します。 |
prcv_dtq | ポーリング方式でデータキューからデータを受信します。 |
trcv_dtq | タイムアウト付きでデータキューからデータを受信します。 |
タイムアウトなしでデータキューからデータを受信するには以下のサービスコールを使用します。
ER rcv_dtq( ID dtqid, VP_INT *p_data )
引数 | 説明 |
---|---|
dtqid | データキューID番号。 |
p_data | データキューから取得したデータを格納する領域のポインタ。 |
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のデータキューID番号。 |
E_NOEXS | 指定したデータキューID番号は登録されていない。 |
E_PAR | パラメータエラー。 |
E_CTX | 非コンテキスト・タスクからの呼び出し。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief データキューからの受信 (タイムアウトなし).
*
* @param [in] dtqid データキューID番号.
* @param [out] p_data データキューから受信したデータを格納する領域のポインタ.
*
* @retval エラーコード.
*/
ER rcv_dtq( ID dtqid, VP_INT *p_data )
{
//! タイムアウトなしでデータキューからデータを受信する.
return trcv_dtq( dtqid, p_data, TMO_FEVR );
}
trcv_dtq()のタイムアウト設定に TMO_FEVR を指定して呼び出します。
データキューにデータが無い場合は、データキューにデータが格納されるまでタスクをスリープさせます。
ポーリングでデータキューからデータを受信するには以下のサービスコールを使用します。
ER prcv_dtq( ID dtqid, VP_INT *p_data )
引数 | 説明 |
---|---|
dtqid | データキューID番号。 |
p_data | データキューから取得したデータを格納する領域のポインタ。 |
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のデータキューID番号。 |
E_NOEXS | 指定したデータキューID番号は登録されていない。 |
E_PAR | パラメータエラー。 |
E_TMOUT | データキューにデータが無い。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief データキューからの受信 (ポーリング).
*
* @param [in] dtqid データキューID番号.
* @param [out] p_data データキューから受信したデータを格納する領域のポインタ.
*
* @retval エラーコード.
*/
ER prcv_dtq( ID dtqid, VP_INT *p_data )
{
//! データ受信待ちなしでデータキューからデータを受信する.
return trcv_dtq( dtqid, p_data, TMO_POL );
}
trcv_dtq()のタイムアウト設定に TMO_POL を指定して呼び出します。
データキューにデータが無い場合は、タスクをスリープさせずに戻り値をE_TMOUTとしてすぐにサービスコールから戻ります。
タイムアウト付きでデータキューからデータを受信するには以下のサービスコールを使用します。
ER trcv_dtq( ID dtqid, VP_INT *p_data, TMO tmout )
引数 | 説明 |
---|---|
dtqid | データキューID番号。 |
p_data | データキューから取得したデータを格納する領域のポインタ。 |
tmout |
タイムアウトの設定値。
|
戻り値 | 説明 |
---|---|
E_OK | 正常終了。 |
E_ID | 範囲外のデータキューID番号。 |
E_NOEXS | 指定したデータキューID番号は登録されていない。 |
E_TMOUT | データキューにデータが無くてタイムアウト。 |
E_PAR | パラメータエラー。 |
E_CTX | 非コンテキスト・タスクからの呼び出し。 |
・サービスコールのソースコードは以下のようになります。
/****************************************************************************/
/*!
* @brief データキューからの受信 (タイムアウトあり).
*
* @param [in] dtqid データキューID番号.
* @param [out] p_data データキューから受信したデータを格納する領域のポインタ.
* @param [in] tmout タイムアウト設定.
*
* @retval エラーコード.
*/
ER trcv_dtq( ID dtqid, VP_INT *p_data, TMO tmout )
{
ER ercd;
DWORD data;
//! 引数が不正な場合はエラーにする.
if( !p_data ){
return E_PAR;
}
wi_CommonLock();
//! データキューからデータを受信する.
ercd = wi_ReceiveDataQueue( dtqid, &data, tmout );
if( ercd == E_OK ){
*p_data = (VP_INT)data;
}
wi_CommonUnlock();
return ercd;
}
指定したデータキューからデータを取得します。
データキューにデータが無い場合は、データキューにデータが格納されるか、タイムアウトで設定した時間が経過するまでタスクをスリープさせます。
データキューからデータを取得する関数
データキューからデータを取得する関数のソースコードは以下のとおりです。
/****************************************************************************/
/*!
* @brief データキューからの受信.
*
* @param [in] id データキューID番号.
* @param [out] data データキューから受信したデータを格納する領域のポインタ.
* @param [in] tmout タイムアウト設定.
*
* @retval エラーコード.
*/
ER wi_ReceiveDataQueue( INT id, DWORD *data, TMO tmout )
{
ER ercd;
WIDTQOBJ *p;
WITSKOBJ *tsk;
//! データキューIDのオブジェクトを取得する.
p = (WIDTQOBJ *)wi_FindObject( id, TMAX_MAXDTQ, ObjList, &ercd );
if( !p ){
return ercd;
}
//! 引数が不正な場合はエラーにする.
if( !data ){
return E_PAR;
}
//! データキューバッファを確保していない場合.
if( p->QueSize == 0 || !p->QueBuf ){
if( p->SndWaitQue ){
tsk = (WITSKOBJ *)(p->SndWaitQue);
//! 送信メッセージを取り出す.
*data = (DWORD)(tsk->Param[0]);
//! メッセージ受信先を待っているタスクを起床させる.
wi_TaskWakeup( tsk->Hdr.Id, TTW_SDTQ, &(p->SndWaitQue) );
return E_OK;
}else{
//! メッセージが送信されるまでタスクをスリープさせる.
ercd = wi_TaskWait( id, TTW_RDTQ, tmout, p->Attribute, &(p->RcvWaitQue) );
if( ercd == E_OK ){
//! 送信メッセージを取り出す.
tsk = wi_GetTaskObject( TSK_SELF );
if( tsk ){
*data = (DWORD)(tsk->Param[0]);
}
}
return ercd;
}
}
//! データキューにデータがある場合、データを取り出して終了する.
if( p->GetPos != p->PutPos ){
//! データキューの先頭からデータを取り出す.
*data = p->QueBuf[p->GetPos];
//! データキューの読み出し位置を更新する.
p->GetPos = wi_IncRingPositon( p->GetPos, p->QueSize );
//! バッファが空くのを待っているタスクがある場合はタスクを起床させる.
if( p->SndWaitQue ){
wi_TaskWakeup( p->SndWaitQue->Id, TTW_SDTQ, &(p->SndWaitQue) );
}
return E_OK;
}
//! メッセージを受信するまでタスクをスリープさせる.
ercd = wi_TaskWait( id, TTW_RDTQ, tmout, p->Attribute, &(p->RcvWaitQue) );
if( ercd == E_OK ){
if( p->GetPos != p->PutPos ){
//! データキューの先頭からデータを取り出す.
*data = p->QueBuf[p->GetPos];
//! データキューの読み出し位置を更新する.
p->GetPos = wi_IncRingPositon( p->GetPos, p->QueSize );
}
}
return ercd;
}
データキューからデータを取得する関数は以下のような処理を行います。
- 引数で指定されたデータキューID番号に該当するデータキュー・オブジェクトを取り出します。
-
データキューのバッファを確保していない場合、メッセージ送信待ちをしているタスクがあれば、送信データを受け取って正常終了します。このとき送信待ちをしているタスクを起床します。
メッセージ送信待ちをしているタスクがない場合はメッセージが送信されるまでタスクをスリープさせます。 - データキューのバッファにデータがある場合はバッファから先頭のデータを取り出して正常終了にします。バッファが空くのを待っているタスクがある場合は、そのタスクを起床して終了にします。
- データキューのバッファにデータがない場合、メッセージを送信されるか、タイムアウトになるまでタスクをスリープさせます。
- タスクのスリープから復帰したときに正常終了で復帰した場合のみ、データキューのバッファの先頭からデータを取り出します。