Skip to content

Commit fd0a1dc

Browse files
committed
feat(esp_eth): added SPI Ethernet module polling mode
Closes #12682
1 parent ef655cb commit fd0a1dc

12 files changed

+295
-57
lines changed

components/esp_eth/include/esp_eth_mac.h

+12-6
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,8 @@ typedef struct
650650
*
651651
*/
652652
typedef struct {
653-
int int_gpio_num; /*!< Interrupt GPIO number */
653+
int int_gpio_num; /*!< Interrupt GPIO number, set -1 to not use interrupt and to poll rx status periodically */
654+
uint32_t poll_period_ms; /*!< Period in ms to poll rx status when interrupt mode is not used */
654655
spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined) */
655656
spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined) */
656657
eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */
@@ -663,9 +664,10 @@ typedef struct {
663664
#define ETH_DM9051_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \
664665
{ \
665666
.int_gpio_num = 4, \
667+
.poll_period_ms = 0, \
666668
.spi_host_id = spi_host, \
667669
.spi_devcfg = spi_devcfg_p, \
668-
.custom_spi_driver = ETH_DEFAULT_SPI, \
670+
.custom_spi_driver = ETH_DEFAULT_SPI, \
669671
}
670672

671673
/**
@@ -687,7 +689,8 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config,
687689
*
688690
*/
689691
typedef struct {
690-
int int_gpio_num; /*!< Interrupt GPIO number */
692+
int int_gpio_num; /*!< Interrupt GPIO number, set -1 to not use interrupt and to poll rx status periodically */
693+
uint32_t poll_period_ms; /*!< Period in ms to poll rx status when interrupt mode is not used */
691694
spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined)*/
692695
spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined)*/
693696
eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */
@@ -700,9 +703,10 @@ typedef struct {
700703
#define ETH_W5500_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \
701704
{ \
702705
.int_gpio_num = 4, \
706+
.poll_period_ms = 0, \
703707
.spi_host_id = spi_host, \
704708
.spi_devcfg = spi_devcfg_p, \
705-
.custom_spi_driver = ETH_DEFAULT_SPI, \
709+
.custom_spi_driver = ETH_DEFAULT_SPI, \
706710
}
707711

708712
/**
@@ -724,7 +728,8 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con
724728
*
725729
*/
726730
typedef struct {
727-
int int_gpio_num; /*!< Interrupt GPIO number */
731+
int int_gpio_num; /*!< Interrupt GPIO number, set -1 to not use interrupt and to poll rx status periodically */
732+
uint32_t poll_period_ms; /*!< Period in ms to poll rx status when interrupt mode is not used */
728733
spi_host_device_t spi_host_id; /*!< SPI peripheral (this field is invalid when custom SPI driver is defined) */
729734
spi_device_interface_config_t *spi_devcfg; /*!< SPI device configuration (this field is invalid when custom SPI driver is defined) */
730735
eth_spi_custom_driver_config_t custom_spi_driver; /*!< Custom SPI driver definitions */
@@ -737,9 +742,10 @@ typedef struct {
737742
#define ETH_KSZ8851SNL_DEFAULT_CONFIG(spi_host, spi_devcfg_p) \
738743
{ \
739744
.int_gpio_num = 4, \
745+
.poll_period_ms = 0, \
740746
.spi_host_id = spi_host, \
741747
.spi_devcfg = spi_devcfg_p, \
742-
.custom_spi_driver = ETH_DEFAULT_SPI, \
748+
.custom_spi_driver = ETH_DEFAULT_SPI, \
743749
}
744750

745751
/**

components/esp_eth/src/esp_eth_mac_dm9051.c

+63-16
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -25,6 +25,7 @@
2525
#include "esp_rom_gpio.h"
2626
#include "esp_rom_sys.h"
2727
#include "esp_cpu.h"
28+
#include "esp_timer.h"
2829

2930
static const char *TAG = "dm9051.mac";
3031

@@ -67,6 +68,8 @@ typedef struct {
6768
TaskHandle_t rx_task_hdl;
6869
uint32_t sw_reset_timeout_ms;
6970
int int_gpio_num;
71+
esp_timer_handle_t poll_timer;
72+
uint32_t poll_period_ms;
7073
uint8_t addr[6];
7174
bool packets_remain;
7275
bool flow_ctrl_enabled;
@@ -421,6 +424,12 @@ IRAM_ATTR static void dm9051_isr_handler(void *arg)
421424
}
422425
}
423426

427+
static void dm9051_poll_timer(void *arg)
428+
{
429+
emac_dm9051_t *emac = (emac_dm9051_t *)arg;
430+
xTaskNotifyGive(emac->rx_task_hdl);
431+
}
432+
424433
static esp_err_t emac_dm9051_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)
425434
{
426435
esp_err_t ret = ESP_OK;
@@ -514,12 +523,21 @@ static esp_err_t emac_dm9051_get_addr(esp_eth_mac_t *mac, uint8_t *addr)
514523
static esp_err_t emac_dm9051_set_link(esp_eth_mac_t *mac, eth_link_t link)
515524
{
516525
esp_err_t ret = ESP_OK;
526+
emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
517527
switch (link) {
518528
case ETH_LINK_UP:
519529
ESP_GOTO_ON_ERROR(mac->start(mac), err, TAG, "dm9051 start failed");
530+
if (emac->poll_timer) {
531+
ESP_GOTO_ON_ERROR(esp_timer_start_periodic(emac->poll_timer, emac->poll_period_ms * 1000),
532+
err, TAG, "start poll timer failed");
533+
}
520534
break;
521535
case ETH_LINK_DOWN:
522536
ESP_GOTO_ON_ERROR(mac->stop(mac), err, TAG, "dm9051 stop failed");
537+
if (emac->poll_timer) {
538+
ESP_GOTO_ON_ERROR(esp_timer_stop(emac->poll_timer),
539+
err, TAG, "stop poll timer failed");
540+
}
523541
break;
524542
default:
525543
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown link status");
@@ -777,12 +795,14 @@ static esp_err_t emac_dm9051_init(esp_eth_mac_t *mac)
777795
esp_err_t ret = ESP_OK;
778796
emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
779797
esp_eth_mediator_t *eth = emac->eth;
780-
esp_rom_gpio_pad_select_gpio(emac->int_gpio_num);
781-
gpio_set_direction(emac->int_gpio_num, GPIO_MODE_INPUT);
782-
gpio_set_pull_mode(emac->int_gpio_num, GPIO_PULLDOWN_ONLY);
783-
gpio_set_intr_type(emac->int_gpio_num, GPIO_INTR_POSEDGE);
784-
gpio_intr_enable(emac->int_gpio_num);
785-
gpio_isr_handler_add(emac->int_gpio_num, dm9051_isr_handler, emac);
798+
if (emac->int_gpio_num >= 0) {
799+
esp_rom_gpio_pad_select_gpio(emac->int_gpio_num);
800+
gpio_set_direction(emac->int_gpio_num, GPIO_MODE_INPUT);
801+
gpio_set_pull_mode(emac->int_gpio_num, GPIO_PULLDOWN_ONLY);
802+
gpio_set_intr_type(emac->int_gpio_num, GPIO_INTR_POSEDGE);
803+
gpio_intr_enable(emac->int_gpio_num);
804+
gpio_isr_handler_add(emac->int_gpio_num, dm9051_isr_handler, emac);
805+
}
786806
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL), err, TAG, "lowlevel init failed");
787807
/* reset dm9051 */
788808
ESP_GOTO_ON_ERROR(dm9051_reset(emac), err, TAG, "reset dm9051 failed");
@@ -796,8 +816,10 @@ static esp_err_t emac_dm9051_init(esp_eth_mac_t *mac)
796816
ESP_GOTO_ON_ERROR(dm9051_get_mac_addr(emac), err, TAG, "fetch ethernet mac address failed");
797817
return ESP_OK;
798818
err:
799-
gpio_isr_handler_remove(emac->int_gpio_num);
800-
gpio_reset_pin(emac->int_gpio_num);
819+
if (emac->int_gpio_num >= 0) {
820+
gpio_isr_handler_remove(emac->int_gpio_num);
821+
gpio_reset_pin(emac->int_gpio_num);
822+
}
801823
eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
802824
return ret;
803825
}
@@ -807,8 +829,13 @@ static esp_err_t emac_dm9051_deinit(esp_eth_mac_t *mac)
807829
emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
808830
esp_eth_mediator_t *eth = emac->eth;
809831
mac->stop(mac);
810-
gpio_isr_handler_remove(emac->int_gpio_num);
811-
gpio_reset_pin(emac->int_gpio_num);
832+
if (emac->int_gpio_num >= 0) {
833+
gpio_isr_handler_remove(emac->int_gpio_num);
834+
gpio_reset_pin(emac->int_gpio_num);
835+
}
836+
if (emac->poll_timer && esp_timer_is_active(emac->poll_timer)) {
837+
esp_timer_stop(emac->poll_timer);
838+
}
812839
eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
813840
return ESP_OK;
814841
}
@@ -819,9 +846,13 @@ static void emac_dm9051_task(void *arg)
819846
uint8_t status = 0;
820847
while (1) {
821848
// check if the task receives any notification
822-
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) == 0 && // if no notification ...
823-
gpio_get_level(emac->int_gpio_num) == 0) { // ...and no interrupt asserted
824-
continue; // -> just continue to check again
849+
if (emac->int_gpio_num >= 0) { // if in interrupt mode
850+
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) == 0 && // if no notification ...
851+
gpio_get_level(emac->int_gpio_num) == 0) { // ...and no interrupt asserted
852+
continue; // -> just continue to check again
853+
}
854+
} else {
855+
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
825856
}
826857
/* clear interrupt status */
827858
dm9051_register_read(emac, DM9051_ISR, &status);
@@ -867,6 +898,9 @@ static void emac_dm9051_task(void *arg)
867898
static esp_err_t emac_dm9051_del(esp_eth_mac_t *mac)
868899
{
869900
emac_dm9051_t *emac = __containerof(mac, emac_dm9051_t, parent);
901+
if (emac->poll_timer) {
902+
esp_timer_delete(emac->poll_timer);
903+
}
870904
vTaskDelete(emac->rx_task_hdl);
871905
emac->spi.deinit(emac->spi.ctx);
872906
heap_caps_free(emac->rx_buffer);
@@ -880,13 +914,13 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config,
880914
emac_dm9051_t *emac = NULL;
881915
ESP_GOTO_ON_FALSE(dm9051_config, NULL, err, TAG, "can't set dm9051 specific config to null");
882916
ESP_GOTO_ON_FALSE(mac_config, NULL, err, TAG, "can't set mac config to null");
917+
ESP_GOTO_ON_FALSE((dm9051_config->int_gpio_num >= 0) != (dm9051_config->poll_period_ms > 0), NULL, err, TAG, "invalid configuration argument combination");
883918
emac = calloc(1, sizeof(emac_dm9051_t));
884919
ESP_GOTO_ON_FALSE(emac, NULL, err, TAG, "calloc emac failed");
885-
/* dm9051 receive is driven by interrupt only for now*/
886-
ESP_GOTO_ON_FALSE(dm9051_config->int_gpio_num >= 0, NULL, err, TAG, "error interrupt gpio number");
887920
/* bind methods and attributes */
888921
emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms;
889922
emac->int_gpio_num = dm9051_config->int_gpio_num;
923+
emac->poll_period_ms = dm9051_config->poll_period_ms;
890924
emac->parent.set_mediator = emac_dm9051_set_mediator;
891925
emac->parent.init = emac_dm9051_init;
892926
emac->parent.deinit = emac_dm9051_deinit;
@@ -937,10 +971,23 @@ esp_eth_mac_t *esp_eth_mac_new_dm9051(const eth_dm9051_config_t *dm9051_config,
937971
emac->rx_buffer = heap_caps_malloc(ETH_MAX_PACKET_SIZE + DM9051_RX_HDR_SIZE, MALLOC_CAP_DMA);
938972
ESP_GOTO_ON_FALSE(emac->rx_buffer, NULL, err, TAG, "RX buffer allocation failed");
939973

974+
if (emac->int_gpio_num < 0) {
975+
const esp_timer_create_args_t poll_timer_args = {
976+
.callback = dm9051_poll_timer,
977+
.name = "emac_spi_poll_timer",
978+
.arg = emac,
979+
.skip_unhandled_events = true
980+
};
981+
ESP_GOTO_ON_FALSE(esp_timer_create(&poll_timer_args, &emac->poll_timer) == ESP_OK, NULL, err, TAG, "create poll timer failed");
982+
}
983+
940984
return &(emac->parent);
941985

942986
err:
943987
if (emac) {
988+
if (emac->poll_timer) {
989+
esp_timer_delete(emac->poll_timer);
990+
}
944991
if (emac->rx_task_hdl) {
945992
vTaskDelete(emac->rx_task_hdl);
946993
}

0 commit comments

Comments
 (0)