mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 17:19:09 -04:00
esp_eth: possible start/stop issue fixed
ESP32 EMAC could hang when stopped/started multiple times at 10Mbps speed mode
This commit is contained in:
parent
dab382c95b
commit
4dc8ce77e4
@ -50,7 +50,7 @@ typedef struct {
|
|||||||
bool auto_nego_en;
|
bool auto_nego_en;
|
||||||
eth_speed_t speed;
|
eth_speed_t speed;
|
||||||
eth_duplex_t duplex;
|
eth_duplex_t duplex;
|
||||||
eth_link_t link;
|
_Atomic eth_link_t link;
|
||||||
atomic_int ref_count;
|
atomic_int ref_count;
|
||||||
void *priv;
|
void *priv;
|
||||||
_Atomic esp_eth_fsm_t fsm;
|
_Atomic esp_eth_fsm_t fsm;
|
||||||
@ -129,7 +129,7 @@ static esp_err_t eth_on_state_changed(esp_eth_mediator_t *eth, esp_eth_state_t s
|
|||||||
case ETH_STATE_LINK: {
|
case ETH_STATE_LINK: {
|
||||||
eth_link_t link = (eth_link_t)args;
|
eth_link_t link = (eth_link_t)args;
|
||||||
ESP_GOTO_ON_ERROR(mac->set_link(mac, link), err, TAG, "ethernet mac set link failed");
|
ESP_GOTO_ON_ERROR(mac->set_link(mac, link), err, TAG, "ethernet mac set link failed");
|
||||||
eth_driver->link = link;
|
atomic_store(ð_driver->link, link);
|
||||||
if (link == ETH_LINK_UP) {
|
if (link == ETH_LINK_UP) {
|
||||||
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_CONNECTED, ð_driver, sizeof(esp_eth_driver_t *), 0), err,
|
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_CONNECTED, ð_driver, sizeof(esp_eth_driver_t *), 0), err,
|
||||||
TAG, "send ETHERNET_EVENT_CONNECTED event failed");
|
TAG, "send ETHERNET_EVENT_CONNECTED event failed");
|
||||||
@ -205,7 +205,7 @@ esp_err_t esp_eth_driver_install(const esp_eth_config_t *config, esp_eth_handle_
|
|||||||
atomic_init(ð_driver->fsm, ESP_ETH_FSM_STOP);
|
atomic_init(ð_driver->fsm, ESP_ETH_FSM_STOP);
|
||||||
eth_driver->mac = mac;
|
eth_driver->mac = mac;
|
||||||
eth_driver->phy = phy;
|
eth_driver->phy = phy;
|
||||||
eth_driver->link = ETH_LINK_DOWN;
|
atomic_init(ð_driver->link, ETH_LINK_DOWN);
|
||||||
eth_driver->duplex = ETH_DUPLEX_HALF;
|
eth_driver->duplex = ETH_DUPLEX_HALF;
|
||||||
eth_driver->speed = ETH_SPEED_10M;
|
eth_driver->speed = ETH_SPEED_10M;
|
||||||
eth_driver->stack_input = config->stack_input;
|
eth_driver->stack_input = config->stack_input;
|
||||||
@ -309,7 +309,14 @@ esp_err_t esp_eth_stop(esp_eth_handle_t hdl)
|
|||||||
ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_STOP),
|
ESP_GOTO_ON_FALSE(atomic_compare_exchange_strong(ð_driver->fsm, &expected_fsm, ESP_ETH_FSM_STOP),
|
||||||
ESP_ERR_INVALID_STATE, err, TAG, "driver not started yet");
|
ESP_ERR_INVALID_STATE, err, TAG, "driver not started yet");
|
||||||
ESP_GOTO_ON_ERROR(esp_timer_stop(eth_driver->check_link_timer), err, TAG, "stop link timer failed");
|
ESP_GOTO_ON_ERROR(esp_timer_stop(eth_driver->check_link_timer), err, TAG, "stop link timer failed");
|
||||||
ESP_GOTO_ON_ERROR(mac->stop(mac), err, TAG, "stop mac failed");
|
|
||||||
|
eth_link_t expected_link = ETH_LINK_UP;
|
||||||
|
if (atomic_compare_exchange_strong(ð_driver->link, &expected_link, ETH_LINK_DOWN)){
|
||||||
|
// MAC is stopped by setting link down
|
||||||
|
ESP_GOTO_ON_ERROR(mac->set_link(mac, ETH_LINK_DOWN), err, TAG, "ethernet mac set link failed");
|
||||||
|
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, ð_driver, sizeof(esp_eth_driver_t *), 0), err,
|
||||||
|
TAG, "send ETHERNET_EVENT_DISCONNECTED event failed");
|
||||||
|
}
|
||||||
|
|
||||||
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(esp_eth_driver_t *), 0),
|
ESP_GOTO_ON_ERROR(esp_event_post(ETH_EVENT, ETHERNET_EVENT_STOP, ð_driver, sizeof(esp_eth_driver_t *), 0),
|
||||||
err, TAG, "send ETHERNET_EVENT_STOP event failed");
|
err, TAG, "send ETHERNET_EVENT_STOP event failed");
|
||||||
@ -336,9 +343,9 @@ esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length)
|
|||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||||
|
|
||||||
if (atomic_load(ð_driver->fsm) != ESP_ETH_FSM_START) {
|
if (atomic_load(ð_driver->link) != ETH_LINK_UP) {
|
||||||
ret = ESP_ERR_INVALID_STATE;
|
ret = ESP_ERR_INVALID_STATE;
|
||||||
ESP_LOGD(TAG, "Ethernet is not started");
|
ESP_LOGD(TAG, "Ethernet link is not up, can't transmit");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,9 +372,9 @@ esp_err_t esp_eth_transmit_vargs(esp_eth_handle_t hdl, uint32_t argc, ...)
|
|||||||
esp_err_t ret = ESP_OK;
|
esp_err_t ret = ESP_OK;
|
||||||
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;
|
||||||
|
|
||||||
if (atomic_load(ð_driver->fsm) != ESP_ETH_FSM_START) {
|
if (atomic_load(ð_driver->link) != ETH_LINK_UP) {
|
||||||
ret = ESP_ERR_INVALID_STATE;
|
ret = ESP_ERR_INVALID_STATE;
|
||||||
ESP_LOGD(TAG, "Ethernet is not started");
|
ESP_LOGD(TAG, "Ethernet link is not up, can't transmit");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
static const char *TAG = "esp.emac";
|
static const char *TAG = "esp.emac";
|
||||||
|
|
||||||
#define PHY_OPERATION_TIMEOUT_US (1000)
|
#define PHY_OPERATION_TIMEOUT_US (1000)
|
||||||
#define MAC_STOP_TIMEOUT_US (250)
|
#define MAC_STOP_TIMEOUT_US (2500) // this is absolute maximum for 10Mbps, it is 10 times faster for 100Mbps
|
||||||
#define FLOW_CONTROL_LOW_WATER_MARK (CONFIG_ETH_DMA_RX_BUFFER_NUM / 3)
|
#define FLOW_CONTROL_LOW_WATER_MARK (CONFIG_ETH_DMA_RX_BUFFER_NUM / 3)
|
||||||
#define FLOW_CONTROL_HIGH_WATER_MARK (FLOW_CONTROL_LOW_WATER_MARK * 2)
|
#define FLOW_CONTROL_HIGH_WATER_MARK (FLOW_CONTROL_LOW_WATER_MARK * 2)
|
||||||
|
|
||||||
@ -262,7 +262,6 @@ static esp_err_t emac_esp32_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *
|
|||||||
ESP_GOTO_ON_FALSE(buf && length, ESP_ERR_INVALID_ARG, err, TAG, "can't set buf and length to null");
|
ESP_GOTO_ON_FALSE(buf && length, ESP_ERR_INVALID_ARG, err, TAG, "can't set buf and length to null");
|
||||||
uint32_t receive_len = emac_hal_receive_frame(&emac->hal, buf, expected_len, &emac->frames_remain, &emac->free_rx_descriptor);
|
uint32_t receive_len = emac_hal_receive_frame(&emac->hal, buf, expected_len, &emac->frames_remain, &emac->free_rx_descriptor);
|
||||||
/* we need to check the return value in case the buffer size is not enough */
|
/* we need to check the return value in case the buffer size is not enough */
|
||||||
ESP_LOGD(TAG, "receive len= %d", receive_len);
|
|
||||||
ESP_GOTO_ON_FALSE(expected_len >= receive_len, ESP_ERR_INVALID_SIZE, err, TAG, "received buffer longer than expected");
|
ESP_GOTO_ON_FALSE(expected_len >= receive_len, ESP_ERR_INVALID_SIZE, err, TAG, "received buffer longer than expected");
|
||||||
*length = receive_len;
|
*length = receive_len;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@ -370,8 +369,6 @@ static esp_err_t emac_esp32_init(esp_eth_mac_t *mac)
|
|||||||
ESP_GOTO_ON_FALSE(to < emac->sw_reset_timeout_ms / 10, ESP_ERR_TIMEOUT, err, TAG, "reset timeout");
|
ESP_GOTO_ON_FALSE(to < emac->sw_reset_timeout_ms / 10, ESP_ERR_TIMEOUT, err, TAG, "reset timeout");
|
||||||
/* set smi clock */
|
/* set smi clock */
|
||||||
emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq());
|
emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq());
|
||||||
/* reset descriptor chain */
|
|
||||||
emac_hal_reset_desc_chain(&emac->hal);
|
|
||||||
/* init mac registers by default */
|
/* init mac registers by default */
|
||||||
emac_hal_init_mac_default(&emac->hal);
|
emac_hal_init_mac_default(&emac->hal);
|
||||||
/* init dma registers with selected EMAC-DMA configuration */
|
/* init dma registers with selected EMAC-DMA configuration */
|
||||||
@ -406,6 +403,7 @@ static esp_err_t emac_esp32_deinit(esp_eth_mac_t *mac)
|
|||||||
static esp_err_t emac_esp32_start(esp_eth_mac_t *mac)
|
static esp_err_t emac_esp32_start(esp_eth_mac_t *mac)
|
||||||
{
|
{
|
||||||
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
|
emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
|
||||||
|
/* reset descriptor chain */
|
||||||
emac_hal_reset_desc_chain(&emac->hal);
|
emac_hal_reset_desc_chain(&emac->hal);
|
||||||
emac_hal_start(&emac->hal);
|
emac_hal_start(&emac->hal);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -230,12 +230,9 @@ static esp_err_t eth_phy_802_3_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|||||||
phy_802_3_t *phy_802_3 = __containerof(phy, phy_802_3_t, parent);
|
phy_802_3_t *phy_802_3 = __containerof(phy, phy_802_3_t, parent);
|
||||||
esp_eth_mediator_t *eth = phy_802_3->eth;
|
esp_eth_mediator_t *eth = phy_802_3->eth;
|
||||||
|
|
||||||
if (phy_802_3->link_status == ETH_LINK_UP) {
|
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
||||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
phy_802_3->link_status = ETH_LINK_DOWN;
|
||||||
phy_802_3->link_status = ETH_LINK_DOWN;
|
|
||||||
/* Indicate to upper stream apps the link is cosidered down */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)phy_802_3->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
/* Set speed */
|
/* Set speed */
|
||||||
bmcr_reg_t bmcr;
|
bmcr_reg_t bmcr;
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
||||||
@ -253,12 +250,9 @@ static esp_err_t eth_phy_802_3_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duple
|
|||||||
phy_802_3_t *phy_802_3 = __containerof(phy, phy_802_3_t, parent);
|
phy_802_3_t *phy_802_3 = __containerof(phy, phy_802_3_t, parent);
|
||||||
esp_eth_mediator_t *eth = phy_802_3->eth;
|
esp_eth_mediator_t *eth = phy_802_3->eth;
|
||||||
|
|
||||||
if (phy_802_3->link_status == ETH_LINK_UP) {
|
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
||||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
phy_802_3->link_status = ETH_LINK_DOWN;
|
||||||
phy_802_3->link_status = ETH_LINK_DOWN;
|
|
||||||
/* Indicate to upper stream apps the link is cosidered down */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)phy_802_3->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
/* Set duplex mode */
|
/* Set duplex mode */
|
||||||
bmcr_reg_t bmcr;
|
bmcr_reg_t bmcr;
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, phy_802_3->addr, ETH_PHY_BMCR_REG_ADDR, &(bmcr.val)), err, TAG, "read BMCR failed");
|
||||||
|
@ -288,12 +288,9 @@ static esp_err_t phy_ksz8851_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
esp_eth_mediator_t *eth = ksz8851->eth;
|
||||||
|
|
||||||
if (ksz8851->link_status == ETH_LINK_UP) {
|
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
||||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
ksz8851->link_status = ETH_LINK_DOWN;
|
||||||
ksz8851->link_status = ETH_LINK_DOWN;
|
|
||||||
/* Indicate to upper stream apps the link is cosidered down */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)ksz8851->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
/* Set speed */
|
/* Set speed */
|
||||||
uint32_t control;
|
uint32_t control;
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
||||||
@ -315,12 +312,9 @@ static esp_err_t phy_ksz8851_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
|||||||
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
phy_ksz8851snl_t *ksz8851 = __containerof(phy, phy_ksz8851snl_t, parent);
|
||||||
esp_eth_mediator_t *eth = ksz8851->eth;
|
esp_eth_mediator_t *eth = ksz8851->eth;
|
||||||
|
|
||||||
if (ksz8851->link_status == ETH_LINK_UP) {
|
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
||||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
ksz8851->link_status = ETH_LINK_DOWN;
|
||||||
ksz8851->link_status = ETH_LINK_DOWN;
|
|
||||||
/* Indicate to upper stream apps the link is cosidered down */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)ksz8851->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
/* Set duplex mode */
|
/* Set duplex mode */
|
||||||
uint32_t control;
|
uint32_t control;
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, ksz8851->addr, KSZ8851_P1CR, &control), err, TAG, "P1CR read failed");
|
||||||
|
@ -259,12 +259,8 @@ static esp_err_t w5500_set_speed(esp_eth_phy_t *phy, eth_speed_t speed)
|
|||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
esp_eth_mediator_t *eth = w5500->eth;
|
||||||
|
|
||||||
if (w5500->link_status == ETH_LINK_UP) {
|
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
||||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
w5500->link_status = ETH_LINK_DOWN;
|
||||||
w5500->link_status = ETH_LINK_DOWN;
|
|
||||||
/* Indicate to upper stream apps the link is cosidered down */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)w5500->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
phycfg_reg_t phycfg;
|
phycfg_reg_t phycfg;
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, w5500->addr, W5500_REG_PHYCFGR, (uint32_t *) & (phycfg.val)), err, TAG, "read PHYCFG failed");
|
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, w5500->addr, W5500_REG_PHYCFGR, (uint32_t *) & (phycfg.val)), err, TAG, "read PHYCFG failed");
|
||||||
@ -298,12 +294,8 @@ static esp_err_t w5500_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
|||||||
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
phy_w5500_t *w5500 = __containerof(phy, phy_w5500_t, parent);
|
||||||
esp_eth_mediator_t *eth = w5500->eth;
|
esp_eth_mediator_t *eth = w5500->eth;
|
||||||
|
|
||||||
if (w5500->link_status == ETH_LINK_UP) {
|
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
||||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
w5500->link_status = ETH_LINK_DOWN;
|
||||||
w5500->link_status = ETH_LINK_DOWN;
|
|
||||||
/* Indicate to upper stream apps the link is cosidered down */
|
|
||||||
ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)w5500->link_status), err, TAG, "change link failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
phycfg_reg_t phycfg;
|
phycfg_reg_t phycfg;
|
||||||
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, w5500->addr, W5500_REG_PHYCFGR, (uint32_t *) & (phycfg.val)), err, TAG, "read PHYCFG failed");
|
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, w5500->addr, W5500_REG_PHYCFGR, (uint32_t *) & (phycfg.val)), err, TAG, "read PHYCFG failed");
|
||||||
|
@ -23,6 +23,18 @@ typedef struct {
|
|||||||
uint32_t copy_len;
|
uint32_t copy_len;
|
||||||
}__attribute__((packed)) emac_hal_auto_buf_info_t;
|
}__attribute__((packed)) emac_hal_auto_buf_info_t;
|
||||||
|
|
||||||
|
static esp_err_t emac_hal_flush_trans_fifo(emac_hal_context_t *hal)
|
||||||
|
{
|
||||||
|
emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
|
||||||
|
/* no other writes to the Operation Mode register until the flush tx fifo bit is cleared */
|
||||||
|
for (uint32_t i = 0; i < 1000; i++) {
|
||||||
|
if (emac_ll_get_flush_trans_fifo(hal->dma_regs) == 0) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
void emac_hal_iomux_init_mii(void)
|
void emac_hal_iomux_init_mii(void)
|
||||||
{
|
{
|
||||||
/* TX_CLK to GPIO0 */
|
/* TX_CLK to GPIO0 */
|
||||||
@ -288,7 +300,7 @@ void emac_hal_init_dma_default(emac_hal_context_t *hal, emac_hal_dma_config_t *h
|
|||||||
/* Disable Transmit Store Forward */
|
/* Disable Transmit Store Forward */
|
||||||
emac_ll_trans_store_forward_enable(hal->dma_regs, false);
|
emac_ll_trans_store_forward_enable(hal->dma_regs, false);
|
||||||
/* Flush Transmit FIFO */
|
/* Flush Transmit FIFO */
|
||||||
emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
|
emac_hal_flush_trans_fifo(hal);
|
||||||
/* Transmit Threshold Control */
|
/* Transmit Threshold Control */
|
||||||
emac_ll_set_transmit_threshold(hal->dma_regs, EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_64);
|
emac_ll_set_transmit_threshold(hal->dma_regs, EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_64);
|
||||||
/* Disable Forward Error Frame */
|
/* Disable Forward Error Frame */
|
||||||
@ -344,22 +356,21 @@ void emac_hal_start(emac_hal_context_t *hal)
|
|||||||
{
|
{
|
||||||
/* Enable Ethernet MAC and DMA Interrupt */
|
/* Enable Ethernet MAC and DMA Interrupt */
|
||||||
emac_ll_enable_corresponding_intr(hal->dma_regs, EMAC_LL_CONFIG_ENABLE_INTR_MASK);
|
emac_ll_enable_corresponding_intr(hal->dma_regs, EMAC_LL_CONFIG_ENABLE_INTR_MASK);
|
||||||
|
/* Clear all pending interrupts */
|
||||||
/* Flush Transmit FIFO */
|
emac_ll_clear_all_pending_intr(hal->dma_regs);
|
||||||
emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
|
|
||||||
|
|
||||||
/* Start DMA transmission */
|
|
||||||
emac_ll_start_stop_dma_transmit(hal->dma_regs, true);
|
|
||||||
/* Start DMA reception */
|
|
||||||
emac_ll_start_stop_dma_receive(hal->dma_regs, true);
|
|
||||||
|
|
||||||
/* Enable transmit state machine of the MAC for transmission on the MII */
|
/* Enable transmit state machine of the MAC for transmission on the MII */
|
||||||
emac_ll_transmit_enable(hal->mac_regs, true);
|
emac_ll_transmit_enable(hal->mac_regs, true);
|
||||||
|
/* Start DMA transmission */
|
||||||
|
/* Note that the EMAC Databook states the DMA could be started prior enabling
|
||||||
|
the MAC transmitter. However, it turned out that such order may cause the MAC
|
||||||
|
transmitter hangs */
|
||||||
|
emac_ll_start_stop_dma_transmit(hal->dma_regs, true);
|
||||||
|
|
||||||
|
/* Start DMA reception */
|
||||||
|
emac_ll_start_stop_dma_receive(hal->dma_regs, true);
|
||||||
/* Enable receive state machine of the MAC for reception from the MII */
|
/* Enable receive state machine of the MAC for reception from the MII */
|
||||||
emac_ll_receive_enable(hal->mac_regs, true);
|
emac_ll_receive_enable(hal->mac_regs, true);
|
||||||
|
|
||||||
/* Clear all pending interrupts */
|
|
||||||
emac_ll_clear_all_pending_intr(hal->dma_regs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t emac_hal_stop(emac_hal_context_t *hal)
|
esp_err_t emac_hal_stop(emac_hal_context_t *hal)
|
||||||
@ -385,6 +396,9 @@ esp_err_t emac_hal_stop(emac_hal_context_t *hal)
|
|||||||
/* Stop DMA reception */
|
/* Stop DMA reception */
|
||||||
emac_ll_start_stop_dma_receive(hal->dma_regs, false);
|
emac_ll_start_stop_dma_receive(hal->dma_regs, false);
|
||||||
|
|
||||||
|
/* Flush Transmit FIFO */
|
||||||
|
emac_hal_flush_trans_fifo(hal);
|
||||||
|
|
||||||
/* Disable Ethernet MAC and DMA Interrupt */
|
/* Disable Ethernet MAC and DMA Interrupt */
|
||||||
emac_ll_disable_all_intr(hal->dma_regs);
|
emac_ll_disable_all_intr(hal->dma_regs);
|
||||||
|
|
||||||
|
@ -417,6 +417,11 @@ static inline void emac_ll_flush_trans_fifo_enable(emac_dma_dev_t *dma_regs, boo
|
|||||||
dma_regs->dmaoperation_mode.flush_tx_fifo = enable;
|
dma_regs->dmaoperation_mode.flush_tx_fifo = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool emac_ll_get_flush_trans_fifo(emac_dma_dev_t *dma_regs)
|
||||||
|
{
|
||||||
|
return dma_regs->dmaoperation_mode.flush_tx_fifo;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void emac_ll_set_transmit_threshold(emac_dma_dev_t *dma_regs, uint32_t threshold)
|
static inline void emac_ll_set_transmit_threshold(emac_dma_dev_t *dma_regs, uint32_t threshold)
|
||||||
{
|
{
|
||||||
dma_regs->dmaoperation_mode.tx_thresh_ctrl = threshold;
|
dma_regs->dmaoperation_mode.tx_thresh_ctrl = threshold;
|
||||||
|
@ -224,12 +224,8 @@ esp_err_t enc28j60_set_duplex(esp_eth_phy_t *phy, eth_duplex_t duplex)
|
|||||||
esp_eth_mediator_t *eth = enc28j60->eth;
|
esp_eth_mediator_t *eth = enc28j60->eth;
|
||||||
phcon1_reg_t phcon1;
|
phcon1_reg_t phcon1;
|
||||||
|
|
||||||
if (enc28j60->link_status == ETH_LINK_UP) {
|
/* Since the link is going to be reconfigured, consider it down to be status updated once the driver re-started */
|
||||||
/* Since the link is going to be reconfigured, consider it down for a while */
|
enc28j60->link_status = ETH_LINK_DOWN;
|
||||||
enc28j60->link_status = ETH_LINK_DOWN;
|
|
||||||
/* Indicate to upper stream apps the link is cosidered down */
|
|
||||||
PHY_CHECK(eth->on_state_changed(eth, ETH_STATE_LINK, (void *)enc28j60->link_status), "change link failed", err);
|
|
||||||
}
|
|
||||||
|
|
||||||
PHY_CHECK(eth->phy_reg_read(eth, enc28j60->addr, 0, &phcon1.val) == ESP_OK,
|
PHY_CHECK(eth->phy_reg_read(eth, enc28j60->addr, 0, &phcon1.val) == ESP_OK,
|
||||||
"read PHCON1 failed", err);
|
"read PHCON1 failed", err);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user