Skip to content

Commit

Permalink
W5500: Add possibility to drive without IRQ line
Browse files Browse the repository at this point in the history
  • Loading branch information
br101 committed Nov 29, 2023
1 parent ab03c2e commit 5b0b1be
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
8 changes: 8 additions & 0 deletions components/esp_eth/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ menu "Ethernet"
making it compatible with the software TCP/IP stack.
Say yes to enable W5500 driver.

if ETH_SPI_ETHERNET_W5500
config ETH_SPI_ETHERNET_W5500_POLLING
bool "Use W5500 in polling mode (without interrupt)"
help
Running W5500 in polling mode is not ideal, but it allows this driver to be used on
hardware where the interrupt line of the W5500 chip is not connected.
endif # ETH_SPI_ETHERNET_W5500

config ETH_SPI_ETHERNET_KSZ8851SNL
bool "Use KSZ8851SNL"
help
Expand Down
14 changes: 14 additions & 0 deletions components/esp_eth/src/esp_eth_mac_w5500.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,7 @@ static esp_err_t emac_w5500_flush_recv_frame(emac_w5500_t *emac)
return ret;
}

#if !CONFIG_ETH_SPI_ETHERNET_W5500_POLLING
IRAM_ATTR static void w5500_isr_handler(void *arg)
{
emac_w5500_t *emac = (emac_w5500_t *)arg;
Expand All @@ -723,6 +724,7 @@ IRAM_ATTR static void w5500_isr_handler(void *arg)
portYIELD_FROM_ISR();
}
}
#endif

static void emac_w5500_task(void *arg)
{
Expand All @@ -732,11 +734,15 @@ static void emac_w5500_task(void *arg)
uint32_t frame_len = 0;
uint32_t buf_len = 0;
while (1) {
#if CONFIG_ETH_SPI_ETHERNET_W5500_POLLING
vTaskDelay(1);
#else
/* check if the task receives any notification */
if (ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(1000)) == 0 && // if no notification ...
gpio_get_level(emac->int_gpio_num) != 0) { // ...and no interrupt asserted
continue; // -> just continue to check again
}
#endif
/* read interrupt status */
w5500_read(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status));
/* packet received */
Expand Down Expand Up @@ -782,12 +788,14 @@ static esp_err_t emac_w5500_init(esp_eth_mac_t *mac)
esp_err_t ret = ESP_OK;
emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent);
esp_eth_mediator_t *eth = emac->eth;
#if !CONFIG_ETH_SPI_ETHERNET_W5500_POLLING
esp_rom_gpio_pad_select_gpio(emac->int_gpio_num);
gpio_set_direction(emac->int_gpio_num, GPIO_MODE_INPUT);
gpio_set_pull_mode(emac->int_gpio_num, GPIO_PULLUP_ONLY);
gpio_set_intr_type(emac->int_gpio_num, GPIO_INTR_NEGEDGE); // active low
gpio_intr_enable(emac->int_gpio_num);
gpio_isr_handler_add(emac->int_gpio_num, w5500_isr_handler, emac);
#endif
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL), err, TAG, "lowlevel init failed");
/* reset w5500 */
ESP_GOTO_ON_ERROR(w5500_reset(emac), err, TAG, "reset w5500 failed");
Expand All @@ -797,8 +805,10 @@ static esp_err_t emac_w5500_init(esp_eth_mac_t *mac)
ESP_GOTO_ON_ERROR(w5500_setup_default(emac), err, TAG, "w5500 default setup failed");
return ESP_OK;
err:
#if !CONFIG_ETH_SPI_ETHERNET_W5500_POLLING
gpio_isr_handler_remove(emac->int_gpio_num);
gpio_reset_pin(emac->int_gpio_num);
#endif
eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
return ret;
}
Expand All @@ -808,8 +818,10 @@ static esp_err_t emac_w5500_deinit(esp_eth_mac_t *mac)
emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent);
esp_eth_mediator_t *eth = emac->eth;
mac->stop(mac);
#if !CONFIG_ETH_SPI_ETHERNET_W5500_POLLING
gpio_isr_handler_remove(emac->int_gpio_num);
gpio_reset_pin(emac->int_gpio_num);
#endif
eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
return ESP_OK;
}
Expand All @@ -831,8 +843,10 @@ esp_eth_mac_t *esp_eth_mac_new_w5500(const eth_w5500_config_t *w5500_config, con
ESP_GOTO_ON_FALSE(w5500_config && mac_config, NULL, err, TAG, "invalid argument");
emac = calloc(1, sizeof(emac_w5500_t));
ESP_GOTO_ON_FALSE(emac, NULL, err, TAG, "no mem for MAC instance");
#if !CONFIG_ETH_SPI_ETHERNET_W5500_POLLING
/* w5500 driver is interrupt driven */
ESP_GOTO_ON_FALSE(w5500_config->int_gpio_num >= 0, NULL, err, TAG, "invalid interrupt gpio number");
#endif
/* bind methods and attributes */
emac->sw_reset_timeout_ms = mac_config->sw_reset_timeout_ms;
emac->int_gpio_num = w5500_config->int_gpio_num;
Expand Down

0 comments on commit 5b0b1be

Please sign in to comment.