rl78F14のUART受信の問題点について

こんにちは TTです。

 

現在、下記のような処理を行おうとしています。

A:自分(RL78F14)

B:通信相手(Aからもらったデータ内容に応じて返信してくる)

1. A→Bへデータを送信する

2.  自分(A)は自分で送信したデータを受信してしまうので、送信したデータと受信したデータが同じならデータを破棄する

3. Bからの返信を受信するまで待つ

4. Bからの返信を受信出来たら、データを取り出す。

 

しかし、上記処理中の3でBからのデータを受信することが出来ません。

通信ログを確認したところ、

・A→Bへ正しくデータを送信できている事、B→Aへデータが正しく送信されていることは確認できています。

・BはAからのデータをもらって15ms程度で返信を返してきています。

現在の不具合の仮説としては、「自分の送信データ受信→受信完了の間にBからの返信が来てしまっている?」と考えています。

そこで、EUARTの受信データの受信完了にはどれくらい時間がかかるものなのでしょうか?

また、ほかに考えられる原因等あればご教授ください。

Parents
  • TTさん、こんにちは。NoMaYと申します。

    r_uartXX_callback_softwareoverrun()関数のソースを見ただけなのですが、UARTの普通のオーバーランとは少し違うものだという気がします。例えば、以下のケースで呼び出されるものかと思います。

    ・例えば、通信パケットが、先頭4バイトを読めば、後何バイト来るか分かる、ような構造になっている
    ・なので、まずrecieve関数で4バイト受信して、その受信データをもとにrecieve関数で残りNバイト受信する、ようにした
    ・ところが、4バイト受信のrecieveが完了した後、Nバイト受信のrecieveを起動する前に、もうデータが来てしまった
    ⇒こういうケースでr_uartXX_callback_softwareoverrun()関数がコールバックされる

    ですので、4バイト受信やNバイト受信の部分をDMAなどで行うようにしても、それでは解消されないと思います。

    ちなみに、「3でBからのデータを受信することが出来ません」とのことですが、2は正しく受信出来ているのですよね?思うに、1のデータ数と3のデータ数の合計分を受信するようにrecieve関数を起動させておき、合計分受信完了後に1のデータを比較後に破棄する、などの対策が必要になるのではないかな?という気がします。

    > 1. A→Bへデータを送信する
    > 2. 自分(A)は自分で送信したデータを受信してしまうので、送信したデータと受信したデータが同じならデータを破棄する
    > 3. Bからの返信を受信するまで待つ
    > 4. Bからの返信を受信出来たら、データを取り出す。

    また、r_uartXX_callback_softwareoverrun()関数の動作を逆手にとって、以下のようにしてみるのも手かも知れません。

    ・(上記1のデータ数 - 1)のデータ数を受信するようにrecieve関数を起動する
    ・素朴なrecieve完了コールバックは使わない
    ・r_uartXX_callback_softwareoverrun(rx_data)コールバック(割り込みルーチンから呼ばれている)関数内で、(上記1のデータ数 - 1)分のデータにその後のrx_dataデータを加えたデータを使って上記2を行い、正常であれば、そのコールバック関数内で上記3のrecieve関数を起動する

    すみません、上のは私が何か勘違いしたような気がしますが、素朴にrecieve完了コールバック内で記3のrecieve関数を起動する、ので良いような気がします。

Reply
  • TTさん、こんにちは。NoMaYと申します。

    r_uartXX_callback_softwareoverrun()関数のソースを見ただけなのですが、UARTの普通のオーバーランとは少し違うものだという気がします。例えば、以下のケースで呼び出されるものかと思います。

    ・例えば、通信パケットが、先頭4バイトを読めば、後何バイト来るか分かる、ような構造になっている
    ・なので、まずrecieve関数で4バイト受信して、その受信データをもとにrecieve関数で残りNバイト受信する、ようにした
    ・ところが、4バイト受信のrecieveが完了した後、Nバイト受信のrecieveを起動する前に、もうデータが来てしまった
    ⇒こういうケースでr_uartXX_callback_softwareoverrun()関数がコールバックされる

    ですので、4バイト受信やNバイト受信の部分をDMAなどで行うようにしても、それでは解消されないと思います。

    ちなみに、「3でBからのデータを受信することが出来ません」とのことですが、2は正しく受信出来ているのですよね?思うに、1のデータ数と3のデータ数の合計分を受信するようにrecieve関数を起動させておき、合計分受信完了後に1のデータを比較後に破棄する、などの対策が必要になるのではないかな?という気がします。

    > 1. A→Bへデータを送信する
    > 2. 自分(A)は自分で送信したデータを受信してしまうので、送信したデータと受信したデータが同じならデータを破棄する
    > 3. Bからの返信を受信するまで待つ
    > 4. Bからの返信を受信出来たら、データを取り出す。

    また、r_uartXX_callback_softwareoverrun()関数の動作を逆手にとって、以下のようにしてみるのも手かも知れません。

    ・(上記1のデータ数 - 1)のデータ数を受信するようにrecieve関数を起動する
    ・素朴なrecieve完了コールバックは使わない
    ・r_uartXX_callback_softwareoverrun(rx_data)コールバック(割り込みルーチンから呼ばれている)関数内で、(上記1のデータ数 - 1)分のデータにその後のrx_dataデータを加えたデータを使って上記2を行い、正常であれば、そのコールバック関数内で上記3のrecieve関数を起動する

    すみません、上のは私が何か勘違いしたような気がしますが、素朴にrecieve完了コールバック内で記3のrecieve関数を起動する、ので良いような気がします。

Children
  • NoMaY さん。ご丁寧な返信ありがとうございます。
    受信するデータ長より長いバッファを用意する
    →とにかく受信したものを放り込む
    →ある程度以上たまったら、該当のデータを探して取り出す
    の手順で受信データをとり切れないことが無い様にしました。
    プログラムの構造的には褒められたモノではありませんが、ひとまず解決できました。
    ありがとうございました