技術ブログ

マイコンで高速Ethernetを手軽に始める方法

wiznet

目次

  1. あえてEthernetを使う意義
  2. 1. コネクタの信頼性
  3. 2. プロトコルの使いやすさ
  4. 3. 通信速度
  5. Ethernet導入の障壁
  6. W5500やW6300を使うという選択肢
  7. W5500とW6300
  8. モジュールを使うと基板設計も楽になる
  9. 使い方
  10. 環境
  11. 配線
  12. ビルド
  13. 書き込み
  14. テスト
  15. ioLibrary_Driver の紹介
  16. おわりに

こんにちは、電気通信大学 ロボメカ工房のKokiです。

今回はWiznetのW6300という、超便利なEthernetコントローラICについて紹介しようと思います。

このICを使うためのソースコードは以下のリンクで公開しています。
https://github.com/Robomech-NHK/WIZ630io-TCP-STM32

あえてEthernetを使う意義

ロボットの開発において、皆さんはPC(ROSなど)とマイコンの間の通信に何を使っていますか?

おそらく最も多いのは USB でしょう。
ここで、あえて Ethernet を使う意義を考えてみます。

私の考えるEthernetを使う利点は、大きく分けて次の3つです。

  1. コネクタの信頼性
  2. プロトコルの使いやすさ
  3. 通信速度

1. コネクタの信頼性

多くのマイコン開発ボードでは、PCとの接続にType-CやMicro-BなどのUSBコネクタが使われています。

しかし、これらのコネクタはロボコンのような強い振動・衝撃にさらされる環境では、抜けてしまう不安があります。さらに、開発中に何度も抜き差ししていると、コネクタが緩くなり、接触不良が起きやすくなります。

その結果、私たちのサークルでは大会のたびに、コネクタ周りをテープで固める伝統芸能が確立されました。

一方、Ethernetで使われるRJ45コネクタにはラッチがあります。差し込むと物理的に固定されるため、USBよりも抜けにくく、振動のある環境でも安心して使えます。

2. プロトコルの使いやすさ

マイコンとPCの間で独自の通信を行う場合、ただデータを送ればよいわけではありません。

たとえばUARTなどで生のバイト列を送る場合、次のような処理を自分で考える必要があります。

  • データの区切りをどう判定するか
  • データ長をどう表すか
  • 受信途中でデータが欠けた場合にどう復帰するか
  • エラーチェックをどう行うか
  • 複数種類のデータをどう振り分けるか

これらを自作プロトコルとして実装することもできますが、安定して動かそうとすると意外と面倒です。

Ethernetを使うと、このあたりの多くを既存の通信レイヤーに任せることができます。
たとえば、Ethernetフレームの破損チェックはデータリンク層で行われます。IPを使えば宛先の管理ができます。TCPなどを使えば、ポート番号によって通信内容を分けることもできます。

これによってスイッチングハブを使えばLiDARなど他の機器とポートを共有することができます。

3. 通信速度

通信速度の面でも、Ethernetには大きな利点があります。

マイコン側が USB-FS の場合、USBそのものの信号速度は 12 Mbps です。また、UARTとして扱う場合は、数Mbps以上になると設定や環境によって安定性が問題になりやすくなります。高周期で大量のデータを流したい場合、UART的な通信では余裕が少なくなります。

一方、Ethernetでは、一般的な 100BASE-TX でも理論上は 100 Mbps の通信が可能です。もちろん実効速度は実装に依存しますが、USB-FSの仮想COMやUARTと比べると、通信帯域にかなり余裕があります。

Ethernet導入の障壁

ここまでEthernetの利点を述べてきましたが、もちろんEthernetにも導入の難しさがあります。

特にマイコンでEthernetを使おうとすると、最初に問題になるのがプロトコルスタックの実装です。

Ethernetで通信するには、単にLANケーブルを挿せばよいわけではありません。実際には、下から順に次のような処理が必要になります。

  • Ethernetフレームの送受信
  • ARPによるMACアドレス解決
  • IPパケットの処理
  • UDPやTCPの処理
  • ソケット管理
  • 再送、タイムアウト、切断処理
  • バッファ管理

PC側ではOSがこれらをほとんど面倒見てくれます。
そのため、アプリケーションからは send() や recv() のような関数を呼ぶだけで通信できます。

しかし、マイコン側ではそう簡単ではありません。

STM32などのマイコンにもEthernet MACを内蔵しているものはありますが、その場合でも外付けPHYが必要になります。さらに、TCP/IPスタックとしてlwIPなどを組み込み、DMA、割り込み、キャッシュ、バッファ、RTOSとの連携などを正しく設定する必要があります。

UDPだけなら比較的軽いとはいえ、IPやARPなどの処理は必要です。
TCPを使う場合はさらに重くなります。

TCPでは、次のような処理をマイコン側で扱う必要があります。

  • 接続状態の管理
  • 順序制御
  • 再送制御
  • 輻輳制御
  • 受信ウィンドウ管理
  • 切断、再接続処理

これらは信頼性の高い通信を実現するためには便利ですが、制御周期の短いロボット用途では負担になることがあります。

また、マイコンのCPUリソースを通信処理に取られすぎると、本来やりたいモーター制御、センサ処理、状態推定などに影響が出る可能性もあります。

W5500やW6300を使うという選択肢

そこで便利なのが、WIZnetの W5500 や W6300 のようなEthernetコントローラICです。


image.png (257.4 kB)

これらは、単なるEthernet PHYではありません。
内部にハードウェアTCP/IPスタックを持っており、TCP、UDP、IP、ARPなどの処理をIC側で行ってくれます。

そのため、マイコン側で複雑なTCP/IPスタックを実装する必要がありません。

マイコンから見ると、W5500やW6300は「SPIやQSPIで操作できるEthernet通信モジュール」のように扱えます。

たとえばUDPで通信する場合、マイコン側はおおよそ次のような処理を行うだけで済みます。

  1. 宛先IPアドレスとポート番号を設定する
  2. 送信バッファにデータを書き込む
  3. 送信コマンドを出す
  4. 受信バッファに届いたデータを読む

もちろん実際の初期化やレジスタ操作は必要ですが、lwIPを移植してTCP/IPスタック全体を管理するよりは、かなり見通しがよくなります。

W5500とW6300

W5500は、SPI接続で使える定番のEthernetコントローラICです。
情報量が多く、ライブラリや使用例も豊富で、マイコンでEthernetを始めるには非常に扱いやすいICです。このICの使い方については多くの解説がすでにあるため省きます。

W5500ではマイコンとの通信がSPIなので、Ethernet自体が100 Mbpsに対応していても、SPIがボトルネックとなり、実質的なスループットは最大55 Mbps程度になります。

W6300ではQSPIを使うことで、マイコンとEthernet IC間の転送速度を上げやすくなります。
そのため、高周期でデータをやり取りしたい場合や、より大きなデータ量を扱いたい場合にはW6300が有利です。

モジュールを使うと基板設計も楽になる

さらに、W5500やW6300を使う場合でも、IC単体を基板に載せる必要はありません。

WIZnetには WIZ850io や WIZ630io のようなモジュールが用意されています。
これらを使うと、Ethernet IC本体だけでなく、RJ45コネクタや周辺部品までまとまった形で扱えます。

EthernetをIC単体で基板に実装しようとすると、通信処理だけでなく、基板設計側にも注意点が増えます。
たとえば、次のような要素を考える必要があります。

  • PHYからRJ45までの差動配線
  • 100Ω差動インピーダンスの管理
  • 配線長やビアの扱い
  • RJ45周辺のレイアウト

これらは一つ一つは基本的な内容ですが、初めてEthernet基板を作る場合にはかなり面倒です。
そこで、WIZ850ioやWIZ630ioのようなモジュールを使うと、このあたりの面倒な部分をかなり省略できます。

使い方

おまたせしました。
WIZ630ioを用いたTCP通信の例について紹介します。

環境

一般的な4線SPIも使用できますが、W6300の特徴である最大90 Mbpsを超えるスループットを活かすには、QSPIが使えるマイコンをおススメします。
今回はH723のOctoSPIをQuad SPIとして使用します。

配線

次のレイアウトで配線します。詳細なピンアウトは公式サイトを参照してください。

W6300MCU
QD0PD11
QD1PD12
QD2PF7
QD3PD13
CLKPB2
NCSPG6
RSTnPF4
3V3–
GND–

画像の様に配線されていたらOKです。

ビルド

以下のGitHubレポジトリをCloneしてください。submoduleとしてioLibraryが含まれているため注意してください。
https://github.com/Robomech-NHK/WIZ630io-TCP-STM32

git clone --recursive https://github.com/Robomech-NHK/WIZ630io-TCP-STM32

CubeIDEのFile→Open Projects from File System...からCloneしたレポジトリを開きます。

WIZ630io-TCP-STM32.iocファイルを開いて、上の歯車マーク⚙からGenerate Codeを実行します。

左上のトンカチ🔨マークを押してビルドします。次のような結果になれば成功です。

書き込み

まず、ST-Link側のMicro-USBをPCに接続します。
CubeIDEのプロジェクト一覧から、WIZ630io-TCP-STM32を右クリックして、Run As→STM32 C/C++ Applicationに進みます。

この画面になれば「OK」を押して書き込みます。次回以降はGUI上部の再生ボタン(Run)のプルダウンからプロジェクトを選択して書き込めます。

ST-LinkのアップデートやST-Link Serverのインストールを求められたら、おとなしく従いましょう。次のようにDowload verified successfullyと表示されたら書き込み成功です。

テスト

ST-LinkのUSBケーブルはそのまま、NucleoのRJ45をLANケーブルでPCに接続します。100base-Tなので、CAT-6a非対応でも構いません。
次に、Windowsの設定→ネットワークとインターネット→イーサネットからWIZ630ioを接続するポートのIPv4を 192.168.0.20 / 255.255.255.0に設定します。

PowerShellでレポジトリの位置を開き、以下のコマンドでPythonを実行します。

py -3 tools\tcp_echo.py

接続に成功すれば、TCP echo (loopback)が実行されるはずです。Ctrl+Cを実行するまで繰り返されます。

オプションを使って送信するデータを変更することもできます。

ioLibrary_Driver の紹介

ioLibrary_Driver は、WIZnet が提供しているW5x00 / W6x00 系 Ethernet コントローラ向けの公式ドライバライブラリです。
W6300 では TCP/IP スタック自体をチップ内部で処理するため、MCU 側ではsocket()、send()、recv() などの Berkeley Socket に近い API を使ってTCP / UDP 通信を扱えます。

主な構成は以下の通りです。

  • Ethernet/
    • W5100 / W5500 / W6100 / W6300 など各チップのドライバ
    • 共通の Socket API
  • Internet/
    • DHCP
    • DNS
    • SNTP
    • MQTT
    • HTTP Server
    • TFTP など
  • Application/
    • TCP / UDP loopback などのサンプル

MCU や通信ペリフェラルには直接依存せず、
SPI / QSPI の read / write や CS 制御などを callback として登録する構成になっています。

このプロジェクトでは W6300 を使用し、STM32H723 の OCTOSPI1 を
ioLibrary_Driver の QSPI callback に接続しています。

Application
    │
    ├─ socket(), send(), recv(), ...
    │
ioLibrary_Driver
    │
    ├─ W6300 register / socket control
    │
STM32 HAL callback
    │
    └─ OCTOSPI1
         │
       W6300

おわりに

今回WIZ850ioとWIZ630ioを提供してくださったWIZnet様に感謝申し上げます。
NHK学生ロボコン2027に向け、開発を続けてまいりますのでよろしくお願いいたします。