WFI32EによるTCP通信

WFI32 Curiosity Development Board

はじめに

TCP/IPとはインターネットなどに代表される通信ネットワークにおいて全世界で標準的に使用されている通信プロトコルで、これに準拠する事でOSや環境に依らず機器間で通信が可能になっています。Webページを閲覧する時はそのTCP/IPの中のTCPという「送ったデータを 相手が 受け取れたか確認しながら通信する」といったプロトコルを用い、動画サイトなど高速なデータ通信が必要な場合はUDPという「相手が受け取ったかは不問とする」プロトコルが良く用いられます。

TCP/IPとは

TCP/IPとは、インターネットなどで標準的に用いられる通信プロトコル(通信手順)で、TCP(Transmission Control Protocol)とIP(Internet Protocol)を組み合わせたもの。また、TCPとIPを含む、インターネット標準のプロトコル群全体の総称。

出典:IT用語辞典

概要

WFI32 Cutiosity Board とスマホ間でTCP通信を行います。GitHub上にサンプルソフトが有りますので、以下のような構成で動作を確認します。

WFI32 Curiosity Boardについてはこちらで紹介しています。

ハードウェア

  1. WFI32 Cutiosity Board
  2. Home Rooter
  3. スマートフォン
  4. PC
  5. USB-Uart変換ボード

ソフトウェア

  1. Teraterm(PC側)
  2. UDP/TCP/REST Network Tool(スマホアプリ)

全体構成

(fig.1)構成ブロック(IPアドレスは例)

MPLAB Harmony

サンプルソフトウェアは MPLAB Harmony3という統合フレームワークで開発されており、(fig.2)のように共通のシステムサービスや、周辺モジュールライブラリ層、ミドルウェア層といったブロックで構成されます。

(fig.2)MPLAB Harmony構成

ソフトウェアコンポーネントとしては(fig.3)のようなライブラリやドライバが含まれており、逐次追加されている模様です。

(fig.3)ソフトウェアコンポーネント60001353C_JP.pdf (microchip.com)より抜粋
Harmony3とは

MPLAB Harmony は、PIC32 マイクロコントローラ向けの柔軟で包括的なファームウェア統合開発環境です。相互動作可能な RTOS対応ライブラリの開発を可能にします。また、迅速かつ広範なサポートによりサードパーティ製ソフトウェアを統合できます。

それらのソフトウェアコンポーネントは開発環境であるMPLAB Xに MPLAB Harmony Configuratorというプラグインで提供され、これを用いる事でGUIにてクロックの設定やI/Oピン設定、上記のシステムサービス、ミドルウェアなどのコードを自動で生成可能となっています。

開発の進め方

1.GitLabからのサンプルプロジェクトダウンロード

①GitHubのGitHub – マイクロチップ-MPLAB-ハーモニー/ワイヤレス:ハーモニー3ワイヤレスソリューションページから「TCPサーバ」をクリック

(fig.4)GitHubダウンロード先

②開いたWebページから「top level of the repository」をクリック

(fig.5)GitHubダウンロード先

③開いたWebページから「Code」をクリックしメニューを開き「Download Zip」でPC上にDLします。

(fig.6)GitHubダウンロード先

2.MPLAB X IDEでの操作

①ダウンロードした「tcp_server\pic32mz_w1_curiosity_freertos.X」プロジェクトを適当なフォルダにコピーして開きます。

②メインメニュー>「Tools」>「Embedded」> 「MPLAB Harmony 3 Configurator」をクリック

(メニューにない場合、プラグインをインストールする必要が有ります)

(fig.7)プラグインの起動方法

③「Harmonyツール」が立ち上がるので「WIFI SERVICE」をクリックし以下の設定を行います。

項目
Device ModeSTA
STA Modeチェック
SSIDHome RooterのSSID
PasswordHome Rooterのパスワード
(fig.8)最低入力項目
(fig.9)WIFI SERVICE設定画面

③「Net Service」をクリックし以下の設定を行う。

項目
Instance 0チェック
IntfWIFI
Ip ProtocolTCP
ModeSERVER
Server Port5555
Host Name/ IP Address192.168.0.1(ここは適当で良い)
(fig.10) 最低入力項目
(fig.11)Net Service画面

④「Code」を押してソースファイルを自動生成する。

(fig12.)コード生成ボタン

⑤プロジェクトをビルドし、ターゲットボードに書き込む。

3.Tera TermとUDP/TCP/REST Network Tool で動作確認

①Tera Termを起動しポートの指定とボーレート(115,200bps)を設定し接続すると、マイコンリセットタイミングでコンソール上に(fig.13)のように表示されます。

(fig.13)Tera termコンソール画面1

② UDP/TCP/REST Network Tool のTCPタブを開き以下の、以下の設定を行い「Connect」をクリック。Remote Hostの値は各自環境で異なります。(コンソール上のIP Addres obtainedで表示された値 )

項目
ModeClient
Remote Host192.168.0.8(※)
Port5555
(fig.14)最低設定画面
(fig.15) UDP/TCP/REST Network Tool イメージ

③コンソール上に「Recived a connection」「TcpServCallback(): Status UP」と表示されます。

(fig.14)Tera termコンソール画面2

④スマフォ側アプリのMessageに適当な文字を入力し「Send」を押下すると、Tera Tarm上に受信データ内容が表示されると共に、スマホ側にも同じメッセージをコールバックします。

(fig.15)受信時メッセージ

クライアント側への応答メッセージ

デフォルトではクライアントから受信したメッセージをそのままコールバックしています。この処理は「app.c」の以下のTcpServCallback関数内で処理をしています。

ネットシステムサービスにより主要な処理は隠蔽され、ユーザーはコールバック関数内の下記のイベントが発生したタイミングでなんらかの処理を行えば良い訳です。サンプルでは受信イベントで受信データを処理し、「 SYS_NET_SendMsg ()」でメッセージを送信しています。

項目イベント
SYS_NET_EVNT_CONNECTED0NETソケットがPeerに接続された
SYS_NET_EVNT_DISCONNECTED1NET ソケットが切断された
SYS_NET_EVNT_RCVD_DATA2Peerに接続された NETソケットが データを受信した
SYS_NET_EVNT_SSL_FAILED3SSLネゴシエーションに失敗した
SYS_NET_EVNT_DNS_RESOLVE_FAILED4DNSリゾルブに失敗した
SYS_NET_EVNT_SOCK_OPEN_FAILED5ソケットのオープンに失敗した
SYS_NET_EVNT_LL_INTF_DOWN6PPPがダウン(Connected Stateでのみ受信)
SYS_NET_EVNT_LL_INTF_UP7 PPPがアップ(Connected Stateでのみ受信)
SYS_NET_EVNT_SERVER_AWAITING_CONNECTION8TCP サーバの接続待ち
(fig.16)SYS_NET_EVENT型

今回は受信した回数を返信するようにサンプルコードを改造しました。下記コードの「//追加」の行を追加し、「//コメントアウト//」の行をコメントアウトします。

void TcpServCallback(uint32_t event, void *data, void* cookie)
{

    static uint16_t RcvNum = 0; //追加
    uint8_t SndBuff[16];        //追加
    uint16_t SndLen;            //追加
    
    switch(event)
    {
        case SYS_NET_EVNT_CONNECTED:
        {
            SYS_CONSOLE_PRINT("TcpServCallback(): Status UP\r\n");
            while(SYS_NET_SendMsg(g_tcpServHandle, (uint8_t*)"hello", 5) <= 0);
            break;
        }

        case SYS_NET_EVNT_DISCONNECTED:
        {
            SYS_CONSOLE_PRINT("TcpServCallback(): Status DOWN\r\n");
            break;
        }

        case SYS_NET_EVNT_RCVD_DATA:
        {
	    int32_t cumm_len = 0;
            int32_t len = RECV_BUFFER_LEN;
            while(len == RECV_BUFFER_LEN)
            {
                len = SYS_NET_RecvMsg(g_tcpServHandle, recv_buffer, RECV_BUFFER_LEN);
                if(len>0)
                {
                    if(cumm_len == 0)
                    {
                            uint8_t buffer[33];
                            int32_t tmp_len = (len > 32)? 32 : len;

                            memcpy(buffer, recv_buffer, tmp_len);
                            buffer[tmp_len] = '\0';
                            SYS_CONSOLE_PRINT("TcpServCallback(): Data Rcvd = %s\r\n", buffer);
                    }
                    cumm_len += len;
                    //SYS_NET_SendMsg(g_tcpServHandle, recv_buffer, len);   //コメントアウト
                    SndLen = sprintf((char *)SndBuff,"Num = %d",RcvNum++);  //追加
                    SYS_NET_SendMsg(g_tcpServHandle, SndBuff, SndLen);      //追加
                }
            }
            SYS_CONSOLE_PRINT("TcpServCallback(): Total Data Rcvd = %d Bytes\r\n", cumm_len);
            
            break;
        }
        
        case SYS_NET_EVNT_LL_INTF_DOWN:
        {
            /* 
            ** User needs to take a decision if they want to close the socket or
            ** wait for the Lower layer to come up
             */
            SYS_CONSOLE_PRINT("TcpServCallback(): Lower Layer Down\r\n");
            break;
        }
        
        case SYS_NET_EVNT_LL_INTF_UP:
        {
            /* 
            ** The lower layer was down and now it has come up again. 
            ** The socket was in connected state all this while
             */
            SYS_CONSOLE_PRINT("TcpServCallback(): Lower Layer Up\r\n");
            break;
        }                
        
        case SYS_NET_EVNT_SERVER_AWAITING_CONNECTION:
        {
            /* 
            ** The server is awaiting connection from the client
             */
            SYS_CONSOLE_PRINT("TcpServCallback(): Server Awaiting Connection\r\n");
            break;
        }                
    }
}

注意点①

当初作成したプログラムをビルドして書き込む事は可能ですが、デバッグモードで「Debug」ボタンを押した後、何分かけてもデバッグ情報の生成が終わらずデバッグができない状況でした。

これは以下の様にMicrochipフォーラムでもスレッドが立っている通り、GCCコンパイラのバージョンがV3以上の場合に詳細なデバッグ情報を書き出すために、非常に時間がかかるようです。ここでGCCオプションに「-gdwarf-4」を入れると速くなるとの事でしたので、これで「我慢できる速さ」でデバッグが可能となりました。

(fig.18)GCCコンパイラ設定

注意点②

Harmony上で 「Device Mode」を「AP」に設定すると、WFI32がアクセスポイントになり外部のルータ不要で直接クライアント側との通信が可能となります。ただし原因は分かりませんが外部ルータを使用する場合と比べ、非常に通信速度が遅くなる現象が発生しました。これに関しては追って調査したいと思います。

コメント

タイトルとURLをコピーしました