1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

esp/esp32: changes in esp_eth for ESP-IDF v4.4

This commit is contained in:
Gunar Schorcht 2022-02-01 21:40:13 +01:00
parent 1d914d1496
commit 3e4dc10740
2 changed files with 138 additions and 92 deletions

View File

@ -18,8 +18,6 @@
#ifdef MODULE_ESP_ETH
#define ENABLE_DEBUG 0
#include "debug.h"
#include "log.h"
#include "tools.h"
@ -32,6 +30,7 @@
#include "net/ethernet.h"
#include "net/netdev/eth.h"
#include "od.h"
#include "timex.h"
#include "ztimer.h"
@ -42,9 +41,17 @@
#include "esp_eth_params.h"
#include "esp_eth_netdev.h"
#include "esp32/esp_event_loop.h"
#include "esp_eth.h"
#include "esp_eth_phy.h"
#include "esp_eth_mac.h"
#include "esp_event.h"
#include "board.h"
#define ENABLE_DEBUG_HEXDUMP 0
#define ENABLE_DEBUG 0
#include "debug.h"
#if !defined(EMAC_PHY_SMI_MDC_PIN) || !defined(EMAC_PHY_SMI_MDIO_PIN)
#error Board definition does not provide EMAC configuration
#endif
@ -54,19 +61,26 @@
#define EMAC_PHY_CLOCK_DELAY_MS (500)
#ifdef EMAC_PHY_LAN8720
#include "eth_phy/phy_lan8720.h"
#define EMAC_ETHERNET_PHY_CONFIG phy_lan8720_default_ethernet_config
#endif
#ifdef EMAC_PHY_IP101G
#include "eth_phy/phy_ip101g.h"
#define EMAC_ETHERNET_PHY_CONFIG phy_ip101g_default_ethernet_config
#endif
#ifdef EMAC_PHY_TLK110
#include "eth_phy/phy_tlk110.h"
#define EMAC_ETHERNET_PHY_CONFIG phy_tlk110_default_ethernet_config
#if defined(EMAC_PHY_DP83848)
#define esp_eth_phy_new_xxxxx(cfg) esp_eth_phy_new_dp83848(cfg)
#elif defined(EMAC_PHY_IP101G)
#define esp_eth_phy_new_xxxxx(cfg) esp_eth_phy_new_ip101(cfg)
#elif defined(EMAC_PHY_LAN8720)
#define esp_eth_phy_new_xxxxx(cfg) esp_eth_phy_new_lan87xx(cfg)
#elif defined(EMAC_PHY_KSZ8041)
#define esp_eth_phy_new_xxxxx(cfg) esp_eth_phy_new_ksz8041(cfg)
#elif defined(EMAC_PHY_KSZ8081)
#define esp_eth_phy_new_xxxxx(cfg) esp_eth_phy_new_ksz8081(cfg)
#elif defined(EMAC_PHY_RTL8201)
#define esp_eth_phy_new_xxxxx(cfg) esp_eth_phy_new_rtl8201(cfg)
#endif
/* for source code compatibility of board definitions from ESP-IDF 3.1 */
#define ETH_CLOCK_GPIO0_IN 0
#define ETH_CLOCK_GPIO0_OUT 1
#define ETH_CLOCK_GPIO16_OUT 2
#define ETH_CLOCK_GPIO17_OUT 3
/**
* There is only one ESP-ETH device. We define it as static device variable
* to have access to the device inside ESP-ETH interrupt routines which do
@ -75,30 +89,14 @@
*/
esp_eth_netdev_t _esp_eth_dev;
static void _eth_gpio_config_rmii(void)
static esp_err_t IRAM_ATTR _eth_input_callback(esp_eth_handle_t hdl,
uint8_t *buffer, uint32_t len,
void *priv)
{
DEBUG("%s\n", __func__);
/*
* RMII data pins are fixed:
* TXD0 = GPIO19
* TXD1 = GPIO22
* TX_EN = GPIO21
* RXD0 = GPIO25
* RXD1 = GPIO26
* CLK = GPIO0
*/
phy_rmii_configure_data_interface_pins();
DEBUG("%s: buf=%p len=%d priv=%p\n", __func__, buffer, len, priv);
/* SMI pins can be configured in board definition */
phy_rmii_smi_configure_pins(EMAC_PHY_SMI_MDC_PIN, EMAC_PHY_SMI_MDIO_PIN);
}
static esp_err_t IRAM_ATTR _eth_input_callback(void *buffer, uint16_t len, void *eb)
{
DEBUG("%s: buf=%p len=%d eb=%p\n", __func__, buffer, len, eb);
CHECK_PARAM_RET (buffer != NULL, -EINVAL);
CHECK_PARAM_RET (len <= ETHERNET_MAX_LEN, -EINVAL);
assert(buffer != NULL);
assert(len <= ETHERNET_MAX_LEN);
mutex_lock(&_esp_eth_dev.dev_lock);
@ -107,6 +105,10 @@ static esp_err_t IRAM_ATTR _eth_input_callback(void *buffer, uint16_t len, void
if (_esp_eth_dev.event == SYSTEM_EVENT_MAX ||
_esp_eth_dev.event == SYSTEM_EVENT_ETH_RX_DONE) {
memcpy(_esp_eth_dev.rx_buf, buffer, len);
/* buffer is allocated by the `emac_esp32_rx_task` upon receipt of a
* MAC frame and is forwarded to the consumer who responsible for
* freeing the buffer. */
free(buffer);
_esp_eth_dev.rx_len = len;
_esp_eth_dev.event = SYSTEM_EVENT_ETH_RX_DONE;
netdev_trigger_event_isr(&_esp_eth_dev.netdev);
@ -117,25 +119,39 @@ static esp_err_t IRAM_ATTR _eth_input_callback(void *buffer, uint16_t len, void
return ESP_OK;
}
static void _esp_eth_phy_power_enable_gpio(bool enable)
/** Event handler for Ethernet events */
static void _esp_eth_event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
assert(EMAC_ETHERNET_PHY_CONFIG.phy_power_enable);
(void)arg;
(void)event_data;
if (EMAC_PHY_POWER_PIN == GPIO_UNDEF) {
return;
}
if (!enable) {
EMAC_ETHERNET_PHY_CONFIG.phy_power_enable(false);
}
gpio_init(EMAC_PHY_POWER_PIN, GPIO_OUT);
gpio_write(EMAC_PHY_POWER_PIN, enable);
ztimer_sleep(ZTIMER_MSEC, 1);
if (enable) {
EMAC_ETHERNET_PHY_CONFIG.phy_power_enable(true);
switch (event_id) {
case ETHERNET_EVENT_START:
DEBUG("%s: Ethernet started\n", __func__);
break;
case ETHERNET_EVENT_STOP:
DEBUG("%s: Ethernet stopped\n", __func__);
break;
case ETHERNET_EVENT_CONNECTED:
DEBUG("%s Ethernet link up\n", __func__);
_esp_eth_dev.link_up = true;
if (SYSTEM_EVENT_MAX) {
_esp_eth_dev.event = SYSTEM_EVENT_ETH_CONNECTED;
netdev_trigger_event_isr(&_esp_eth_dev.netdev);
}
break;
case ETHERNET_EVENT_DISCONNECTED:
DEBUG("%s: Ethernet link down\n", __func__);
_esp_eth_dev.link_up = false;
if (SYSTEM_EVENT_MAX) {
_esp_eth_dev.event = SYSTEM_EVENT_ETH_DISCONNECTED;
netdev_trigger_event_isr(&_esp_eth_dev.netdev);
}
break;
default:
DEBUG("%s: event=%d\n", __func__, event_id);
break;
}
}
@ -147,41 +163,63 @@ static int _esp_eth_init(netdev_t *netdev)
mutex_lock(&dev->dev_lock);
esp_err_t ret = ESP_OK;
eth_config_t config = EMAC_ETHERNET_PHY_CONFIG;
/* set PHY configuration */
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
/* Set configuration */
config.phy_addr = EMAC_PHY_ADDRESS;
config.clock_mode = EMAC_PHY_CLOCK_MODE;
config.gpio_config = _eth_gpio_config_rmii;
config.tcpip_input = _eth_input_callback;
phy_config.phy_addr = EMAC_PHY_ADDRESS;
phy_config.reset_gpio_num = EMAC_PHY_POWER_PIN;
/*
* Replace the default 'power enable' function with an example-specific
* one that toggles a power GPIO.
*/
if (EMAC_PHY_POWER_PIN != GPIO_UNDEF) {
config.phy_power_enable = _esp_eth_phy_power_enable_gpio;
/* set MAC configuration */
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
mac_config.sw_reset_timeout_ms = 500;
mac_config.smi_mdc_gpio_num = EMAC_PHY_SMI_MDC_PIN;
mac_config.smi_mdio_gpio_num = EMAC_PHY_SMI_MDIO_PIN;
if (EMAC_PHY_CLOCK_MODE == ETH_CLOCK_GPIO0_IN) {
mac_config.clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
mac_config.clock_config.rmii.clock_gpio = EMAC_CLK_IN_GPIO;
}
else if (EMAC_PHY_CLOCK_MODE == ETH_CLOCK_GPIO0_OUT) {
mac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT;
mac_config.clock_config.rmii.clock_gpio = EMAC_APPL_CLK_OUT_GPIO;
}
else if (EMAC_PHY_CLOCK_MODE == ETH_CLOCK_GPIO16_OUT) {
mac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT;
mac_config.clock_config.rmii.clock_gpio = EMAC_CLK_OUT_GPIO;
}
else if (EMAC_PHY_CLOCK_MODE == ETH_CLOCK_GPIO17_OUT) {
mac_config.clock_config.rmii.clock_mode = EMAC_CLK_OUT;
mac_config.clock_config.rmii.clock_gpio = EMAC_CLK_OUT_180_GPIO;
}
/* initialize EMAC with config */
if (ret == ESP_OK && (ret = esp_eth_init(&config)) != ESP_OK) {
LOG_TAG_ERROR("esp_eth", "initialization failed");
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&mac_config);
esp_eth_phy_t *phy = esp_eth_phy_new_xxxxx(&phy_config);
/* generate Ethernet driver configuration */
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
/* install Ethernet driver */
if (esp_eth_driver_install(&config, &_esp_eth_dev.eth_driver) != ESP_OK) {
LOG_TAG_ERROR("esp_eth", "driver installation failed");
return -ENODEV;
}
/*
* after activating clock logic it can take some time before we can
* enable EMAC
*/
ztimer_sleep(ZTIMER_MSEC, EMAC_PHY_CLOCK_DELAY_MS);
esp_event_handler_instance_register(ETH_EVENT, ESP_EVENT_ANY_ID,
&_esp_eth_event_handler, NULL, NULL);
if (ret == ESP_OK && (ret = esp_eth_enable()) != ESP_OK) {
LOG_TAG_ERROR("esp_eth", "enable failed");
/* start Ethernet driver state machine */
if (esp_eth_start(_esp_eth_dev.eth_driver) != ESP_OK) {
LOG_TAG_ERROR("esp_eth", "driver installation failed");
return -ENODEV;
}
esp_eth_update_input_path(_esp_eth_dev.eth_driver,
_eth_input_callback, &_esp_eth_dev);
mutex_unlock(&dev->dev_lock);
return (ret == ESP_OK) ? 0 : -1;
return 0;
}
static int _esp_eth_send(netdev_t *netdev, const iolist_t *iolist)
@ -216,13 +254,15 @@ static int _esp_eth_send(netdev_t *netdev, const iolist_t *iolist)
if (IS_ACTIVE(ENABLE_DEBUG)) {
printf ("%s: send %d byte\n", __func__, dev->tx_len);
/* esp_hexdump (dev->tx_buf, dev->tx_len, 'b', 16); */
if (IS_ACTIVE(ENABLE_DEBUG_HEXDUMP) && IS_USED(MODULE_OD)) {
od_hex_dump(dev->tx_buf, dev->tx_len, OD_WIDTH_DEFAULT);
}
}
int ret = 0;
/* send the the packet to the peer(s) mac address */
if (esp_eth_tx(dev->tx_buf, dev->tx_len) == ESP_OK) {
if (esp_eth_transmit(dev->eth_driver, dev->tx_buf, dev->tx_len) == ESP_OK) {
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);
}
else {
@ -265,7 +305,10 @@ static int _esp_eth_recv(netdev_t *netdev, void *buf, size_t len, void *info)
}
if (IS_ACTIVE(ENABLE_DEBUG)) {
esp_hexdump (dev->rx_buf, dev->rx_len, 'b', 16);
printf ("%s: received %d byte\n", __func__, dev->rx_len);
if (IS_ACTIVE(ENABLE_DEBUG) && IS_USED(MODULE_OD)) {
od_hex_dump(dev->rx_buf, dev->rx_len, OD_WIDTH_DEFAULT);
}
}
/* copy received date and reset the receive length */
@ -289,7 +332,7 @@ static int _esp_eth_get(netdev_t *netdev, netopt_t opt, void *val, size_t max_le
switch (opt) {
case NETOPT_ADDRESS:
assert(max_len >= ETHERNET_ADDR_LEN);
esp_eth_get_mac((uint8_t *)val);
esp_eth_ioctl(dev->eth_driver, ETH_CMD_G_MAC_ADDR, (uint8_t *)val);
return ETHERNET_ADDR_LEN;
case NETOPT_LINK:
assert(max_len == sizeof(netopt_enable_t));
@ -306,13 +349,15 @@ static int _esp_eth_set(netdev_t *netdev, netopt_t opt, const void *val, size_t
DEBUG("%s: netdev=%p opt=%s val=%p len=%u\n",
__func__, netdev, netopt2str(opt), val, max_len);
CHECK_PARAM_RET (netdev != NULL, -ENODEV);
CHECK_PARAM_RET (val != NULL, -EINVAL);
CHECK_PARAM_RET(netdev != NULL, -ENODEV);
CHECK_PARAM_RET(val != NULL, -EINVAL);
esp_eth_netdev_t* dev = container_of(netdev, esp_eth_netdev_t, netdev);
switch (opt) {
case NETOPT_ADDRESS:
assert(max_len == ETHERNET_ADDR_LEN);
esp_eth_set_mac((uint8_t *)val);
esp_eth_ioctl(dev->eth_driver, ETH_CMD_S_MAC_ADDR, (uint8_t *)val);
return ETHERNET_ADDR_LEN;
default:
return netdev_eth_set(netdev, opt, val, max_len);
@ -323,7 +368,7 @@ static void _esp_eth_isr(netdev_t *netdev)
{
DEBUG("%s: netdev=%p\n", __func__, netdev);
CHECK_PARAM (netdev != NULL);
CHECK_PARAM(netdev != NULL);
esp_eth_netdev_t* dev = container_of(netdev, esp_eth_netdev_t, netdev);
@ -350,12 +395,12 @@ static void _esp_eth_isr(netdev_t *netdev)
static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t *event)
{
switch(event->event_id) {
switch (event->event_id) {
case SYSTEM_EVENT_ETH_START:
DEBUG("%s: Ethernet started\n", __func__);
break;
case SYSTEM_EVENT_ETH_STOP:
DEBUG("%s: Ethernet started\n", __func__);
DEBUG("%s: Ethernet stopped\n", __func__);
break;
case SYSTEM_EVENT_ETH_CONNECTED:
DEBUG("%s Ethernet link up\n", __func__);
@ -366,7 +411,7 @@ static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t *
}
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
DEBUG("%s: Ethernet link up\n", __func__);
DEBUG("%s: Ethernet link down\n", __func__);
_esp_eth_dev.link_up = false;
if (SYSTEM_EVENT_MAX) {
_esp_eth_dev.event = SYSTEM_EVENT_ETH_DISCONNECTED;

View File

@ -37,12 +37,13 @@ extern const netdev_driver_t esp_eth_driver;
/**
* @brief Device descriptor for ESP-ETH devices
*/
typedef struct
{
typedef struct {
netdev_t netdev; /**< netdev parent struct */
uint16_t rx_len; /**< number of bytes received */
uint16_t tx_len; /**< number of bytes in transmit buffer */
void *eth_driver; /**< EMAC driver handle */
uint16_t rx_len; /**< number of bytes received */
uint16_t tx_len; /**< number of bytes in transmit buffer */
uint8_t rx_buf[ETHERNET_MAX_LEN]; /**< receive buffer */
uint8_t tx_buf[ETHERNET_MAX_LEN]; /**< transmit buffer */