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のほうがいいのでしょうか?
  • リカルドさんシェルティ さん

    __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と比較して

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

  • IKUZOさん

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

    おお、pingが通りましたね。おめでとうございます。

    SH7670とSH7216のphy, ehterのサンプルコードですが、SH7216のものをおススメします。

    改めて以下2点のアプリケーションノートのコードを開いて確認してみました。

    気になったのでついでに色々調べてルネサスマイコンのEtherドライバの系譜をまとめてみました。


    SH7216グループ アプリケーションノート Ethernetを使用したユーザプログラムモードフラッシュ書き換え動作例
    R01AN0289JJ0211

    SH7670グループ イーサネット送信設定例
    R01AN0302JJ0101


    SH7670のether.c は、送信用のコードと受信用のコードが分かれていて、割り込み関数も中身が空っぽで、

    TCP/IPと結合するのに苦労すると思います。<Etherドライバ世代1>

    SH7216のeth.c は上記問題がなく一通り実装されていてTCP/IPとインタフェースを合わせれば使えそう、という印象です。

    SH2A用のT4のサンプルもこれをほとんど流用していますね。

    それから、SH7216のeth.c はRX62Nの従来のEtherドライバのコードと同一ですね。<Etherドライバ世代2>

     

    次に最新のRX62N/RX63N用のEtherドライバは現在T4のサンプルに取り込まれているようで、以下アプリケーションノートに含まれています。

    RXファミリ 組み込み用TCP/IP M3S-T4-Tinyを用いたサンプルプログラム
    Firmware Integration Technology

    R20AN0312JJ0100

    →\an_r20an0312jj0100_rx_t4_connectivity\workspace\reference\rx62n_rx63n_ether_driver

    こちらは、LANケーブル活線挿抜に対応したり、Etherドライバ内でのデータコピーを省いたりかなり進歩した、という印象です。<Etherドライバ世代3>

     

    さらにさらに、最近はソフトウェアのモジュール化が進んできたのか、

    RXマイコンで「FIT(Firmware Integration Technology)」というのが出てきており、

    その一環でRX用のEtherドライバがモジュール化されていました。(まだRX64Mしか対応していませんが)

    RXファミリ イーサネットモジュール Firmware Integration Technology
    R01AN2009JJ0100

     これが現在のルネサスのEtherドライバの最終形のようです。<Etherドライバ世代4>

    以下、FITの説明を読むと、BSP(Board Support Package)上に積み木のようにFITモジュールを組み立てていく感じですね。

    http://japan.renesas.com/products/mpumcu/rx/child/fit.jsp

    これまでアプリケーションノートのコードをくっつけるのが面倒だったのが解消されますね。


    横道に逸れてしまいました。

    ひとまずSH7216のEtherドライバをおススメしましたが、

    もし余力があるのであれば、<Etherドライバ世代4>のEtherドライバをSH7216 or SH7670に再移植すると

    転送レート/CPU負荷率共にグっと向上すると思います。

    iodefine.h の交換と target フォルダの中身をSH7216 or SH7670用に作ってあげると良いかと思います。

    ちなみに、<Etherドライバ世代2>のデータコピー関数(_eth_fifoRead()と_eth_fifoWrite())は

    最下層で1バイトずつforループでデータコピーするかなり残念な仕様ですね。

     

    長文失礼しました

    以上です

     

     

  • シェルティです、すみません訂正です。

    <Etherドライバ世代4>はRXマイコン用のBSPが前提のコードが有り

    これをSH7216 or SH7670に移植するのは少し骨が折れそうです。

    <Etherドライバ世代3>であればiodefine.h の差分だけ何とかしてあげれば

    RXマイコン用→SH7216 or SH7670用に移植が出来そうな印象を受けました。

    以上です

  • シェルティ さん、なるほどこれから苦労しそうということですね

    一応変更したところですが、自己流に改造してしまったというところですが

    ///////////////////////////////////////////////////////////////////////

    //etherから呼び出す

    ///////////////////////////////////////////////////////////////////////

    t4_H lan_read( t4_B **buf )

    {

    t4_H return_code;

    return_code=(t4_H)lan_recv(lan_buf); //etherからデータを受信する

    if(return_code > 0){

    //有効なデータを読み込んだ

    *buf = (t4_B*)lan_buf;

    t4_stat.t4_rec_cnt++;

    t4_stat.t4_rec_byte+=return_code;

    }else{//有効なデータは受信しなかった

    return_code = -1;

    }

    return return_code;

    }

    ///////////////////////////////////////////////////////////////////////

    //etherから呼び出す end

    ///////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////

    //etherから呼び出す

    ///////////////////////////////////////////////////////////////////////

    t4_H lan_write( t4_B *header , t4_H header_len, t4_B *data , t4_H data_len)

    {

    t4_H return_code;

    if (header_len+data_len > 1514 || header_len+data_len <= 0){

    return -5; // Return code "-5" notifies "data transmission fail" to T4.

    }

    memcpy(lan_buf, header, header_len);

    memcpy(lan_buf + header_len, data, data_len);

    //etherにデータを送信する

    return_code=(t4_H)lan_send(lan_buf,header_len+data_len);

    if (return_code < 0){

    return -5;//登録失敗

    }else{

    //登録成功

    t4_stat.t4_snd_cnt++;

    t4_stat.t4_snd_byte += (header_len + data_len);

    }

    return return_code;

    }

    ///////////////////////////////////////////////////////////////////////

    //etherから呼び出す end

    ///////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////

    //tcp_apiから呼び出す

    ///////////////////////////////////////////////////////////////////////

    //TCP/IP処理関数の周期起動の制御

    //パラメータcycactにしたがって、TCP/IP処理関数_process_tcpipの周期起動を制御します。

    //関数_process_tcpipの周期起動間隔は、10msec以下に設定します。

    //プロトコル処理部で使用します。

    void tcpudp_act_cyc(unsigned char cycact)

    {

    switch(cycact){

    case 0: //TCP/IP処理関数の周期起動を停止

    tcpip_flag=0;

    break;

    case 1: //CP/IP処理関数の周期起動を開始

    tcpip_flag=1;

    break;

    default:

    tcpip_flag = 0;

    break;

    }

    }

    ///////////////////////////////////////////////////////////////////////

    //tcp_apiから呼び出す

    ///////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////

    //T4処理(CPUの10mS割り込みで処理)

    ///////////////////////////////////////////////////////////////////////

    //T4ライブラリのTCP/IP部の処理を行います。

    //本APIからドライバ層へのリードライト関数など、種々ドライバ関数が呼び出されます。

    //本APIの処理時間は通信状態やドライバ層の実装方法によって変化します。

    //本APIのスタックはドライバ層の実装方法によって変化します。

    //本APIはtypeに”1”を指定し、任意の間隔(10msec推奨)で定期的に起動してください。

    //(タイマ割り込みなどを使用)

    extern BOOL ether_enable;

    //WDTの10mS割り込みから

    void t4_interval(void)

    {

    tcpudp_time_cnt++;

    if(ether_enable && tcpip_flag)_process_tcpip(1);

    }

    //EtherCの割り込みから

    void t4_interval_(void)

    {

    if(ether_enable && tcpip_flag)_process_tcpip(1);

    }

    ///////////////////////////////////////////////////////////////////////

    //T4処理(CPUの10mS割り込みで処理) end

    ///////////////////////////////////////////////////////////////////////

    というぐあいで、こんなことになりました、TCPのノンブロッキングサンプルから

    最初にtelnetサーバーでもやってみようかと思います

  • IKUZOさん

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

    コード拝見しました。TCP/IPとEtherドライバが無駄なく結合出来ていると思います。

    これから、アプリを載せていって通信速度やCPU負荷状況が気になってきた場合に、

    Etherドライバに改善の余地有り、と思い返していただけると良いかなと思います。

    アプリ変更せずにEtherドライバとt4_driver.c の改定のみで改善できると思います。


    あと、T4用のアプリですが以下が参考になるかもしれません。

    ワークスペースとしてはRXマイコン用ですがT4のAPIはSH2Aと共通なので

    アプリ部分(DHCP/DNS/FTP/HTTPのコード)の移植は容易と思います。

    RXファミリ 組み込み用TCP/IP M3S-T4-Tinyを使った応用例(DHCP/DNS/FTP/HTTP) Firmware Integration Technology
    R20AN0314JJ0100

    RXマイコンをWebサーバにして、ブラウザからRXマイコンボード上のLEDをコントロール出来るサンプルになってました。

    Webサーバのコンテンツを内蔵ROMに配置するタイプとSDカードかUSBメモリに配置するタイプが用意されています。

    以上です

     

     

     

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

    2014/9/11 2:21の投稿では画像を添付されてますが、どのようにしたらできますか?

    ご存知であれば、教えていただけませんか?

    RXファミリ 組み込み用TCP/IP M3S-T4-Tinyを使った応用例(DHCP/DNS/FTP/HTTP) Firmware Integration Technologyですがダウンロードしてftpサーバのサンプルところを取り出して

    例のT4のドライバーに接続しまして、ftpからの接続とユザー名、パスワードまでは正常に行くのですが

    ls-lのコマンドで固まります、もうすこしがんばってみます。