Merge branch 'bugfix/fix_bug_ethernet_v3.2' into 'release/v3.2'
ethernet: fix some bugs in phy&mac driver(backport v3.2) See merge request idf/esp-idf!3640
This commit is contained in:
commit
e84289077c
10 changed files with 284 additions and 213 deletions
|
@ -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
|
||||
|
|
|
@ -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,10 +257,10 @@ 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 32KB 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
|
||||
we ever support external RAM chips of 2M or smaller, this may need adjusting.
|
||||
Note: this assumes the amount of external RAM is >2MB. If it is 2MB or less, what this code does is undefined. If
|
||||
we ever support external RAM chips of 2MB or smaller, this may need adjusting.
|
||||
*/
|
||||
for (x=0; x<1024*64; x+=32) {
|
||||
i+=psram[x];
|
||||
|
@ -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
|
||||
|
|
|
@ -21,7 +21,7 @@ config DMA_TX_BUF_NUM
|
|||
|
||||
config EMAC_L2_TO_L3_RX_BUF_MODE
|
||||
bool "Enable copy between Layer2 and Layer3"
|
||||
default n
|
||||
default y
|
||||
help
|
||||
If this options is selected, a copy of each received buffer will be created when
|
||||
passing it from the Ethernet MAC (L2) to the IP stack (L3). Otherwise, IP stack
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
@ -72,6 +73,7 @@ static uint8_t emac_sig_cnt[EMAC_SIG_MAX] = {0};
|
|||
static TimerHandle_t emac_timer = NULL;
|
||||
static SemaphoreHandle_t emac_rx_xMutex = NULL;
|
||||
static SemaphoreHandle_t emac_tx_xMutex = NULL;
|
||||
static intr_handle_t eth_intr_handle = NULL;
|
||||
static const char *TAG = "emac";
|
||||
static bool pause_send = false;
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
|
@ -93,7 +95,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 +108,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 +184,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 +235,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 +249,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 +257,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 +323,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 +391,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 +414,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 +432,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 +456,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 +473,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 +496,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 +523,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 +553,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 +608,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 +630,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 +651,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 +674,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 +709,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 +721,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 +738,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 +766,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 +824,6 @@ static void emac_start(void *param)
|
|||
|
||||
emac_mac_init();
|
||||
|
||||
//ptp TODO
|
||||
|
||||
emac_enable_intr();
|
||||
|
||||
emac_config.emac_status = EMAC_RUNTIME_START;
|
||||
|
@ -869,8 +833,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 +877,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,37 +1067,38 @@ 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)
|
||||
{
|
||||
/* 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_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);
|
||||
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);
|
||||
}
|
||||
|
||||
esp_err_t esp_eth_init_internal(eth_config_t *config)
|
||||
{
|
||||
int i = 0;
|
||||
esp_err_t ret = ESP_OK;
|
||||
if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) {
|
||||
goto _exit;
|
||||
goto _initialised;
|
||||
}
|
||||
|
||||
/* dynamically alloc memory for ethernet 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 (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);
|
||||
}
|
||||
|
||||
emac_init_default_data();
|
||||
|
||||
if (config != NULL) {
|
||||
if (config) {
|
||||
emac_set_user_config_data(config);
|
||||
}
|
||||
|
||||
ret = emac_verify_args();
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
goto _exit;
|
||||
goto _verify_err;
|
||||
}
|
||||
|
||||
emac_config.emac_phy_power_enable(true);
|
||||
|
@ -1142,6 +1107,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 _verify_err;
|
||||
} 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 +1125,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,21 +1163,47 @@ 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);
|
||||
esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, ð_intr_handle);
|
||||
|
||||
emac_config.emac_status = EMAC_RUNTIME_INIT;
|
||||
|
||||
_exit:
|
||||
return ESP_OK;
|
||||
|
||||
_verify_err:
|
||||
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_buf[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < DMA_TX_BUF_NUM; i++) {
|
||||
free(emac_dma_tx_buf[i]);
|
||||
emac_dma_tx_buf[i] = NULL;
|
||||
}
|
||||
_initialised:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_eth_deinit(void)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
esp_err_t ret = ESP_OK;
|
||||
int i = 0;
|
||||
|
||||
if (emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
|
||||
goto _exit;
|
||||
}
|
||||
if (emac_config.emac_status == EMAC_RUNTIME_START) {
|
||||
esp_eth_disable();
|
||||
}
|
||||
if (!emac_task_hdl) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto _exit;
|
||||
|
@ -1223,21 +1221,20 @@ esp_err_t esp_eth_deinit(void)
|
|||
periph_module_disable(PERIPH_EMAC_MODULE);
|
||||
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 memory that dynamically allocated */
|
||||
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;
|
||||
|
||||
esp_intr_free(eth_intr_handle);
|
||||
_exit:
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -7,17 +7,19 @@
|
|||
* @author morris
|
||||
* @date 2018-08-24
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_eth.h"
|
||||
#include "unity.h"
|
||||
|
||||
#include "rom/gpio.h"
|
||||
|
||||
|
@ -37,6 +39,9 @@ static const char *TAG = "eth_test_deinit";
|
|||
#define CONFIG_PHY_ADDRESS 31
|
||||
#define CONFIG_PHY_CLOCK_MODE 0
|
||||
|
||||
static EventGroupHandle_t eth_event_group = NULL;
|
||||
static const int GOTIP_BIT = BIT0;
|
||||
|
||||
static void phy_device_power_enable_via_gpio(bool enable)
|
||||
{
|
||||
if (!enable) {
|
||||
|
@ -67,6 +72,47 @@ static void eth_gpio_config_rmii(void)
|
|||
phy_rmii_smi_configure_pins(PIN_SMI_MDC, PIN_SMI_MDIO);
|
||||
}
|
||||
|
||||
static esp_err_t eth_event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
tcpip_adapter_ip_info_t ip;
|
||||
|
||||
switch (event->event_id) {
|
||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
||||
ESP_LOGI(TAG, "Ethernet Link Up");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "Ethernet Link Down");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_START:
|
||||
ESP_LOGI(TAG, "Ethernet Started");
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
||||
memset(&ip, 0, sizeof(tcpip_adapter_ip_info_t));
|
||||
ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(ESP_IF_ETH, &ip));
|
||||
ESP_LOGI(TAG, "Ethernet Got IP Addr");
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip.ip));
|
||||
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip.netmask));
|
||||
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip.gw));
|
||||
ESP_LOGI(TAG, "~~~~~~~~~~~");
|
||||
xEventGroupSetBits(eth_event_group, GOTIP_BIT);
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_STOP:
|
||||
ESP_LOGI(TAG, "Ethernet Stopped");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
TEST_CASE("start event loop", "[ethernet][ignore]")
|
||||
{
|
||||
eth_event_group = xEventGroupCreate();
|
||||
tcpip_adapter_init();
|
||||
ESP_ERROR_CHECK(esp_event_loop_init(eth_event_handler, NULL));
|
||||
}
|
||||
|
||||
TEST_CASE("test emac deinit", "[ethernet][ignore]")
|
||||
{
|
||||
eth_config_t config = DEFAULT_ETHERNET_PHY_CONFIG;
|
||||
|
@ -79,7 +125,8 @@ TEST_CASE("test emac deinit", "[ethernet][ignore]")
|
|||
ESP_ERROR_CHECK(esp_eth_init(&config));
|
||||
ESP_ERROR_CHECK(esp_eth_enable());
|
||||
|
||||
vTaskDelay(2000 / portTICK_RATE_MS);
|
||||
xEventGroupWaitBits(eth_event_group, GOTIP_BIT, true, true, portMAX_DELAY);
|
||||
vTaskDelay(15000 / portTICK_RATE_MS);
|
||||
|
||||
ESP_ERROR_CHECK(esp_eth_disable());
|
||||
ESP_ERROR_CHECK(esp_eth_deinit());
|
||||
|
|
|
@ -196,7 +196,6 @@ if (netif->input(p, netif) != ERR_OK) {
|
|||
/* full packet send to tcpip_thread to process */
|
||||
if (netif->input(p, netif) != ERR_OK) {
|
||||
LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
|
||||
p->l2_owner = NULL;
|
||||
pbuf_free(p);
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue