Merge branch 'feature/ethernet_driver' into 'master'
feature/ethernet_driver: update ethernet driver See merge request !319
This commit is contained in:
commit
3ad6dbbaa1
12 changed files with 501 additions and 203 deletions
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
28
examples/14_ethernet/main/tlk110_phy.h
Normal file
28
examples/14_ethernet/main/tlk110_phy.h
Normal 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)
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue