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