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

タイムアウトの設定値。

  • TMO_FEVRの場合、永久にデータキューにデータがセットされるのを待ちます。
  • TMO_POLの場合、データキューにデータが無くてもタスクをスリープしません。
  • その他の正数はタイムアウト値となります。

戻り値説明
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番号に該当するデータキュー・オブジェクトを取り出します。
  • データキューのバッファを確保していない場合、メッセージ受信待ちをしているタスクがあれば、送信データを受け渡して正常終了します。このとき受信待ちをしているタスクを起床します。
    メッセージ受信待ちをしているタスクがない場合はメッセージが受信されるまでタスクをスリープさせます。
  • データキューのバッファに空きがない場合、バッファが空くか、タイムアウトになるまでタスクをスリープさせます。
  • データキューのバッファに空きがある場合、バッファの最後に送信データを追加します。
  • データ受信待ちをしているタスクがある場合、そのタスクを起床します。


Windowsは米国Microsoft Corporationの登録商標です。