uIP TCP/IPについて

先ごろ(だいぶ前ですが)ルネサスサイトから uIP TCP/IP Protocol Stack Demostration Document number:R01AN0169EU0100 Ver 1.01 NOTEs: * The demostration directory structure is explained in the application note. * This application note supports RX62N and the demostration project runs on RSK+RX62N. UIPのサンプルを入手しましてSH7670へ移植しました、その結果とても良好な結果を得ましたので報告します 自前のソースでTCP/IPを実装して稼動させていましたがよく応答ができなくなったりしていました いろいろな遷移状態でわけがわからないような(たぶんプロトコルが十分でない)遷移もありました UIPにすると必ず応答して、応答不良などまだ経験がありません、 ただこのUIP長い(大きい)データ転送には弱いんです、”どうしてこんなに時間がかかるの”というぐらい なにか説明ではACKが200mセコンドウェイト方式を採用しているからだとか これの速度はもっと速くはならないものでしょうか? IWIPなど聞きますが、UIPと比べてどうなのでしょうか、IWIPのほうがいいのでしょうか?
Parents
  • こんにちは、ルネサスマイコン(RXマイコン中心ですが)でTCP/IP関連をいろいろ実験しておりますシェルティと申します。

    TCP/IPですが、複雑怪奇な仕様であり、スクラッチ開発となると相当な難易度ですね。

    実験/研究レベルならスクラッチ開発もありかもしれませんが、量産製品に適用となると、

    第一にネットワーク関連ソフトを組み込みマイコン向けに製品化しているソフトウェアハウス製のものがおすすめです。

    例えば、図研エルミック殿やデータテクノロジー殿、ユビキタス殿などの組み込み用TCP/IPが有名です。

    ルネサス製でも組み込み用TCP/IP M3S-T4-Tinyというのが有償製品として提供されています。(SH2A用の無償ダウンロードもあるようです)

    http://japan.renesas.com/mw/t4

     

    第二に組み込み用OSに内包されているTCP/IP機能を使うのも良いです。

    (ここでいう組み込み用OSはリアルタイムOSではなく、組み込み用Linuxを指します)

     

    第三にuIPやlwIP等のオープンソース系のコードを頑張って量産製品に適用する道です。

    第四にスクラッチ開発でTCP/IPを手作りする道です。

    第三・第四の道は技術力に自信が有る場合におすすめですね。

    安く仕上げられるというメリットも捨てがたいと思います。

    -------

    さて、uIPで大きいデータ転送に弱い件ですが、uIPのTCP処理の実装に問題があります。

    lwIPでも私が調査した限り同様の問題を含んでいます。

    組み込み用TCP/IP M3S-T4-TinyもRXマイコン用パッケージにて、最近ソースコードが公開されたので中の実装を確認したところ、

    uIPやlwIPよりはマシですが、もう一段の改善が必要といったところです。

    各TCP/IPを比較すると以下の通りです。

    uIP or lwIP : TCPの送信アルゴリズムが貧弱。データ送信1回につき1個のACKが戻ってくることを期待している。

             多くの一般的なTCP/IPはTCPデータ受信時は2個データを受信する or 1個データ受信し200ms経過後タイムアウトしACKを返す実装になっている。

             その結果、毎回タイムアウトが発生し1秒に5回のデータ転送しか実現出来ない。

    組み込み用TCP/IP M3S-T4-Tiny : TCPの送信アルゴリズムが少し貧弱。データ送信は2個セットでACKが戻ってくることを期待している。

             多くの一般的なTCP/IPはTCPデータ受信時は2個データを受信する or 1個データ受信し200ms経過後タイムアウトしACKを返す実装になっている。

             その結果ACKがすぐ戻ってくるネットワーク環境(LAN)においては転送速度に問題は発生しないが、

             ACKがすぐに戻ってこないネットワーク環境(WAN)においては転送速度がACKが返ってくる時間に律速する。

             ACKが返ってくるまで200msかかる(東京-北米西海岸等)通信をする場合は、uIP or lwIPと変わらない程度の通信速度に落ちる。

             ※ローカル環境ではSH7216@200MHz で、TCP送受信が60Mbps程度出せることを確認しました。(RX62N@100MHz では30Mbps程度確認)

    -----

    これは組み込み用TCP/IPが多くの場合、RAM容量に制限の多いマイコンでの動作を期待しているため、

    送信用/受信用のバッファを多く持たないことに起因します。

    TCPの規格上、お互いに受信用のバッファサイズ(受信ウィンドウと呼ばれます)を常にTCPヘッダの特定16bitエリア(0xffff=最大64KB)に載せて

    通知し合っているわけですが、上述したTCP/IPたちはここにTCPパケット1個分(=1460バイト)の容量を設定しているのです。

    #組み込み用TCP/IP M3S-T4-Tinyではここが可変になっていて柔軟にチューニングが効くようにはなっています。

    その上、送信アルゴリズムも上述した通り貧弱ですのでいずれにしても大きなデータ通信には向きません。

    -----

    長くなりました。

    結論ですが、量産製品にTCP/IP機能を付ける目的であれば、有償のTCP/IP製品をお求めになるのが良いかと思います。

    とにかくまず実験して感触を掴んでみたい/通信速度が気になる/LANでしか通信しない、ということであれば、

    SH2A用の組み込み用TCP/IP M3S-T4-Tinyを使って実験されるのが良いかと思います。

    ただ、ソフトは無償ダウンロードがありますが、SH7216の評価ボードとE10Aエミュレータが必要となり、ちょっと実験してみるのには敷居が高そうですね。

    (TCP/IP処理部分はSH7670でも動作するでしょうけれど、サンプル全体がSH7216用に作られているため、

     Etherドライバ付近とボード周りの設定プログラム、スタートアップ等を調整してあげる必要はありそうです)

    もちろん、せっかくuIPをSH7670に移植されたのですから、大きなデータ通信については目をつむり、そのまま使用し続ける案も十分に有りと思います。

    以上です。

     

     

  • すみません、少し書き漏れました。

    一般的なTCP送信アルゴリズムは、「通信相手の受信ウィンドウサイズに空きがあればACKが返ってこなくてもお構いなしに送信する」です。

    このように実装するためには、通信相手の受信ウィンドウサイズの最大値(0xffff=64KB)の容量の送信バッファが必要です。

    しかも、通信相手が複数同時に居る場合は通信相手の数分だけ64KBの送信バッファが要ります。もちろん受信ウィンドウも要ります。

    従って、多くの(オープンソース系)組み込み用TCP/IPは多くのマイコンで動作させることを優先し、

    バッファサイズを制限し通信速度を犠牲にしたのだと思います。

    組み込みソフトを専業でやっているソフトウェアハウスのTCP/IPの場合、この辺りが柔軟に設定できるものがあると聞きますので

    本格的に量産製品を作られる場合は一度ソフトウェアハウスに相談してみるのが良いかと思います。

     

     

  • シェルティ さん

    回答ありがとうございます、

    なにか、今一番必要なことを教えられた気分です、なるほど

    要約すると、組み込み用の多くのTCP/IP機能は組み込み用に特化するため

    大容量、高速通信を犠牲にして作成されているということでしょうか

    できればUIPでも動作している環境ですので、なにか設定を変更するなどすれば

    高速になることも期待したりもしたのですが、基本的なところの設計が違うということなのでしょうか、

    このプロジェクトはまだ量産の段階ではありませんので

    その段階になりましたら、さしせまってきたらソフトウェアハウスに相談してみたいと思います。

  • シェルティ さん

    その前に

     ※ローカル環境ではSH7216@200MHz で、TCP送受信が60Mbps程度出せることを確認しました。(RX62N@100MHz では30Mbps程度確認)

    が結構早い?

    組み込み用TCP/IP M3S-T4-Tinyというのが有償製品として提供されています。(SH2A用の無償ダウンロードもあるようです)

    http://japan.renesas.com/mw/t4

    これ今日ダウンロードしましてインストールさせていただきました。(SH2A用の無償ダウンロードもあるようです)

    これからはこれを使用することに切り替えたいと思います。

    シェルティ さん有益な情報ありがとうございました。

  • IKUZOさん

    私の情報が少しでも役に立てたようで嬉しいです

    私は組み込み用TCP/IP M3S-T4-Tinyに関してはそこそこ詳しくなってきましたので、

    通信速度性能測定などで思ったように性能が出ない、等ありましたらご連絡ください。

    アドバイスできることがあるかもしれません。

    #IKUZOさんがSH7670に移植されたuIPもとても良いと思います。設定で通信速度改善出来ないかuIPのコードを見てみます。何か分かったら連絡します。

Reply
  • IKUZOさん

    私の情報が少しでも役に立てたようで嬉しいです

    私は組み込み用TCP/IP M3S-T4-Tinyに関してはそこそこ詳しくなってきましたので、

    通信速度性能測定などで思ったように性能が出ない、等ありましたらご連絡ください。

    アドバイスできることがあるかもしれません。

    #IKUZOさんがSH7670に移植されたuIPもとても良いと思います。設定で通信速度改善出来ないかuIPのコードを見てみます。何か分かったら連絡します。

Children
  • シェルティ さん

    ほんとうに心強い思いです、自分一人で悩んでいたところで、かふぇルネから助けられた思いです

    「TCP/IPですが、複雑怪奇な仕様であり」とありましたが、この言葉にはなぐさめられました、苦労してきましたから

    シェルティ さん、これからもよろしくお願いします。

  • シェルティ さんお世話になります

    an_r20an0050jj_sh2a_t4_v106r00\sample のフォルダ

    Ether.hws でコンパイルすると下記エラー発生なのですが

    何かdefine する必要がありますか?

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_t4_itcpip.h(75) :  DC201 (E) A header file does not exist 'stdint.h'

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_stdint.h(25) :  DC201 (E) A header file does not exist 'stdint.h'

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_t4_itcpip.h(75) :  DC201 (E) A header file does not exist 'stdint.h'

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_stdint.h(25) :  DC201 (E) A header file does not exist 'stdint.h'

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_t4_itcpip.h(75) :  DC201 (E) A header file does not exist 'stdint.h'

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_stdint.h(25) :  DC201 (E) A header file does not exist 'stdint.h'

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_t4_itcpip.h(75) :  DC201 (E) A header file does not exist 'stdint.h'

    Phase: SH C/C++ Compiler, File: SH C/C++ Compiler, dependency scan error

    C:\Dev\BASE\T4\sh2a\an_r20an0050jj_sh2a_t4_v106r00\sample\src\t4\lib\r_stdint.h(25) :  DC201 (E) A header file does not exist 'stdint.h'

  • 申し訳ありません

    エラーのようなものは出ることには出ますが

    ビルドはできました、H8S等もやってみましたが

    正常に出来ました、

    これから導入いたします。

  •  エラーの出ているヘッダファイルの中に include 'stdint.h' と書いてありませんか。

     その 'stdint.h' が見つからないと言うエラーだと思う。

  • IKUZOさん、リカルドさん

    こんにちは、シェルティです。

    エラーについて少し調べてみました。

    エラーはDependencyのチェックのエラーで、コンパイルのエラーではないですね。

    Cコンパイラのプリプロセッサが動く前に#includeで指定されているファイルの有無をチェックしており、

    #ifdef で括られた部分のヘッダファイル「stdint.h」が無いというエラーが出力されていました。

    以下のコードの「★ここでDependencyエラー検出」というところでエラーが出てますね。

    #if defined(__RX)
    #include "stdint.h"            // ★ここでDependencyエラー検出
    #else
    #include "r_stdint.h"
    #endif

    T4ライブラリはルネサスマイコン全般で使えるようにしてあるようで、

    ヘッダファイル(r_t4_itcpip.h)では種々マイコンのプリデファインマクロとITRONの使用有無のマクロで

    標準型定義が切り分けられているようです。

    __RXはRXコンパイラがコンパイル時に自動的に定義してくれるマクロ名ですね。

    以上です

  • リカルドさんシェルティ さん

    __RX #define があれば#include "stdint.h"を探しに行くというような内容で

    sh2a用で使用するので__RXはないはずですが、コンパイラ(プリプロセッサ)が

    一応はチェックするようで

    Dependencyエラー検出なのでしょう

    #if defined(__RX)

    //#include "stdint.h"            // ★ここでDependencyエラー検出

    #else

    #include "r_stdint.h"

    #endif

    こうしてやればエラーは一応でません

    他の箇所も同様にしました

    内容を精査したところどうも7216用なので

    7670のドライバがレジスタ構成も異なり

    それを調整するのに手間取りそうです

    typedefの定義も特徴的なものに変更いたしました

    まだまだこれからです

  • IKUZOさん

    こんにちは、シェルティです。

    SH2A用のT4ライブラリに付属しているサンプルはIKUZOさんが仰るとおりSH7216用ですね。

    私はT4ライブラリに付属しているSH7216のEtherドライバのコードをSH7670に移植しその上でT4ライブラリを動作確認したことがあります。

    このときのEtherドライバのソースコードの差分を調べたので参考にしてください。

    思ったより差分はなく、iodefine.hのレジスタアクセス方法の違いを合わせて変更してあげるだけで移植が出来ております。

    (この掲示板、表を書けるみたいなので使ってみます。変になったらすみません)
     

    比較項目 SH7216 SH7670
    iodefine.hのバージョン Jun.10,2009 Ver.1.00.00 Oct.08,2010 ver.1.00.02
    EtherCのRFLRレジスタ EtherC.RFLR.LONG EtherC.RFLR
    EtherCのIPGRレジスタ EtherC.IPGR.LONG EtherC.IPGR
    EtherCのMALRレジスタ EtherC.MALR.LONG EtherC.MALR
    EDMACのTFTRレジスタ EDMAC.TFTR.LONG EDMAC.TFTR

    以上です

     

  • シェルティ さん ありがとうございます

    ソースコードの差分どうりです、ほとんどのところはLONGを消すことでコンパイラはOKでした

    ただベクタ関連でしょうか違うところが

    SH7216

    // INTC.IPR19.BIT._EDMAC = EINT0_INT_LV; //EINT0 priority level  コンパイラNG

    SH7670

    INTC.IPR12.BIT._ETC=EINT0_INT_LV;//EINT0 priority levelこれが替わりに?

    SH7216

    // 153 E-DMAC EINT0

    void INT_EDMAC_EINT0(void){

    lan_recv_handler();

    }

    SH7670

    // 171 ETC EINT0

    void INT_ETC_EINT0(void)

    {

    unsigned long stat_edmac;

    unsigned long stat_EtherC;

    パソコンからpingコールして割り込みが入るかテストしたのですが

    SH7670サンプルコードの組み合わせphy,etherでは割り込みが入るのですが

    SH7216サンプルコードの組み合わせphy,ethでは不能?なので(たぶん?もう一度やってみても良いが)

    少し考えました

    t4_driver.cのところの

    lan_readをSH7670サンプルコードのlan_recvに渡し

    lan_writeをSH7670サンプルコードのlan_sendに渡したらと思いましたが

    t4ライブラリが完全にphy,eth層と別であればうまくいくと思ったのですが

    SH7670サンプルコードの組み合わせphy,etherと

    SH7216サンプルコードの組み合わせphy,ethでは基本的な構造上の違いがあるのでしょうか?

  • IKUZOさん

    こんにちは、シェルティです。

    コンパイルが通ったとのことで良かったです。

    あとはご指摘通り割り込み周りの差分ですね。

    (一度に案内できず、すみません)

     

    SH7216もSH7670もEther関連は基本構造は同じですね。

    ご推察の通り  t4_driver.c にはEtherドライバからの割り込みを受け付ける lan_recv_handler()が有ります。

    また、T4ライブラリからのR/Wや初期化を受け付けるlan_read()、lan_write()、tcpudp_act_cyc()等の

    T4ライブラリのユーザ定義関数があります。

    t4_driver.c はT4ライブラリとEtherドライバの橋渡し的な存在ですね。

     

    まず割り込みコントローラの設定でレジスタ定義が異なるので以下のように変更します。(左側:SH7216、右側SH7670)

    これはIKUZOさんが試された通り、SH7670の場合、INTC.IPR12.BIT._ETCを使用するように変更です。

     

    次にlan_recv_handler()です。(左側:SH7216、右側SH7670)

    これはコードが整理できていなくて差分が出ているだけです。続くlan_recv_handler()の呼び出し元の

    intprg.c の差分と合わせてご参照ください。

    大事なのは、EDMACのEESRレジスタをクリアしてあげることです。そうしないと次の割り込みが入りません。

    (このレジスタは少し変わっていて、'1' を書いたらクリアされるタイプです)

     

    次にintprg.c の差分です。(上画像の左側がSH7216のEther割り込みの入口、下画像の右側がSH7670のEther割り込みの入口)

    こちらもサンプルコード切り貼りなので整理出来てなくてすみません。

    実行していることは、SH7216もSH7670も同じで、「割り込み受付→割り込みフラグクリア→_process_tcpip()呼び出し」のセットです。

     

     

  • シェルティ さんお世話になります

    SH7216サンプルコードの組み合わせphy,ethを用いた差分他設定ありがとうございます

    こちらでも同時にSH7670サンプルコードの組み合わせphy,etherをt4_driver.c に組み込んでテストしました

    t4ライブラリが完全にphy,eth層と別であるということマニュアルに記されていまして

    どんなドライバでも接続可能ということでしたので

    マニュアルのとうりに設定をしているうちに

    C:\Dev\BASE\T4\sh2a\test2\test2>ping 192.168.0.3

    192.168.0.3 に ping を送信しています 32 バイトのデータ:

    192.168.0.3 からの応答: バイト数 =32 時間 =1ms TTL=80

    192.168.0.3 からの応答: バイト数 =32 時間 <1ms TTL=80

    192.168.0.3 からの応答: バイト数 =32 時間 <1ms TTL=80

    192.168.0.3 からの応答: バイト数 =32 時間 <1ms TTL=80

    192.168.0.3 の ping 統計:

       パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、

    ラウンド トリップの概算時間 (ミリ秒):

       最小 = 0ms、最大 = 1ms、平均 = 0ms

    C:\Dev\BASE\T4\sh2a\test2\test2>

    PINGが通りました、これができたということで、一応成功ということで

    ひとつ

    SH7670サンプルコードの組み合わせphy,etherと

    SH7216サンプルコードの組み合わせphy,ethと比較して

    どちらが良いと思われますか?