mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
Merge branch 'fix/w5500_10m_mode_v5_4' into 'release/v5.4'
fix(esp_eth): Fixed W5500 poor performance in 10M mode v5.4 See merge request espressif/esp-idf!42729
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
@@ -30,6 +31,8 @@ static const char *TAG = "w5500.mac";
|
|||||||
#define W5500_SPI_LOCK_TIMEOUT_MS (50)
|
#define W5500_SPI_LOCK_TIMEOUT_MS (50)
|
||||||
#define W5500_TX_MEM_SIZE (0x4000)
|
#define W5500_TX_MEM_SIZE (0x4000)
|
||||||
#define W5500_RX_MEM_SIZE (0x4000)
|
#define W5500_RX_MEM_SIZE (0x4000)
|
||||||
|
#define W5500_100M_TX_TMO_US (200)
|
||||||
|
#define W5500_10M_TX_TMO_US (1500)
|
||||||
#define W5500_ETH_MAC_RX_BUF_SIZE_AUTO (0)
|
#define W5500_ETH_MAC_RX_BUF_SIZE_AUTO (0)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -64,6 +67,7 @@ typedef struct {
|
|||||||
uint8_t addr[6];
|
uint8_t addr[6];
|
||||||
bool packets_remain;
|
bool packets_remain;
|
||||||
uint8_t *rx_buffer;
|
uint8_t *rx_buffer;
|
||||||
|
uint32_t tx_tmo;
|
||||||
} emac_w5500_t;
|
} emac_w5500_t;
|
||||||
|
|
||||||
static void *w5500_spi_init(const void *spi_config)
|
static void *w5500_spi_init(const void *spi_config)
|
||||||
@@ -245,18 +249,8 @@ err:
|
|||||||
static esp_err_t w5500_write_buffer(emac_w5500_t *emac, const void *buffer, uint32_t len, uint16_t offset)
|
static esp_err_t w5500_write_buffer(emac_w5500_t *emac, const void *buffer, uint32_t len, uint16_t offset)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
uint32_t remain = len;
|
|
||||||
const uint8_t *buf = buffer;
|
|
||||||
offset %= W5500_TX_MEM_SIZE;
|
|
||||||
if (offset + len > W5500_TX_MEM_SIZE) {
|
|
||||||
remain = (offset + len) % W5500_TX_MEM_SIZE;
|
|
||||||
len = W5500_TX_MEM_SIZE - offset;
|
|
||||||
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_MEM_SOCK_TX(0, offset), buf, len), err, TAG, "write TX buffer failed");
|
|
||||||
offset += len;
|
|
||||||
buf += len;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_MEM_SOCK_TX(0, offset), buf, remain), err, TAG, "write TX buffer failed");
|
|
||||||
|
|
||||||
|
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_MEM_SOCK_TX(0, offset), buffer, len), err, TAG, "write TX buffer failed");
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -264,18 +258,7 @@ err:
|
|||||||
static esp_err_t w5500_read_buffer(emac_w5500_t *emac, void *buffer, uint32_t len, uint16_t offset)
|
static esp_err_t w5500_read_buffer(emac_w5500_t *emac, void *buffer, uint32_t len, uint16_t offset)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
uint32_t remain = len;
|
ESP_GOTO_ON_ERROR(w5500_read(emac, W5500_MEM_SOCK_RX(0, offset), buffer, len), err, TAG, "read RX buffer failed");
|
||||||
uint8_t *buf = buffer;
|
|
||||||
offset %= W5500_RX_MEM_SIZE;
|
|
||||||
if (offset + len > W5500_RX_MEM_SIZE) {
|
|
||||||
remain = (offset + len) % W5500_RX_MEM_SIZE;
|
|
||||||
len = W5500_RX_MEM_SIZE - offset;
|
|
||||||
ESP_GOTO_ON_ERROR(w5500_read(emac, W5500_MEM_SOCK_RX(0, offset), buf, len), err, TAG, "read RX buffer failed");
|
|
||||||
offset += len;
|
|
||||||
buf += len;
|
|
||||||
}
|
|
||||||
ESP_GOTO_ON_ERROR(w5500_read(emac, W5500_MEM_SOCK_RX(0, offset), buf, remain), err, TAG, "read RX buffer failed");
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -284,7 +267,6 @@ static esp_err_t w5500_set_mac_addr(emac_w5500_t *emac)
|
|||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_MAC, emac->addr, 6), err, TAG, "write MAC address register failed");
|
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_MAC, emac->addr, 6), err, TAG, "write MAC address register failed");
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -338,7 +320,8 @@ static esp_err_t w5500_setup_default(emac_w5500_t *emac)
|
|||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
uint8_t reg_value = 16;
|
uint8_t reg_value = 16;
|
||||||
|
|
||||||
// Only SOCK0 can be used as MAC RAW mode, so we give the whole buffer (16KB TX and 16KB RX) to SOCK0
|
// Only SOCK0 can be used as MAC RAW mode, so we give the whole buffer (16KB TX and 16KB RX) to SOCK0, which doesn't have any effect for TX though.
|
||||||
|
// A larger TX buffer doesn't buy us pipelining - each SEND is one frame and must complete before the next.
|
||||||
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_RXBUF_SIZE(0), ®_value, sizeof(reg_value)), err, TAG, "set rx buffer size failed");
|
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_RXBUF_SIZE(0), ®_value, sizeof(reg_value)), err, TAG, "set rx buffer size failed");
|
||||||
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_TXBUF_SIZE(0), ®_value, sizeof(reg_value)), err, TAG, "set tx buffer size failed");
|
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_TXBUF_SIZE(0), ®_value, sizeof(reg_value)), err, TAG, "set tx buffer size failed");
|
||||||
reg_value = 0;
|
reg_value = 0;
|
||||||
@@ -490,11 +473,14 @@ err:
|
|||||||
static esp_err_t emac_w5500_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
|
static esp_err_t emac_w5500_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
|
||||||
{
|
{
|
||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
|
emac_w5500_t *emac = __containerof(mac, emac_w5500_t, parent);
|
||||||
switch (speed) {
|
switch (speed) {
|
||||||
case ETH_SPEED_10M:
|
case ETH_SPEED_10M:
|
||||||
|
emac->tx_tmo = W5500_10M_TX_TMO_US;
|
||||||
ESP_LOGD(TAG, "working in 10Mbps");
|
ESP_LOGD(TAG, "working in 10Mbps");
|
||||||
break;
|
break;
|
||||||
case ETH_SPEED_100M:
|
case ETH_SPEED_100M:
|
||||||
|
emac->tx_tmo = W5500_100M_TX_TMO_US;
|
||||||
ESP_LOGD(TAG, "working in 100Mbps");
|
ESP_LOGD(TAG, "working in 100Mbps");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -589,14 +575,16 @@ static esp_err_t emac_w5500_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t
|
|||||||
ESP_GOTO_ON_ERROR(w5500_send_command(emac, W5500_SCR_SEND, 100), err, TAG, "issue SEND command failed");
|
ESP_GOTO_ON_ERROR(w5500_send_command(emac, W5500_SCR_SEND, 100), err, TAG, "issue SEND command failed");
|
||||||
|
|
||||||
// pooling the TX done event
|
// pooling the TX done event
|
||||||
int retry = 0;
|
|
||||||
uint8_t status = 0;
|
uint8_t status = 0;
|
||||||
while (!(status & W5500_SIR_SEND)) {
|
uint64_t start = esp_timer_get_time();
|
||||||
ESP_GOTO_ON_ERROR(w5500_read(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status)), err, TAG, "read SOCK0 IR failed");
|
uint64_t now = 0;
|
||||||
if ((retry++ > 3 && !is_w5500_sane_for_rxtx(emac)) || retry > 10) {
|
do {
|
||||||
|
now = esp_timer_get_time();
|
||||||
|
if (!is_w5500_sane_for_rxtx(emac) || (now - start) > emac->tx_tmo) {
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
}
|
ESP_GOTO_ON_ERROR(w5500_read(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status)), err, TAG, "read SOCK0 IR failed");
|
||||||
|
} while (!(status & W5500_SIR_SEND));
|
||||||
// clear the event bit
|
// clear the event bit
|
||||||
status = W5500_SIR_SEND;
|
status = W5500_SIR_SEND;
|
||||||
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status)), err, TAG, "write SOCK0 IR failed");
|
ESP_GOTO_ON_ERROR(w5500_write(emac, W5500_REG_SOCK_IR(0), &status, sizeof(status)), err, TAG, "write SOCK0 IR failed");
|
||||||
|
|||||||
Reference in New Issue
Block a user