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
21 changes: 21 additions & 0 deletions examples/slaveinfo/slaveinfo.ino
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@

#include <SOEM.h>

// ESP32 boards with internal EMAC (e.g. Olimex ESP32-POE-ISO) need the ETH
// stack brought up in setup() before ec_init() can open the HAL. The event
// flag lets setup() block until the PHY reports link-up without any busy-wait
// in the SOEM layer itself.
#if defined(ARDUINO_ESP32_POE_ISO) || defined(ARDUINO_ESP32_POE) || defined(SOEM_INTERNAL_ETH)
#include <ETH.h>
static volatile bool eth_ready = false;
static void onEthEvent(arduino_event_id_t e) {
if (e == ARDUINO_EVENT_ETH_CONNECTED) eth_ready = true;
}
#endif

char IOmap[4096];
ec_ODlistt ODlist;
ec_OElistt OElist;
Expand Down Expand Up @@ -657,6 +669,15 @@ void app_loop()
void setup()
{
Serial.begin(115200);
// On ESP32 boards with internal EMAC the ETH stack must be started here so
// the PHY is powered and the link is up before the first ec_init() call.
// ETH_PHY_* constants come from the board's pins_arduino.h (e.g. Olimex
// ESP32-POE-ISO sets ETH_PHY_POWER=12 and ETH_CLK_MODE=ETH_CLOCK_GPIO17_OUT).
#if defined(ARDUINO_ESP32_POE_ISO) || defined(ARDUINO_ESP32_POE) || defined(SOEM_INTERNAL_ETH)
Network.onEvent(onEthEvent);
ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_MDC, ETH_PHY_MDIO, ETH_PHY_POWER, ETH_CLK_MODE);
while (!eth_ready) delay(10);
#endif
}

void loop()
Expand Down
77 changes: 77 additions & 0 deletions src/SOEM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,83 @@ void hal_ethernet_recv_rel(void)
}
#endif

#elif defined(ARDUINO_ESP32_POE_ISO) || \
defined(ARDUINO_ESP32_POE) || \
defined(SOEM_INTERNAL_ETH)
/**************************************************
for ESP32 with internal EMAC (e.g. Olimex ESP32-POE-ISO)
ETH must be initialised in setup() before ec_init() is called.
**************************************************/

#include <ETH.h>
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "esp_eth.h"

#define HAL_RX_QSIZE 4
static esp_eth_handle_t s_eth = NULL;
static QueueHandle_t s_rxq = NULL;
struct HalRxFrame { uint8_t *buf; uint32_t len; };
static unsigned char s_rx_static[1536];

static esp_err_t s_rx_cb(esp_eth_handle_t, uint8_t *buf, uint32_t len, void*)
{
uint8_t *copy = (uint8_t*)malloc(len);
if (copy) {
memcpy(copy, buf, len);
HalRxFrame f = {copy, len};
xQueueSend(s_rxq, &f, 0);
}
free(buf);
return ESP_OK;
}

#ifdef __cplusplus
extern "C" {
#endif

int hal_ethernet_open(void)
{
if (s_eth) return 0;
if (!s_rxq) { s_rxq = xQueueCreate(HAL_RX_QSIZE, sizeof(HalRxFrame)); if (!s_rxq) return -1; }
s_eth = ETH.handle();
if (!s_eth) return -2;
if (!ETH.linkUp()) return -3;
esp_eth_update_input_path(s_eth, s_rx_cb, NULL);
return 0;
}

void hal_ethernet_close(void)
{
s_eth = NULL; // allow re-open after ec_close() + ec_init()
}

int hal_ethernet_send(unsigned char *data, int len)
{
if (!s_eth) return -1;
return (esp_eth_transmit(s_eth, data, (size_t)len) == ESP_OK) ? 0 : -1;
}

int hal_ethernet_recv(unsigned char **data)
{
if (!s_rxq) return 0;
HalRxFrame f;
if (xQueueReceive(s_rxq, &f, 0) == pdTRUE) {
uint32_t len = (f.len < sizeof(s_rx_static)) ? f.len : sizeof(s_rx_static);
memcpy(s_rx_static, f.buf, len);
free(f.buf);
*data = s_rx_static;
return (int)len;
}
return 0;
}

void hal_ethernet_recv_rel(void) {}

#ifdef __cplusplus
}
#endif

#else
/**************************************************
for Ethernet Shield (W5500)
Expand Down