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
This commit is contained in:
morris 2018-10-15 20:35:05 +08:00
parent 364f033a49
commit b6d7675e60
7 changed files with 197 additions and 195 deletions

View File

@ -102,4 +102,14 @@ void esp_spiram_writeback_cache();
esp_err_t esp_spiram_reserve_dma_pool(size_t size); 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 #endif

View File

@ -280,4 +280,15 @@ void IRAM_ATTR esp_spiram_writeback_cache()
#endif #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 #endif

View File

@ -14,8 +14,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "rom/ets_sys.h" #include "rom/ets_sys.h"
#include "rom/gpio.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_EMACDUPLEX);
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACMII); REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACMII);
REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED); REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED);
REG_SET_BIT(EMAC_GMACFF_REG, EMAC_PAM);
} }

View File

@ -39,6 +39,7 @@
#include "esp_eth.h" #include "esp_eth.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_pm.h" #include "esp_pm.h"
#include "esp_spiram.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
@ -59,8 +60,8 @@
static struct emac_config_data emac_config; 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_rx_chain_buf;
static dma_extended_desc_t *emac_dma_tx_chain_buf[DMA_TX_BUF_NUM]; 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_rx_buf[DMA_RX_BUF_NUM];
static uint8_t *emac_dma_tx_buf[DMA_TX_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]) 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); memcpy(&(emac_config.macaddr[0]), mac, 6);
return ESP_OK; return ESP_OK;
} else { } else {
@ -106,22 +107,20 @@ eth_speed_mode_t esp_eth_get_speed(void)
return emac_config.emac_phy_get_speed_mode(); 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.desc1 = size & 0xfff;
tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT |
EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
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.desc1 = 0;
tx_desc->basic.desc0 = 0; tx_desc->basic.desc0 = 0;
} }
static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc, static void emac_clean_rx_desc(dma_extended_desc_t *rx_desc, uint32_t buf_ptr)
uint32_t buf_ptr)
{ {
if (buf_ptr != 0) { if (buf_ptr != 0) {
rx_desc->basic.desc2 = buf_ptr; rx_desc->basic.desc2 = buf_ptr;
@ -184,46 +183,46 @@ static void emac_reset_dma_chain(void)
static void emac_init_dma_chain(void) static void emac_init_dma_chain(void)
{ {
int i; int i;
uint32_t dma_phy;
dma_extended_desc_t *p = NULL; dma_extended_desc_t *p = NULL;
//init tx chain //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.cnt_tx = 0;
emac_config.cur_tx = 0; emac_config.cur_tx = 0;
emac_config.dirty_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++) { for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++) {
dma_phy += sizeof(dma_extended_desc_t);
emac_clean_tx_desc(p); emac_clean_tx_desc(p);
/* point to the buffer */
p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]); p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]);
/* point to next descriptor */ p->basic.desc3 = dma_phy;
p->basic.desc3 = (uint32_t)(emac_dma_tx_chain_buf[i + 1]); p++;
p = emac_dma_tx_chain_buf[i + 1];
} }
emac_clean_tx_desc(p); emac_clean_tx_desc(p);
/* point to the buffer */
p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]); p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]);
/* point to first descriptor */
p->basic.desc3 = (uint32_t)(emac_config.dma_etx); p->basic.desc3 = (uint32_t)(emac_config.dma_etx);
//init rx chain //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.cnt_rx = 0;
emac_config.cur_rx = 0; emac_config.cur_rx = 0;
emac_config.dirty_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++) { 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])); emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i]));
/* point to the buffer */ p->basic.desc3 = dma_phy;
p->basic.desc3 = (uint32_t)(emac_dma_rx_chain_buf[i + 1]); p++;
/* point to next descriptor */
p = emac_dma_rx_chain_buf[i + 1];
} }
/* point to the buffer */
emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i])); 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); 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_MIIDATA_REG, value);
REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | ((0x3) << 2));
((phy_num & 0x1f) << 11) | ((0x3) << 2));
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) { 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) { while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) {
} }
REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | (0x3 << 2));
((phy_num & 0x1f) << 11) | (0x3 << 2));
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) { while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) {
} }
value = (REG_READ(EMAC_MIIDATA_REG) & 0xffff); value = (REG_READ(EMAC_MIIDATA_REG) & 0xffff);
@ -259,12 +256,10 @@ uint16_t esp_eth_smi_read(uint32_t reg_num)
return value; return value;
} }
esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms)
uint16_t value_mask, int timeout_ms)
{ {
unsigned start = xTaskGetTickCount(); unsigned start = xTaskGetTickCount();
unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS;
portTICK_PERIOD_MS;
uint16_t current_value = 0; uint16_t current_value = 0;
while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) { 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; emac_config.emac_flow_ctrl_enable = false;
#endif #endif
emac_config.emac_phy_get_partner_pause_enable = emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable;
config->phy_get_partner_pause_enable;
emac_config.emac_phy_power_enable = config->phy_power_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; ret = ESP_FAIL;
} }
if (emac_config.emac_flow_ctrl_enable == true && if (emac_config.emac_flow_ctrl_enable && !emac_config.emac_phy_get_partner_pause_enable) {
emac_config.emac_phy_get_partner_pause_enable == NULL) {
ESP_LOGE(TAG, "phy get partner pause enable func is null"); ESP_LOGE(TAG, "phy get partner pause enable func is null");
ret = ESP_FAIL; ret = ESP_FAIL;
} }
@ -420,8 +413,8 @@ static void emac_process_tx(void)
xSemaphoreTakeRecursive(emac_tx_xMutex, portMAX_DELAY); xSemaphoreTakeRecursive(emac_tx_xMutex, portMAX_DELAY);
while ((uint32_t)(emac_dma_tx_chain_buf[emac_config.dirty_tx]) != cur_tx_desc) { while (((uint32_t) & (emac_config.dma_etx[emac_config.dirty_tx])) != cur_tx_desc) {
emac_clean_tx_desc(emac_dma_tx_chain_buf[emac_config.dirty_tx]); 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.dirty_tx = (emac_config.dirty_tx + 1) % DMA_TX_BUF_NUM;
emac_config.cnt_tx--; emac_config.cnt_tx--;
@ -438,20 +431,19 @@ void esp_eth_free_rx_buf(void *buf)
{ {
xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY); 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.cur_rx = (emac_config.cur_rx + 1) % DMA_RX_BUF_NUM;
emac_config.cnt_rx--; emac_config.cnt_rx--;
if (emac_config.cnt_rx < 0) { 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(); emac_poll_rx_cmd();
xSemaphoreGiveRecursive(emac_rx_xMutex); 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); portENTER_CRITICAL(&g_emac_mux);
if (pause_send == true && emac_config.cnt_rx < if (pause_send && emac_config.cnt_rx < FLOW_CONTROL_LOW_WATERMARK) {
FLOW_CONTROL_LOW_WATERMARK) {
emac_send_pause_zero_frame_enable(); emac_send_pause_zero_frame_enable();
pause_send = false; 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 cnt = 0;
uint32_t cur_rx_desc = emac_read_rx_cur_reg(); 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) { while (cur_desc->basic.desc0 == EMAC_DESC_RX_OWN && cnt < DMA_RX_BUF_NUM) {
cnt++; cnt++;
cur_desc = (struct dma_extended_desc *)cur_desc->basic.desc3; cur_desc = (dma_extended_desc_t *)cur_desc->basic.desc3;
} }
return cnt; return cnt;
} }
@ -480,19 +472,15 @@ static void emac_process_rx(void)
} }
uint32_t cur_rx_desc = emac_read_rx_cur_reg(); 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 //copy data to lwip
emac_config.emac_tcpip_input((emac_dma_rx_buf[emac_config.dirty_rx]), emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
(((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0) >> (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH), NULL);
EMAC_DESC_FRAME_LENGTH),
NULL);
emac_clean_rx_desc(emac_dma_rx_chain_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));
(uint32_t)(emac_dma_rx_buf[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;
//if open this ,one intr can do many intrs ?
cur_rx_desc = emac_read_rx_cur_reg(); cur_rx_desc = emac_read_rx_cur_reg();
} }
@ -507,21 +495,16 @@ static void emac_process_rx_unavail(void)
uint32_t dirty_cnt = 0; uint32_t dirty_cnt = 0;
while (dirty_cnt < DMA_RX_BUF_NUM) { while (dirty_cnt < DMA_RX_BUF_NUM) {
if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) {
if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) {
break; break;
} }
dirty_cnt++; dirty_cnt++;
//copy data to lwip //copy data to lwip
emac_config.emac_tcpip_input((emac_dma_rx_buf[emac_config.dirty_rx]), emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
(((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0) >> (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH), NULL);
EMAC_DESC_FRAME_LENGTH),
NULL);
emac_clean_rx_desc(emac_dma_rx_chain_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));
(uint32_t)(emac_dma_rx_buf[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;
} }
emac_enable_rx_intr(); emac_enable_rx_intr();
@ -539,24 +522,20 @@ static void emac_process_rx_unavail(void)
xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY); xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY);
while (emac_config.cnt_rx < DMA_RX_BUF_NUM) { while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) {
if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) {
break; break;
} }
emac_config.cnt_rx++; emac_config.cnt_rx++;
if (emac_config.cnt_rx > DMA_RX_BUF_NUM) { 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; 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 //copy data to lwip
emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]), emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
(((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >> (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH), NULL);
EMAC_DESC_FRAME_LENGTH),
NULL);
} }
emac_enable_rx_intr(); emac_enable_rx_intr();
emac_enable_rx_unavail_intr(); emac_enable_rx_unavail_intr();
@ -573,51 +552,41 @@ static void emac_process_rx(void)
xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY); xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY);
if (((uint32_t)(emac_dma_rx_chain_buf[emac_config.dirty_rx])) != if ((((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx])) != cur_rx_desc)) {
cur_rx_desc) { while ((((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx])) != cur_rx_desc) &&
while (((uint32_t)(emac_dma_rx_chain_buf[emac_config.dirty_rx]) != cur_rx_desc) &&
emac_config.cnt_rx < DMA_RX_BUF_NUM) { emac_config.cnt_rx < DMA_RX_BUF_NUM) {
emac_config.cnt_rx++; emac_config.cnt_rx++;
if (emac_config.cnt_rx > DMA_RX_BUF_NUM) { 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; 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 //copy data to lwip
emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]), emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
(((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >> (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH), NULL);
EMAC_DESC_FRAME_LENGTH),
NULL);
cur_rx_desc = emac_read_rx_cur_reg(); cur_rx_desc = emac_read_rx_cur_reg();
} }
} else { } else {
if (emac_config.cnt_rx < DMA_RX_BUF_NUM) { if (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
if ((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 & if (!(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN)) {
EMAC_DESC_RX_OWN) == 0) {
while (emac_config.cnt_rx < DMA_RX_BUF_NUM) { while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) {
if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) {
break; break;
} }
emac_config.cnt_rx++; emac_config.cnt_rx++;
if (emac_config.cnt_rx > DMA_RX_BUF_NUM) { 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; uint32_t tmp_dirty = emac_config.dirty_rx;
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
DMA_RX_BUF_NUM;
//copy data to lwip //copy data to lwip
emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]), emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
(((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >> (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH), NULL);
EMAC_DESC_FRAME_LENGTH),
NULL);
} }
} }
} }
@ -638,9 +607,8 @@ static void IRAM_ATTR emac_process_intr(void *arg)
if (event & EMAC_RECV_INT) { if (event & EMAC_RECV_INT) {
emac_disable_rx_intr(); emac_disable_rx_intr();
if (emac_config.emac_flow_ctrl_partner_support == true) { if (emac_config.emac_flow_ctrl_partner_support) {
if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && !pause_send) {
pause_send == false) {
pause_send = true; pause_send = true;
emac_send_pause_frame_enable(); 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) 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_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) | REG_WRITE(EMAC_ADDR0LOW_REG, (emac_config.macaddr[3] << 24) | (emac_config.macaddr[2] << 16) |
(emac_config.macaddr[2] << 16) | (emac_config.macaddr[1] << 8) | (emac_config.macaddr[1] << 8) | (emac_config.macaddr[0]));
(emac_config.macaddr[0]));
} }
static void emac_check_phy_init(void) static void emac_check_phy_init(void)
@ -683,8 +650,8 @@ static void emac_check_phy_init(void)
emac_disable_flowctrl(); emac_disable_flowctrl();
emac_config.emac_flow_ctrl_partner_support = false; emac_config.emac_flow_ctrl_partner_support = false;
#else #else
if (emac_config.emac_flow_ctrl_enable == true) { if (emac_config.emac_flow_ctrl_enable) {
if (emac_config.emac_phy_get_partner_pause_enable() == true && if (emac_config.emac_phy_get_partner_pause_enable() &&
emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) { emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
emac_enable_flowctrl(); emac_enable_flowctrl();
emac_config.emac_flow_ctrl_partner_support = true; 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; emac_config.phy_link_up = link_status;
if (link_status == true) { if (link_status) {
emac_check_phy_init(); emac_check_phy_init();
ESP_LOGD(TAG, "eth link_up"); ESP_LOGD(TAG, "eth link_up");
emac_enable_dma_tx(); 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; esp_err_t ret = ESP_OK;
if (emac_config.emac_status != EMAC_RUNTIME_START) { if (emac_config.emac_status != EMAC_RUNTIME_START) {
ESP_LOGE(TAG, "tx netif is not ready, emac_status=%d", ESP_LOGE(TAG, "tx netif is not ready, emac_status=%d", emac_config.emac_status);
emac_config.emac_status);
ret = ESP_ERR_INVALID_STATE; ret = ESP_ERR_INVALID_STATE;
return ret; return ret;
} }
@ -754,9 +720,9 @@ esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
goto _exit; 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.cnt_tx++;
emac_config.cur_tx = (emac_config.cur_tx + 1) % DMA_TX_BUF_NUM; 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) 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) 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) static bool emac_link_check_timer_init(void)
{ {
emac_timer = xTimerCreate("emac_timer", emac_timer = xTimerCreate("emac_timer",
(CONFIG_EMAC_CHECK_LINK_PERIOD_MS / (CONFIG_EMAC_CHECK_LINK_PERIOD_MS / portTICK_PERIOD_MS),
portTICK_PERIOD_MS),
pdTRUE, pdTRUE,
NULL, NULL,
emac_link_check_func); emac_link_check_func);
@ -858,8 +823,6 @@ static void emac_start(void *param)
emac_mac_init(); emac_mac_init();
//ptp TODO
emac_enable_intr(); emac_enable_intr();
emac_config.emac_status = EMAC_RUNTIME_START; emac_config.emac_status = EMAC_RUNTIME_START;
@ -869,8 +832,8 @@ static void emac_start(void *param)
esp_event_send(&evt); esp_event_send(&evt);
//set a timer to check link up status //set a timer to check link up status
if (emac_link_check_timer_init() == true) { if (emac_link_check_timer_init()) {
if (emac_link_check_timer_start() != true) { if (!emac_link_check_timer_start()) {
cmd->err = EMAC_CMD_FAIL; cmd->err = EMAC_CMD_FAIL;
emac_link_check_timer_delete(); 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_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; open_cmd.err = EMAC_CMD_FAIL;
goto cleanup; 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) esp_err_t esp_eth_init(eth_config_t *config)
{ {
int i = 0;
/* dynamically alloc memory for ethernet dma */ /* dynamically alloc memory for ethernet dma */
for (int i = 0; i < DMA_RX_BUF_NUM; i++) { 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_rx_chain_buf[i] = (struct dma_extended_desc *)heap_caps_malloc(sizeof(struct dma_extended_desc), 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); 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++) { for (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);
emac_dma_tx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_TX_BUF_SIZE, MALLOC_CAP_DMA); emac_dma_tx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_TX_BUF_SIZE, MALLOC_CAP_DMA);
} }
esp_event_set_default_eth_handlers(); esp_event_set_default_eth_handlers();
return esp_eth_init_internal(config); 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(); emac_init_default_data();
if (config != NULL) { if (config) {
emac_set_user_config_data(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); periph_module_enable(PERIPH_EMAC_MODULE);
if (emac_config.clock_mode != ETH_CLOCK_GPIO0_IN) { 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 // 50 MHz = 40MHz * (6 + 4) / (2 * (2 + 2) = 400MHz / 8
rtc_clk_apll_enable(1, 0, 0, 6, 2); 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); 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); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
ESP_LOGD(TAG, "EMAC 50MHz clock output on GPIO16"); ESP_LOGD(TAG, "EMAC 50MHz clock output on GPIO16");
} else if (emac_config.clock_mode == ETH_CLOCK_GPIO17_OUT) { } else if (emac_config.clock_mode == ETH_CLOCK_GPIO17_OUT) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
FUNC_GPIO17_EMAC_CLK_OUT_180);
ESP_LOGD(TAG, "EMAC 50MHz inverted clock output on GPIO17"); ESP_LOGD(TAG, "EMAC 50MHz inverted clock output on GPIO17");
} }
} }
emac_enable_clk(true); emac_enable_clk(true);
REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, EMAC_EX_PHY_INTF_RMII);
EMAC_EX_PHY_INTF_RMII);
emac_dma_init(); emac_dma_init();
if (emac_config.clock_mode == ETH_CLOCK_GPIO0_IN) { 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_rx_xMutex = xSemaphoreCreateRecursiveMutex();
emac_tx_xMutex = xSemaphoreCreateRecursiveMutex(); emac_tx_xMutex = xSemaphoreCreateRecursiveMutex();
emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t)); emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t));
xTaskCreate(emac_task, "emacT", EMAC_TASK_STACK_SIZE, NULL, xTaskCreate(emac_task,
EMAC_TASK_PRIORITY, &emac_task_hdl); "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); 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 esp_eth_deinit(void)
{ {
esp_err_t ret = ESP_FAIL; esp_err_t ret = ESP_FAIL;
int i = 0;
if (!emac_task_hdl) { if (!emac_task_hdl) {
ret = ESP_ERR_INVALID_STATE; ret = ESP_ERR_INVALID_STATE;
@ -1224,20 +1199,19 @@ esp_err_t esp_eth_deinit(void)
emac_config.emac_status = EMAC_RUNTIME_NOT_INIT; emac_config.emac_status = EMAC_RUNTIME_NOT_INIT;
/* free memory that dynamically allocted */ /* free memory that dynamically allocted */
for (int i = 0; i < DMA_RX_BUF_NUM; i++) { free(emac_dma_rx_chain_buf);
free(emac_dma_rx_chain_buf[i]); 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]); free(emac_dma_rx_buf[i]);
emac_dma_rx_chain_buf[i] = NULL;
emac_dma_rx_buf[i] = NULL; emac_dma_rx_buf[i] = NULL;
} }
for (int i = 0; i < DMA_TX_BUF_NUM; i++) { for (i = 0; i < DMA_TX_BUF_NUM; i++) {
free(emac_dma_tx_chain_buf[i]);
free(emac_dma_tx_buf[i]); free(emac_dma_tx_buf[i]);
emac_dma_tx_chain_buf[i] = NULL;
emac_dma_tx_buf[i] = NULL; emac_dma_tx_buf[i] = NULL;
} }
ret = ESP_OK; ret = ESP_OK;
_exit: _exit:
return ret; return ret;
} }

View File

@ -26,26 +26,16 @@
#define LAN8720_PHY_ID2_MASK 0xFFF0 #define LAN8720_PHY_ID2_MASK 0xFFF0
/* LAN8720-specific registers */ /* 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 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_HALF 0x04
#define SPEED_DUPLEX_INDICATION_10T_FULL 0x14 #define SPEED_DUPLEX_INDICATION_10T_FULL 0x14
#define SPEED_DUPLEX_INDICATION_100T_HALF 0x08 #define SPEED_DUPLEX_INDICATION_100T_HALF 0x08
#define SPEED_DUPLEX_INDICATION_100T_FULL 0x18 #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"; 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) void phy_lan8720_power_enable(bool enable)
{ {
if (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 // TODO: only enable if config.flow_ctrl_enable == true
phy_mii_enable_flow_ctrl(); 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); 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); 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, uint32_t data = esp_eth_smi_read(MII_BASIC_MODE_CONTROL_REG);
DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE); data |= MII_AUTO_NEGOTIATION_ENABLE | MII_RESTART_AUTO_NEGOTIATION;
esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, data);
ets_delay_us(300); ets_delay_us(300);

View File

@ -28,10 +28,10 @@ typedef enum {
ETH_MODE_MII, ETH_MODE_MII,
} eth_mode_t; } eth_mode_t;
typedef enum { typedef enum {
ETH_CLOCK_GPIO0_IN = 0, ETH_CLOCK_GPIO0_IN = 0,
ETH_CLOCK_GPIO16_OUT = 2, ETH_CLOCK_GPIO16_OUT = 2,
ETH_CLOCK_GPIO17_OUT = 3, ETH_CLOCK_GPIO17_OUT = 3
} eth_clock_mode_t; } eth_clock_mode_t;
typedef enum { typedef enum {
@ -94,24 +94,22 @@ typedef void (*eth_phy_power_enable_func)(bool enable);
* *
*/ */
typedef struct { typedef struct {
eth_phy_base_t phy_addr; /*!< phy base addr (0~31) */ eth_phy_base_t phy_addr; /*!< phy base addr (0~31) */
eth_mode_t mac_mode; /*!< mac mode only support RMII now */ eth_mode_t mac_mode; /*!< mac mode only support RMII now */
eth_clock_mode_t clock_mode; /*!< external/internal clock mode selecton */ eth_clock_mode_t clock_mode; /*!< external/internal clock mode selecton */
eth_tcpip_input_func tcpip_input; /*!< tcpip input func */ eth_tcpip_input_func tcpip_input; /*!< tcpip input func */
eth_phy_func phy_init; /*!< phy init func */ eth_phy_func phy_init; /*!< phy init func */
eth_phy_check_link_func phy_check_link; /*!< phy check link 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_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_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_phy_get_duplex_mode_func phy_get_duplex_mode; /*!< phy check init func */
eth_gpio_config_func gpio_config; /*!< gpio config func */ eth_gpio_config_func gpio_config; /*!< gpio config func */
bool flow_ctrl_enable; /*!< flag of flow ctrl enable */ 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_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 */ eth_phy_power_enable_func phy_power_enable; /*!< enable or disable phy power */
uint32_t reset_timeout_ms; /*!< timeout value for reset emac */ uint32_t reset_timeout_ms; /*!< timeout value for reset emac */
} eth_config_t; } eth_config_t;
/** /**
* @brief Init ethernet mac * @brief Init ethernet mac
* *

View File

@ -14,24 +14,40 @@
#pragma once #pragma once
#ifdef __cplusplus
extern "C" {
#endif
/* This header contains register/bit masks for the standard /* This header contains register/bit masks for the standard
PHY MII registers that should be supported by all PHY models. PHY MII registers that should be supported by all PHY models.
*/ */
#define MII_BASIC_MODE_CONTROL_REG (0x0) #define MII_BASIC_MODE_CONTROL_REG (0x0)
#define MII_SOFTWARE_RESET BIT(15) #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_BASIC_MODE_STATUS_REG (0x1)
#define MII_AUTO_NEGOTIATION_COMPLETE BIT(5) #define MII_AUTO_NEGOTIATION_COMPLETE BIT(5)
#define MII_LINK_STATUS BIT(2) #define MII_LINK_STATUS BIT(2)
#define MII_PHY_IDENTIFIER_1_REG (0x2) #define MII_PHY_IDENTIFIER_1_REG (0x2)
#define MII_PHY_IDENTIFIER_2_REG (0x3) #define MII_PHY_IDENTIFIER_2_REG (0x3)
#define MII_AUTO_NEG_ADVERTISEMENT_REG (0x4) #define MII_AUTO_NEGOTIATION_ADVERTISEMENT_REG (0x4)
#define MII_ASM_DIR BIT(11) #define MII_ASM_DIR BIT(11)
#define MII_PAUSE BIT(10) #define MII_PAUSE BIT(10)
#define MII_PHY_LINK_PARTNER_ABILITY_REG (0x5) #define MII_PHY_LINK_PARTNER_ABILITY_REG (0x5)
#define MII_PARTNER_ASM_DIR BIT(11) #define MII_PARTNER_ASM_DIR BIT(11)
#define MII_PARTNER_PAUSE BIT(10) #define MII_PARTNER_PAUSE BIT(10)
/******************************legacy*******************************/
#define MII_AUTO_NEG_ADVERTISEMENT_REG MII_AUTO_NEGOTIATION_ADVERTISEMENT_REG
#ifdef __cplusplus
}
#endif