マイコンのEthernet対応システム設計【STM32Nucleo】
目次
マイコンをネット接続するための基礎知識
ネットワークに接続して使用するIoT化は組み込み機器でも浸透してきました。テレビ等を始めとする家電やスマホなどの身近な民生品ではWiFiによるネットワーク接続が一般的になっていますが、動作安定性やセキュリティが求められる産業機器向け製品には有線通信の一つであるイーサネットが使用されます。
今回は、これまで慣れ親しんできた汎用マイコン(Nucleo-F103RB)に外付けのイーサネット対応LANコントローラW5500を適用してイーサネットIoTに対応する方法を解説します。対象はSTM32マイコンですが、マイコンとLANコントローラ間のインターフェース(SPI通信)をカスタマイズすればどの機種にも対応できる手軽な手段です。
ここでは、IPアドレス等ネットワーク関連の解説は割愛します。
ネットワーク階層
ネットワークには様々な規格の装置・機器が接続されているのですが、ネットワークの規格は以下のOSC参照モデルで共通化されていますのでどのような装置・機器でも共通規格であれば通信できるようになります。
イーサネットは有線LANの一つで最も普及している規格でありIEEE802.3で定義されたものです。
規格に従って、物理層のLANケーブルから例えばウェブブラウザを使用したHTTPアプリケーション層までの通信システムを構築することになります。データリンク層までは大抵ハードウェアで構成され、それ以降はソフトウェアで構成されます。
イーサネット対応のためのLANコントローラの選択
イーサネット通信に関してマイコンを大別すると3種類あり、下記のように分類できます。
- 汎用マイコン(イーサネットコントローラ非搭載)
- MACデバイスを内蔵したマイコン
- MAC/PHYデバイスを内蔵したマイコン
1番めの汎用マイコンはイーサネットコントローラが非搭載ですのでMAC/PHYデバイスコントローラを外付けして汎用バスであるSPI、I2Cなどをインターフェースとして通信を行います。今回扱うNucleo-F103RBのマイコンはこれに当たります。
2番めのマイコンはイーサネットMACデバイスを内蔵したもので例えばSTM32F407がこれに当たります。PHYデバイスコントローラを外付けしてマイコン内蔵のMACデバイスとMII/RMIIとよばれる方式で通信を行います。
3番めのマイコンはイーサネットに必要なデバイスMACおよびPHYを内蔵したもので、追加部品はパルストランス内蔵のRJ-45のみです。
マイコンと組み合わせてイーサネット対応にするコントローラで一般的に使用されていて取得性のよいものを紹介します。
XPORT
イーサネットの知識がなくてもWiFiのときに使用したESP32のように汎用シリアル通信をインターフェースとしたコントローラでシリアル通信感覚で使用できます。
最も簡易的なIoT対応コントローラとして選択できます。シリアル通信のみ対応の既存の機器に外付けするだけなのはメリットですが、メーカー提供のドライバに従うため汎用性が高いとはいえないことと、既存の製品に組み込むのは他の手段に比べコスト的に採用しにくいことがデメリットです。
ENC28J60コントローラ
ENC28J60コントローラはイーサネットコントローラ非搭載のマイコンでもSPI通信を持っていればイーサネット対応にできます。
TCP/IPプロトコルスタックを自分で組み込まなければなりませんのでSTM32F1シリーズでは実施例の資料が少なく大変そうです。移植するには選択したTCP/IPプロトコルスタックの中身を理解する必要がありますが、そこに時間をかけたくない場合は次のW5500がおすすめです。
W5500コントローラ
ENC28J60コントローラの場合と同じくイーサネットコントローラ非搭載のマイコンでSPI通信を持っている場合に適用できます。両者の大きな違いはW5500はTCP/IPプロトコルスタックをハードウェアに内蔵していることで搭載のわずらわしさがなくコネクションが安定しています。
そのため、TCP/IPプロトコル・スタックについての知識がなくても使用できることに加え、ソフトウェア負荷が小さいのでメモリの小さなマイコンに搭載できることも大きな利点です。
Nucleo-F103RBのSTM32マイコンに対して外付け部品も少なくてすみ、TCPプロトコルを利用したソケット通信やさらに上位のHTTPプロトコルを利用したブラウザからの通信にも発展できるバランスのとれたコントローラです。
LAN8720コントローラ
STM32F407マイコンのようにイーサネット対応MACを内蔵したものにはPHYデバイスのみを持つLAN8720やDP83848等のコントローラがよりマイコンの機能を活かせます。
上位機種であるCortex-M4コアを内蔵するSTM32F407を新規に採用する場合はもはやライブラリはSPLにこだわるのではなくHALやLLドライバを使用したほうが手っ取り早いです。
開発環境STM32CubeIDEを使用すれば開発プロジェクトを作成する段階で自動生成機能を利用するとTCP/IPプロトコル(LwIP)も簡単に組みこめ、トランスポート層のTCPやUDPプロトコルまで実装できてしまいます。
はじめからネットワーク機器向け製品を設計する場合はネットワーク内蔵のマイコンを選択するのが良いのではないでしょうか。
Arduinoのイーサネットシールド(互換品も含む)としてW5500を搭載したモデルがNucleoボードにも使用できればよいと考え仕様を確認してみたのですが、肝心のインターフェース部分であるSPI通信端子がNucleoには対応していないので使用できません。
TCP/IPプロトコル・スタック内蔵のコントローラW5500
イーサネットコントローラ非搭載のマイコンSTM32F1シリーズでイーサネット対応にするには汎用性を考えるとW5500かENC28J60あたりになります。
TCP/IPプロトコルスタックをハードウェアに内蔵しているW5500はとりわけネットワーク仕様としての性能は申し分なく気軽にマイコンをネットワーク化対応にできるためこちらを選択することにします。
TCP/IPプロトコルスタックについては規格に準じたものなので内部詳細をあえて理解する必要性はあまり感じられず既成のモジュールとして割り切ってもよいのではないでしょうか。
NUCLEO-F103RBとW5500モジュール
外付けでW5500でNucleo-F103RBをネットワークにつなげるにはここでは市販W5500ボードを利用します。ボードは安価で最低限の周辺部品が備わっていますがMACアドレスがないボードも多いです。
製品開発をする場合にはこの市販W5500ボードに使用されている最低限の周辺部品の他にMACアドレスを保持するためのEEPROM等メモリが必要になります。
Nucleoとの接続は割り込みや外部リセットを使わないのであれば電源とSPI通信部のみで機能します。リセットはソフトウェアで実行するのであればなくても機能はしますがW5500はパワーオンリセットではないので、リセットの確実性を高めるため特に製品化の場合にはハードウェアリセットは使用すべきです。今回はSPI2を使用するため下図のような接続になります。
MACアドレスについて:
イーサネットを使用するにあたってMACアドレスが必要となるのですが、使用するLANコントローラにはMACアドレスは搭載していません。ネットで動作を確認するくらいであれば問題ないのですが、製品として世に出す場合は各製品固有のMACアドレス登録を事前に行う必要があります。
STM32マイコンとW5500ドライバ
W5500はIC内部のレジスタをSPI通信で操作して通信を行います。レジスタの詳細はW5500データシートに詳細が記載していますが、プログラミングにおいてはメーカーが提供するドライバ類をライブラリ(ioLibrary_BSD)として登録しておき、必要に応じて関数類を呼び出して使用します。
W5500のドライバとは
STM32マイコンとのSPI通信のインターフェースにあたる関数をまとめたファイルがwizchip_conf.c/wizchip_conf.hです。このファイルでは使用するコントローラICチップ(W5500)の指定や、レジスタアドレス等が登録されています。マイコンとのインターフェースカスタマイズで一部修正する必要はあります。
w5500.c/w5500.hはコントローラW5500で使用するマイコンとの送受信関数を定義してまとめたものです。
socket.c/socket.hはTCPソケット通信で使用する関数群をまとめたものです。バークレーソケット(BSDソケット)に準じた関数となっています。
これらを最低限ドライバとしてioLibrary_driverフォルダ内に登録しておき、他はDHCPに関するものなど必要に応じて追加するのが良いと思います。
W5500のSPI通信とドライバのカスタマイズ
LANコントローラW5500には書き込み/読み込み等の操作、IPアドレス等パラメータ、プロトコル指定など仕様を設定するためのコモンレジスタブロック、およびソケット通信で使用するソケットレジスタブロックがあります。
レジスタの詳細はW5500の取説に解説しており、かなりきめ細かな設定ができるようになっていますが、一般的な用途では使用するのは一部だけです。
これらのレジスタブロックを操作するためにSPI通信をインターフェースとしてマイコンとやり取りしますのでこの部分を確立できればほぼできたようなものです。
ドライバのインターフェースのファイル(wizchip_func.c)に手を加えてSTM32マイコン仕様にするのはほんの一部だけです。実際のプログラミングにおいてはドライバ内で定義した関数が使用できますので一度ポイントを理解してしまえば手間はほとんどかかりません 。
実際にどのような仕組みでレジスタを操作しているかを一度は取説を見ながらドライバ内の関数を順に追ってみるのがよいと思います。
W5500のSPIフレームフォーマット
W5500でのspi通信のフレームフォーマットでは1バイト(8ビット)ごとのブロックで下図に示す3フェイズで構成されます。上位・下位2バイト分のアドレスフェイズ、1バイトのコントロールフェイズ、そしてデータフェイズです。
ドライバのカスタマイズ
STM32マイコンで定義するSPI関連の関数(チップセレクト、送受信)をW5500ドライバに紐付けるためのカスタマイズです。
SPIインターフェース(wizchip_conf.c)で下記の赤色で囲った部分を追加登録します。チップセレクト関数SPI_CS1_Select()/ SPI_CS1_Deselect() はSTM32Nucleo用に自作したものです。
自作した送受信関数SPI_Send_Receive() も同様に追加登録します。
内容が異なる場合は上図で追加定義したSPI送受信関数を下図のようにドライバ定義の関数に紐付けします。
実際、ドライバに追加したり、書き換える重要な部分はこれだけです。その他、ビルドの際にそのままではエラーとなりますがインクルードするファイルパスを修正すればよいだけです。
自作したSPI関連関数を定義したファイルをSPIインターフェース(wizchip_conf.c)のヘッダファイルにインクルードさせてリンクできるようにするのを忘れないでください。
- wizchip_conf.h内 #include "W5500/w5500.h"を "W5500.h" に修正
- wizchip_conf.h内 #include "net_func.h"(自作関数ファイル)を追加
- w5500.h内 #include "Ethernet/wizchip_conf.h"を "wizchip_conf.h" に修正
- socket.h内 #include "Ethernet/wizchip_conf.h"を "wizchip_conf.h" に修正
SPIインターフェース(wizchip_conf.c)内で定義している関数wizchip_init()で変数iが符号付きint8_t iで宣言されていて、このままだと色々warningがでるので符号なしuint8_t iに変更しておいてください。
W5500初期設定
SPI通信でのインターフェースが準備できたら実際のプログラミングではドライバ内で定義している関数を利用して初期設定をします。.
初期設定フロー
初期化フローチャートはプログラム内では下記のようにW5500_ini()関数にまとめています。レジスタ操作するための関数はドライバのヘッダファイルW5500.hで定義しています。
初期化の動作詳細
W5500はマルチキャストなど高度な設定もできますがここでは簡単なシングルキャストの基本設定で初期化をします。
レジスタのリセット(MR_RST)発行を行い、PHY初期化、送信元(サーバー側)のMACアドレス、IPアドレス、そしてKeepAlive,タイムアウト等を登録します。
① モードレジスタMRの初期化
MRレジスタ内のRSTビットを立ててリセットを実行。
実行関数: setMR(MR_RST)
② PHY初期設定
PHY設定をデフォルト値にリセット
実行関数:
v=getPHYCFGR() & PHYCFGR_RST;
setPHYCFGR(v);
v=getPHYCFGR() | ~PHYCFGR_RST;
setPHYCFGR(v);
PHYモードはレジスタで細かく設定できますがここはピン43,44,45の回路設定 (すべてHi)を優先させ、標準的な自動ネゴシエーションがデフォルトになっています。
③ MACアドレス、IPアドレス、GWアドレス、サブネットマスクの設定
setSHAR(MAC_address);//マックアドレス設定
setSIPR(IP_address); //IPアドレス設定
setGAR(GW_address); //ゲートウェイ設定
setSUBR(SUBNET_mask);//サブネットマスク設定
IPアドレスなど配列データを扱うので書き込みにWIZCHIP_WRITE_BUF()関数を使っています。 製品化する場合、MACアドレス以外は書き換えられるようにしてEEPROM等のメモリに保存したものを使用します。
④ KeepAlive, タイムアウトの設定
setSn_KPALVTR(SN, 6);//KeepAlive設定
setRTR(2000);//タイムアウト設定
setRCR(8);//タイムアウトリトライ回数設定
setSIMR(0b00000010) ;//ソケット1 割り込みマスク有効;
setSn_IMR(SN, Sn_IR_TIMEOUT);//タイムアウト割り込みマスク
setSn_IR(SN,0x1f);// 割り込みフラグリセット
これらは必須のものではないですが使用状況に合わせて標準的なものを設定しておけばよいものです。 設定詳細はW5500データシート(英文)に記載しています。
プログラム全容
これまでの初期設定を完了させるとネットワーク層までの通信環境が整ったことになります。プログラム全容は下記のようになります。
初期化関数W5500_ini()やネット関連の自作関数等は別途モジュールnet_func.cにまとめていてそのヘッダファイルをインクルードしています。
実際の動作確認
接続準備が整ったところでいよいよLANに接続してネットワークに参加します。ネットワークアドレスは使用環境により異なりますので実際のものに合わせてください。
LANに接続したNucleo-F103RB+W5500
プログラムを実行させると、設定したIPアドレスに属するネットワークアドレスをもったLANに接続することができます。
ここではネットワークアドレスが192.168.3でIPアドレスを192.168.3.100に設定しています。
PINGコマンドによる接続確認
PCのコマンドプロンプト画面から「ping」コマンドを実行してネットワーク内で認識されているかを確認します。 "ping 192.168.3.100"と入力した場合の応答を確認します。
下記のような画面の場合は何らかの原因で不備がありpingが通っていない状態を示しています。
このような場合は大抵、ケーブルに不備があったり設定したIPアドレスと異なったものを入力していたり何らかの原因があります。
プログラミング直後の初接続時にping応答がこのような場合はプログラムに何らかの不備がある可能性があるため、バグの原因を突き止めることになります。特にspi通信関連の動作確認とドライバ関連ファイルのパスは大切です。一度機能すれば大丈夫です。
プログラムが正常に機能すると下の画面が現れます。この状態ではpingが通っているため、無事ネットワークに参加することができたことを示しています。
pingコマンドはICMPプロトコルのものなのでOSI参照モデルのネットワーク層まで通信システムが確立したことになります。
pingコマンドだけでは通信チェック以外には何の仕事もできないのですが、ここまでのネットワークを確立できると、あとは上位のTCPプロトコルによるソケット通信やさらにその上位のHTTPプロトコルを搭載してwebサーバーを作成してブラウザからアクセスできるようになります。
今回はIPアドレスはメモリに保存した固定値"192.168.3.100"を使用しています。ここでは解説しませんが、DHCP機能を搭載するとDHCPサーバーから自動的に割り当てられたIPアドレスを使用できるようになります。
次回は上位プロトコルであるTCPを実装してソケット通信を実現します。
初めてネット接続を試みるとハードウェアとのからみがあるためpingが通るまでが大変ですが、一度pingが通ればネット通信はほぼ完成みたいなものです。ここまでくればあとはソフトウェアによりソケット通信やwebサーバー等に発展させていくことができます。