ロボカップで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で実行するためにはどうすればいいですか。