「ソフテックだより」では、ソフトウェア開発に関する情報や開発現場における社員の取り組みなどを定期的にお知らせしています。
さまざまなテーマを取り上げていますので、他のソフテックだよりも、ぜひご覧下さい。
ソフテックだより(発行日順)のページへ
ソフテックだより 技術レポート(技術分野別)のページへ
ソフテックだより 現場の声(シーン別)のページへ
最近、「IoT」という言葉をよく聞くようになりましたが、マイコン開発でもTCP/IP(Transmission Control Protocol/Internet Protocol)通信の開発が増えてきました。マイコン開発でTCP/IP通信を実現するにはTCP/IPプロトコルスタックというものが必要になります。
TCP/IP通信のプロトコルは公開されていますが、コストパフォーマンスを考えるとTCP/IPプロトコルスタックをイチから作るという選択はよほどの理由がない限り行わないと思います。TCP/IPプロトコルスタックを提供するベンダから購入するか、オープンソースのTCP/IPプロトコルスタックを使用するなどのアプローチをとるのが一般的です。
2016〜2017年にかけて、弊社でTCP/IP通信を必要とするシステムの開発(以下、弊社開発)を行いましたが、TCP/IPプロトコルスタックはルネサスエレクトロニクス製(以下、ルネサス)のM3S-T4-Tiny(以下、T4)無償版を使用しました。
今回はこのT4について、特徴や組み込み手順、組み込み時に注意すべき点などについて紹介したいと思います。
T4の特徴について、ルネサスのWEBサイトに以下のように書かれています。
また、ソフテックだより第179号の「マイコンでTCP/IP通信を実現するには」において、ベンダから入手する際の選定ポイント(第179号 表3)をあげさせていただきましたが、T4は表1の通りです。
No. | 項目 | T4の内容 | 補足 |
---|---|---|---|
1 | OS依存 | なし | |
2 | IPv4/IPv6 | IPv4のみ | |
3 | 必要リソース (ROM/RAMサイズ) |
ROM:約23.3KByte RAM:約0.2KByte |
ルネサス RXファミリ 組み込み用TCP/IP M3S-T4-Tiny 導入ガイドより |
4 | 提供形態 | ライブラリ形式 (ライブラリのソース提供あり) |
|
5 | サンプルドライバ | あり | |
6 | アプリケーション提供 | あり | |
7 | ライセンス形態 | 無償 | 技術サポートを付加した有償版あり |
8 | マルチチャンネル対応 | あり | T4で同時に実行可能なAPIの数は、TCPとUDPで各々端点毎に1つ。 同時に複数のAPIを実行した場合、戻り値にE_QOVRが返る。 |
9 | アプリケーションインタフェース(API) | ITRON TCP/IP APIおよびBSDソケットインタフェースに対応 |
表1. T4の特徴
弊社開発時にT4を選定したのは、システムのCPUがT4に対応していたこと、ドキュメントやサンプルが豊富であったこと、LANポートが1つであるためT4で必要十分であったこと(T4はマルチチャンネル対応が行われていますが、同時に複数のAPIを実行できないため、複数のマルチチャンネルの場合には注意が必要と考えます)がポイントとしてありました。
次にT4の組み込み手順について説明します。
T4の組み込み手順について、ルネサスから統合開発環境CS+とe² studioの2種類の組み込み手順の資料が公開されています。
基本的には資料に沿って組み込みを行っていきますが、実際にTCP/IP通信が行われるところまで辿り着くにはいくつか設定を変更する必要がありました。
弊社開発時に使用したときのT4のバージョンからバージョンアップが行われていますので、今回の執筆にあたり、新しいバージョンのT4であらためて確認を行いました。確認に使用したハードは株式会社アルファプロジェクト製のAP-RX63N-0AのCPUボードを使用しました。CPUはRX63N(R5F563NEDxFB)です。
また、弊社開発時に使用した統合開発環境はCS+ですが、e² studioでも確認してみましたので、組み込み方法の違いなども説明します。
T4を使用したソフトウェア構成は図 1のようになります。
(ルネサス RXファミリ 組み込み用TCP/IP M3S-T4-Tiny 導入ガイドより)
図1. T4を使用したソフトウェア構成
アプリケーション以外のライブラリ・モジュールはすべてルネサスから提供されます。括弧内の英数字はライブラリ・モジュールのアプリケーションノート番号です。このアプリケーションノート番号を元にルネサスのWEBサイトからライブラリ・モジュールを検索し、ダウンロードすることができます。
アプリケーションはユーザーが作成する必要がありますが、サンプルプログラムがルネサスから公開されています。
CS+とe² studioで詳細の手順が異なります。それぞれのベースとなる手順は以下のアプリケーションノートに記載されています。
また、確認に使用した統合開発環境のバージョンは以下の通りです。
使用するBSP(*1)およびFITモジュール(*2)を表2に示します。
No. | モジュール | Rev. | アプリケーション ノート番号 |
---|---|---|---|
1 | BSP | 3.80 | R01AN1685 |
2 | CMT Driver | 3.21 | R01AN1856 |
3 | System Timer | 1.00 | R20AN0431 |
4 | Ether Driver | 1.15 | R01AN2009 |
5 | Interface conversion module for Ether Driver and Embedded system T4 | 1.06 | R20AN0311 |
6 | T4 Library | 2.07 | R20AN0051 |
表2. BSPおよびFITモジュール一覧
T4組み込み手順は図2のように進めます。
図2. T4組み込み手順
それでは図2の手順1.〜5.について以下に説明します。
[CS+]
[e² studio]
[CS+]
[e² studio]
図3. FITモジュールのダウンロード
次にプロジェクトへ追加するモジュールを図4の左側の「選択したモジュール」の通り、「r_bsp」、「r_cmt_rx」、「r_ether_rx」、「r_sys_time_rx」、「r_sys_time_rx」、「r_t4_rx」、「r_t4_driver_rx」の最新バージョンを選択し、追加します。
次に端子設定が必要なモジュールについて設定を行います。
設定が必要なモジュールは「r_ether_rx」のみで、図4の右側の「端子設定」のように、基板の端子設定にあわせて選択していきます。
図4. モジュールの追加および端子設定
[CS+]
No. | 項目 | セクション名 | 配置アドレス |
---|---|---|---|
1 | 送信バッファおよび受信バッファ領域 | B_ETHERNET_BUFFERS_1 | 32バイト境界 (32の倍数) |
2 | 受信ディスクリプタ領域 | B_RX_DESC_1 | 16バイト境界 (16の倍数) |
3 | 送信ディスクリプタ領域 | B_TX_DESC_1 | 16バイト境界 (16の倍数) |
表3. RAM配置アドレスの条件
[e² studio]
各変更内容の詳細については省略させていただきますが、ヘッダファイルおよびソースファイルの変更が必要となります。
CS+とe² studioでほぼ同じ対応となりますが、違いがある部分については補足記載しています。
なお、変更内容は今回確認に使用した基板(AP-RX63N-0A)に対応したものであり、その他の基板には適用されない内容もありますのでご了承ください。
r_configフォルダにあるヘッダファイル内の定義を表 4のように変更します。
No. | 項目 | ヘッダファイル名 | マクロ名 | 設定値 |
---|---|---|---|---|
1 | CPUのROM、RAM、データフラッシュのサイズ | r_bsp_config.h | BSP_CFG_MCU_PART_MEMORY_SIZE | 0xF →0xE |
2 | 使用するCPUパッケージ | r_bsp_config.h | BSP_CFG_MCU_PART_PACKAGE | 0x0 → 0x3 |
3 | システムコールバック有無 | r_t4_rx_config.h | T4_CFG_SYSTEM_CALLBACK_FUNCTION_USE | 1 → 0 |
4 | IPアドレス | r_t4_rx_config.h | T4_CFG_FIXED_IP_ADDRESS_CH0 | 192,168,0,3 → 任意のIPアドレス |
5 | サブネットマスク | r_t4_rx_config.h | T4_CFG_FIXED_SABNET_MASK_CH0 | 192,168,0,3 → 任意のサブネットマスク |
6 | MACアドレス | r_t4_rx_config.h | T4_CFG_ETHER_CH0_MAC_ADDRESS | 0x74,0x90,0x50, 0x00, 0x79,0x03 → 基板のMACアドレス |
7 | DHCP使用有無 | r_t4_rx_config.h | T4_CFG_SYSTEM_DHCP | 1 → 0 |
8 | ETHERCとイーサネットPHY-LSI 間のインタフェース | r_ether_rx_config.h | ETHER_CFG_MODE_SEL | 0 → 1 |
9 | PHYのアクセスチャネル | r_ether_rx_config.h | ETHER_CFG_CH0_PHY_ACCESS | 1 → 0 |
10 | リンク状態変化の検出 | r_ether_rx_config.h | ETHER_CFG_USE_LINKSTA | 1 → 0 |
表4. T4ヘッダファイル変更一覧
次にソースコードを表5のように変更します。
No. | 項目 | ソースファイル名 | 対応内容 |
---|---|---|---|
1 | イーサネットの端子設定 | [CS+] [e² studio] |
[CS+] [e² studio] |
2 | イーサネットの端子設定初期化関数コール | \r_bsp\board\rskrx63n\hwsetup.c | peripheral_modules_enable関数からNo.1の関数をコールする処理を追加する。 |
3 | 基板のポートおよびピンの方向設定 | \r_bsp\board\rskrx63n\hwsetup.c | output_ports_configure関数に記述されているサンプルのポート初期化コードを削除し、基板のポート初期化コードを記述する。 |
表5. T4ソースファイル変更一覧
ここから先はアプリケーションの作成となりますが、CS+とe² studioで違いはありません。
以下はTCPクライアントのサンプルプログラムです。IPアドレス192.168.0.10のTCPサーバーと接続し、受信したデータをそのまま返すエコーバックプログラムのサンプルです。
(省略)
/* システムタイマモジュール開始 */
systime_ercd = R_SYS_TIME_Open();
if (systime_ercd != SYS_TIME_SUCCESS)
{
while (1);
}
/* Ethernet ドライバ・オープン */
ercd = lan_open();
if (ercd != E_OK){
while (1);
}
/* ワークメモリ使用サイズの取得 */
size = tcpudp_get_ramsize();
if (size > (sizeof(tcpudp_work)))
{
while (1);
}
/* T4 ライブラリ・オープン */
ercd = tcpudp_open(tcpudp_work);
if (ercd != E_OK)
{
while (1);
}
/* TCP 接続要求(能動オープン) */
cepid = 1;
dst.ipaddr = 0xc0a8000a; // 192 = 0xc0, 168 = 0xa8, 0= 0x00, 10 = 0x0a
dst.portno = 1024;
ercd = tcp_con_cep(cepid, &src, &dst, TMO_FEVR);
if (ercd == E_OK)
{
while (1)
{
/* TCPデータ受信 */
ercd = tcp_rcv_dat(cepid, rcv_buf, sizeof(rcv_buf), TMO_FEVR);
/* error or fin check */
if ((ercd < 0) || (ercd == 0))
{
break;
}
/* TCPデータ送信 */
snd_size = ercd;
memcpy(snd_buf, rcv_buf, snd_size);
ercd = tcp_snd_dat(cepid, snd_buf, snd_size, TMO_FEVR);
/* error check */
if (ercd < 0)
{
break;
}
}
}
(省略)
IPアドレスやMACアドレスはヘッダファイル(r_t4_rx_config.h)に記述した設定を使用しますが、システムによっては外部で設定したIPアドレスを起動時に読み込み、その設定で動作させたいということがあると思います。
これらの設定変数は表 6に示すグローバル変数に割り当てられていますので、TCP/IPプロトコルスタックの初期化前に値を書き換えてから初期化を行うことで任意の設定で動作させることができます。
No. | 項目 | 変数名 |
---|---|---|
1 | IPアドレス サブネットマスク デフォルトゲートウェイ |
TCPUDP_ENV tcpudp_env[] |
2 | MACアドレス | UB _myethaddr [][6] |
表6. IPアドレスやMACアドレスの変数
3.2.3項に記載したように、バッファ配置アドレスは32の倍数、ディスクリプタ配置アドレスは16の倍数のRAMアドレスに配置する必要があります。
これはCPUのイーサネットコントローラ用DMAコントローラ(EDMAC)の仕様によるものです。
e² studioはセットアップ時に自動で適切なアドレスに配置してくれますが、RAMアドレス配置を変更する場合は注意が必要です。
T4はOSあり/なしのどちらにも対応していますが、OSなしで使用する場合は注意が必要です。
TCP/IP接続時や送信時にタイムアウト指定などのブロッキングコールでAPIコールした場合、処理が完了またはタイムアウトするまでAPIから戻ってきません。
OSを組み込んでいればタスク切り替えで他のタスクの処理が動きますが、OSなしの場合は他のすべての処理が待たされることになります。そのため、OSなしの場合はノンブロッキングコールでAPIをコールし、コールバック関数で完了を受け取る形にしなければならない場合があります。
なお、OSありで使用する場合にはr_bsp_config.hの「BSP_CFG_RTOS_USED」の設定を定義されているOSの番号に変更します。T4にはOS専用の処理が実装されており、FreeRTOSとRenesas RI600V4 & RI600PX(ITRON仕様)用の処理はありますが、この仕様以外のOSを使用する場合はユーザーが同様の処理を実装する必要があります。
TCP/IPプロトコルスタックを使用することで、TCP/IPプロトコルを意識しなくてもTCP/IP通信を組み込むことができますが、TCP/IPプロトコルをきちんと知っておいた方が良い場合があります。
例えば、T4においてTCPパケット送信を行った際に、短いデータサイズにも関わらず、2パケットに分割されて送信される動作になります。
TCP/IPの受信側は「2パケットを受けたらACKを返す」という実装になっていることが多く、1パケットだけを受信した場合は200ms程度の待ち時間の後にACKを返す(TCP遅延ACK)動きをします。2パケットに分割して送信するのは、この対策のためです。
なお、T4ではパケット送信分割を無効とする設定(r_t4_rx_config.hの「T4_CFG_TCP_DIVIDE_SENDING_PACKET」を0にする)がありますが、無効とした場合、伝送効率が悪くなる可能性(アプリケーションの通信プロトコルにもよる)があります。
また、T4に実装されていない機能としてキープアライブがあります。キープアライブは接続が切断されるのを防止するために、ネットワーク間で定期的に送信される通信のことです。
アプリケーション側の通信プロトコルが定期的な送信を行う仕様であれば問題ありませんが、キープアライブを使用する前提の通信プロトコルも過去にありましたので、この場合はキープアライブがあるTCPプロトコルスタックを選択する必要があります。
このように、TCP/IPプロトコルをきちんと知っておくことで事前に何を調査する必要があるのか、問題が発生した場合に何から調査したら良いのかなどの判断ができるようになると考えます。
T4の組み込み手順を中心に説明させていただきました。
TCP/IPプロトコルスタックの組み込みを行って動かなかった場合、何が原因なのかの調査に時間がかかることがあります。動かない原因はちょっとした設定の間違いや漏れであったりします。
弊社開発時には、かふぇルネというルネサスユーザ同士の技術的な情報交換のためのフォーラムサイトの書き込みを参考にして解決した問題もありました。
今回のソフテックだよりもT4を組み込む際の参考になれば幸いです。
(M.A.)
関連ページへのリンク
関連するソフテックだより