R_UART0_Receive関数の仕様について

お世話になっております、ムヌルです。

RL78/G14とCS+を使用しています。

『R_UART0_Receive』関数について、気になった事がありました。

こちらの関数は初期の設定だと、

MD_STATUS R_UART0_Receive(uint8_t * const rx_buf, uint16_t rx_num)
{
MD_STATUS status = MD_OK; //正常終了ではなく、正常起動

if (rx_num < 1U)
{
status = MD_ARGERROR;
}
else
{
g_uart0_rx_count = 0U;
g_uart0_rx_length = rx_num;
gp_uart0_rx_address = rx_buf;
}

return (status);
}

という様になっていますが、ここでお聞きしたいことが3つあります。

①この関数の処理が行われるタイミングはいつか?

②この関数の戻り値(MD_OK等)は必ず使用しないとダメか?

 又、この戻り値を無視しても問題はないのか。

 (サンプルコードを見る限り、この戻り値を代入したり参照されたりしていない)

③この関数の戻り値を使用しない場合、void型に変更し、戻り値を使用しない

処理内容に変更してもよいか?(void型に変更し、returnを無くす程度)

  • 戻り値というのは意味があって用意されています。

    内容を理解した上で戻り値を使わないなら関数に先駆け(void)をつけるとC言語的かなと・・・

    static char buf[BUF_SIZE]
    (void)R_UART_Receive(buf, sizeof(buf_size));

    中を読んでわかると思いますが受信時の書き込み先バッファポインタとそのサイズをセットして受信数が0ですよってことをしているだけです。戻り値でOKな状態もバッファサイズが0じゃないということだけの判定で、バッファのポインタが妥当?とかはチェックしてないので無視して構わないと思います。でもそれって実装の中身がわかるから無視してもいいって判断できますが、通常は戻り値がお願いしたい処理の結果として得られるので成功したのかを知る上で戻り値チェックをする癖があった方がいいと思います。

    これを設計した人の意図がよくわからないですが、「Receive」とついてて受信動作開始しないのは如何なもの?というのは私個人の意見なので声を小にして叫びます。実際にはこの関数の後にペリフェラルの動作開始をする仕組みを呼び出すか?内部変数が受信を要求している状態だと判断する部分があって、状態をポールして受信割り込みを有効化する仕組みとかあるのかな?

  • チョコです。

    UARTが対象としている調歩同期通信の受信では、こんなR_UART_Receiveは単にデータバッファを設定しているだけの関数で、実際のUART受信動作とは全く無関係です。おそらく、SPIやI2Cと同じように関数を準備しただけではないかと思っています。私は、こんな関数はなくすべきだと思っています。

    こんな関数でごまかすよりも、最初から受信バッファ(FIFO)を準備して、初期化が終わったらUARは勝手に受信待機させておけばいいのです。受信したなら、そのステータスを確認して、受信したデータを読み出せばいいだけです。

    以前(2016/8)、サンプルプログラム等に以下のサンプルプロジェクトを投稿しています。

    「RL78コード生成へのリングバッファ追加」https://community-ja.renesas.com/cafe_rene/m/sample_program/306

    とにかく、UARTではいつ受信データが来るかは分からないので、最初から受信待機させておくべきです。

    このサンプルプロジェクトではR_UART_Receiveなしで動くようにしています。詳細はダウンロードして眺めてみてください。

    以上

  • チョコです。

    ムヌルさんの質問に直接回答していなかったので、追加でコメントします。

    >①この関数の処理が行われるタイミングはいつか?

    当然、呼び出されたらすぐに処理されます。その結果は受信データの格納バッファ等を定義しているだけです。UARTの受信動作とは全く無関係です。

    >この関数の戻り値(MD_OK等)は必ず使用しないとダメか?

    単に受信データ数が0ならエラーにしているだけで、大して意味があるような戻り値ではありません。確実に、0以外の引数しか使わないなら、戻り値に意味はありません。

    >この関数の戻り値を使用しない場合、void型に変更し、戻り値を使用しない

    注意が必要です。コード生成では、生成をし直すたびに戻り値ありに初期化されます。やるなら、コード生成は、初期設定だけにして、残りは全て自分でコーディングするようにしてください。

    それが出来なかったら、#ifdef等の条件付きコンパイルを使う必要があります。プログラム部だけでなく、ヘッダ・ファイルも関係してくるので、

    これは、あまりお勧めできません。

    以上

  • チョコ様

    ご返信ありがとうございます。

    ①受信感知ですぐに実行

    ②戻り値に意味はない(使用しなくて良い)

    ③変更する場合は初期化のみの記述にとどめ、そこから先は自分でかく。

    という風に解釈致しました(間違っていたらご指摘ください)。

  • Shoji Yamamoto様

    返信どうもありがとうございました。

    「Receive」というのには語弊がある、というのは色々なサイトで良く見るような意見でした。

    関数名に惑わされず、処理で何をしている関数なのか見極める必要があると感じています。

    (私の場合は受信格納先設定関数というような認識で扱っております…)

  • チョコです。

    >①受信感知ですぐに実行

    いいえ、違います。受信の実際の動作とは全く無関係に、単に関数を呼び出すと実行されます。

    >戻り値に意味はない(使用しなくて良い)戻り値に意味はない(使用しなくて良い)

    意味がないことはないですが。「わざわざ使うほどのことはないでしょう」程度です。

    >③変更する場合は初期化のみの記述にとどめ、そこから先は自分でかく。

    はい、そうです。

    ちなみに、前回紹介した「RL78コード生成へのリングバッファ追加」では、コード生成されたコードにそのままFIFOを追加しても動くようにしてあるので、「R_UART0_Receive」は全く使わなくても受信処理ができるようになっています。その代わり、FIFOの状態を確認して、データを受信していたら、受信したデータをFIFOから読み出す処理になります。(そのための関数は準備してあります。)

    以上