Skip to content

Commit 7372fc0

Browse files
authored
Merge pull request #944 from bensuffolk/network
Fix ETHSPI build
2 parents 4838931 + d0852f3 commit 7372fc0

File tree

2 files changed

+182
-61
lines changed

2 files changed

+182
-61
lines changed

lib/ETHSPI/esp_eth_mac_w5500.c

Lines changed: 180 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ static const char *TAG = "w5500.mac";
3939
#define W5500_SPI_LOCK_TIMEOUT_MS (50)
4040
#define W5500_TX_MEM_SIZE (0x4000)
4141
#define W5500_RX_MEM_SIZE (0x4000)
42+
#define W5500_ETH_MAC_RX_BUF_SIZE_AUTO (0)
43+
44+
typedef struct {
45+
uint32_t offset;
46+
uint32_t copy_len;
47+
uint32_t rx_len;
48+
uint32_t remain;
49+
}__attribute__((packed)) emac_w5500_auto_buf_info_t;
4250

4351
typedef struct {
4452
esp_eth_mac_t parent;
@@ -50,6 +58,7 @@ typedef struct {
5058
int int_gpio_num;
5159
uint8_t addr[6];
5260
bool packets_remain;
61+
uint8_t *rx_buffer;
5362
} emac_w5500_t;
5463

5564
static inline bool w5500_lock(emac_w5500_t *emac)
@@ -302,59 +311,6 @@ static esp_err_t emac_w5500_stop(esp_eth_mac_t *mac)
302311
return ret;
303312
}
304313

305-
IRAM_ATTR static void w5500_isr_handler(void *arg)
306-
{
307-
emac_w5500_t *emac = (emac_w5500_t *)arg;
308-
BaseType_t high_task_wakeup = pdFALSE;
309-
/* notify w5500 task */
310-
vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
311-
if (high_task_wakeup != pdFALSE) {
312-
portYIELD_FROM_ISR();
313-
}
314-
}
315-
316-
static void emac_w5500_task(void *arg)
317-
{
318-
emac_w5500_t *emac = (emac_w5500_t *)arg;
319-
uint8_t status = 0;
320-
uint8_t *buffer = NULL;
321-
uint32_t length = 0;
322-
while (1) {
323-
// check if the task receives any notification
324-
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) == 0 && // if no notification ...
325-
gpio_get_level(emac->int_gpio_num) != 0) { // ...and no interrupt asserted
326-
continue; // -> just continue to check again
327-
}
328-
329-
/* read interrupt status */
330-
w5500_read(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status));
331-
/* packet received */
332-
if (status & W5500_SIR_RECV) {
333-
status = W5500_SIR_RECV;
334-
// clear interrupt status
335-
w5500_write(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status));
336-
do {
337-
length = ETH_MAX_PACKET_SIZE;
338-
buffer = heap_caps_malloc(length, MALLOC_CAP_DMA);
339-
if (!buffer) {
340-
ESP_LOGE(TAG, "no mem for receive buffer");
341-
break;
342-
} else if (emac->parent.receive(&emac->parent, buffer, &length) == ESP_OK) {
343-
/* pass the buffer to stack (e.g. TCP/IP layer) */
344-
if (length) {
345-
emac->eth->stack_input(emac->eth, buffer, length);
346-
} else {
347-
free(buffer);
348-
}
349-
} else {
350-
free(buffer);
351-
}
352-
} while (emac->packets_remain);
353-
}
354-
}
355-
vTaskDelete(NULL);
356-
}
357-
358314
static esp_err_t emac_w5500_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)
359315
{
360316
esp_err_t ret = ESP_OK;
@@ -520,6 +476,8 @@ static esp_err_t emac_w5500_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t
520476
emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent);
521477
uint16_t offset = 0;
522478

479+
ESP_GOTO_ON_FALSE(length <= ETH_MAX_PACKET_SIZE, ESP_ERR_INVALID_ARG, err,
480+
TAG, "frame size is too big (actual %u, maximum %u)", length, ETH_MAX_PACKET_SIZE);
523481
// check if there're free memory to store this packet
524482
uint16_t free_size = 0;
525483
ESP_GOTO_ON_ERROR(w5500_get_tx_free_size(emac, &free_size), err, TAG, "get free size failed");
@@ -553,12 +511,103 @@ static esp_err_t emac_w5500_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t
553511
return ret;
554512
}
555513

514+
static esp_err_t emac_w5500_alloc_recv_buf(emac_w5500_t *emac, uint8_t **buf, uint32_t *length)
515+
{
516+
esp_err_t ret = ESP_OK;
517+
uint16_t offset = 0;
518+
uint16_t rx_len = 0;
519+
uint32_t copy_len = 0;
520+
uint16_t remain_bytes = 0;
521+
*buf = NULL;
522+
523+
w5500_get_rx_received_size(emac, &remain_bytes);
524+
if (remain_bytes) {
525+
// get current read pointer
526+
ESP_GOTO_ON_ERROR(w5500_read(emac, W5500_REG_SOCK_RX_RD(0), &offset, sizeof(offset)), err, TAG, "read RX RD failed");
527+
offset = __builtin_bswap16(offset);
528+
// read head
529+
ESP_GOTO_ON_ERROR(w5500_read_buffer(emac, &rx_len, sizeof(rx_len), offset), err, TAG, "read frame header failed");
530+
rx_len = __builtin_bswap16(rx_len) - 2; // data size includes 2 bytes of header
531+
// frames larger than expected will be truncated
532+
copy_len = rx_len > *length ? *length : rx_len;
533+
// runt frames are not forwarded by W5500 (tested on target), but check the length anyway since it could be corrupted at SPI bus
534+
ESP_GOTO_ON_FALSE(copy_len >= ETH_MIN_PACKET_SIZE - ETH_CRC_LEN, ESP_ERR_INVALID_SIZE, err, TAG, "invalid frame length %u", copy_len);
535+
*buf = malloc(copy_len);
536+
if (*buf != NULL) {
537+
emac_w5500_auto_buf_info_t *buff_info = (emac_w5500_auto_buf_info_t *)*buf;
538+
buff_info->offset = offset;
539+
buff_info->copy_len = copy_len;
540+
buff_info->rx_len = rx_len;
541+
buff_info->remain = remain_bytes;
542+
} else {
543+
ret = ESP_ERR_NO_MEM;
544+
goto err;
545+
}
546+
}
547+
err:
548+
*length = rx_len;
549+
return ret;
550+
}
551+
556552
static esp_err_t emac_w5500_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length)
557553
{
558554
esp_err_t ret = ESP_OK;
559555
emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent);
560556
uint16_t offset = 0;
561557
uint16_t rx_len = 0;
558+
uint16_t copy_len = 0;
559+
uint16_t remain_bytes = 0;
560+
emac->packets_remain = false;
561+
562+
if (*length != W5500_ETH_MAC_RX_BUF_SIZE_AUTO) {
563+
w5500_get_rx_received_size(emac, &remain_bytes);
564+
if (remain_bytes) {
565+
// get current read pointer
566+
ESP_GOTO_ON_ERROR(w5500_read(emac, W5500_REG_SOCK_RX_RD(0), &offset, sizeof(offset)), err, TAG, "read RX RD failed");
567+
offset = __builtin_bswap16(offset);
568+
// read head first
569+
ESP_GOTO_ON_ERROR(w5500_read_buffer(emac, &rx_len, sizeof(rx_len), offset), err, TAG, "read frame header failed");
570+
rx_len = __builtin_bswap16(rx_len) - 2; // data size includes 2 bytes of header
571+
// frames larger than expected will be truncated
572+
copy_len = rx_len > *length ? *length : rx_len;
573+
} else {
574+
// silently return when no frame is waiting
575+
goto err;
576+
}
577+
} else {
578+
emac_w5500_auto_buf_info_t *buff_info = (emac_w5500_auto_buf_info_t *)buf;
579+
offset = buff_info->offset;
580+
copy_len = buff_info->copy_len;
581+
rx_len = buff_info->rx_len;
582+
remain_bytes = buff_info->remain;
583+
}
584+
// 2 bytes of header
585+
offset += 2;
586+
// read the payload
587+
ESP_GOTO_ON_ERROR(w5500_read_buffer(emac, emac->rx_buffer, copy_len, offset), err, TAG, "read payload failed, len=%d, offset=%d", rx_len, offset);
588+
memcpy(buf, emac->rx_buffer, copy_len);
589+
offset += rx_len;
590+
// update read pointer
591+
offset = __builtin_bswap16(offset);
592+
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_RX_RD(0), &offset, sizeof(offset)), err, TAG, "write RX RD failed");
593+
/* issue RECV command */
594+
ESP_GOTO_ON_ERROR(w5500_send_command(emac, W5500_SCR_RECV, 100), err, TAG, "issue RECV command failed");
595+
// check if there're more data need to process
596+
remain_bytes -= rx_len + 2;
597+
emac->packets_remain = remain_bytes > 0;
598+
599+
*length = copy_len;
600+
return ret;
601+
err:
602+
*length = 0;
603+
return ret;
604+
}
605+
606+
static esp_err_t emac_w5500_flush_recv_frame(emac_w5500_t *emac)
607+
{
608+
esp_err_t ret = ESP_OK;
609+
uint16_t offset = 0;
610+
uint16_t rx_len = 0;
562611
uint16_t remain_bytes = 0;
563612
emac->packets_remain = false;
564613

@@ -569,26 +618,90 @@ static esp_err_t emac_w5500_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *
569618
offset = __builtin_bswap16(offset);
570619
// read head first
571620
ESP_GOTO_ON_ERROR(w5500_read_buffer(emac, &rx_len, sizeof(rx_len), offset), err, TAG, "read frame header failed");
572-
rx_len = __builtin_bswap16(rx_len) - 2; // data size includes 2 bytes of header
573-
offset += 2;
574-
// read the payload
575-
ESP_GOTO_ON_ERROR(w5500_read_buffer(emac, buf, rx_len, offset), err, TAG, "read payload failed, len=%d, offset=%d", rx_len, offset);
576-
offset += rx_len;
577621
// update read pointer
622+
rx_len = __builtin_bswap16(rx_len);
623+
offset += rx_len;
578624
offset = __builtin_bswap16(offset);
579625
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_RX_RD(0), &offset, sizeof(offset)), err, TAG, "write RX RD failed");
580626
/* issue RECV command */
581627
ESP_GOTO_ON_ERROR(w5500_send_command(emac, W5500_SCR_RECV, 100), err, TAG, "issue RECV command failed");
582628
// check if there're more data need to process
583-
remain_bytes -= rx_len + 2;
629+
remain_bytes -= rx_len;
584630
emac->packets_remain = remain_bytes > 0;
585631
}
586-
587-
*length = rx_len;
588632
err:
589633
return ret;
590634
}
591635

636+
IRAM_ATTR static void w5500_isr_handler(void *arg)
637+
{
638+
emac_w5500_t *emac = (emac_w5500_t *)arg;
639+
BaseType_t high_task_wakeup = pdFALSE;
640+
/* notify w5500 task */
641+
vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
642+
if (high_task_wakeup != pdFALSE) {
643+
portYIELD_FROM_ISR();
644+
}
645+
}
646+
647+
static void emac_w5500_task(void *arg)
648+
{
649+
emac_w5500_t *emac = (emac_w5500_t *)arg;
650+
uint8_t status = 0;
651+
uint8_t *buffer = NULL;
652+
uint32_t frame_len = 0;
653+
uint32_t buf_len = 0;
654+
esp_err_t ret;
655+
while (1) {
656+
/* check if the task receives any notification */
657+
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) == 0 && // if no notification ...
658+
gpio_get_level(emac->int_gpio_num) != 0) { // ...and no interrupt asserted
659+
continue; // -> just continue to check again
660+
}
661+
/* read interrupt status */
662+
w5500_read(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status));
663+
/* packet received */
664+
if (status & W5500_SIR_RECV) {
665+
status = W5500_SIR_RECV;
666+
/* clear interrupt status */
667+
w5500_write(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status));
668+
do {
669+
/* define max expected frame len */
670+
frame_len = ETH_MAX_PACKET_SIZE;
671+
if ((ret = emac_w5500_alloc_recv_buf(emac, &buffer, &frame_len)) == ESP_OK) {
672+
if (buffer != NULL) {
673+
/* we have memory to receive the frame of maximal size previously defined */
674+
buf_len = W5500_ETH_MAC_RX_BUF_SIZE_AUTO;
675+
if (emac->parent.receive(&emac->parent, buffer, &buf_len) == ESP_OK) {
676+
if (buf_len == 0) {
677+
free(buffer);
678+
} else if (frame_len > buf_len) {
679+
ESP_LOGE(TAG, "received frame was truncated");
680+
free(buffer);
681+
} else {
682+
ESP_LOGD(TAG, "receive len=%u", buf_len);
683+
/* pass the buffer to stack (e.g. TCP/IP layer) */
684+
emac->eth->stack_input(emac->eth, buffer, buf_len);
685+
}
686+
} else {
687+
ESP_LOGE(TAG, "frame read from module failed");
688+
free(buffer);
689+
}
690+
} else if (frame_len) {
691+
ESP_LOGE(TAG, "invalid combination of frame_len(%u) and buffer pointer(%p)", frame_len, buffer);
692+
}
693+
} else if (ret == ESP_ERR_NO_MEM) {
694+
ESP_LOGE(TAG, "no mem for receive buffer");
695+
emac_w5500_flush_recv_frame(emac);
696+
} else {
697+
ESP_LOGE(TAG, "unexpected error 0x%x", ret);
698+
}
699+
} while (emac->packets_remain);
700+
}
701+
}
702+
vTaskDelete(NULL);
703+
}
704+
592705
static esp_err_t emac_w5500_init(esp_eth_mac_t *mac)
593706
{
594707
esp_err_t ret = ESP_OK;
@@ -631,6 +744,7 @@ static esp_err_t emac_w5500_del(esp_eth_mac_t *mac)
631744
emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent);
632745
vTaskDelete(emac->rx_task_hdl);
633746
vSemaphoreDelete(emac->spi_lock);
747+
heap_caps_free(emac->rx_buffer);
634748
free(emac);
635749
return ESP_OK;
636750
}
@@ -677,6 +791,10 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con
677791
BaseType_t xReturned = xTaskCreatePinnedToCore(emac_w5500_task, "w5500_tsk", mac_config->rx_task_stack_size, emac,
678792
mac_config->rx_task_prio, &emac->rx_task_hdl, core_num);
679793
ESP_GOTO_ON_FALSE(xReturned == pdPASS, NULL, err, TAG, "create w5500 task failed");
794+
795+
emac->rx_buffer = heap_caps_malloc(ETH_MAX_PACKET_SIZE, MALLOC_CAP_DMA);
796+
ESP_GOTO_ON_FALSE(emac->rx_buffer, NULL, err, TAG, "RX buffer allocation failed");
797+
680798
return &(emac->parent);
681799

682800
err:
@@ -687,6 +805,7 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con
687805
if (emac->spi_lock) {
688806
vSemaphoreDelete(emac->spi_lock);
689807
}
808+
heap_caps_free(emac->rx_buffer);
690809
free(emac);
691810
}
692811
return ret;

src/sys/net/hasp_wireguard.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#ifndef HASP_WIREGUARD_H
55
#define HASP_WIREGUARD_H
66

7+
#include "ArduinoJson.h"
8+
79
void wg_setup();
810
int wg_config_valid();
911
void wg_network_disconnected();

0 commit comments

Comments
 (0)