STM32でEthernetするっ!

投稿者: | 2018年5月13日

ロボカップで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からチェックボックス一つで導入することができる。

ハードウェア

用意するもの

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の初期化手順を記す。

  1. New Project -> MCU Selector -> STM32F407VGを選択し新規プロジェクトを作る。
  2. 先程の表に書いてあった通りピンを設定し、左のPeripheralsからETHを選択し、RMIIモードに設定する。
  3. さらに、RCCのHSEをCrystalに、SYSのDebugをSerial Wireに、Timebase Sourceを適当なTIM(今回はTIM10)に変更する。
  4. Middlewareの欄からFREERTOSとLWIPにチェックを入れる
  5. Clock Configurationのタブで、Input frequencyを8MHzに、PLLを以下のように設定する。
  6. Configuration -> Middleware -> LWIP -> General SettingsにDHCPを使用するかどうかを選択する項目がある。
    DHCPを使用せずに静的にIPを割り振りたい場合はLWIP_DHCPをDisabledに設定する。
    割り当てるIPアドレス等は各個のLANの設定に合わせること。
    また、TCPを用いない場合はLWIP_TCPをDisabledに変更する。
  7. Configuration -> Middleware -> FREERTOS-> Tasks and Queues -> Tasks -> defaultTaskを選択。
    Stack Sizeを512に変更。
    RTOSを用いる場合、タスクのスタックが不足すると他タスクのスタック破壊を起こし、異常動作・HardFaultの原因となる。(とはいえ計算資源は有限なので、闇雲に増やせばいいわけではないが…)
  8. 左上のメニューから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のドキュメントを別途参照する必要がある。(気が向けばまた書こうかと…)

参考

STM32でEthernetするっ!」への1件のフィードバック

  1. ペ·インオク

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

    返信

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です