Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions components/esp32-ethernet-kit/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
idf_component_register(
INCLUDE_DIRS "include"
SRC_DIRS "src"
REQUIRES
"base_component"
"esp_eth"
"esp_netif"
"esp_event"
REQUIRED_IDF_TARGETS "esp32"
)
130 changes: 130 additions & 0 deletions components/esp32-ethernet-kit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# ESP32-Ethernet-Kit A V1.2

[![Badge](https://components.espressif.com/components/espp/esp32-ethernet-kit/badge.svg)](https://components.espressif.com/components/espp/esp32-ethernet-kit)

Board Support Package (BSP) for the Espressif **ESP32-Ethernet-Kit A V1.2**.

## Official board documentation

- [ESP32-Ethernet-Kit overview](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-ethernet-kit/index.html)
- [ESP32-Ethernet-Kit V1.2 User Guide](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-ethernet-kit/user_guide_v1.2.html)
- [Board schematic V1.2](https://dl.espressif.com/dl/schematics/SCH_ESP32-ETHERNET-KIT_A_V1.2_20200528.pdf)

## What this BSP provides

The `espp::Esp32EthernetKit` class is a singleton hardware abstraction for:

- **10/100 Ethernet** — internal ESP32 EMAC + IP101GRI RMII PHY, selectable
DHCP client **or** DHCP server mode

## Initialization API

The BSP exposes two initialization entry points:

- `initialize_ethernet()`
- `initialize_ethernet(const EthernetConfig &config)`

The no-argument overload is equivalent to `EthernetConfig{}` (DHCP client mode,
no callbacks).

```cpp
auto &board = espp::Esp32EthernetKit::get();
bool ok = board.initialize_ethernet();
```

## DHCP modes and callbacks

Mode selection is done through `EthernetConfig::mode`:

- `DhcpMode::CLIENT` (default): obtains an address from an upstream DHCP server.
- `DhcpMode::SERVER`: serves leases to connected hosts from a static interface IP.

Callback behavior:

- `on_link_up`: cable/link negotiated.
- `on_link_down`: link lost.
- `on_got_ip`: IPv4 becomes usable.
- Client mode: after DHCP lease is obtained.
- Server mode: when link comes up (static IP is already known).
- `on_lost_ip`: IPv4 no longer usable.
- `server_config.on_client_assigned` (server mode only): fires for each lease assignment.

### DHCP client (default)

```cpp
using Kit = espp::Esp32EthernetKit;

Kit::EthernetConfig cfg;
cfg.mode = Kit::DhcpMode::CLIENT;
cfg.on_link_up = []() {
// physical link is up
};
cfg.on_got_ip = [](esp_ip4_addr_t ip) {
// DHCP lease acquired
};
cfg.on_lost_ip = []() {
// lease lost or interface disconnected
};

auto &board = Kit::get();
bool ok = board.initialize_ethernet(cfg);
```

### DHCP server

```cpp
using Kit = espp::Esp32EthernetKit;

Kit::EthernetConfig cfg;
cfg.mode = Kit::DhcpMode::SERVER;

// Leave ip_info all-zero to use default 192.168.4.1/24.
// Or set custom static address information:
// IP4_ADDR(&cfg.server_config.ip_info.ip, 10, 0, 0, 1);
// IP4_ADDR(&cfg.server_config.ip_info.netmask, 255, 255, 255, 0);
// IP4_ADDR(&cfg.server_config.ip_info.gw, 10, 0, 0, 1);

cfg.on_got_ip = [](esp_ip4_addr_t ip) {
// server interface IP became active
};
cfg.server_config.on_client_assigned = [](esp_ip4_addr_t ip, std::array<uint8_t, 6> mac) {
// a client received a lease
};

auto &board = Kit::get();
bool ok = board.initialize_ethernet(cfg);
```

## RMII pin mapping

The ESP32 RMII data-plane signals are fixed to specific GPIOs via IO_MUX and
**cannot be changed**. The control-plane signals (MDC/MDIO/PHY_RST) can be
routed via the GPIO matrix.

| Signal | GPIO | Notes |
|--------------|------|--------------------------------------------|
| REF_CLK (in) | 0 | External 50 MHz oscillator on V1.2 |
| TX_EN | 21 | IO_MUX — fixed |
| TXD0 | 19 | IO_MUX — fixed |
| TXD1 | 22 | IO_MUX — fixed |
| CRS_DV | 27 | IO_MUX — fixed |
| RXD0 | 25 | IO_MUX — fixed |
| RXD1 | 26 | IO_MUX — fixed |
| MDC | 23 | GPIO matrix — reconfigurable |
| MDIO | 18 | GPIO matrix — reconfigurable |
| PHY_RST | 5 | Active-low; set `eth_phy_reset_gpio = -1` to skip |

> [!WARNING]
> **GPIO0 / REF_CLK conflict.** GPIO0 is both the RMII REF_CLK input (driven by
> the on-board 50 MHz oscillator) and the BOOT strapping pin. Pressing BOOT while
> Ethernet is running briefly pulls the clock line to GND, disrupting the 50 MHz
> clock and corrupting active traffic. Do **not** use GPIO0 as a runtime input
> while Ethernet is active.

## sdkconfig requirements

```
CONFIG_ETH_ENABLED=y
CONFIG_ETH_USE_ESP32_EMAC=y
CONFIG_ETH_PHY_ENABLE_IP101=y
```
22 changes: 22 additions & 0 deletions components/esp32-ethernet-kit/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.20)

set(ENV{IDF_COMPONENT_MANAGER} "0")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

# add the component directories that we want to use
set(EXTRA_COMPONENT_DIRS
"../../../components/"
)

set(
COMPONENTS
"main esptool_py esp32-ethernet-kit"
CACHE STRING
"List of components to include"
)

project(esp32_ethernet_kit_example)

set(CMAKE_CXX_STANDARD 20)
15 changes: 15 additions & 0 deletions components/esp32-ethernet-kit/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ESP32-Ethernet-Kit Example

This example shows how to use the `espp::Esp32EthernetKit` BSP to bring up the
Ethernet interface and print the assigned IP address.

## Hardware

[ESP32-Ethernet-Kit A V1.2](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32/esp32-ethernet-kit/index.html)

## How to build and flash

```bash
idf.py set-target esp32
idf.py -p PORT flash monitor
```
4 changes: 4 additions & 0 deletions components/esp32-ethernet-kit/example/main/CMakeLists.txt
Comment thread
finger563 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
idf_component_register(
SRC_DIRS "."
INCLUDE_DIRS "."
)
45 changes: 45 additions & 0 deletions components/esp32-ethernet-kit/example/main/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
menu "ESP32-Ethernet-Kit Example Configuration"

choice EXAMPLE_ETH_DHCP_MODE
prompt "DHCP mode"
default EXAMPLE_ETH_DHCP_CLIENT
help
Select whether the board acts as a DHCP client (acquires an IP from
an upstream router) or as a DHCP server (assigns IPs to connected hosts).

config EXAMPLE_ETH_DHCP_CLIENT
bool "DHCP client"
help
The ESP32 requests an IP address from the network's DHCP server.

config EXAMPLE_ETH_DHCP_SERVER
bool "DHCP server"
help
The ESP32 acts as a DHCP server. It gets a static IP and hands out
addresses to connected hosts. Configure the static IP below.
endchoice

if EXAMPLE_ETH_DHCP_SERVER

config EXAMPLE_ETH_SERVER_IP
string "Server static IP address"
default "192.168.4.1"
help
Static IPv4 address assigned to the ESP32's Ethernet interface when
operating as a DHCP server.

config EXAMPLE_ETH_SERVER_NETMASK
string "Server netmask"
default "255.255.255.0"
help
Netmask for the DHCP server subnet.

config EXAMPLE_ETH_SERVER_GW
string "Server gateway"
default "192.168.4.1"
help
Gateway address advertised to DHCP clients (usually the server's own IP).

endif # EXAMPLE_ETH_DHCP_SERVER

endmenu
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include <chrono>
#include <thread>

#include <sdkconfig.h>

#include "esp32-ethernet-kit.hpp"
#include "logger.hpp"

#if CONFIG_EXAMPLE_ETH_DHCP_SERVER
#include <lwip/ip4_addr.h>
#endif

using namespace std::chrono_literals;
using DhcpMode = espp::Esp32EthernetKit::DhcpMode;
using EthConfig = espp::Esp32EthernetKit::EthernetConfig;

extern "C" void app_main(void) {
espp::Logger logger({.tag = "EthKitExample", .level = espp::Logger::Verbosity::INFO});
logger.info("ESP32-Ethernet-Kit A V1.2 example starting");

// Example 1: get the singleton board instance
//! [esp32 ethernet kit get instance]
auto &board = espp::Esp32EthernetKit::get();
//! [esp32 ethernet kit get instance]

#if CONFIG_EXAMPLE_ETH_DHCP_SERVER
// Example 2: init as DHCP server -- ESP32 assigns IPs to connected hosts.
// ServerConfig::ip_info zero -> default 192.168.4.1/24. Supply Kconfig
// values (EXAMPLE_ETH_SERVER_IP / _NETMASK / _GW) for a custom static IP.
//! [esp32 ethernet kit dhcp server]
espp::Esp32EthernetKit::ServerConfig srv_cfg;
ip4addr_aton(CONFIG_EXAMPLE_ETH_SERVER_IP, reinterpret_cast<ip4_addr_t *>(&srv_cfg.ip_info.ip));
ip4addr_aton(CONFIG_EXAMPLE_ETH_SERVER_NETMASK,
reinterpret_cast<ip4_addr_t *>(&srv_cfg.ip_info.netmask));
ip4addr_aton(CONFIG_EXAMPLE_ETH_SERVER_GW, reinterpret_cast<ip4_addr_t *>(&srv_cfg.ip_info.gw));
srv_cfg.on_client_assigned = [&](esp_ip4_addr_t ip, std::array<uint8_t, 6> mac) {
logger.info("Client assigned {}.{}.{}.{} (mac {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x})",
esp_ip4_addr1_16(&ip), esp_ip4_addr2_16(&ip), esp_ip4_addr3_16(&ip),
esp_ip4_addr4_16(&ip), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
};
bool eth_ok = board.initialize_ethernet({
.mode = DhcpMode::SERVER,
.server_config = srv_cfg,
.on_link_up = [&]() { logger.info("Ethernet link up"); },
.on_link_down = [&]() { logger.warn("Ethernet link down"); },
.on_got_ip =
[&](esp_ip4_addr_t ip) {
logger.info("DHCP server up at {}.{}.{}.{}", esp_ip4_addr1_16(&ip),
esp_ip4_addr2_16(&ip), esp_ip4_addr3_16(&ip), esp_ip4_addr4_16(&ip));
},
.on_lost_ip = [&]() { logger.warn("Ethernet lost IP"); },
});
//! [esp32 ethernet kit dhcp server]
#else
// Example 3: init as DHCP client -- ESP32 acquires an IP from the network.
//! [esp32 ethernet kit dhcp client]
bool eth_ok = board.initialize_ethernet({
.mode = DhcpMode::CLIENT,
.on_link_up = [&]() { logger.info("Ethernet link up"); },
.on_link_down = [&]() { logger.warn("Ethernet link down"); },
.on_got_ip =
[&](esp_ip4_addr_t ip) {
logger.info("DHCP lease acquired: {}.{}.{}.{}", esp_ip4_addr1_16(&ip),
esp_ip4_addr2_16(&ip), esp_ip4_addr3_16(&ip), esp_ip4_addr4_16(&ip));
},
.on_lost_ip = [&]() { logger.warn("Ethernet lost IP"); },
});
//! [esp32 ethernet kit dhcp client]
#endif

if (!eth_ok) {
logger.error("Ethernet initialization failed");
return;
}

// SERVER mode: connected as soon as the cable is plugged in (static IP).
// CLIENT mode: connected once the DHCP lease is granted (up to ~30 s).
logger.info("Waiting for Ethernet...");
for (int i = 0; i < 60 && !board.is_ethernet_connected(); ++i) {
std::this_thread::sleep_for(500ms);
}

if (board.is_ethernet_connected()) {
auto ip = board.ethernet_ip();
logger.info("Connected. IP: {}.{}.{}.{}", esp_ip4_addr1_16(&ip), esp_ip4_addr2_16(&ip),
esp_ip4_addr3_16(&ip), esp_ip4_addr4_16(&ip));
} else {
logger.warn("Ethernet not ready within 30 s");
}

while (true) {
std::this_thread::sleep_for(5s);
if (board.is_ethernet_connected()) {
auto ip = board.ethernet_ip();
logger.info("Ethernet up, IP: {}.{}.{}.{}", esp_ip4_addr1_16(&ip), esp_ip4_addr2_16(&ip),
esp_ip4_addr3_16(&ip), esp_ip4_addr4_16(&ip));
} else {
logger.warn("Ethernet not connected");
}
}
}
13 changes: 13 additions & 0 deletions components/esp32-ethernet-kit/example/sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CONFIG_IDF_TARGET="esp32"

# Ethernet
CONFIG_ETH_ENABLED=y
CONFIG_ETH_USE_ESP32_EMAC=y
CONFIG_ETH_PHY_ENABLE_IP101=y

# FreeRTOS tick rate
CONFIG_FREERTOS_HZ=1000

# Allow RMII clock on GPIO0 (strapping pin warning suppressed by IDF when used
# as EMAC_CLK_EXT_IN input — GPIO0 is configured as input by the EMAC driver).
CONFIG_ESP_SYSTEM_GPIO_MATRIX_BYPASS=n
22 changes: 22 additions & 0 deletions components/esp32-ethernet-kit/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## IDF Component Manager Manifest File
license: "MIT"
description: "ESP32-Ethernet-Kit A V1.2 Board Support Package (BSP) component in C++"
url: "https://github.com/esp-cpp/espp/tree/main/components/esp32-ethernet-kit"
repository: "git://github.com/esp-cpp/espp.git"
maintainers:
- William Emfinger <waemfinger@gmail.com>
documentation: "https://esp-cpp.github.io/espp/dev_boards/espressif/esp32_ethernet_kit.html"
examples:
- path: example
tags:
- cpp
- Component
- BSP
- ESP32
- Ethernet
- EthernetKit
dependencies:
idf: ">=5.0"
espp/base_component: ">=1.0"
targets:
- esp32
Loading