mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
ethernet: support flow control
This commit is contained in:
parent
a3f6728797
commit
0e701e1cac
@ -1035,14 +1035,20 @@
|
||||
#define DPORT_WIFI_CLK_EN_V 0xFFFFFFFF
|
||||
#define DPORT_WIFI_CLK_EN_S 0
|
||||
|
||||
#define DPORT_WIFI_RST_EN_REG (DR_REG_DPORT_BASE + 0x0D0)
|
||||
/* DPORT_WIFI_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
|
||||
#define DPORT_CORE_RST_EN_REG (DR_REG_DPORT_BASE + 0x0D0)
|
||||
/* DPORT_CORE_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
|
||||
/*description: */
|
||||
#define DPROT_RW_BTLP_RST (BIT(10))
|
||||
#define DPROT_RW_BTMAC_RST (BIT(9))
|
||||
#define DPORT_MACPWR_RST (BIT(8))
|
||||
#define DPORT_EMAC_RST (BIT(7))
|
||||
#define DPORT_SDIO_HOST_RST (BIT(6))
|
||||
#define DPORT_SDIO_RST (BIT(5))
|
||||
#define DPORT_BTMAC_RST (BIT(4))
|
||||
#define DPORT_BT_RST (BIT(3))
|
||||
#define DPORT_MAC_RST (BIT(2))
|
||||
#define DPORT_WIFI_RST 0xFFFFFFFF
|
||||
#define DPORT_WIFI_RST_M ((DPORT_WIFI_RST_V)<<(DPORT_WIFI_RST_S))
|
||||
#define DPORT_WIFI_RST_V 0xFFFFFFFF
|
||||
#define DPORT_WIFI_RST_S 0
|
||||
#define DPORT_FE_RST (BIT(1))
|
||||
#define DPORT_BB_RST (BIT(0))
|
||||
|
||||
#define DPORT_BT_LPCK_DIV_INT_REG (DR_REG_DPORT_BASE + 0x0D4)
|
||||
/* DPORT_BTEXTWAKEUP_REQ : R/W ;bitpos:[12] ;default: 1'b0 ; */
|
||||
|
@ -39,8 +39,8 @@ esp_err_t esp_phy_init(const esp_phy_init_data_t* init_data,
|
||||
assert(calibration_data);
|
||||
// Initialize PHY pointer table
|
||||
phy_get_romfunc_addr();
|
||||
REG_SET_BIT(DPORT_WIFI_RST_EN_REG, DPORT_MAC_RST);
|
||||
REG_CLR_BIT(DPORT_WIFI_RST_EN_REG, DPORT_MAC_RST);
|
||||
REG_SET_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
|
||||
REG_CLR_BIT(DPORT_CORE_RST_EN_REG, DPORT_MAC_RST);
|
||||
// Enable WiFi peripheral clock
|
||||
SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, 0x87cf);
|
||||
ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d",
|
||||
|
@ -111,9 +111,13 @@ void IRAM_ATTR esp_restart(void)
|
||||
uart_tx_wait_idle(1);
|
||||
uart_tx_wait_idle(2);
|
||||
|
||||
// Reset wifi/bluetooth (bb/mac)
|
||||
SET_PERI_REG_MASK(DPORT_WIFI_RST_EN_REG, 0x1f);
|
||||
REG_WRITE(DPORT_WIFI_RST_EN_REG, 0);
|
||||
// Reset wifi/bluetooth/ethernet/sdio (bb/mac)
|
||||
SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG,
|
||||
DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST |
|
||||
DPORT_BT_RST | DPORT_BTMAC_RST | DPORT_SDIO_RST |
|
||||
DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST |
|
||||
DPROT_RW_BTMAC_RST | DPROT_RW_BTLP_RST);
|
||||
REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
|
||||
|
||||
// Reset timer/spi/uart
|
||||
SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
|
||||
|
@ -72,6 +72,9 @@ struct emac_config_data {
|
||||
eth_phy_check_init_func emac_phy_check_init;
|
||||
eth_phy_get_speed_mode_func emac_phy_get_speed_mode;
|
||||
eth_phy_get_duplex_mode_func emac_phy_get_duplex_mode;
|
||||
bool emac_flow_ctrl_enable;
|
||||
bool emac_flow_ctrl_partner_support;
|
||||
eth_phy_get_partner_pause_enable_func emac_phy_get_partner_pause_enable;
|
||||
};
|
||||
|
||||
enum emac_post_type {
|
||||
@ -109,6 +112,13 @@ struct emac_close_cmd {
|
||||
#define DMA_RX_BUF_SIZE 1600
|
||||
#define DMA_TX_BUF_SIZE 1600
|
||||
|
||||
//rest buf num
|
||||
#define FLOW_CONTROL_HIGH_WATERMARK 3
|
||||
//used buf num
|
||||
#define FLOW_CONTROL_LOW_WATERMARK 6
|
||||
|
||||
#define PHY_LINK_CHECK_NUM 5
|
||||
|
||||
#define EMAC_CMD_OK 0
|
||||
#define EMAC_CMD_FAIL -1
|
||||
|
||||
|
@ -34,6 +34,24 @@
|
||||
|
||||
static const char *TAG = "emac";
|
||||
|
||||
void emac_enable_flowctrl(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_TRANSMIT_FLOW_CONTROL_ENABLE);
|
||||
REG_SET_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_RECEIVE_FLOW_CONTROL_ENABLE);
|
||||
REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_DISABLE_ZERO_QUANTA_PAUSE);
|
||||
REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_TIME, 0x1648);
|
||||
REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_LOW_THRESHOLD, 0x1);
|
||||
}
|
||||
|
||||
void emac_disable_flowctrl(void)
|
||||
{
|
||||
REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_TRANSMIT_FLOW_CONTROL_ENABLE);
|
||||
REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_RECEIVE_FLOW_CONTROL_ENABLE);
|
||||
REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_DISABLE_ZERO_QUANTA_PAUSE);
|
||||
REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_TIME, 0);
|
||||
REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_LOW_THRESHOLD, 0);
|
||||
}
|
||||
|
||||
void emac_enable_dma_tx(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND);
|
||||
@ -100,18 +118,21 @@ void emac_dma_init(void)
|
||||
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES);
|
||||
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPERATE_SECOND_FRAME);
|
||||
REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_PROG_BURST_LEN, 4);
|
||||
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG,EMAC_DMAOPERATION_MODE_REG);
|
||||
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_DMAOPERATION_MODE_REG);
|
||||
}
|
||||
|
||||
void emac_mac_enable_txrx(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACRX);
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACTX);
|
||||
}
|
||||
|
||||
void emac_mac_init(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACMIIGMII);
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
|
||||
REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
|
||||
REG_SET_BIT(EMAC_GMACFRAMEFILTER_REG, EMAC_PROMISCUOUS_MODE);
|
||||
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACRX);
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACTX);
|
||||
}
|
||||
|
||||
void emac_set_clk_rmii(void)
|
||||
|
@ -52,6 +52,9 @@ void emac_enable_dma_tx(void);
|
||||
void emac_enable_dma_rx(void);
|
||||
void emac_disable_dma_tx(void);
|
||||
void emac_disable_dma_rx(void);
|
||||
void emac_enable_flowctrl(void);
|
||||
void emac_disable_flowctrl(void);
|
||||
void emac_mac_enable_txrx(void);
|
||||
|
||||
uint32_t inline emac_read_tx_cur_reg(void)
|
||||
{
|
||||
@ -77,22 +80,32 @@ void inline emac_poll_rx_cmd(void)
|
||||
|
||||
void inline emac_disable_rx_intr(void)
|
||||
{
|
||||
REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_INTERRUPT_ENABLE);
|
||||
REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_INTERRUPT_ENABLE);
|
||||
}
|
||||
|
||||
void inline emac_enable_rx_intr(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_INTERRUPT_ENABLE);
|
||||
REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_INTERRUPT_ENABLE);
|
||||
}
|
||||
|
||||
void inline emac_disable_rx_unavail_intr(void)
|
||||
{
|
||||
REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE);
|
||||
REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE);
|
||||
}
|
||||
|
||||
void inline emac_enable_rx_unavail_intr(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG,EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE);
|
||||
REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE);
|
||||
}
|
||||
|
||||
void IRAM_ATTR inline emac_send_pause_frame_enable(void)
|
||||
{
|
||||
REG_SET_BIT(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_SBD_FLOWCTRL);
|
||||
}
|
||||
|
||||
void inline emac_send_pause_zero_frame_enable(void)
|
||||
{
|
||||
REG_CLR_BIT(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_SBD_FLOWCTRL);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -68,6 +68,7 @@ static TimerHandle_t emac_timer = NULL;
|
||||
static SemaphoreHandle_t emac_rx_xMutex = NULL;
|
||||
static SemaphoreHandle_t emac_tx_xMutex = NULL;
|
||||
static const char *TAG = "emac";
|
||||
static bool pause_send = false;
|
||||
|
||||
static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par);
|
||||
esp_err_t emac_post(emac_sig_t sig, emac_par_t par);
|
||||
@ -96,9 +97,9 @@ static void emac_clean_tx_desc(struct dma_extended_desc *tx_desc)
|
||||
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(struct dma_extended_desc *rx_desc , uint32_t buf_ptr)
|
||||
{
|
||||
if(buf_ptr != 0) {
|
||||
if (buf_ptr != 0) {
|
||||
rx_desc->basic.desc2 = buf_ptr;
|
||||
}
|
||||
rx_desc->basic.desc1 = EMAC_DESC_RX_SECOND_ADDR_CHAIN | DMA_RX_BUF_SIZE;
|
||||
@ -215,6 +216,8 @@ static void emac_set_user_config_data(eth_config_t *config )
|
||||
emac_config.emac_phy_check_init = config->phy_check_init;
|
||||
emac_config.emac_phy_get_speed_mode = config->phy_get_speed_mode;
|
||||
emac_config.emac_phy_get_duplex_mode = config->phy_get_duplex_mode;
|
||||
emac_config.emac_flow_ctrl_enable = config->flow_ctrl_enable;
|
||||
emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable;
|
||||
}
|
||||
|
||||
static void emac_enable_intr()
|
||||
@ -276,6 +279,11 @@ 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) {
|
||||
ESP_LOGE(TAG, "phy get partner pause enable func is null");
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -293,13 +301,13 @@ static void emac_process_tx(void)
|
||||
{
|
||||
uint32_t cur_tx_desc = emac_read_tx_cur_reg();
|
||||
|
||||
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
|
||||
while (((uint32_t) &(emac_config.dma_etx[emac_config.dirty_tx].basic.desc0) != cur_tx_desc)) {
|
||||
while (((uint32_t) & (emac_config.dma_etx[emac_config.dirty_tx].basic.desc0) != 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 --;
|
||||
@ -317,21 +325,43 @@ void esp_eth_free_rx_buf(void *buf)
|
||||
{
|
||||
xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
|
||||
emac_clean_rx_desc(&(emac_config.dma_erx[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");
|
||||
if (emac_config.cnt_rx < 0) {
|
||||
ESP_LOGE(TAG, "emac rx buf err!!\n");
|
||||
}
|
||||
emac_poll_rx_cmd();
|
||||
|
||||
xSemaphoreGiveRecursive( emac_rx_xMutex );
|
||||
|
||||
if (emac_config.emac_flow_ctrl_partner_support == true) {
|
||||
portENTER_CRITICAL(&g_emac_mux);
|
||||
if (pause_send == true && emac_config.cnt_rx < FLOW_CONTROL_LOW_WATERMARK) {
|
||||
emac_send_pause_zero_frame_enable();
|
||||
pause_send = false;
|
||||
}
|
||||
portEXIT_CRITICAL(&g_emac_mux);
|
||||
}
|
||||
}
|
||||
|
||||
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 = (struct dma_extended_desc *)cur_rx_desc;
|
||||
|
||||
while (cur_desc->basic.desc0 == EMAC_DESC_RX_OWN) {
|
||||
cnt++;
|
||||
cur_desc = (struct dma_extended_desc *)cur_desc->basic.desc3;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
|
||||
static void emac_process_rx(void)
|
||||
{
|
||||
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
return;
|
||||
}
|
||||
uint32_t cur_rx_desc = emac_read_rx_cur_reg();
|
||||
@ -341,7 +371,7 @@ static void emac_process_rx(void)
|
||||
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_config.dma_erx[emac_config.dirty_rx]),(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
|
||||
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 ?
|
||||
@ -353,14 +383,14 @@ static void emac_process_rx(void)
|
||||
|
||||
static void emac_process_rx_unavail(void)
|
||||
{
|
||||
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t dirty_cnt = 0;
|
||||
while (dirty_cnt < DMA_RX_BUF_NUM) {
|
||||
|
||||
if(emac_config.dma_erx[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;
|
||||
}
|
||||
|
||||
@ -369,7 +399,7 @@ static void emac_process_rx_unavail(void)
|
||||
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_config.dma_erx[emac_config.dirty_rx]),(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
|
||||
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();
|
||||
@ -380,7 +410,7 @@ static void emac_process_rx_unavail(void)
|
||||
#else
|
||||
static void emac_process_rx_unavail(void)
|
||||
{
|
||||
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -392,7 +422,7 @@ static void emac_process_rx_unavail(void)
|
||||
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_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");
|
||||
}
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
@ -404,7 +434,7 @@ static void emac_process_rx_unavail(void)
|
||||
|
||||
static void emac_process_rx(void)
|
||||
{
|
||||
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -412,16 +442,16 @@ static void emac_process_rx(void)
|
||||
|
||||
xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
|
||||
if(((uint32_t) &(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
|
||||
if (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
|
||||
|
||||
while (((uint32_t) &(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc) && emac_config.cnt_rx < DMA_RX_BUF_NUM ) {
|
||||
while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc) && emac_config.cnt_rx < DMA_RX_BUF_NUM ) {
|
||||
//copy data to lwip
|
||||
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_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
|
||||
|
||||
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");
|
||||
}
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
@ -429,16 +459,16 @@ static void emac_process_rx(void)
|
||||
cur_rx_desc = emac_read_rx_cur_reg();
|
||||
}
|
||||
} else {
|
||||
if(emac_config.cnt_rx < DMA_RX_BUF_NUM) {
|
||||
if((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) == 0) {
|
||||
if (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
|
||||
if ((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) == 0) {
|
||||
while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
|
||||
|
||||
//copy data to lwip
|
||||
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_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
|
||||
emac_config.cnt_rx++;
|
||||
if(emac_config.cnt_rx > DMA_RX_BUF_NUM) {
|
||||
ESP_LOGE(TAG,"emac rx buf err!!!\n");
|
||||
if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
|
||||
ESP_LOGE(TAG, "emac rx buf err!!!\n");
|
||||
}
|
||||
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
@ -462,12 +492,18 @@ 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 ) {
|
||||
pause_send = true;
|
||||
emac_send_pause_frame_enable();
|
||||
}
|
||||
}
|
||||
emac_post(SIG_EMAC_RX_DONE, 0);
|
||||
}
|
||||
|
||||
if (event & EMAC_RECV_BUF_UNAVAIL) {
|
||||
emac_disable_rx_unavail_intr();
|
||||
emac_post(SIG_EMAC_RX_UNAVAIL,0);
|
||||
emac_post(SIG_EMAC_RX_UNAVAIL, 0);
|
||||
}
|
||||
|
||||
if (event & EMAC_TRANS_INT) {
|
||||
@ -475,25 +511,43 @@ static void IRAM_ATTR emac_process_intr(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
static void emac_set_macaddr_reg(void)
|
||||
{
|
||||
REG_SET_FIELD(EMAC_GMACADDR0HIGH_REG, EMAC_MAC_ADDRESS0_HI, (emac_config.macaddr[0] << 8) | (emac_config.macaddr[1]));
|
||||
REG_WRITE(EMAC_GMACADDR0LOW_REG, (emac_config.macaddr[2] << 24) | (emac_config.macaddr[3] << 16) | (emac_config.macaddr[4] << 8) | (emac_config.macaddr[5]));
|
||||
}
|
||||
|
||||
static void emac_check_phy_init(void)
|
||||
{
|
||||
emac_config.emac_phy_check_init();
|
||||
if(emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
|
||||
if (emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
|
||||
} else {
|
||||
REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
|
||||
}
|
||||
if(emac_config.emac_phy_get_speed_mode() == ETH_SPEED_MODE_100M) {
|
||||
if (emac_config.emac_phy_get_speed_mode() == ETH_SPEED_MODE_100M) {
|
||||
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
|
||||
} else {
|
||||
REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
|
||||
}
|
||||
|
||||
emac_mac_init();
|
||||
if (emac_config.emac_flow_ctrl_enable == true) {
|
||||
if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
|
||||
emac_enable_flowctrl();
|
||||
emac_config.emac_flow_ctrl_partner_support = true;
|
||||
} else {
|
||||
emac_disable_flowctrl();
|
||||
emac_config.emac_flow_ctrl_partner_support = false;
|
||||
}
|
||||
} else {
|
||||
emac_disable_flowctrl();
|
||||
emac_config.emac_flow_ctrl_partner_support = false;
|
||||
}
|
||||
emac_mac_enable_txrx();
|
||||
}
|
||||
static void emac_process_link_updown(bool link_status)
|
||||
{
|
||||
system_event_t evt;
|
||||
uint8_t i = 0;
|
||||
|
||||
emac_config.phy_link_up = link_status;
|
||||
|
||||
@ -502,6 +556,10 @@ static void emac_process_link_updown(bool link_status)
|
||||
ESP_LOGI(TAG, "eth link_up!!!");
|
||||
emac_enable_dma_tx();
|
||||
emac_enable_dma_rx();
|
||||
for (i = 0; i < PHY_LINK_CHECK_NUM; i++) {
|
||||
emac_check_phy_init();
|
||||
}
|
||||
|
||||
evt.event_id = SYSTEM_EVENT_ETH_CONNECTED;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "eth link_down!!!");
|
||||
@ -534,7 +592,7 @@ esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
|
||||
}
|
||||
|
||||
xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
if (emac_config.cnt_tx == DMA_TX_BUF_NUM -1) {
|
||||
if (emac_config.cnt_tx == DMA_TX_BUF_NUM - 1) {
|
||||
ESP_LOGD(TAG, "tx buf full");
|
||||
ret = ERR_MEM;
|
||||
goto _exit;
|
||||
@ -557,13 +615,13 @@ _exit:
|
||||
|
||||
static void emac_init_default_data(void)
|
||||
{
|
||||
memset((uint8_t *)&emac_config, 0,sizeof(struct emac_config_data));
|
||||
memset((uint8_t *)&emac_config, 0, sizeof(struct emac_config_data));
|
||||
}
|
||||
|
||||
void emac_process_link_check(void)
|
||||
{
|
||||
if (emac_config.emac_status != EMAC_RUNTIME_START ||
|
||||
emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
|
||||
emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -580,7 +638,7 @@ void emac_process_link_check(void)
|
||||
|
||||
void emac_link_check_func(void *pv_parameters)
|
||||
{
|
||||
emac_post(SIG_EMAC_CHECK_LINK,0);
|
||||
emac_post(SIG_EMAC_CHECK_LINK, 0);
|
||||
}
|
||||
|
||||
static bool emac_link_check_timer_init(void)
|
||||
@ -634,10 +692,13 @@ static void emac_start(void *param)
|
||||
emac_check_mac_addr();
|
||||
|
||||
emac_set_mac_addr();
|
||||
emac_set_macaddr_reg();
|
||||
|
||||
emac_set_tx_base_reg();
|
||||
emac_set_rx_base_reg();
|
||||
|
||||
emac_mac_init();
|
||||
|
||||
emac_config.phy_init();
|
||||
|
||||
//ptp TODO
|
||||
@ -818,7 +879,7 @@ void emac_task(void *pv)
|
||||
|
||||
esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
|
||||
{
|
||||
if(sig <= SIG_EMAC_RX_DONE) {
|
||||
if (sig <= SIG_EMAC_RX_DONE) {
|
||||
if (emac_sig_cnt[sig]) {
|
||||
return ESP_OK;
|
||||
} else {
|
||||
@ -831,11 +892,11 @@ esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
|
||||
|
||||
ret = xQueueSendFromISR(emac_xqueue, &evt, &tmp);
|
||||
|
||||
if(tmp != pdFALSE) {
|
||||
if (tmp != pdFALSE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
if(ret != pdPASS) {
|
||||
if (ret != pdPASS) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ typedef eth_duplex_mode_t (*eth_phy_get_duplex_mode_func)(void);
|
||||
typedef void (*eth_phy_func)(void);
|
||||
typedef esp_err_t (*eth_tcpip_input_func)(void *buffer, uint16_t len, void *eb);
|
||||
typedef void (*eth_gpio_config_func)(void);
|
||||
typedef bool (*eth_phy_get_partner_pause_enable_func)(void);
|
||||
|
||||
|
||||
/**
|
||||
@ -95,6 +96,9 @@ typedef struct {
|
||||
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_config_t;
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,7 @@ Type Definitions
|
||||
.. doxygentypedef:: eth_phy_func
|
||||
.. doxygentypedef:: eth_tcpip_input_func
|
||||
.. doxygentypedef:: eth_gpio_config_func
|
||||
.. doxygentypedef:: eth_phy_get_partner_pause_enable_func
|
||||
|
||||
Enumerations
|
||||
^^^^^^^^^^^^
|
||||
|
@ -71,6 +71,22 @@ bool phy_tlk110_check_phy_link_status(void)
|
||||
return ((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & LINK_STATUS) == LINK_STATUS );
|
||||
}
|
||||
|
||||
bool phy_tlk110_get_partner_pause_enable(void)
|
||||
{
|
||||
if((esp_eth_smi_read(PHY_LINK_PARTNER_ABILITY_REG) & PARTNER_PAUSE) == PARTNER_PAUSE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void phy_enable_flow_ctrl(void)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
data = esp_eth_smi_read(AUTO_NEG_ADVERTISEMENT_REG);
|
||||
esp_eth_smi_write(AUTO_NEG_ADVERTISEMENT_REG,data|ASM_DIR|PAUSE);
|
||||
}
|
||||
|
||||
void phy_tlk110_init(void)
|
||||
{
|
||||
esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET);
|
||||
@ -78,8 +94,12 @@ void phy_tlk110_init(void)
|
||||
while (esp_eth_smi_read(PHY_IDENTIFIER_REG) != OUI_MSB_21TO6_DEF) {
|
||||
}
|
||||
|
||||
esp_eth_smi_write(SOFTWARE_STAP_CONTROL_REG, DEFAULT_PHY_CONFIG |SW_STRAP_CONFIG_DONE);
|
||||
esp_eth_smi_write(SOFTWARE_STRAP_CONTROL_REG, DEFAULT_PHY_CONFIG |SW_STRAP_CONFIG_DONE);
|
||||
|
||||
ets_delay_us(300);
|
||||
|
||||
//if config.flow_ctrl_enable == true ,enable this
|
||||
phy_enable_flow_ctrl();
|
||||
}
|
||||
|
||||
void eth_gpio_config_rmii(void)
|
||||
@ -140,6 +160,9 @@ void app_main()
|
||||
config.phy_check_link = phy_tlk110_check_phy_link_status;
|
||||
config.phy_get_speed_mode = phy_tlk110_get_speed_mode;
|
||||
config.phy_get_duplex_mode = phy_tlk110_get_duplex_mode;
|
||||
//Only FULLDUPLEX mode support flow ctrl now!
|
||||
config.flow_ctrl_enable = true;
|
||||
config.phy_get_partner_pause_enable = phy_tlk110_get_partner_pause_enable;
|
||||
|
||||
ret = esp_eth_init(&config);
|
||||
|
||||
|
@ -5,7 +5,15 @@
|
||||
#define PHY_IDENTIFIER_REG (0x2)
|
||||
#define OUI_MSB_21TO6_DEF 0x2000
|
||||
|
||||
#define SOFTWARE_STAP_CONTROL_REG (0x9)
|
||||
#define AUTO_NEG_ADVERTISEMENT_REG (0x4)
|
||||
#define ASM_DIR BIT(11)
|
||||
#define PAUSE BIT(10)
|
||||
|
||||
#define PHY_LINK_PARTNER_ABILITY_REG (0x5)
|
||||
#define PARTNER_ASM_DIR BIT(11)
|
||||
#define PARTNER_PAUSE BIT(10)
|
||||
|
||||
#define SOFTWARE_STRAP_CONTROL_REG (0x9)
|
||||
#define SW_STRAP_CONFIG_DONE BIT(15)
|
||||
#define AUTO_MDIX_ENABLE BIT(14)
|
||||
#define AUTO_NEGOTIATION_ENABLE BIT(13)
|
||||
|
Loading…
x
Reference in New Issue
Block a user