ロボカップでSTM32のEthernet機能を使用したところ反響があったため、今回はその紹介を行う。
Contents
概要
STM32F4DiscoveryとEthernet PHYチップであるDP83848を接続し、マイコンからPCにUDPでデータを送信する手順を説明する。ソフトウェアの開発にはSTM32CubeMXとTrueSTUDIOを用いる。
用語説明
STM32CubeMX
STM32CubeMXはST社が提供する初期化コード自動生成ツールである。
生成したコードは各IDEのプロジェクトとして出力できる。
TrueSTUDIO
TrueSTUDIOとは、旧Atollic社が開発したSTM32用のIDEである。(Atollic社は2017年にSTに買収された)
Ethernet PHY
通常マイコンから直接LANのコネクタを生やすことはできず、PHYチップを挟むことではじめてEthernetを扱うことができる。
マイコンとPHYチップ間の通信にはMIIやRMIIといったインターフェースが用いられる。
lwIP
lwIP (Lightweight IP)とは、オープンソースのTCP/IPスタックであり、軽量なため組み込み用途で広く用いられている。
CubeMXからチェックボックス一つでインポートできる。
FreeRTOS
FreeRTOSは組み込み向けのReal-Time OSの一つであり、lwIPを動かす際に必要となる。
EE Timesによる2017年のEmbedded Market Surveyでは20%の回答者がFreeRTOSを使用していると答えており、高いシェアを占めていることが分かる。
以前はGPL系ライセンスだったが、Amazonに買収されたのをきっかけにバージョン10からはMITライセンスで公開されている。神。
lwIP同様、CubeMXからチェックボックス一つで導入することができる。
ハードウェア
用意するもの
- STM32F4DISCOVERY [秋月]
- DP83848 PHY breakout board [回路図] [eBay]
- ジャンパワイヤ(メスーメス) [秋月] [Amazon]
F4Discovery+PHYチップで開発する以外に、以下の開発ボードを使用する方法も存在する。
これらのボード上には既にPHYチップとRJ45コネクタが実装されているため、ワンボードのみでEthernetの機能を試すことが出来る。
また、DP83848のbreakoutボード以外に、LAN8720というPHYのbreakoutボードを用いる方法もある。
DiscoveryやNucleoで使用されているのはLAN8742Aである。ただし、LAN8720やLAN8742AはQFNパッケージでハンダ付けが少々難しいため、ロボコン等の手半田勢はDP83848を使って設計することを薦める。ハンダ付けに自信ニキはLAN8720を使ってどうぞ。
配線
F4DiscoveryとDP83848のボードを、下表のようにジャンパワイヤで接続する。
STM32F4DiscoveryとDP83848の接続
| STM32 | DP83848 | |
|---|---|---|
| 3.3V | VDD | VCC |
| GND | GND | GND |
| MDC | PC1 | MDC |
| REF_CLK | PA1 | OSCIN |
| MDIO | PA2 | MDIO |
| CRS_DV | PA7 | CRS |
| RXD0 | PC4 | RX0 |
| RXD1 | PC5 | RX1 |
| TX_EN | PB11 | TX_EN |
| TXD0 | PB12 | TX0 |
| TXD1 | PB13 | TX1 |
ソフトウェア
CubeMX ~初期化コードの作成~
以下にCubeMXを用いたEthernetの初期化手順を記す。
- New Project -> MCU Selector -> STM32F407VGを選択し新規プロジェクトを作る。
- 先程の表に書いてあった通りピンを設定し、左のPeripheralsからETHを選択し、RMIIモードに設定する。

- さらに、RCCのHSEをCrystalに、SYSのDebugをSerial Wireに、Timebase Sourceを適当なTIM(今回はTIM10)に変更する。

- Middlewareの欄からFREERTOSとLWIPにチェックを入れる

- Clock Configurationのタブで、Input frequencyを8MHzに、PLLを以下のように設定する。

- Configuration -> Middleware -> LWIP -> General SettingsにDHCPを使用するかどうかを選択する項目がある。
DHCPを使用せずに静的にIPを割り振りたい場合はLWIP_DHCPをDisabledに設定する。
割り当てるIPアドレス等は各個のLANの設定に合わせること。
また、TCPを用いない場合はLWIP_TCPをDisabledに変更する。

- Configuration -> Middleware -> FREERTOS-> Tasks and Queues -> Tasks -> defaultTaskを選択。
Stack Sizeを512に変更。
RTOSを用いる場合、タスクのスタックが不足すると他タスクのスタック破壊を起こし、異常動作・HardFaultの原因となる。(とはいえ計算資源は有限なので、闇雲に増やせばいいわけではないが…) - 左上のメニューからProject -> Settingsを選択し、Toolchain / IDEの項目を自分が使用する開発環境のものに変更する。今回はTrueSTUDIOを選択する。
以上の設定を行ったらGenerateボタンを押し、ソースコードを生成する。
UDP送信サンプル
UDPでマイコンからPCにデータを送るコードを記述します。
生成したプロジェクトをTrueSTUDIOで開き、main.c内の関数を以下のように変更する。
このサンプルコードは以下の環境を想定したものであるため、各自の環境に合わせて数値を変更する必要がある。
- マイコンのIPアドレス: 192.168.11.60 (CubeMXで設定した値)
- 送信元ポート: 12345
- PCのIPアドレス:192.168.11.20
- 宛先ポート: 8080
void StartDefaultTask(void const * argument)
{
/* init code for LWIP */
MX_LWIP_Init();
/* USER CODE BEGIN 5 */
struct udp_pcb *pcb;
struct pbuf *p;
err_t err;
ip4_addr_t dst_addr;
const unsigned short src_port = 12345;
const unsigned short dst_port = 8080;
IP4_ADDR(&dst_addr,192,168,11,20);
pcb = udp_new();
err = udp_bind(pcb, IP_ADDR_ANY, src_port);
uint32_t cnt = 0;
/* Infinite loop */
for(;;)
{
p = pbuf_alloc(PBUF_TRANSPORT, sizeof(4), PBUF_RAM);
*(uint32_t *)p->payload = cnt++;
p->len = 4;
err = udp_sendto(pcb, p, &dst_addr, dst_port);
pbuf_free(p);
osDelay(1000);
}
/* USER CODE END 5 */
}
変更を保存したら、Ctrl+Bでプロジェクトをビルドし、実行 -> デバッグからマイコンへ実行ファイルを書き込む。
受信データの確認
実際にデータが正しく送られているか、WireSharkを用いて確認する。
受信できている場合は、このようにパケットの内容が表示される。
終わりに
STM32F4DiscoveryとDP83848を用いてPCとUDP通信を行う方法を示した。
マイコン側でのUDPの受信方法など、詳細な使い方はlwIPのドキュメントを別途参照する必要がある。(気が向けばまた書こうかと…)
参考

ロボットと電子工作とプログラミング!
女の子は甘いもので出来てる?


おはようございます
IARで実行するためにはどうすればいいですか。