0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ESP32 内蔵macとLAN8720(PHY)でethrnet

0
Posted at

ESPはIOTゲートウェイにふさわしいマイコン

趣味の範囲でsmart home用のiotゲートウェイ基板を作っています。無線LANで各センサからデータを収集して、有線LANでPCに送信するという画策をしています。有線無線でethrnet通信できる基板を趣味の範囲で作るには、低予算で入手性も良いものは、今のところESP32の初代しかありません。S3からはmacが削除されてしまいました。

有線LANモジュールを試す

PHYの定番チップで入手性良く、安いものにLAN8720があります。8720はRMIIのみ対応しています。今回は、amazonで以下のモジュールを購入しました。500円ほどでした。
{37867F73-1830-4D36-AFF4-F7A179BABA28}.png

gitで公開しています

ESPで使うにはちょっとクセがある

AN8720のRMIIは50MHzの基準クロック(REF_CLK)が必要です。
ESP32側は、ピンのペリフェラルが決まっており、GPIO0 がRMIIクロック(EMAC_TX_CLK/REF_CLK)になります。
ところが GPIO0はブートストラップピンも兼ねており、起動時にここがクロックで暴れると、書き込みモードに入ったりして起動が不安定になります

そこでモジュールの改造が必要になります。改造方法は、50MHz振動子の1pin(クロックイネーブルで改造前N.C)をモジュールのNCに接続して、ESP32から50MHzクロックを操作してやります。これで起動時は、クロックを出さず、起動後の安定したタイミングでクロックを出すことで、ブートストラップに干渉する問題を防ぐことができます。

詳しい改造方法は、先駆者の記事に書かれています。GP0(ブートストラップ/CLK)は3.6kでプルアップ、GP17(クロックイネーブル)はプルダウンします。

ピンアサイン

ピンアサインは以下の通りです

信号 GPIO
MDC 23
MDIO 18
TXD0 19
TXD1 22
TX_EN 21
RXD0 25
RXD1 26
CRS_DV 27
REF_CLK 0
OSC_EN 17

API紹介

gitで公開しています

以下が、RMIIのAPIの説明になります
UDP通信を使っています

start_enet_rmii_lan8720_task()

Ethernetタスクを起動

enet_rmii_task()

メイン処理

  1. 発振器ON
  2. netif初期化
  3. Ethernet初期化
  4. netif接続
  5. IP設定
  6. Ethernet開始
  7. 監視ループ

enable_oscillator()

外部50MHz発振器を有効化

GPIO17制御:
LOW → 待機 → HIGH → 安定待ち

eth_init_lan8720()

Ethernet初期化

  • MAC生成(esp32内蔵)
  • PHY生成(LAN8720)
  • RMII設定
  • ドライバインストール
  • MACアドレス設定

eth_event_handler()

Ethernetイベント処理

  • LINK UP
  • LINK DOWN
  • START
  • STOP

got_ip_event_handler()

IP取得イベント

IP / MASK / GW をログ出力

enet_set_ip(host_id)

IP変更

ネットワーク初期化

esp_netif_init()
esp_event_loop_create_default()

netif接続

esp_netif_new()
esp_eth_new_netif_glue()
esp_netif_attach()

DHCP停止

esp_netif_dhcpc_stop()

Ethernet開始

esp_eth_start()

状態取得

esp_netif_is_netif_up()
esp_netif_get_ip_info()

UDPソケット生成

int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

送信先アドレス設定

struct sockaddr_in dest = {
    .sin_family = AF_INET,
    .sin_port   = htons(54321),
    .sin_addr.s_addr = inet_addr("192.168.1.10"),
};

UDPデータ送信

const char *msg = "ESP32-ETH-TX-TEST";

int tx_ret = sendto(sock,
                    msg,
                    strlen(msg),
                    0,
                    (struct sockaddr *)&dest,
                    sizeof(dest));

エラーチェック

if (tx_ret < 0) {
    // 送信失敗
} else {
    // 送信成功(バイト数返却)
}

送信周期

vTaskDelay(pdMS_TO_TICKS(5000));で調整

今日はここまで

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?