Skip to content
Open
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"
)
103 changes: 103 additions & 0 deletions components/esp32-ethernet-kit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# 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

## DHCP modes

`initialize_ethernet` accepts a `DhcpMode` parameter (default `CLIENT`).

### DHCP client (default)

The ESP32 requests an IP address from an upstream router/switch.
The `on_link_up` callback fires once the DHCP lease is granted.

```cpp
auto &board = espp::Esp32EthernetKit::get();

board.initialize_ethernet(
[](esp_ip4_addr_t ip) {
// called when lease is acquired
},
espp::Esp32EthernetKit::DhcpMode::CLIENT); // default — can be omitted
```

### DHCP server

The ESP32 assigns IP addresses to connected hosts using a static IP.
The `on_link_up` callback fires when the cable is connected (IP is static, so
it is known immediately). An optional `on_client_assigned` callback fires each
time a client receives a lease.

```cpp
using DhcpMode = espp::Esp32EthernetKit::DhcpMode;
using ServerConfig = espp::Esp32EthernetKit::ServerConfig;

auto &board = espp::Esp32EthernetKit::get();

ServerConfig cfg;
// Leave cfg.ip_info zero to use the built-in default: 192.168.4.1 / 255.255.255.0
// Or set a custom address:
// IP4_ADDR(&cfg.ip_info.ip, 10, 0, 0, 1);
// IP4_ADDR(&cfg.ip_info.netmask, 255, 255, 255, 0);
// IP4_ADDR(&cfg.ip_info.gw, 10, 0, 0, 1);

cfg.on_client_assigned = [](esp_ip4_addr_t ip, std::array<uint8_t, 6> mac) {
// fired each time a client gets a DHCP lease
};

board.initialize_ethernet(
[](esp_ip4_addr_t ip) {
// called when link is up (static IP is already known)
},
DhcpMode::SERVER,
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
```
5 changes: 5 additions & 0 deletions components/esp32-ethernet-kit/example/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
idf_component_register(
SRC_DIRS "."
INCLUDE_DIRS "."
REQUIRES "esp32-ethernet-kit"
)
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,97 @@
#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;

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(
[&](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));
},
DhcpMode::SERVER, srv_cfg);
//! [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(
[&](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));
},
DhcpMode::CLIENT);
//! [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