From b6d7675e60626bc890ea68c80084906afaccb5f4 Mon Sep 17 00:00:00 2001 From: morris Date: Mon, 15 Oct 2018 20:35:05 +0800 Subject: [PATCH] ethernet: fix some bugs in phy&mac driver 1. Original register mapping for LAN8720 has some registers that doesn't exist/support. So just remove them, and fix the power and init function for LAN8720. 2. GPIO16 and GPIO17 is occupied by PSRAM, so only ETH_CLOCK_GPIO_IN mode is supported in that case if using PSRAM. 3. Fix bug of OTA failing with Ethernet 4. Fix bug of multicast with Ethernet Closes https://github.com/espressif/esp-idf/issues/2564 Closes https://github.com/espressif/esp-idf/issues/2620 Closes https://github.com/espressif/esp-idf/issues/2657 --- components/esp32/include/esp_spiram.h | 12 +- components/esp32/spiram.c | 23 +- components/ethernet/emac_dev.c | 4 +- components/ethernet/emac_main.c | 250 ++++++++---------- components/ethernet/eth_phy/phy_lan8720.c | 27 +- components/ethernet/include/esp_eth.h | 34 ++- components/ethernet/include/eth_phy/phy_reg.h | 42 ++- 7 files changed, 197 insertions(+), 195 deletions(-) diff --git a/components/esp32/include/esp_spiram.h b/components/esp32/include/esp_spiram.h index c12da6802..ab76f3b56 100644 --- a/components/esp32/include/esp_spiram.h +++ b/components/esp32/include/esp_spiram.h @@ -56,7 +56,7 @@ void esp_spiram_init_cache(); /** * @brief Memory test for SPI RAM. Should be called after SPI RAM is initialized and - * (in case of a dual-core system) the app CPU is online. This test overwrites the + * (in case of a dual-core system) the app CPU is online. This test overwrites the * memory with crap, so do not call after e.g. the heap allocator has stored important * stuff in SPI RAM. * @@ -102,4 +102,14 @@ void esp_spiram_writeback_cache(); esp_err_t esp_spiram_reserve_dma_pool(size_t size); +/** + * @brief If SPI RAM(PSRAM) has been initialized + * + * @return + * - true SPI RAM has been initialized successfully + * - false SPI RAM hasn't been initialized or initialized failed + */ +bool esp_spiram_is_initialized(void); + + #endif diff --git a/components/esp32/spiram.c b/components/esp32/spiram.c index 58360aa0e..ecd95dcdb 100644 --- a/components/esp32/spiram.c +++ b/components/esp32/spiram.c @@ -1,5 +1,5 @@ /* -Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_psram functions, but if +Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_psram functions, but if we add more types of external RAM memory, this can be made into a more intelligent dispatcher. */ @@ -159,7 +159,7 @@ esp_err_t esp_spiram_init() } #endif - ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device", + ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device", (esp_spiram_get_size()*8)/(1024*1024)); ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_F40M_S40M ? "flash 40m sram 40m" : \ PSRAM_SPEED == PSRAM_CACHE_F80M_S40M ? "flash 80m sram 40m" : \ @@ -225,7 +225,7 @@ size_t esp_spiram_get_size() Note that this routine assumes some unique mapping for the first 2 banks of the PSRAM memory range, as well as the 2 banks after the 2 MiB mark. */ -void IRAM_ATTR esp_spiram_writeback_cache() +void IRAM_ATTR esp_spiram_writeback_cache() { int x; volatile int i=0; @@ -234,7 +234,7 @@ void IRAM_ATTR esp_spiram_writeback_cache() if (!spiram_inited) return; - //We need cache enabled for this to work. Re-enable it if needed; make sure we + //We need cache enabled for this to work. Re-enable it if needed; make sure we //disable it again on exit as well. if (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) { cache_was_disabled|=(1<<0); @@ -257,9 +257,9 @@ void IRAM_ATTR esp_spiram_writeback_cache() } #else /* - Low/high psram cache mode uses one 32K cache for the lowest 2MiB of SPI flash and another 32K for the highest + Low/high psram cache mode uses one 32K cache for the lowest 2MiB of SPI flash and another 32K for the highest 2MiB. Clear this by reading from both regions. - Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If + Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If we ever support external RAM chips of 2M or smaller, this may need adjusting. */ for (x=0; x<1024*64; x+=32) { @@ -280,4 +280,15 @@ void IRAM_ATTR esp_spiram_writeback_cache() #endif } +/** + * @brief If SPI RAM(PSRAM) has been initialized + * + * @return true SPI RAM has been initialized successfully + * @return false SPI RAM hasn't been initialized or initialized failed + */ +bool esp_spiram_is_initialized() +{ + return spiram_inited; +} + #endif diff --git a/components/ethernet/emac_dev.c b/components/ethernet/emac_dev.c index d07386b2b..e0269a489 100644 --- a/components/ethernet/emac_dev.c +++ b/components/ethernet/emac_dev.c @@ -14,8 +14,7 @@ #include #include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" + #include "rom/ets_sys.h" #include "rom/gpio.h" @@ -98,4 +97,5 @@ void emac_mac_init(void) REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX); REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACMII); REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED); + REG_SET_BIT(EMAC_GMACFF_REG, EMAC_PAM); } diff --git a/components/ethernet/emac_main.c b/components/ethernet/emac_main.c index 5a00a1fd9..a22827c5c 100644 --- a/components/ethernet/emac_main.c +++ b/components/ethernet/emac_main.c @@ -39,6 +39,7 @@ #include "esp_eth.h" #include "esp_intr_alloc.h" #include "esp_pm.h" +#include "esp_spiram.h" #include "driver/periph_ctrl.h" @@ -59,8 +60,8 @@ static struct emac_config_data emac_config; -static dma_extended_desc_t *emac_dma_rx_chain_buf[DMA_RX_BUF_NUM]; -static dma_extended_desc_t *emac_dma_tx_chain_buf[DMA_TX_BUF_NUM]; +static dma_extended_desc_t *emac_dma_rx_chain_buf; +static dma_extended_desc_t *emac_dma_tx_chain_buf; static uint8_t *emac_dma_rx_buf[DMA_RX_BUF_NUM]; static uint8_t *emac_dma_tx_buf[DMA_TX_BUF_NUM]; @@ -93,7 +94,7 @@ void esp_eth_get_mac(uint8_t mac[6]) esp_err_t esp_eth_set_mac(const uint8_t mac[6]) { - if ((mac[0] & 0x01) == 0) { + if (!(mac[0] & 0x01)) { memcpy(&(emac_config.macaddr[0]), mac, 6); return ESP_OK; } else { @@ -106,22 +107,20 @@ eth_speed_mode_t esp_eth_get_speed(void) return emac_config.emac_phy_get_speed_mode(); } -static void emac_setup_tx_desc(struct dma_extended_desc *tx_desc, uint32_t size) +static void emac_setup_tx_desc(dma_extended_desc_t *tx_desc, uint32_t size) { tx_desc->basic.desc1 = size & 0xfff; - tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | - EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | - EMAC_DESC_SECOND_ADDR_CHAIN; + tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | + EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN; } -static void emac_clean_tx_desc(struct dma_extended_desc *tx_desc) +static void emac_clean_tx_desc(dma_extended_desc_t *tx_desc) { tx_desc->basic.desc1 = 0; tx_desc->basic.desc0 = 0; } -static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc, - uint32_t buf_ptr) +static void emac_clean_rx_desc(dma_extended_desc_t *rx_desc, uint32_t buf_ptr) { if (buf_ptr != 0) { rx_desc->basic.desc2 = buf_ptr; @@ -184,46 +183,46 @@ static void emac_reset_dma_chain(void) static void emac_init_dma_chain(void) { int i; + uint32_t dma_phy; dma_extended_desc_t *p = NULL; //init tx chain - emac_config.dma_etx = emac_dma_tx_chain_buf[0]; + emac_config.dma_etx = emac_dma_tx_chain_buf; emac_config.cnt_tx = 0; emac_config.cur_tx = 0; emac_config.dirty_tx = 0; - p = emac_dma_tx_chain_buf[0]; + dma_phy = (uint32_t)(emac_config.dma_etx); + p = emac_config.dma_etx; + for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++) { + dma_phy += sizeof(dma_extended_desc_t); emac_clean_tx_desc(p); - /* point to the buffer */ p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]); - /* point to next descriptor */ - p->basic.desc3 = (uint32_t)(emac_dma_tx_chain_buf[i + 1]); - p = emac_dma_tx_chain_buf[i + 1]; + p->basic.desc3 = dma_phy; + p++; } emac_clean_tx_desc(p); - /* point to the buffer */ p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]); - /* point to first descriptor */ p->basic.desc3 = (uint32_t)(emac_config.dma_etx); //init rx chain - emac_config.dma_erx = emac_dma_rx_chain_buf[0]; + emac_config.dma_erx = emac_dma_rx_chain_buf; emac_config.cnt_rx = 0; emac_config.cur_rx = 0; emac_config.dirty_rx = 0; - p = emac_dma_rx_chain_buf[0]; + dma_phy = (uint32_t)(emac_config.dma_erx); + p = emac_config.dma_erx; + for (i = 0; i < (DMA_RX_BUF_NUM - 1); i++) { + dma_phy += sizeof(dma_extended_desc_t); emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i])); - /* point to the buffer */ - p->basic.desc3 = (uint32_t)(emac_dma_rx_chain_buf[i + 1]); - /* point to next descriptor */ - p = emac_dma_rx_chain_buf[i + 1]; + p->basic.desc3 = dma_phy; + p++; } - /* point to the buffer */ + emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i])); - /* point to first descriptor */ p->basic.desc3 = (uint32_t)(emac_config.dma_erx); } @@ -235,8 +234,7 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value) } REG_WRITE(EMAC_MIIDATA_REG, value); - REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | - ((phy_num & 0x1f) << 11) | ((0x3) << 2)); + REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | ((0x3) << 2)); while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) { } @@ -250,8 +248,7 @@ uint16_t esp_eth_smi_read(uint32_t reg_num) while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) { } - REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | - ((phy_num & 0x1f) << 11) | (0x3 << 2)); + REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | (0x3 << 2)); while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) { } value = (REG_READ(EMAC_MIIDATA_REG) & 0xffff); @@ -259,12 +256,10 @@ uint16_t esp_eth_smi_read(uint32_t reg_num) return value; } -esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, - uint16_t value_mask, int timeout_ms) +esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms) { unsigned start = xTaskGetTickCount(); - unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / - portTICK_PERIOD_MS; + unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS; uint16_t current_value = 0; while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) { @@ -327,8 +322,7 @@ static void emac_set_user_config_data(eth_config_t *config) } emac_config.emac_flow_ctrl_enable = false; #endif - emac_config.emac_phy_get_partner_pause_enable = - config->phy_get_partner_pause_enable; + emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable; emac_config.emac_phy_power_enable = config->phy_power_enable; } @@ -396,8 +390,7 @@ static esp_err_t emac_verify_args(void) ret = ESP_FAIL; } - if (emac_config.emac_flow_ctrl_enable == true && - emac_config.emac_phy_get_partner_pause_enable == NULL) { + if (emac_config.emac_flow_ctrl_enable && !emac_config.emac_phy_get_partner_pause_enable) { ESP_LOGE(TAG, "phy get partner pause enable func is null"); ret = ESP_FAIL; } @@ -420,8 +413,8 @@ static void emac_process_tx(void) xSemaphoreTakeRecursive(emac_tx_xMutex, portMAX_DELAY); - while ((uint32_t)(emac_dma_tx_chain_buf[emac_config.dirty_tx]) != cur_tx_desc) { - emac_clean_tx_desc(emac_dma_tx_chain_buf[emac_config.dirty_tx]); + while (((uint32_t) & (emac_config.dma_etx[emac_config.dirty_tx])) != cur_tx_desc) { + emac_clean_tx_desc(&(emac_config.dma_etx[emac_config.dirty_tx])); emac_config.dirty_tx = (emac_config.dirty_tx + 1) % DMA_TX_BUF_NUM; emac_config.cnt_tx--; @@ -438,20 +431,19 @@ void esp_eth_free_rx_buf(void *buf) { xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY); - emac_clean_rx_desc(emac_dma_rx_chain_buf[emac_config.cur_rx], (uint32_t)buf); + emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.cur_rx]), (uint32_t)buf); emac_config.cur_rx = (emac_config.cur_rx + 1) % DMA_RX_BUF_NUM; emac_config.cnt_rx--; if (emac_config.cnt_rx < 0) { - ESP_LOGE(TAG, "emac rx buf err!!\n"); + ESP_LOGE(TAG, "emac rx buf err"); } emac_poll_rx_cmd(); xSemaphoreGiveRecursive(emac_rx_xMutex); - if (emac_config.emac_flow_ctrl_partner_support == true) { + if (emac_config.emac_flow_ctrl_partner_support) { portENTER_CRITICAL(&g_emac_mux); - if (pause_send == true && emac_config.cnt_rx < - FLOW_CONTROL_LOW_WATERMARK) { + if (pause_send && emac_config.cnt_rx < FLOW_CONTROL_LOW_WATERMARK) { emac_send_pause_zero_frame_enable(); pause_send = false; } @@ -463,11 +455,11 @@ static uint32_t IRAM_ATTR emac_get_rxbuf_count_in_intr(void) { uint32_t cnt = 0; uint32_t cur_rx_desc = emac_read_rx_cur_reg(); - struct dma_extended_desc *cur_desc = (dma_extended_desc_t *)cur_rx_desc; + dma_extended_desc_t *cur_desc = (dma_extended_desc_t *)cur_rx_desc; while (cur_desc->basic.desc0 == EMAC_DESC_RX_OWN && cnt < DMA_RX_BUF_NUM) { cnt++; - cur_desc = (struct dma_extended_desc *)cur_desc->basic.desc3; + cur_desc = (dma_extended_desc_t *)cur_desc->basic.desc3; } return cnt; } @@ -480,19 +472,15 @@ static void emac_process_rx(void) } uint32_t cur_rx_desc = emac_read_rx_cur_reg(); - while (((uint32_t)(emac_dma_rx_chain_buf[emac_config.dirty_rx]) != cur_rx_desc)) { + while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx])) != cur_rx_desc) { //copy data to lwip - emac_config.emac_tcpip_input((emac_dma_rx_buf[emac_config.dirty_rx]), - (((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0) >> - EMAC_DESC_FRAME_LENGTH_S) & - EMAC_DESC_FRAME_LENGTH), - NULL); + emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2), + (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & + EMAC_DESC_FRAME_LENGTH), NULL); - emac_clean_rx_desc(emac_dma_rx_chain_buf[emac_config.dirty_rx], - (uint32_t)(emac_dma_rx_buf[emac_config.dirty_rx])); + emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]), (emac_config.dma_erx[emac_config.dirty_rx].basic.desc2)); emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM; - //if open this ,one intr can do many intrs ? cur_rx_desc = emac_read_rx_cur_reg(); } @@ -507,21 +495,16 @@ static void emac_process_rx_unavail(void) uint32_t dirty_cnt = 0; while (dirty_cnt < DMA_RX_BUF_NUM) { - - if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) { + if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) { break; } - dirty_cnt++; //copy data to lwip - emac_config.emac_tcpip_input((emac_dma_rx_buf[emac_config.dirty_rx]), - (((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0) >> - EMAC_DESC_FRAME_LENGTH_S) & - EMAC_DESC_FRAME_LENGTH), - NULL); + emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2), + (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & + EMAC_DESC_FRAME_LENGTH), NULL); - emac_clean_rx_desc(emac_dma_rx_chain_buf[emac_config.dirty_rx], - (uint32_t)(emac_dma_rx_buf[emac_config.dirty_rx])); + emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]), (emac_config.dma_erx[emac_config.dirty_rx].basic.desc2)); emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM; } emac_enable_rx_intr(); @@ -539,24 +522,20 @@ static void emac_process_rx_unavail(void) xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY); while (emac_config.cnt_rx < DMA_RX_BUF_NUM) { - - if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) { + if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) { break; } - emac_config.cnt_rx++; if (emac_config.cnt_rx > DMA_RX_BUF_NUM) { - ESP_LOGE(TAG, "emac rx unavail buf err !!\n"); + ESP_LOGE(TAG, "emac rx buf full"); } uint32_t tmp_dirty = emac_config.dirty_rx; emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM; //copy data to lwip - emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]), - (((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >> - EMAC_DESC_FRAME_LENGTH_S) & - EMAC_DESC_FRAME_LENGTH), - NULL); + emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2), + (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & + EMAC_DESC_FRAME_LENGTH), NULL); } emac_enable_rx_intr(); emac_enable_rx_unavail_intr(); @@ -573,51 +552,41 @@ static void emac_process_rx(void) xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY); - if (((uint32_t)(emac_dma_rx_chain_buf[emac_config.dirty_rx])) != - cur_rx_desc) { - - while (((uint32_t)(emac_dma_rx_chain_buf[emac_config.dirty_rx]) != cur_rx_desc) && + if ((((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx])) != cur_rx_desc)) { + while ((((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx])) != cur_rx_desc) && emac_config.cnt_rx < DMA_RX_BUF_NUM) { emac_config.cnt_rx++; if (emac_config.cnt_rx > DMA_RX_BUF_NUM) { - ESP_LOGE(TAG, "emac rx buf err!!\n"); + ESP_LOGE(TAG, "emac rx buf full"); } uint32_t tmp_dirty = emac_config.dirty_rx; emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM; //copy data to lwip - emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]), - (((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >> - EMAC_DESC_FRAME_LENGTH_S) & - EMAC_DESC_FRAME_LENGTH), - NULL); + emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2), + (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & + EMAC_DESC_FRAME_LENGTH), NULL); cur_rx_desc = emac_read_rx_cur_reg(); } } else { if (emac_config.cnt_rx < DMA_RX_BUF_NUM) { - if ((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 & - EMAC_DESC_RX_OWN) == 0) { + if (!(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN)) { while (emac_config.cnt_rx < DMA_RX_BUF_NUM) { - - if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) { + if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) { break; } - emac_config.cnt_rx++; if (emac_config.cnt_rx > DMA_RX_BUF_NUM) { - ESP_LOGE(TAG, "emac rx buf err!!!\n"); + ESP_LOGE(TAG, "emac rx buf full"); } uint32_t tmp_dirty = emac_config.dirty_rx; - emac_config.dirty_rx = (emac_config.dirty_rx + 1) % - DMA_RX_BUF_NUM; + emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM; //copy data to lwip - emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]), - (((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >> - EMAC_DESC_FRAME_LENGTH_S) & - EMAC_DESC_FRAME_LENGTH), - NULL); + emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2), + (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & + EMAC_DESC_FRAME_LENGTH), NULL); } } } @@ -638,9 +607,8 @@ static void IRAM_ATTR emac_process_intr(void *arg) if (event & EMAC_RECV_INT) { emac_disable_rx_intr(); - if (emac_config.emac_flow_ctrl_partner_support == true) { - if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && - pause_send == false) { + if (emac_config.emac_flow_ctrl_partner_support) { + if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && !pause_send) { pause_send = true; emac_send_pause_frame_enable(); } @@ -661,9 +629,8 @@ static void IRAM_ATTR emac_process_intr(void *arg) static void emac_set_macaddr_reg(void) { REG_SET_FIELD(EMAC_ADDR0HIGH_REG, EMAC_ADDRESS0_HI, (emac_config.macaddr[5] << 8) | (emac_config.macaddr[4])); - REG_WRITE(EMAC_ADDR0LOW_REG, (emac_config.macaddr[3] << 24) | - (emac_config.macaddr[2] << 16) | (emac_config.macaddr[1] << 8) | - (emac_config.macaddr[0])); + REG_WRITE(EMAC_ADDR0LOW_REG, (emac_config.macaddr[3] << 24) | (emac_config.macaddr[2] << 16) | + (emac_config.macaddr[1] << 8) | (emac_config.macaddr[0])); } static void emac_check_phy_init(void) @@ -683,8 +650,8 @@ static void emac_check_phy_init(void) emac_disable_flowctrl(); emac_config.emac_flow_ctrl_partner_support = false; #else - if (emac_config.emac_flow_ctrl_enable == true) { - if (emac_config.emac_phy_get_partner_pause_enable() == true && + if (emac_config.emac_flow_ctrl_enable) { + if (emac_config.emac_phy_get_partner_pause_enable() && emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) { emac_enable_flowctrl(); emac_config.emac_flow_ctrl_partner_support = true; @@ -706,7 +673,7 @@ static void emac_process_link_updown(bool link_status) emac_config.phy_link_up = link_status; - if (link_status == true) { + if (link_status) { emac_check_phy_init(); ESP_LOGD(TAG, "eth link_up"); emac_enable_dma_tx(); @@ -741,8 +708,7 @@ esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size) esp_err_t ret = ESP_OK; if (emac_config.emac_status != EMAC_RUNTIME_START) { - ESP_LOGE(TAG, "tx netif is not ready, emac_status=%d", - emac_config.emac_status); + ESP_LOGE(TAG, "tx netif is not ready, emac_status=%d", emac_config.emac_status); ret = ESP_ERR_INVALID_STATE; return ret; } @@ -754,9 +720,9 @@ esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size) goto _exit; } - memcpy(emac_dma_tx_buf[emac_config.cur_tx], buf, size); + memcpy((void *)(emac_config.dma_etx[emac_config.cur_tx].basic.desc2), buf, size); - emac_setup_tx_desc(emac_dma_tx_chain_buf[emac_config.cur_tx], size); + emac_setup_tx_desc(&(emac_config.dma_etx[emac_config.cur_tx]), size); emac_config.cnt_tx++; emac_config.cur_tx = (emac_config.cur_tx + 1) % DMA_TX_BUF_NUM; @@ -771,7 +737,7 @@ _exit: static void emac_init_default_data(void) { - memset((uint8_t *)&emac_config, 0, sizeof(struct emac_config_data)); + memset((void *)&emac_config, 0, sizeof(struct emac_config_data)); } void emac_process_link_check(void) @@ -799,8 +765,7 @@ void emac_link_check_func(void *pv_parameters) static bool emac_link_check_timer_init(void) { emac_timer = xTimerCreate("emac_timer", - (CONFIG_EMAC_CHECK_LINK_PERIOD_MS / - portTICK_PERIOD_MS), + (CONFIG_EMAC_CHECK_LINK_PERIOD_MS / portTICK_PERIOD_MS), pdTRUE, NULL, emac_link_check_func); @@ -858,8 +823,6 @@ static void emac_start(void *param) emac_mac_init(); - //ptp TODO - emac_enable_intr(); emac_config.emac_status = EMAC_RUNTIME_START; @@ -869,8 +832,8 @@ static void emac_start(void *param) esp_event_send(&evt); //set a timer to check link up status - if (emac_link_check_timer_init() == true) { - if (emac_link_check_timer_start() != true) { + if (emac_link_check_timer_init()) { + if (!emac_link_check_timer_start()) { cmd->err = EMAC_CMD_FAIL; emac_link_check_timer_delete(); } @@ -913,7 +876,7 @@ esp_err_t esp_eth_enable(void) } if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) { - if (emac_ioctl(SIG_EMAC_START, (emac_par_t)(&post_cmd)) != 0) { + if (emac_ioctl(SIG_EMAC_START, (emac_par_t)(&post_cmd))) { open_cmd.err = EMAC_CMD_FAIL; goto cleanup; } @@ -1103,16 +1066,16 @@ esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par) esp_err_t esp_eth_init(eth_config_t *config) { + int i = 0; /* dynamically alloc memory for ethernet dma */ - for (int i = 0; i < DMA_RX_BUF_NUM; i++) { - emac_dma_rx_chain_buf[i] = (struct dma_extended_desc *)heap_caps_malloc(sizeof(struct dma_extended_desc), MALLOC_CAP_DMA); + emac_dma_rx_chain_buf = (dma_extended_desc_t *)heap_caps_malloc(sizeof(dma_extended_desc_t) * DMA_RX_BUF_NUM, MALLOC_CAP_DMA); + emac_dma_tx_chain_buf = (dma_extended_desc_t *)heap_caps_malloc(sizeof(dma_extended_desc_t) * DMA_TX_BUF_NUM, MALLOC_CAP_DMA); + for (i = 0; i < DMA_RX_BUF_NUM; i++) { emac_dma_rx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_RX_BUF_SIZE, MALLOC_CAP_DMA); } - for (int i = 0; i < DMA_TX_BUF_NUM; i++) { - emac_dma_tx_chain_buf[i] = (struct dma_extended_desc *)heap_caps_malloc(sizeof(struct dma_extended_desc), MALLOC_CAP_DMA); + for (i = 0; i < DMA_TX_BUF_NUM; i++) { emac_dma_tx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_TX_BUF_SIZE, MALLOC_CAP_DMA); } - esp_event_set_default_eth_handlers(); return esp_eth_init_internal(config); } @@ -1126,7 +1089,7 @@ esp_err_t esp_eth_init_internal(eth_config_t *config) emac_init_default_data(); - if (config != NULL) { + if (config) { emac_set_user_config_data(config); } @@ -1142,6 +1105,15 @@ esp_err_t esp_eth_init_internal(eth_config_t *config) periph_module_enable(PERIPH_EMAC_MODULE); if (emac_config.clock_mode != ETH_CLOCK_GPIO0_IN) { +#if CONFIG_SPIRAM_SUPPORT + if (esp_spiram_is_initialized()) { + ESP_LOGE(TAG, "GPIO16 and GPIO17 has been occupied by PSRAM, Only ETH_CLOCK_GPIO_IN is supported!"); + ret = ESP_FAIL; + goto _exit; + } else { + ESP_LOGW(TAG, "GPIO16/17 is used for clock of EMAC, Please Make Sure you're not using PSRAM."); + } +#endif // 50 MHz = 40MHz * (6 + 4) / (2 * (2 + 2) = 400MHz / 8 rtc_clk_apll_enable(1, 0, 0, 6, 2); REG_SET_FIELD(EMAC_EX_CLKOUT_CONF_REG, EMAC_EX_CLK_OUT_H_DIV_NUM, 0); @@ -1151,15 +1123,13 @@ esp_err_t esp_eth_init_internal(eth_config_t *config) PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT); ESP_LOGD(TAG, "EMAC 50MHz clock output on GPIO16"); } else if (emac_config.clock_mode == ETH_CLOCK_GPIO17_OUT) { - PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, - FUNC_GPIO17_EMAC_CLK_OUT_180); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180); ESP_LOGD(TAG, "EMAC 50MHz inverted clock output on GPIO17"); } } emac_enable_clk(true); - REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, - EMAC_EX_PHY_INTF_RMII); + REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, EMAC_EX_PHY_INTF_RMII); emac_dma_init(); if (emac_config.clock_mode == ETH_CLOCK_GPIO0_IN) { @@ -1191,8 +1161,12 @@ esp_err_t esp_eth_init_internal(eth_config_t *config) emac_rx_xMutex = xSemaphoreCreateRecursiveMutex(); emac_tx_xMutex = xSemaphoreCreateRecursiveMutex(); emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t)); - xTaskCreate(emac_task, "emacT", EMAC_TASK_STACK_SIZE, NULL, - EMAC_TASK_PRIORITY, &emac_task_hdl); + xTaskCreate(emac_task, + "emacT", + EMAC_TASK_STACK_SIZE, + NULL, + EMAC_TASK_PRIORITY, + &emac_task_hdl); esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL); @@ -1205,6 +1179,7 @@ _exit: esp_err_t esp_eth_deinit(void) { esp_err_t ret = ESP_FAIL; + int i = 0; if (!emac_task_hdl) { ret = ESP_ERR_INVALID_STATE; @@ -1224,20 +1199,19 @@ esp_err_t esp_eth_deinit(void) emac_config.emac_status = EMAC_RUNTIME_NOT_INIT; /* free memory that dynamically allocted */ - for (int i = 0; i < DMA_RX_BUF_NUM; i++) { - free(emac_dma_rx_chain_buf[i]); + free(emac_dma_rx_chain_buf); + free(emac_dma_tx_chain_buf); + emac_dma_rx_chain_buf = NULL; + emac_dma_tx_chain_buf = NULL; + for (i = 0; i < DMA_RX_BUF_NUM; i++) { free(emac_dma_rx_buf[i]); - emac_dma_rx_chain_buf[i] = NULL; emac_dma_rx_buf[i] = NULL; } - for (int i = 0; i < DMA_TX_BUF_NUM; i++) { - free(emac_dma_tx_chain_buf[i]); + for (i = 0; i < DMA_TX_BUF_NUM; i++) { free(emac_dma_tx_buf[i]); - emac_dma_tx_chain_buf[i] = NULL; emac_dma_tx_buf[i] = NULL; } ret = ESP_OK; - _exit: return ret; } diff --git a/components/ethernet/eth_phy/phy_lan8720.c b/components/ethernet/eth_phy/phy_lan8720.c index 7b9958e65..e3ecfb1c6 100644 --- a/components/ethernet/eth_phy/phy_lan8720.c +++ b/components/ethernet/eth_phy/phy_lan8720.c @@ -26,26 +26,16 @@ #define LAN8720_PHY_ID2_MASK 0xFFF0 /* LAN8720-specific registers */ -#define SW_STRAP_CONTROL_REG (0x9) -#define SW_STRAP_CONFIG_DONE BIT(15) -#define AUTO_MDIX_ENABLE BIT(14) -#define AUTO_NEGOTIATION_ENABLE BIT(13) -#define AN_1 BIT(12) -#define AN_0 BIT(11) -#define LED_CFG BIT(10) -#define RMII_ENHANCED_MODE BIT(9) -#define DEFAULT_STRAP_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG) - -#define PHY_SPECIAL_CONTROL_STATUS_REG (0x1f) +#define PHY_SPECIAL_CONTROL_STATUS_REG (0x1f) #define AUTO_NEGOTIATION_DONE BIT(12) +#define DUPLEX_INDICATION_FULL BIT(4) +#define SPEED_INDICATION_100T BIT(3) +#define SPEED_INDICATION_10T BIT(2) #define SPEED_DUPLEX_INDICATION_10T_HALF 0x04 #define SPEED_DUPLEX_INDICATION_10T_FULL 0x14 #define SPEED_DUPLEX_INDICATION_100T_HALF 0x08 #define SPEED_DUPLEX_INDICATION_100T_FULL 0x18 -#define SPEED_INDICATION_100T BIT(3) -#define SPEED_INDICATION_10T BIT(2) -#define DUPLEX_INDICATION_FULL BIT(4) static const char *TAG = "lan8720"; @@ -82,7 +72,9 @@ eth_duplex_mode_t phy_lan8720_get_duplex_mode(void) void phy_lan8720_power_enable(bool enable) { if (enable) { - esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); + uint32_t data = esp_eth_smi_read(MII_BASIC_MODE_CONTROL_REG); + data |= MII_AUTO_NEGOTIATION_ENABLE | MII_RESTART_AUTO_NEGOTIATION; + esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, data); // TODO: only enable if config.flow_ctrl_enable == true phy_mii_enable_flow_ctrl(); } @@ -100,8 +92,9 @@ esp_err_t phy_lan8720_init(void) res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, LAN8720_PHY_ID1, UINT16_MAX, 1000); res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, LAN8720_PHY_ID2, LAN8720_PHY_ID2_MASK, 1000); - esp_eth_smi_write(SW_STRAP_CONTROL_REG, - DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); + uint32_t data = esp_eth_smi_read(MII_BASIC_MODE_CONTROL_REG); + data |= MII_AUTO_NEGOTIATION_ENABLE | MII_RESTART_AUTO_NEGOTIATION; + esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, data); ets_delay_us(300); diff --git a/components/ethernet/include/esp_eth.h b/components/ethernet/include/esp_eth.h index 94330594d..beb990491 100644 --- a/components/ethernet/include/esp_eth.h +++ b/components/ethernet/include/esp_eth.h @@ -28,10 +28,10 @@ typedef enum { ETH_MODE_MII, } eth_mode_t; -typedef enum { +typedef enum { ETH_CLOCK_GPIO0_IN = 0, ETH_CLOCK_GPIO16_OUT = 2, - ETH_CLOCK_GPIO17_OUT = 3, + ETH_CLOCK_GPIO17_OUT = 3 } eth_clock_mode_t; typedef enum { @@ -94,24 +94,22 @@ typedef void (*eth_phy_power_enable_func)(bool enable); * */ typedef struct { - eth_phy_base_t phy_addr; /*!< phy base addr (0~31) */ - eth_mode_t mac_mode; /*!< mac mode only support RMII now */ - eth_clock_mode_t clock_mode; /*!< external/internal clock mode selecton */ - eth_tcpip_input_func tcpip_input; /*!< tcpip input func */ - eth_phy_func phy_init; /*!< phy init func */ - eth_phy_check_link_func phy_check_link; /*!< phy check link func */ - eth_phy_check_init_func phy_check_init; /*!< phy check init func */ - eth_phy_get_speed_mode_func phy_get_speed_mode; /*!< phy check init func */ - eth_phy_get_duplex_mode_func phy_get_duplex_mode; /*!< phy check init func */ - eth_gpio_config_func gpio_config; /*!< gpio config func */ - bool flow_ctrl_enable; /*!< flag of flow ctrl enable */ - eth_phy_get_partner_pause_enable_func phy_get_partner_pause_enable; /*!< get partner pause enable */ - eth_phy_power_enable_func phy_power_enable; /*!< enable or disable phy power */ - uint32_t reset_timeout_ms; /*!< timeout value for reset emac */ - + eth_phy_base_t phy_addr; /*!< phy base addr (0~31) */ + eth_mode_t mac_mode; /*!< mac mode only support RMII now */ + eth_clock_mode_t clock_mode; /*!< external/internal clock mode selecton */ + eth_tcpip_input_func tcpip_input; /*!< tcpip input func */ + eth_phy_func phy_init; /*!< phy init func */ + eth_phy_check_link_func phy_check_link; /*!< phy check link func */ + eth_phy_check_init_func phy_check_init; /*!< phy check init func */ + eth_phy_get_speed_mode_func phy_get_speed_mode; /*!< phy check init func */ + eth_phy_get_duplex_mode_func phy_get_duplex_mode; /*!< phy check init func */ + eth_gpio_config_func gpio_config; /*!< gpio config func */ + bool flow_ctrl_enable; /*!< flag of flow ctrl enable */ + eth_phy_get_partner_pause_enable_func phy_get_partner_pause_enable; /*!< get partner pause enable */ + eth_phy_power_enable_func phy_power_enable; /*!< enable or disable phy power */ + uint32_t reset_timeout_ms; /*!< timeout value for reset emac */ } eth_config_t; - /** * @brief Init ethernet mac * diff --git a/components/ethernet/include/eth_phy/phy_reg.h b/components/ethernet/include/eth_phy/phy_reg.h index 33c9a064a..7dbf02b2e 100644 --- a/components/ethernet/include/eth_phy/phy_reg.h +++ b/components/ethernet/include/eth_phy/phy_reg.h @@ -14,24 +14,40 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + /* This header contains register/bit masks for the standard PHY MII registers that should be supported by all PHY models. */ -#define MII_BASIC_MODE_CONTROL_REG (0x0) -#define MII_SOFTWARE_RESET BIT(15) +#define MII_BASIC_MODE_CONTROL_REG (0x0) +#define MII_SOFTWARE_RESET BIT(15) +#define MII_SPEED_SELECT BIT(13) +#define MII_AUTO_NEGOTIATION_ENABLE BIT(12) +#define MII_POWER_DOWN BIT(11) +#define MII_RESTART_AUTO_NEGOTIATION BIT(9) +#define MII_DUPLEX_MODE BIT(8) -#define MII_BASIC_MODE_STATUS_REG (0x1) -#define MII_AUTO_NEGOTIATION_COMPLETE BIT(5) -#define MII_LINK_STATUS BIT(2) +#define MII_BASIC_MODE_STATUS_REG (0x1) +#define MII_AUTO_NEGOTIATION_COMPLETE BIT(5) +#define MII_LINK_STATUS BIT(2) -#define MII_PHY_IDENTIFIER_1_REG (0x2) -#define MII_PHY_IDENTIFIER_2_REG (0x3) +#define MII_PHY_IDENTIFIER_1_REG (0x2) +#define MII_PHY_IDENTIFIER_2_REG (0x3) -#define MII_AUTO_NEG_ADVERTISEMENT_REG (0x4) -#define MII_ASM_DIR BIT(11) -#define MII_PAUSE BIT(10) +#define MII_AUTO_NEGOTIATION_ADVERTISEMENT_REG (0x4) +#define MII_ASM_DIR BIT(11) +#define MII_PAUSE BIT(10) -#define MII_PHY_LINK_PARTNER_ABILITY_REG (0x5) -#define MII_PARTNER_ASM_DIR BIT(11) -#define MII_PARTNER_PAUSE BIT(10) +#define MII_PHY_LINK_PARTNER_ABILITY_REG (0x5) +#define MII_PARTNER_ASM_DIR BIT(11) +#define MII_PARTNER_PAUSE BIT(10) + +/******************************legacy*******************************/ +#define MII_AUTO_NEG_ADVERTISEMENT_REG MII_AUTO_NEGOTIATION_ADVERTISEMENT_REG + +#ifdef __cplusplus +} +#endif