Merge branch 'feature/ethernet_driver' into 'master'

feature/ethernet_driver: update ethernet driver



See merge request !319
This commit is contained in:
Wu Jian Gang 2016-12-26 15:50:21 +08:00
commit 3ad6dbbaa1
12 changed files with 501 additions and 203 deletions

View file

@ -4,17 +4,31 @@ menuconfig ETHERNET
help help
Enable this option to enable ethernet driver and show the menu with ethernet features. Enable this option to enable ethernet driver and show the menu with ethernet features.
config DMA_RX_BUF_NUM config DMA_RX_BUF_NUM
int "Dma Rx Buf Num" int "DMA Rx Buf Num"
default 10 default 10
depends on ETHERNET depends on ETHERNET
help help
Dma rx buf num ,can not be 0 . Dma rx buf num ,can not be 0 .
config DMA_TX_BUF_NUM config DMA_TX_BUF_NUM
int "Dma Tx Buf Num" int "DMA Tx Buf Num"
default 10 default 10
depends on ETHERNET depends on ETHERNET
help help
Dma tx Buf num ,can not be 0. Dma tx Buf num ,can not be 0.
config EMAC_L2_TO_L3_RX_BUF_MODE
bool "L2 To L3 RX BUF COPY MODE"
default n
depends on ETHERNET
help
Receive Buf user copy mode or pointer mode.
config EMAC_TASK_PRIORITY
int "EMAC_TASK_PRIORITY"
default 20
depends on ETHERNET
help
Emac task priority ,suggest 3 ~ 23.

View file

@ -19,6 +19,7 @@
#include "esp_err.h" #include "esp_err.h"
#include "emac_dev.h" #include "emac_dev.h"
#include "esp_eth.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -32,11 +33,6 @@ typedef struct {
emac_par_t par; emac_par_t par;
} emac_event_t; } emac_event_t;
enum emac_mode {
EMAC_MODE_RMII = 0,
EMAC_MDOE_MII,
};
enum emac_runtime_status { enum emac_runtime_status {
EMAC_RUNTIME_NOT_INIT = 0, EMAC_RUNTIME_NOT_INIT = 0,
EMAC_RUNTIME_INIT, EMAC_RUNTIME_INIT,
@ -45,36 +41,37 @@ enum emac_runtime_status {
}; };
enum { enum {
SIG_EMAC_RX_UNAVAIL,
SIG_EMAC_TX_DONE, SIG_EMAC_TX_DONE,
SIG_EMAC_RX_DONE, SIG_EMAC_RX_DONE,
SIG_EMAC_TX,
SIG_EMAC_START, SIG_EMAC_START,
SIG_EMAC_STOP, SIG_EMAC_STOP,
SIG_EMAC_CHECK_LINK,
SIG_EMAC_MAX SIG_EMAC_MAX
}; };
typedef void (*emac_phy_fun)(void);
typedef esp_err_t (*emac_tcpip_input_fun)(void *buffer, uint16_t len, void *eb);
typedef void (*emac_gpio_config_func)(void);
struct emac_config_data { struct emac_config_data {
unsigned int phy_addr; eth_phy_base_t phy_addr;
enum emac_mode mac_mode; eth_mode_t mac_mode;
struct dma_extended_desc *dma_etx; struct dma_extended_desc *dma_etx;
unsigned int cur_tx; uint32_t cur_tx;
unsigned int dirty_tx; uint32_t dirty_tx;
signed int cnt_tx; int32_t cnt_tx;
struct dma_extended_desc *dma_erx; struct dma_extended_desc *dma_erx;
unsigned int cur_rx; uint32_t cur_rx;
unsigned int dirty_rx; uint32_t dirty_rx;
signed int cnt_rx; int32_t cnt_rx;
unsigned int rx_need_poll; uint32_t rx_need_poll;
bool phy_link_up; bool phy_link_up;
enum emac_runtime_status emac_status; enum emac_runtime_status emac_status;
uint8_t macaddr[6]; uint8_t macaddr[6];
emac_phy_fun phy_init; eth_phy_func phy_init;
emac_tcpip_input_fun emac_tcpip_input; eth_tcpip_input_func emac_tcpip_input;
emac_gpio_config_func emac_gpio_config; eth_gpio_config_func emac_gpio_config;
eth_phy_check_link_func emac_phy_check_link;
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;
}; };
enum emac_post_type { enum emac_post_type {
@ -103,18 +100,15 @@ struct emac_close_cmd {
#if CONFIG_ETHERNET #if CONFIG_ETHERNET
#define DMA_RX_BUF_NUM CONFIG_DMA_RX_BUF_NUM #define DMA_RX_BUF_NUM CONFIG_DMA_RX_BUF_NUM
#define DMA_TX_BUF_NUM CONFIG_DMA_TX_BUF_NUM #define DMA_TX_BUF_NUM CONFIG_DMA_TX_BUF_NUM
#define EMAC_TASK_PRIORITY CONFIG_EMAC_TASK_PRIORITY
#else #else
#define DMA_RX_BUF_NUM 1 #define DMA_RX_BUF_NUM 1
#define DMA_TX_BUF_NUM 1 #define DMA_TX_BUF_NUM 1
#define EMAC_TASK_PRIORITY 10
#endif #endif
#define DMA_RX_BUF_SIZE 1600 #define DMA_RX_BUF_SIZE 1600
#define DMA_TX_BUF_SIZE 1600 #define DMA_TX_BUF_SIZE 1600
//lwip err
#define ERR_OK 0
#define ERR_MEM -1
#define ERR_IF -16
#define EMAC_CMD_OK 0 #define EMAC_CMD_OK 0
#define EMAC_CMD_FAIL -1 #define EMAC_CMD_FAIL -1

View file

@ -34,18 +34,6 @@
static const char *TAG = "emac"; static const char *TAG = "emac";
void emac_poll_tx_cmd(void)
{
//write any to wake up dma
REG_WRITE(EMAC_DMATXPOLLDEMAND_REG, 1);
}
void emac_poll_rx_cmd(void)
{
//write any to wake up dma
REG_WRITE(EMAC_DMARXPOLLDEMAND_REG, 1);
}
void emac_enable_dma_tx(void) void emac_enable_dma_tx(void)
{ {
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND); REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND);
@ -66,15 +54,6 @@ void emac_disable_dma_rx(void)
REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RECEIVE); REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RECEIVE);
} }
uint32_t emac_read_tx_cur_reg(void)
{
return REG_READ(EMAC_DMATXCURRDESC_REG);
}
uint32_t emac_read_rx_cur_reg(void)
{
return REG_READ(EMAC_DMARXCURRDESC_REG);
}
uint32_t emac_read_mac_version(void) uint32_t emac_read_mac_version(void)
{ {
@ -121,16 +100,18 @@ 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_FORWARD_UNDERSIZED_GOOD_FRAMES);
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPERATE_SECOND_FRAME); REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPERATE_SECOND_FRAME);
REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_PROG_BURST_LEN, 4); REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_PROG_BURST_LEN, 4);
REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG,EMAC_DMAOPERATION_MODE_REG);
} }
void emac_mac_init(void) void emac_mac_init(void)
{ {
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACRX);
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACTX);
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX); REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACMIIGMII); REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACMIIGMII);
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED); REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED);
REG_SET_BIT(EMAC_GMACFRAMEFILTER_REG, EMAC_PROMISCUOUS_MODE); 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) void emac_set_clk_rmii(void)

View file

@ -49,14 +49,52 @@ uint32_t emac_read_mac_version(void);
void emac_dma_init(void); void emac_dma_init(void);
void emac_mac_init(void); void emac_mac_init(void);
void emac_enable_dma_tx(void); void emac_enable_dma_tx(void);
void emac_poll_tx_cmd(void);
uint32_t emac_read_tx_cur_reg(void);
void emac_enable_dma_rx(void); void emac_enable_dma_rx(void);
uint32_t emac_read_rx_cur_reg(void);
void emac_poll_rx_cmd(void);
void emac_disable_dma_tx(void); void emac_disable_dma_tx(void);
void emac_disable_dma_rx(void); void emac_disable_dma_rx(void);
uint32_t inline emac_read_tx_cur_reg(void)
{
return REG_READ(EMAC_DMATXCURRDESC_REG);
}
uint32_t inline emac_read_rx_cur_reg(void)
{
return REG_READ(EMAC_DMARXCURRDESC_REG);
}
void inline emac_poll_tx_cmd(void)
{
//write any to wake up dma
REG_WRITE(EMAC_DMATXPOLLDEMAND_REG, 1);
}
void inline emac_poll_rx_cmd(void)
{
//write any to wake up dma
REG_WRITE(EMAC_DMARXPOLLDEMAND_REG, 1);
}
void inline emac_disable_rx_intr(void)
{
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);
}
void inline emac_disable_rx_unavail_intr(void)
{
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);
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -47,6 +47,8 @@
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "freertos/timers.h" #include "freertos/timers.h"
#include "lwip/err.h"
#define EMAC_EVT_QNUM 200 #define EMAC_EVT_QNUM 200
#define EMAC_SIG_MAX 50 #define EMAC_SIG_MAX 50
@ -63,7 +65,8 @@ static xTaskHandle emac_task_hdl;
static xQueueHandle emac_xqueue; static xQueueHandle emac_xqueue;
static uint8_t emac_sig_cnt[EMAC_SIG_MAX] = {0}; static uint8_t emac_sig_cnt[EMAC_SIG_MAX] = {0};
static TimerHandle_t emac_timer = NULL; 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 const char *TAG = "emac";
static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par); static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par);
@ -82,20 +85,24 @@ void esp_eth_get_mac(uint8_t mac[6])
static void emac_setup_tx_desc(struct dma_extended_desc *tx_desc , uint32_t size) static void emac_setup_tx_desc(struct dma_extended_desc *tx_desc , uint32_t size)
{ {
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.desc1 = size & 0xfff; tx_desc->basic.desc1 = size & 0xfff;
tx_desc->basic.desc0 = 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(struct dma_extended_desc *tx_desc)
{ {
tx_desc->basic.desc0 = 0;
tx_desc->basic.desc1 = 0; tx_desc->basic.desc1 = 0;
tx_desc->basic.desc0 = 0;
} }
static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc) static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc ,uint32_t buf_ptr)
{ {
rx_desc->basic.desc0 = EMAC_DESC_RX_OWN; if(buf_ptr != 0) {
rx_desc->basic.desc2 = buf_ptr;
}
rx_desc->basic.desc1 = EMAC_DESC_RX_SECOND_ADDR_CHAIN | DMA_RX_BUF_SIZE; rx_desc->basic.desc1 = EMAC_DESC_RX_SECOND_ADDR_CHAIN | DMA_RX_BUF_SIZE;
rx_desc->basic.desc0 = EMAC_DESC_RX_OWN;
} }
static void emac_set_tx_base_reg(void) static void emac_set_tx_base_reg(void)
@ -156,18 +163,15 @@ static void emac_init_dma_chain(void)
dma_phy = (uint32_t)(emac_config.dma_erx); dma_phy = (uint32_t)(emac_config.dma_erx);
p = emac_config.dma_erx; p = emac_config.dma_erx;
for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++ ) { for (i = 0; i < (DMA_RX_BUF_NUM - 1); i++ ) {
dma_phy += sizeof(struct dma_extended_desc); dma_phy += sizeof(struct dma_extended_desc);
emac_clean_rx_desc(p); emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
p->basic.desc3 = dma_phy; p->basic.desc3 = dma_phy;
p->basic.desc2 = (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE);
p++; p++;
} }
p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
p->basic.desc2 = (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE);
//init desc0 desc1 emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
emac_clean_rx_desc(p); p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
} }
void esp_eth_smi_write(uint32_t reg_num, uint16_t value) void esp_eth_smi_write(uint32_t reg_num, uint16_t value)
@ -207,18 +211,32 @@ static void emac_set_user_config_data(eth_config_t *config )
emac_config.phy_init = config->phy_init; emac_config.phy_init = config->phy_init;
emac_config.emac_tcpip_input = config->tcpip_input; emac_config.emac_tcpip_input = config->tcpip_input;
emac_config.emac_gpio_config = config->gpio_config; emac_config.emac_gpio_config = config->gpio_config;
emac_config.emac_phy_check_link = config->phy_check_link;
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;
}
static void emac_enable_intr()
{
REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, EMAC_INTR_ENABLE_BIT);
}
static void emac_disable_intr()
{
REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, 0);
} }
static esp_err_t emac_verify_args(void) static esp_err_t emac_verify_args(void)
{ {
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
if (emac_config.phy_addr > 31) { if (emac_config.phy_addr > PHY31) {
ESP_LOGE(TAG, "phy addr err"); ESP_LOGE(TAG, "phy addr err");
ret = ESP_FAIL; ret = ESP_FAIL;
} }
if (emac_config.mac_mode != EMAC_MODE_RMII) { if (emac_config.mac_mode != ETH_MODE_RMII) {
ESP_LOGE(TAG, "mac mode err,now only support RMII"); ESP_LOGE(TAG, "mac mode err,now only support RMII");
ret = ESP_FAIL; ret = ESP_FAIL;
} }
@ -238,6 +256,26 @@ static esp_err_t emac_verify_args(void)
ret = ESP_FAIL; ret = ESP_FAIL;
} }
if (emac_config.emac_phy_check_link == NULL) {
ESP_LOGE(TAG, "phy check link func is null");
ret = ESP_FAIL;
}
if (emac_config.emac_phy_check_init == NULL) {
ESP_LOGE(TAG, "phy check init func is null");
ret = ESP_FAIL;
}
if (emac_config.emac_phy_get_speed_mode == NULL) {
ESP_LOGE(TAG, "phy get speed mode func is null");
ret = ESP_FAIL;
}
if (emac_config.emac_phy_get_duplex_mode == NULL) {
ESP_LOGE(TAG, "phy get duplex mode func is null");
ret = ESP_FAIL;
}
return ret; return ret;
} }
@ -255,6 +293,12 @@ static void emac_process_tx(void)
{ {
uint32_t cur_tx_desc = emac_read_tx_cur_reg(); uint32_t cur_tx_desc = emac_read_tx_cur_reg();
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_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;
@ -263,11 +307,33 @@ static void emac_process_tx(void)
if (emac_config.cnt_tx < 0) { if (emac_config.cnt_tx < 0) {
ESP_LOGE(TAG, "emac tx chain err"); ESP_LOGE(TAG, "emac tx chain err");
} }
} cur_tx_desc = emac_read_tx_cur_reg();
} }
xSemaphoreGiveRecursive( emac_tx_xMutex );
}
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_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");
}
emac_poll_rx_cmd();
xSemaphoreGiveRecursive( emac_rx_xMutex );
}
#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
static void emac_process_rx(void) static void emac_process_rx(void)
{ {
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
return;
}
uint32_t cur_rx_desc = emac_read_rx_cur_reg(); uint32_t cur_rx_desc = emac_read_rx_cur_reg();
while (((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)) {
@ -275,16 +341,115 @@ static void emac_process_rx(void)
emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2), 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_clean_rx_desc(&(emac_config.dma_erx[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_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
if (emac_config.rx_need_poll != 0) {
emac_poll_rx_cmd();
emac_config.rx_need_poll = 0;
}
//if open this ,one intr can do many intrs ? //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();
}
emac_enable_rx_intr();
}
static void emac_process_rx_unavail(void)
{
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) {
break;
}
dirty_cnt ++;
//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_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();
emac_enable_rx_unavail_intr();
emac_poll_rx_cmd();
}
#else
static void emac_process_rx_unavail(void)
{
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
return;
}
xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
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.cnt_rx++;
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;
}
emac_enable_rx_intr();
emac_enable_rx_unavail_intr();
xSemaphoreGiveRecursive( emac_rx_xMutex );
}
static void emac_process_rx(void)
{
if(emac_config.emac_status == EMAC_RUNTIME_STOP) {
return;
}
uint32_t cur_rx_desc = emac_read_rx_cur_reg();
xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
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 ) {
//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.cnt_rx++;
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;
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) {
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.cnt_rx++;
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;
} }
} }
}
}
emac_enable_rx_intr();
xSemaphoreGiveRecursive( emac_rx_xMutex );
}
#endif
//TODO other events need to do something //TODO other events need to do something
static void IRAM_ATTR emac_process_intr(void *arg) static void IRAM_ATTR emac_process_intr(void *arg)
@ -295,35 +460,37 @@ static void IRAM_ATTR emac_process_intr(void *arg)
//clr intrs //clr intrs
REG_WRITE(EMAC_DMASTATUS_REG, event); REG_WRITE(EMAC_DMASTATUS_REG, event);
if (event & EMAC_RECV_BUF_UNAVAIL) { if (event & EMAC_RECV_INT) {
emac_config.rx_need_poll = 1; emac_disable_rx_intr();
} else if (event & EMAC_TRANS_INT) {
emac_post(SIG_EMAC_TX_DONE, 0);
} else if (event & EMAC_RECV_INT) {
emac_post(SIG_EMAC_RX_DONE, 0); 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);
}
if (event & EMAC_TRANS_INT) {
emac_post(SIG_EMAC_TX_DONE, 0);
}
}
static void emac_check_phy_init(void)
{
emac_config.emac_phy_check_init();
if(emac_config.emac_phy_get_duplex_mode() == ETH_MDOE_FULLDUPLEX) {
REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
} else { } else {
//other events REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX);
} }
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);
} }
//ToDo: this should only be called once because this allocates the interrupt as well. emac_mac_init();
static void emac_enable_intr()
{
//init emac intr
esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, EMAC_INTR_ENABLE_BIT);
} }
static void emac_disable_intr()
{
REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, 0);
}
static bool emac_check_phy_link_status(void)
{
return ((esp_eth_smi_read(1) & 0x4) == 0x4 );
}
static void emac_process_link_updown(bool link_status) static void emac_process_link_updown(bool link_status)
{ {
system_event_t evt; system_event_t evt;
@ -331,10 +498,10 @@ 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 == true) {
emac_check_phy_init();
ESP_LOGI(TAG, "eth link_up!!!"); ESP_LOGI(TAG, "eth link_up!!!");
emac_enable_dma_tx(); emac_enable_dma_tx();
emac_enable_dma_rx(); emac_enable_dma_rx();
ets_delay_us(200000);
evt.event_id = SYSTEM_EVENT_ETH_CONNECTED; evt.event_id = SYSTEM_EVENT_ETH_CONNECTED;
} else { } else {
ESP_LOGI(TAG, "eth link_down!!!"); ESP_LOGI(TAG, "eth link_down!!!");
@ -356,26 +523,20 @@ static void emac_hw_init(void)
//ipc TODO //ipc TODO
} }
static esp_err_t emac_xmit(void *param) esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
{ {
struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)param;
struct emac_tx_cmd *cmd = (struct emac_tx_cmd *)(post_cmd->cmd);
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
void *buf = cmd->buf;
uint16_t size = cmd->size;
if (emac_config.emac_status != EMAC_RUNTIME_START || emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) { if (emac_config.emac_status != EMAC_RUNTIME_START || emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
ESP_LOGI(TAG, "tx netif close"); ESP_LOGI(TAG, "tx netif close");
cmd->err = ERR_IF; ret = ERR_IF;
ret = ESP_FAIL;
goto _exit; goto _exit;
} }
if (emac_config.cnt_tx == DMA_TX_BUF_NUM) { xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
ESP_LOGI(TAG, "tx buf full"); if (emac_config.cnt_tx == DMA_TX_BUF_NUM -1) {
cmd->err = ERR_MEM; ESP_LOGD(TAG, "tx buf full");
ret = ESP_FAIL; ret = ERR_MEM;
goto _exit; goto _exit;
} }
@ -390,26 +551,23 @@ static esp_err_t emac_xmit(void *param)
_exit: _exit:
if (post_cmd->post_type == EMAC_POST_SYNC) { xSemaphoreGiveRecursive( emac_tx_xMutex );
xSemaphoreGive(emac_g_sem);
}
return ret; return ret;
} }
static void emac_init_default_data(void) static void emac_init_default_data(void)
{ {
emac_config.rx_need_poll = 0; memset((uint8_t *)&emac_config, 0,sizeof(struct emac_config_data));
} }
void emac_link_check_func(void *pv_parameters) void emac_process_link_check(void)
{ {
if (emac_config.emac_status != EMAC_RUNTIME_START || 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; return;
} }
if (emac_check_phy_link_status() == true ) { if (emac_config.emac_phy_check_link() == true ) {
if (emac_config.phy_link_up == false) { if (emac_config.phy_link_up == false) {
emac_process_link_updown(true); emac_process_link_updown(true);
} }
@ -420,9 +578,14 @@ void emac_link_check_func(void *pv_parameters)
} }
} }
void emac_link_check_func(void *pv_parameters)
{
emac_post(SIG_EMAC_CHECK_LINK,0);
}
static bool emac_link_check_timer_init(void) static bool emac_link_check_timer_init(void)
{ {
emac_timer = xTimerCreate("emac_timer", (1000 / portTICK_RATE_MS), emac_timer = xTimerCreate("emac_timer", (2000 / portTICK_RATE_MS),
pdTRUE, (void *)rand(), emac_link_check_func); pdTRUE, (void *)rand(), emac_link_check_func);
if (emac_timer == NULL) { if (emac_timer == NULL) {
return false; return false;
@ -473,18 +636,11 @@ static void emac_start(void *param)
emac_set_tx_base_reg(); emac_set_tx_base_reg();
emac_set_rx_base_reg(); emac_set_rx_base_reg();
emac_mac_init();
emac_config.phy_init(); emac_config.phy_init();
//for test
//emac_wait_linkup();
//mmc not support
//ptp TODO //ptp TODO
//enable emac intr
emac_enable_intr(); emac_enable_intr();
emac_config.emac_status = EMAC_RUNTIME_START; emac_config.emac_status = EMAC_RUNTIME_START;
@ -573,7 +729,7 @@ esp_err_t esp_eth_disable(void)
return close_cmd.err; return close_cmd.err;
} }
if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) { if (emac_config.emac_status == EMAC_RUNTIME_START) {
if (emac_ioctl(SIG_EMAC_STOP, (emac_par_t)(&post_cmd)) != 0) { if (emac_ioctl(SIG_EMAC_STOP, (emac_par_t)(&post_cmd)) != 0) {
close_cmd.err = EMAC_CMD_FAIL; close_cmd.err = EMAC_CMD_FAIL;
} }
@ -608,9 +764,6 @@ static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par)
case SIG_EMAC_TX_DONE: case SIG_EMAC_TX_DONE:
emac_process_tx(); emac_process_tx();
break; break;
case SIG_EMAC_TX:
emac_xmit((void *)par);
break;
case SIG_EMAC_START: case SIG_EMAC_START:
emac_start((void *)par); emac_start((void *)par);
break; break;
@ -626,29 +779,6 @@ static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par)
return ret; return ret;
} }
esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
{
struct emac_post_cmd post_cmd;
struct emac_tx_cmd tx_cmd;
post_cmd.cmd = (void *)(&tx_cmd);
if (emac_check_phy_link_status() == false) {
emac_process_link_updown(false);
tx_cmd.err = ERR_IF;
} else {
tx_cmd.buf = buf;
tx_cmd.size = size;
tx_cmd.err = ERR_OK;
if (emac_ioctl(SIG_EMAC_TX, (emac_par_t)(&post_cmd)) != 0) {
tx_cmd.err = ERR_MEM;
}
}
return tx_cmd.err;
}
void emac_task(void *pv) void emac_task(void *pv)
{ {
emac_event_t e; emac_event_t e;
@ -662,18 +792,21 @@ void emac_task(void *pv)
case SIG_EMAC_RX_DONE: case SIG_EMAC_RX_DONE:
emac_process_rx(); emac_process_rx();
break; break;
case SIG_EMAC_RX_UNAVAIL:
emac_process_rx_unavail();
break;
case SIG_EMAC_TX_DONE: case SIG_EMAC_TX_DONE:
emac_process_tx(); emac_process_tx();
break; break;
case SIG_EMAC_TX:
emac_xmit((void *)e.par);
break;
case SIG_EMAC_START: case SIG_EMAC_START:
emac_start((void *)e.par); emac_start((void *)e.par);
break; break;
case SIG_EMAC_STOP: case SIG_EMAC_STOP:
emac_stop((void *)e.par); emac_stop((void *)e.par);
break; break;
case SIG_EMAC_CHECK_LINK:
emac_process_link_check();
break;
default: default:
ESP_LOGE(TAG, "unexpect sig %d", e.sig); ESP_LOGE(TAG, "unexpect sig %d", e.sig);
break; break;
@ -684,29 +817,37 @@ void emac_task(void *pv)
esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par) esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
{ {
portENTER_CRITICAL(&g_emac_mux); if(sig <= SIG_EMAC_RX_DONE) {
if (emac_sig_cnt[sig]) {
if (emac_sig_cnt[sig] && sig != SIG_EMAC_TX) {
portEXIT_CRITICAL(&g_emac_mux);
return ESP_OK; return ESP_OK;
} else { } else {
emac_sig_cnt[sig]++; emac_sig_cnt[sig]++;
portEXIT_CRITICAL(&g_emac_mux); emac_event_t evt;
signed portBASE_TYPE ret;
evt.sig = sig;
evt.par = par;
portBASE_TYPE tmp;
ret = xQueueSendFromISR(emac_xqueue, &evt, &tmp);
if(tmp != pdFALSE) {
portYIELD_FROM_ISR();
}
if(ret != pdPASS) {
return ESP_FAIL;
}
}
} else {
emac_sig_cnt[sig]++;
emac_event_t evt; emac_event_t evt;
evt.sig = sig; evt.sig = sig;
evt.par = par; evt.par = par;
if (sig <= SIG_EMAC_RX_DONE) {
portBASE_TYPE tmp;
if (xQueueSendFromISR(emac_xqueue, &evt, &tmp) != pdPASS) {
return ESP_FAIL;
}
} else {
if (xQueueSend(emac_xqueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) { if (xQueueSend(emac_xqueue, &evt, 10 / portTICK_RATE_MS) != pdTRUE) {
return ESP_FAIL; return ESP_FAIL;
} }
} }
}
return ESP_OK; return ESP_OK;
} }
@ -737,7 +878,7 @@ esp_err_t esp_eth_init(eth_config_t *config)
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(); emac_dma_init();
if (emac_config.mac_mode == EMAC_MODE_RMII) { if (emac_config.mac_mode == ETH_MODE_RMII) {
emac_set_clk_rmii(); emac_set_clk_rmii();
} else { } else {
emac_set_clk_mii(); emac_set_clk_mii();
@ -752,8 +893,12 @@ esp_err_t esp_eth_init(eth_config_t *config)
//init task for emac //init task for emac
emac_g_sem = xSemaphoreCreateBinary(); emac_g_sem = xSemaphoreCreateBinary();
emac_rx_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", 2048 * 4, NULL, (19), &emac_task_hdl); xTaskCreate(emac_task, "emacT", 2048, NULL, EMAC_TASK_PRIORITY, &emac_task_hdl);
esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
emac_reset(); emac_reset();
emac_enable_clk(false); emac_enable_clk(false);

View file

@ -22,15 +22,21 @@
extern "C" { extern "C" {
#endif #endif
typedef void (*eth_phy_fun)(void);
typedef esp_err_t (*eth_tcpip_input_fun)(void *buffer, uint16_t len, void *eb);
typedef void (*eth_gpio_config_func)(void);
typedef enum { typedef enum {
ETH_MODE_RMII = 0, ETH_MODE_RMII = 0,
ETH_MDOE_MII, ETH_MDOE_MII,
} eth_mode_t; } eth_mode_t;
typedef enum {
ETH_SPEED_MODE_10M = 0,
ETH_SPEED_MODE_100M,
} eth_speed_mode_t;
typedef enum {
ETH_MODE_HALFDUPLEX = 0,
ETH_MDOE_FULLDUPLEX,
} eth_duplex_mode_t;
typedef enum { typedef enum {
PHY0 = 0, PHY0 = 0,
PHY1, PHY1,
@ -66,6 +72,15 @@ typedef enum {
PHY31, PHY31,
} eth_phy_base_t; } eth_phy_base_t;
typedef bool (*eth_phy_check_link_func)(void);
typedef void (*eth_phy_check_init_func)(void);
typedef eth_speed_mode_t (*eth_phy_get_speed_mode_func)(void);
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);
/** /**
* @brief ethernet configuration * @brief ethernet configuration
* *
@ -73,8 +88,12 @@ typedef enum {
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_tcpip_input_fun tcpip_input; /*!< tcpip input func */ eth_tcpip_input_func tcpip_input; /*!< tcpip input func */
eth_phy_fun 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_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 */ eth_gpio_config_func gpio_config; /*!< gpio config func */
} eth_config_t; } eth_config_t;
@ -159,6 +178,16 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value);
*/ */
uint16_t esp_eth_smi_read(uint32_t reg_num); uint16_t esp_eth_smi_read(uint32_t reg_num);
/**
* @brief Free emac rx buf.
*
* @note buf can not be null,and it is tcpip input buf.
*
* @param[in] buf: start address of recevie packet data.
*
*/
void esp_eth_free_rx_buf(void *buf);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -80,6 +80,7 @@
#if ESP_LWIP #if ESP_LWIP
#include "esp_wifi_internal.h" #include "esp_wifi_internal.h"
#include "esp_eth.h"
#endif #endif
#define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf)) #define SIZEOF_STRUCT_PBUF LWIP_MEM_ALIGN_SIZE(sizeof(struct pbuf))
@ -351,7 +352,8 @@ pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
p->flags = 0; p->flags = 0;
#if ESP_LWIP #if ESP_LWIP
p->eb = NULL; p->user_buf = NULL;
p->user_flag = PBUF_USER_FLAG_OWNER_NULL;
#endif #endif
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p)); LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_alloc(length=%"U16_F") == %p\n", length, (void *)p));
@ -720,9 +722,13 @@ pbuf_free(struct pbuf *p)
} else if (type == PBUF_ROM || type == PBUF_REF) { } else if (type == PBUF_ROM || type == PBUF_REF) {
#if ESP_LWIP #if ESP_LWIP
if (type == PBUF_REF && p->eb != NULL ) esp_wifi_internal_free_rx_buffer(p->eb); if (type == PBUF_REF && p->user_flag == PBUF_USER_FLAG_OWNER_WIFI ) {
esp_wifi_internal_free_rx_buffer(p->user_buf);
}
if (type == PBUF_REF && p->user_flag == PBUF_USER_FLAG_OWNER_ETH ) {
esp_eth_free_rx_buf(p->user_buf);
}
#endif #endif
memp_free(MEMP_PBUF, p); memp_free(MEMP_PBUF, p);
/* type == PBUF_RAM */ /* type == PBUF_RAM */
} else { } else {

View file

@ -105,6 +105,12 @@ typedef enum {
/** indicates this pbuf includes a TCP FIN flag */ /** indicates this pbuf includes a TCP FIN flag */
#define PBUF_FLAG_TCP_FIN 0x20U #define PBUF_FLAG_TCP_FIN 0x20U
#if ESP_LWIP
#define PBUF_USER_FLAG_OWNER_NULL 0
#define PBUF_USER_FLAG_OWNER_WIFI 1
#define PBUF_USER_FLAG_OWNER_ETH 2
#endif
struct pbuf { struct pbuf {
/** next pbuf in singly linked pbuf chain */ /** next pbuf in singly linked pbuf chain */
struct pbuf *next; struct pbuf *next;
@ -138,7 +144,8 @@ struct pbuf {
u16_t ref; u16_t ref;
#if ESP_LWIP #if ESP_LWIP
void *eb; void *user_buf;
u8_t user_flag;
#endif #endif
}; };

View file

@ -113,7 +113,8 @@ ethernet_low_level_output(struct netif *netif, struct pbuf *p)
esp_interface_t eth_if = tcpip_adapter_get_esp_if(netif); esp_interface_t eth_if = tcpip_adapter_get_esp_if(netif);
if (eth_if != ESP_IF_ETH) { if (eth_if != ESP_IF_ETH) {
printf("eth_if=%d netif=%p pbuf=%p len=%d\n", eth_if, netif, p, p->len); LWIP_DEBUGF(NETIF_DEBUG,("eth_if=%d netif=%p pbuf=%p len=%d\n", eth_if, netif, p, p->len));
return ERR_IF; return ERR_IF;
} }
@ -134,7 +135,6 @@ ethernet_low_level_output(struct netif *netif, struct pbuf *p)
} }
} }
//printf("netif=%p pbuf=%p len=%d\n", netif, p, p->len);
return esp_eth_tx(q->payload, pbuf_x_len); return esp_eth_tx(q->payload, pbuf_x_len);
#else #else
for(q = p; q != NULL; q = q->next) { for(q = p; q != NULL; q = q->next) {
@ -160,7 +160,7 @@ ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
if(buffer== NULL || netif == NULL) if(buffer== NULL || netif == NULL)
goto _exit; goto _exit;
#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM);
if (p == NULL) { if (p == NULL) {
//g_rx_alloc_pbuf_fail_cnt++; //g_rx_alloc_pbuf_fail_cnt++;
@ -174,6 +174,22 @@ ethernetif_input(struct netif *netif, void *buffer, uint16_t len)
pbuf_free(p); pbuf_free(p);
} }
#else
p = pbuf_alloc(PBUF_RAW, len, PBUF_REF);
if (p == NULL){
return;
}
p->payload = buffer;
p->user_flag = PBUF_USER_FLAG_OWNER_ETH;
p->user_buf = buffer;
/* 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->user_flag = PBUF_USER_FLAG_OWNER_NULL;
pbuf_free(p);
}
#endif
_exit: _exit:
; ;
} }

View file

@ -176,7 +176,8 @@ wlanif_input(struct netif *netif, void *buffer, u16_t len, void* eb)
return; return;
} }
p->payload = buffer; p->payload = buffer;
p->eb = eb; p->user_buf = eb;
p->user_flag = PBUF_USER_FLAG_OWNER_WIFI;
#endif #endif
/* full packet send to tcpip_thread to process */ /* full packet send to tcpip_thread to process */

View file

@ -0,0 +1,28 @@
#define BASIC_MODE_STATUS_REG (0x1)
#define AUTO_NEGOTIATION_COMPLETE BIT(5)
#define LINK_STATUS BIT(2)
#define PHY_IDENTIFIER_REG (0x2)
#define OUI_MSB_21TO6_DEF 0x2000
#define SOFTWARE_STAP_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 PHY_STATUS_REG (0x10)
#define AUTO_NEGTIATION_STATUS BIT(4)
#define DUPLEX_STATUS BIT(2)
#define SPEED_STATUS BIT(1)
#define CABLE_DIAGNOSTIC_CONTROL_REG (0x1e)
#define DIAGNOSTIC_DONE BIT(1)
#define PHY_RESET_CONTROL_REG (0x1f)
#define SOFTWARE_RESET BIT(15)

View file

@ -32,30 +32,64 @@
#include "tcpip_adapter.h" #include "tcpip_adapter.h"
#include "nvs_flash.h" #include "nvs_flash.h"
#include "driver/gpio.h" #include "driver/gpio.h"
#include "tlk110_phy.h"
static const char *TAG = "eth_demo"; static const char *TAG = "eth_demo";
void phy_tlk110_init(void) #define DEFAULT_PHY_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG)
{
esp_eth_smi_write(0x1f, 0x8000);
ets_delay_us(20000);
while (esp_eth_smi_read(0x2) != 0x2000) { void phy_tlk110_check_phy_init(void)
{
while((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & AUTO_NEGOTIATION_COMPLETE ) != AUTO_NEGOTIATION_COMPLETE)
{};
while((esp_eth_smi_read(PHY_STATUS_REG) & AUTO_NEGTIATION_STATUS ) != AUTO_NEGTIATION_STATUS)
{};
while((esp_eth_smi_read(CABLE_DIAGNOSTIC_CONTROL_REG) & DIAGNOSTIC_DONE ) != DIAGNOSTIC_DONE)
{};
} }
esp_eth_smi_write(0x9, 0x7400); eth_speed_mode_t phy_tlk110_get_speed_mode(void)
esp_eth_smi_write(0x9, 0xf400); {
ets_delay_us(20000); if((esp_eth_smi_read(PHY_STATUS_REG) & SPEED_STATUS ) != SPEED_STATUS) {
return ETH_SPEED_MODE_100M;
} else {
return ETH_SPEED_MODE_10M;
}
}
eth_duplex_mode_t phy_tlk110_get_duplex_mode(void)
{
if((esp_eth_smi_read(PHY_STATUS_REG) & DUPLEX_STATUS ) == DUPLEX_STATUS) {
return ETH_MDOE_FULLDUPLEX;
} else {
return ETH_MODE_HALFDUPLEX;
}
}
bool phy_tlk110_check_phy_link_status(void)
{
return ((esp_eth_smi_read(BASIC_MODE_STATUS_REG) & LINK_STATUS) == LINK_STATUS );
}
void phy_tlk110_init(void)
{
esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET);
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);
ets_delay_us(300);
} }
void eth_gpio_config_rmii(void) void eth_gpio_config_rmii(void)
{ {
//txd0 to gpio19 ,can not change //txd0 to gpio19 ,can not change
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, 5); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
//rx_en to gpio21 ,can not change //tx_en to gpio21 ,can not change
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, 5); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
//txd1 to gpio22 , can not change //txd1 to gpio22 , can not change
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, 5); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
//rxd0 to gpio25 , can not change //rxd0 to gpio25 , can not change
gpio_set_direction(25, GPIO_MODE_INPUT); gpio_set_direction(25, GPIO_MODE_INPUT);
//rxd1 to gpio26 ,can not change //rxd1 to gpio26 ,can not change
@ -102,8 +136,13 @@ void app_main()
config.phy_init = phy_tlk110_init; config.phy_init = phy_tlk110_init;
config.gpio_config = eth_gpio_config_rmii; config.gpio_config = eth_gpio_config_rmii;
config.tcpip_input = tcpip_adapter_eth_input; config.tcpip_input = tcpip_adapter_eth_input;
config.phy_check_init = phy_tlk110_check_phy_init;
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;
ret = esp_eth_init(&config); ret = esp_eth_init(&config);
if(ret == ESP_OK) { if(ret == ESP_OK) {
esp_eth_enable(); esp_eth_enable();
xTaskCreate(eth_task, "eth_task", 2048, NULL, (tskIDLE_PRIORITY + 2), NULL); xTaskCreate(eth_task, "eth_task", 2048, NULL, (tskIDLE_PRIORITY + 2), NULL);