SSP: Communications Frameworkのreadファンクションについて

こんにちは。
久しぶりの投稿です。


SynergyS1でUART通信をするコードを書こうとしているのですが、こういった場合どのように書くのが一番スマートなのか、アイデアを頂けたらと思っております。
宜しくお願いします。
------
現在、可変長データの受信のため、readファンクションでタイムアウトを設け1バイトずつ読み出しています。
    e = g_sf_comms9.p_api->read(g_sf_comms9.p_ctrl, (uint8_t*)c, 1, 1);
    // e==SSP_SUCCESSなら有効な受信データ、それ以外ならデータが無かった

仮にreadファンクション呼び出し直前にドライバ側で複数の受信データが溜まっていた場合、上記1バイト受信を繰り返すのは効率が悪いだけので、
一回のreadでまとめて手元のバッファに取り出したいと考えています。

素直コードを書くと以下の感じになりそうなものですが、受信データ長はconstデータで渡すため、実際に読み出すことができたデータ長がわかりません。
    e = g_sf_comms9.p_api->read(g_sf_comms9.p_ctrl, (uint8_t*)mybuf, sizeof(mybuf), 1);

やはりSSPを使う限り地道に1バイトずつreadするしかないのでしょうか・・・?

環境はSSP 1.2.1です。

以上です。

Parents
  • > SynergyS1でUART通信をするコードを書こうとしているのですが、こういった場合どのように書くのが一番スマートなのか、

    コールバック使うのが良いんじゃないですか。
  • 早速のリプライありがとうございました。
    コールバックを使うとなると、フレームワークを使わず下のドライバを直接扱うということですね。
    (=Communications Frameworkに関連付けされたUART DriverのコールバックプロパティはNULLでロックされてユーザーのコールバックは登録できないようです)

    せっかく汎用性ありそうなフレームワークプログラミングですが、ドライバアクセスでコールバック使用を試してみたいと思います。

    ありがとうございました。
  • わわいです
    可変長データのメッセージ受信なら、一文字づつ取り込んでいってその都度判断する、ということをしないとどーにもならんのではないかと思いますが。
    たいていはそのメッセージの先頭部分にメッセージ長のデータを置いておいて、そこまで読み込んだら残りのバイト数を読みにかかる、という処理にしますねー

    #タイムアウトを待つ、とかウェイトする、ってのはそれで済むならいいですが、ダメダメですぜ

  • わわいさん、ありがとうございます。
    ドライバ/フレームワークで何バイトの受信バッファを持っているのかはわかりませんが、「受信バイト数と(Frameworkの)read呼び出し回数が等しい」というのが効率的に気になるということが今回質問の原点です。特に通信ビットレートが高い時など。

    その意味ではコールバックで根本解決するわけではありませんが、コールバックはThread外の処理となると思いますので、ユーザーThread内のread呼び出しよりは効率がいいのかなと推定しています。

    ※いわゆるモデムのような相手との通信で、終了文字まで受信してから受信内容の解析処理を始めるといったことをしたいと考えています。
  • わわいです
    >ドライバ/フレームワークで何バイトの受信バッファを持っているのかはわかりませんが、
    まあ、そういう大層なライブラリ(?)なら、SCIの受信なんかは当然割り込み駆動で実装されてるだろうし、受信バッファもそれなりのサイズ確保されてるだろうから、あまりその心配はないんじゃないかと思います。
    まあ、ソースの該当部分を参照し、受信バッファのサイズを確認、足らなければ追加しておくのは必須ですが。

    まーしかし、(そのライブラリがどういう実装をしてるかは知りませんが)ブロックで読み込むと言っても、多分内部で1バイトづつ読んでるんでしょうから、そこら辺を気にする必要はないと思いますねー
  • こんにちは。

    >ドライバ/フレームワークで何バイトの受信バッファを持っているのかはわかりませんが

    デフォルト値は、おそらく60バイトだと思います。
    (sf_uart_commsのプロパティに Read Input Queue Sizeがあります (4×15))

    もっと詳しい仕様があると、回答がつきやすくなるかも知れませんね。
    ・受信する周期は?
    ・最大で何バイトか?
    ・通信速度は?
    ・ CR (LF) で終わるのか?
    など

    可変長ならば、わわいさんのおっしゃるように、先頭部分にバイト長をおくのがわかりやすと思います。
    そうすればフレームワークを使っても受信可能だと思います。
  • > (=Communications Frameworkに関連付けされたUART DriverのコールバックプロパティはNULLでロックされてユーザーのコールバックは登録できないようです)

    void* user_uart_callback = NULL;
    

    のようなことがされているということでしょうか?

  • わわいさん、moonさん、fujitaさん、ありがとうございます。

    Queue sizeについてありがとうございました。ドライバとフレームワークのソースコードを少し見てみましたが、FIFO無しUARTチャネルの場合は 1Queue=1キャラクタ でキューに積まれるようです。

    おっしゃる通り先頭部分にフレーム長のデータがあれば、SSPで準備されているAPIの仕様に沿った受信ができそうですね。

    ・受信する周期は?→不定期
    ・最大で何バイトか?→1フレームあたり5~1024バイト
    ・通信速度は?→115200bps
    ・ CR (LF) で終わるのか?→終端文字CR+LF

     

    >void* user_uart_callback = NULL;
    >のようなことがされているということでしょうか?

    こんな感じで鍵マークが付き、いじれません(↓e2 studioの画面キャプチャ)

    受信データをコールバックで抜かれると、フレームワークの処理が成り立たないと思われるので、わざとNULL固定にしているのかなと推測しました。

  • わわいです
    私なら、受信バッファを十分大きくしておき(512byteとか1024byteとか)、メインループで1文字づつ受信データ用のバッファに展開していき、CRLFが来たらメッセージの処理を行う、ということをしますね。
    メッセージ長がヘッダとかコマンドで類推できないなら、どーしよーもないですねえ

    #RXの案件が入ってきたのでいじってるんだが、SCIの送信割り込みがなんでエッジなんだよ!!
    #TIEを1にしても割り込みかかんなくて一日潰したよ。。ブツブツ。。
  • moonです。

    >・受信する周期は?→不定期
    >・最大で何バイトか?→1フレームあたり5~1024バイト
    >・通信速度は?→115200bps
    >・ CR (LF) で終わるのか?→終端文字CR+LF

    どうにも、しんどい通信仕様ですね。。
    これではフレームワークは使えそうにありません。
    CR LF を見つけなければならないので、(callbackを使うなどして)1バイト単位で受信するしかありません。
    不定期というのも、あぶない仕様です。
    何かの要因でとりこぼしとかあったら、検出できそうにない仕様です。

    お役に立てずにすみません。
    降参ですぅ (>_<);
  • わわいさん、moonさん、fujitaさん お付き合いくださりありがとうございました。

    用途に応じて、フレームワークでお気軽に組むのがいいのか、ドライバレベルできめ細かく書くのがいいのか、選択するのって難しいですね。。。

    また他のスレッドでお会いできれば幸いです。
    以上です。
Reply
  • わわいさん、moonさん、fujitaさん お付き合いくださりありがとうございました。

    用途に応じて、フレームワークでお気軽に組むのがいいのか、ドライバレベルできめ細かく書くのがいいのか、選択するのって難しいですね。。。

    また他のスレッドでお会いできれば幸いです。
    以上です。
Children
No Data