forked from espressif/esp-idf
ethernet: support esp_eth_deinit
1. change static emac-dma memory to dynamic 2. add esp_eth_deinit 3. modify ethernet example 4. add testcase for ethernet deinit function 5. GPIO0 could not output the 50MHz clock to PHY, so remove this configuration
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rom/ets_sys.h"
|
||||
@@ -58,15 +59,15 @@
|
||||
|
||||
static struct emac_config_data emac_config;
|
||||
|
||||
static uint8_t emac_dma_rx_chain_buf[sizeof(struct dma_extended_desc) * DMA_RX_BUF_NUM];
|
||||
static uint8_t emac_dma_tx_chain_buf[sizeof(struct dma_extended_desc) * DMA_TX_BUF_NUM];
|
||||
static uint8_t emac_dma_rx_buf[DMA_RX_BUF_SIZE * DMA_RX_BUF_NUM];
|
||||
static uint8_t emac_dma_tx_buf[DMA_TX_BUF_SIZE * DMA_TX_BUF_NUM];
|
||||
static dma_extended_desc_t *emac_dma_rx_chain_buf[DMA_RX_BUF_NUM];
|
||||
static dma_extended_desc_t *emac_dma_tx_chain_buf[DMA_TX_BUF_NUM];
|
||||
static uint8_t *emac_dma_rx_buf[DMA_RX_BUF_NUM];
|
||||
static uint8_t *emac_dma_tx_buf[DMA_TX_BUF_NUM];
|
||||
|
||||
static SemaphoreHandle_t emac_g_sem;
|
||||
static SemaphoreHandle_t emac_g_sem = NULL;
|
||||
static portMUX_TYPE g_emac_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
static xTaskHandle emac_task_hdl;
|
||||
static xQueueHandle emac_xqueue;
|
||||
static xTaskHandle emac_task_hdl = NULL;
|
||||
static xQueueHandle emac_xqueue = NULL;
|
||||
static uint8_t emac_sig_cnt[EMAC_SIG_MAX] = {0};
|
||||
static TimerHandle_t emac_timer = NULL;
|
||||
static SemaphoreHandle_t emac_rx_xMutex = NULL;
|
||||
@@ -92,19 +93,23 @@ void esp_eth_get_mac(uint8_t mac[6])
|
||||
|
||||
esp_err_t esp_eth_set_mac(const uint8_t mac[6])
|
||||
{
|
||||
if((mac[0] & 0x01) == 0) {
|
||||
memcpy(&(emac_config.macaddr[0]),mac, 6);
|
||||
if ((mac[0] & 0x01) == 0) {
|
||||
memcpy(&(emac_config.macaddr[0]), mac, 6);
|
||||
return ESP_OK;
|
||||
} else {
|
||||
return ESP_ERR_INVALID_MAC;
|
||||
}
|
||||
}
|
||||
|
||||
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.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;
|
||||
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)
|
||||
@@ -113,7 +118,8 @@ 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) {
|
||||
rx_desc->basic.desc2 = buf_ptr;
|
||||
@@ -133,23 +139,34 @@ static void emac_set_rx_base_reg(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* dirty_rx indicates the hardware has been fed with data packets and is the first node software needs to handle;
|
||||
* dirty_rx indicates the hardware has been fed with data packets and is the
|
||||
* first node software needs to handle;
|
||||
*
|
||||
* cur_rx indicates the completion of software handling and is the last node hardware could use;
|
||||
* cur_rx indicates the completion of software handling and is the last node
|
||||
* hardware could use;
|
||||
*
|
||||
* cnt_rx is to count the numbers of packets handled by software, passed to protocol stack and not been freed.
|
||||
* cnt_rx is to count the numbers of packets handled by software, passed to
|
||||
* protocol stack and not been freed.
|
||||
*
|
||||
* (1) Initializing the Linked List. Connect the numerable nodes to a circular linked list, appoint one of the nodes as the head node, mark* the dirty_rx and cur_rx into the node, and mount the node on the hardware base address. Initialize cnt_rx into 0.
|
||||
* (1) Initializing the Linked List. Connect the numerable nodes to a circular
|
||||
* linked list, appoint one of the nodes as the head node, mark* the dirty_rx
|
||||
* and cur_rx into the node, and mount the node on the hardware base address.
|
||||
* Initialize cnt_rx into 0.
|
||||
*
|
||||
* (2) When hardware receives packets, nodes of linked lists will be fed with data packets from the base address by turns, marks the node
|
||||
* (2) When hardware receives packets, nodes of linked lists will be fed with
|
||||
* data packets from the base address by turns, marks the node
|
||||
* of linked lists as “HARDWARE UNUSABLE” and reports interrupts.
|
||||
*
|
||||
* (3) When the software receives the interrupts, it will handle the linked lists by turns from dirty_rx, send data packets to protocol
|
||||
* (3) When the software receives the interrupts, it will handle the linked
|
||||
* lists by turns from dirty_rx, send data packets to protocol
|
||||
* stack. dirty_rx will deviate backwards by turns and cnt_rx will by turns ++.
|
||||
*
|
||||
* (4) After the protocol stack handles all the data and calls the free function, it will deviate backwards by turns from cur_rx, mark the * node of linked lists as “HARDWARE USABLE” and cnt_rx will by turns --.
|
||||
* (4) After the protocol stack handles all the data and calls the free function,
|
||||
* it will deviate backwards by turns from cur_rx, mark the * node of linked
|
||||
* lists as “HARDWARE USABLE” and cnt_rx will by turns --.
|
||||
*
|
||||
* (5) Cycle from Step 2 to Step 4 without break and build up circular linked list handling.
|
||||
* (5) Cycle from Step 2 to Step 4 without break and build up circular linked
|
||||
* list handling.
|
||||
*/
|
||||
static void emac_reset_dma_chain(void)
|
||||
{
|
||||
@@ -165,48 +182,46 @@ static void emac_reset_dma_chain(void)
|
||||
static void emac_init_dma_chain(void)
|
||||
{
|
||||
int i;
|
||||
uint32_t dma_phy;
|
||||
struct dma_extended_desc *p = NULL;
|
||||
dma_extended_desc_t *p = NULL;
|
||||
|
||||
//init tx chain
|
||||
emac_config.dma_etx = (struct dma_extended_desc *)(&emac_dma_tx_chain_buf[0]);
|
||||
emac_config.dma_etx = emac_dma_tx_chain_buf[0];
|
||||
emac_config.cnt_tx = 0;
|
||||
emac_config.cur_tx = 0;
|
||||
emac_config.dirty_tx = 0;
|
||||
|
||||
dma_phy = (uint32_t)(emac_config.dma_etx);
|
||||
p = emac_config.dma_etx;
|
||||
|
||||
for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++ ) {
|
||||
dma_phy += sizeof(struct dma_extended_desc);
|
||||
p = emac_dma_tx_chain_buf[0];
|
||||
for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++) {
|
||||
emac_clean_tx_desc(p);
|
||||
p->basic.desc3 = dma_phy;
|
||||
p->basic.desc2 = (uint32_t)(&emac_dma_tx_buf[0]) + (i * DMA_TX_BUF_SIZE);
|
||||
p++;
|
||||
/* point to the buffer */
|
||||
p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]);
|
||||
/* point to next descriptor */
|
||||
p->basic.desc3 = (uint32_t)(emac_dma_tx_chain_buf[i + 1]);
|
||||
p = emac_dma_tx_chain_buf[i + 1];
|
||||
}
|
||||
p->basic.desc3 = (uint32_t)(emac_config.dma_etx);
|
||||
p->basic.desc2 = (uint32_t)(&emac_dma_tx_buf[0]) + (i * DMA_TX_BUF_SIZE);
|
||||
|
||||
//init desc0 desc1
|
||||
emac_clean_tx_desc(p);
|
||||
/* point to the buffer */
|
||||
p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]);
|
||||
/* point to first descriptor */
|
||||
p->basic.desc3 = (uint32_t)(emac_config.dma_etx);
|
||||
|
||||
//init rx chain
|
||||
emac_config.dma_erx = (struct dma_extended_desc *)(&emac_dma_rx_chain_buf[0]);
|
||||
emac_config.dma_erx = emac_dma_rx_chain_buf[0];
|
||||
emac_config.cnt_rx = 0;
|
||||
emac_config.cur_rx = 0;
|
||||
emac_config.dirty_rx = 0;
|
||||
|
||||
dma_phy = (uint32_t)(emac_config.dma_erx);
|
||||
p = emac_config.dma_erx;
|
||||
|
||||
for (i = 0; i < (DMA_RX_BUF_NUM - 1); i++ ) {
|
||||
dma_phy += sizeof(struct dma_extended_desc);
|
||||
emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
|
||||
p->basic.desc3 = dma_phy;
|
||||
p++;
|
||||
p = emac_dma_rx_chain_buf[0];
|
||||
for (i = 0; i < (DMA_RX_BUF_NUM - 1); i++) {
|
||||
emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i]));
|
||||
/* point to the buffer */
|
||||
p->basic.desc3 = (uint32_t)(emac_dma_rx_chain_buf[i + 1]);
|
||||
/* point to next descriptor */
|
||||
p = emac_dma_rx_chain_buf[i + 1];
|
||||
}
|
||||
|
||||
emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
|
||||
/* point to the buffer */
|
||||
emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i]));
|
||||
/* point to first descriptor */
|
||||
p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
|
||||
}
|
||||
|
||||
@@ -214,13 +229,14 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value)
|
||||
{
|
||||
uint32_t phy_num = emac_config.phy_addr;
|
||||
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) {
|
||||
}
|
||||
|
||||
REG_WRITE(EMAC_MIIDATA_REG, value);
|
||||
REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | ((0x3) << 2));
|
||||
REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) |
|
||||
((phy_num & 0x1f) << 11) | ((0x3) << 2));
|
||||
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,21 +245,24 @@ uint16_t esp_eth_smi_read(uint32_t reg_num)
|
||||
uint32_t phy_num = emac_config.phy_addr;
|
||||
uint16_t value = 0;
|
||||
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) {
|
||||
}
|
||||
|
||||
REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | (0x3 << 2));
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
|
||||
REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) |
|
||||
((phy_num & 0x1f) << 11) | (0x3 << 2));
|
||||
while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1) {
|
||||
}
|
||||
value = (REG_READ(EMAC_MIIDATA_REG) & 0xffff);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms)
|
||||
esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value,
|
||||
uint16_t value_mask, int timeout_ms)
|
||||
{
|
||||
unsigned start = xTaskGetTickCount();
|
||||
unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS;
|
||||
unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) /
|
||||
portTICK_PERIOD_MS;
|
||||
uint16_t current_value = 0;
|
||||
|
||||
while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) {
|
||||
@@ -253,13 +272,12 @@ esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t valu
|
||||
}
|
||||
vTaskDelay(1);
|
||||
}
|
||||
ESP_LOGE(TAG, "Timed out waiting for PHY register 0x%x to have value 0x%04x (mask 0x%04x). Current value 0x%04x",
|
||||
ESP_LOGE(TAG, "Timed out waiting for PHY register 0x%x to have value 0x%04x(mask 0x%04x). Current value 0x%04x",
|
||||
reg_num, value, value_mask, current_value);
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
static void emac_set_user_config_data(eth_config_t *config )
|
||||
static void emac_set_user_config_data(eth_config_t *config)
|
||||
{
|
||||
emac_config.phy_addr = config->phy_addr;
|
||||
emac_config.mac_mode = config->mac_mode;
|
||||
@@ -274,12 +292,13 @@ static void emac_set_user_config_data(eth_config_t *config )
|
||||
#if DMA_RX_BUF_NUM > 9
|
||||
emac_config.emac_flow_ctrl_enable = config->flow_ctrl_enable;
|
||||
#else
|
||||
if(config->flow_ctrl_enable == true) {
|
||||
if (config->flow_ctrl_enable == true) {
|
||||
ESP_LOGE(TAG, "eth flow ctrl init err!!! Please run make menuconfig and make sure DMA_RX_BUF_NUM > 9 .");
|
||||
}
|
||||
emac_config.emac_flow_ctrl_enable = false;
|
||||
#endif
|
||||
emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable;
|
||||
emac_config.emac_phy_get_partner_pause_enable =
|
||||
config->phy_get_partner_pause_enable;
|
||||
emac_config.emac_phy_power_enable = config->phy_power_enable;
|
||||
}
|
||||
|
||||
@@ -347,12 +366,13 @@ static esp_err_t emac_verify_args(void)
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
if (emac_config.emac_flow_ctrl_enable == true && emac_config.emac_phy_get_partner_pause_enable == NULL) {
|
||||
if (emac_config.emac_flow_ctrl_enable == true &&
|
||||
emac_config.emac_phy_get_partner_pause_enable == NULL) {
|
||||
ESP_LOGE(TAG, "phy get partner pause enable func is null");
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
|
||||
if(emac_config.emac_phy_power_enable == NULL) {
|
||||
if (emac_config.emac_phy_power_enable == NULL) {
|
||||
ESP_LOGE(TAG, "phy power enable func is null");
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
@@ -368,12 +388,12 @@ static void emac_process_tx(void)
|
||||
return;
|
||||
}
|
||||
|
||||
xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
xSemaphoreTakeRecursive(emac_tx_xMutex, portMAX_DELAY);
|
||||
|
||||
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]));
|
||||
while ((uint32_t)(emac_dma_tx_chain_buf[emac_config.dirty_tx]) != cur_tx_desc) {
|
||||
emac_clean_tx_desc(emac_dma_tx_chain_buf[emac_config.dirty_tx]);
|
||||
emac_config.dirty_tx = (emac_config.dirty_tx + 1) % DMA_TX_BUF_NUM;
|
||||
emac_config.cnt_tx --;
|
||||
emac_config.cnt_tx--;
|
||||
|
||||
if (emac_config.cnt_tx < 0) {
|
||||
ESP_LOGE(TAG, "emac tx chain err");
|
||||
@@ -381,14 +401,14 @@ static void emac_process_tx(void)
|
||||
cur_tx_desc = emac_read_tx_cur_reg();
|
||||
}
|
||||
|
||||
xSemaphoreGiveRecursive( emac_tx_xMutex );
|
||||
xSemaphoreGiveRecursive(emac_tx_xMutex);
|
||||
}
|
||||
|
||||
void esp_eth_free_rx_buf(void *buf)
|
||||
{
|
||||
xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY);
|
||||
|
||||
emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.cur_rx]), (uint32_t) buf);
|
||||
emac_clean_rx_desc(emac_dma_rx_chain_buf[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) {
|
||||
@@ -396,11 +416,12 @@ void esp_eth_free_rx_buf(void *buf)
|
||||
}
|
||||
emac_poll_rx_cmd();
|
||||
|
||||
xSemaphoreGiveRecursive( emac_rx_xMutex );
|
||||
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) {
|
||||
if (pause_send == true && emac_config.cnt_rx <
|
||||
FLOW_CONTROL_LOW_WATERMARK) {
|
||||
emac_send_pause_zero_frame_enable();
|
||||
pause_send = false;
|
||||
}
|
||||
@@ -412,7 +433,7 @@ 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;
|
||||
struct dma_extended_desc *cur_desc = (dma_extended_desc_t *)cur_rx_desc;
|
||||
|
||||
while (cur_desc->basic.desc0 == EMAC_DESC_RX_OWN && cnt < DMA_RX_BUF_NUM) {
|
||||
cnt++;
|
||||
@@ -429,12 +450,16 @@ static void emac_process_rx(void)
|
||||
}
|
||||
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_dma_rx_chain_buf[emac_config.dirty_rx]) != cur_rx_desc)) {
|
||||
//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.emac_tcpip_input((emac_dma_rx_buf[emac_config.dirty_rx]),
|
||||
(((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0) >>
|
||||
EMAC_DESC_FRAME_LENGTH_S) &
|
||||
EMAC_DESC_FRAME_LENGTH),
|
||||
NULL);
|
||||
|
||||
emac_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_dma_rx_chain_buf[emac_config.dirty_rx],
|
||||
(uint32_t)(emac_dma_rx_buf[emac_config.dirty_rx]));
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
|
||||
//if open this ,one intr can do many intrs ?
|
||||
@@ -453,16 +478,20 @@ static void emac_process_rx_unavail(void)
|
||||
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_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) {
|
||||
break;
|
||||
}
|
||||
|
||||
dirty_cnt ++;
|
||||
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_config.emac_tcpip_input((emac_dma_rx_buf[emac_config.dirty_rx]),
|
||||
(((emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0) >>
|
||||
EMAC_DESC_FRAME_LENGTH_S) &
|
||||
EMAC_DESC_FRAME_LENGTH),
|
||||
NULL);
|
||||
|
||||
emac_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_dma_rx_chain_buf[emac_config.dirty_rx],
|
||||
(uint32_t)(emac_dma_rx_buf[emac_config.dirty_rx]));
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
}
|
||||
emac_enable_rx_intr();
|
||||
@@ -477,11 +506,11 @@ static void emac_process_rx_unavail(void)
|
||||
return;
|
||||
}
|
||||
|
||||
xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY);
|
||||
|
||||
while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
|
||||
|
||||
if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 == EMAC_DESC_RX_OWN) {
|
||||
if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -493,13 +522,15 @@ static void emac_process_rx_unavail(void)
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
|
||||
//copy data to lwip
|
||||
emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
|
||||
(((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
|
||||
|
||||
}
|
||||
emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]),
|
||||
(((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >>
|
||||
EMAC_DESC_FRAME_LENGTH_S) &
|
||||
EMAC_DESC_FRAME_LENGTH),
|
||||
NULL);
|
||||
}
|
||||
emac_enable_rx_intr();
|
||||
emac_enable_rx_unavail_intr();
|
||||
xSemaphoreGiveRecursive( emac_rx_xMutex );
|
||||
xSemaphoreGiveRecursive(emac_rx_xMutex);
|
||||
}
|
||||
|
||||
static void emac_process_rx(void)
|
||||
@@ -510,31 +541,36 @@ static void emac_process_rx(void)
|
||||
|
||||
uint32_t cur_rx_desc = emac_read_rx_cur_reg();
|
||||
|
||||
xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
xSemaphoreTakeRecursive(emac_rx_xMutex, portMAX_DELAY);
|
||||
|
||||
if (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
|
||||
if (((uint32_t)(emac_dma_rx_chain_buf[emac_config.dirty_rx])) !=
|
||||
cur_rx_desc) {
|
||||
|
||||
while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc) && emac_config.cnt_rx < DMA_RX_BUF_NUM ) {
|
||||
while (((uint32_t)(emac_dma_rx_chain_buf[emac_config.dirty_rx]) != cur_rx_desc) &&
|
||||
emac_config.cnt_rx < DMA_RX_BUF_NUM) {
|
||||
emac_config.cnt_rx++;
|
||||
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");
|
||||
}
|
||||
uint32_t tmp_dirty = emac_config.dirty_rx;
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
|
||||
|
||||
//copy data to lwip
|
||||
emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
|
||||
(((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
|
||||
emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]),
|
||||
(((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >>
|
||||
EMAC_DESC_FRAME_LENGTH_S) &
|
||||
EMAC_DESC_FRAME_LENGTH),
|
||||
NULL);
|
||||
|
||||
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_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 &
|
||||
EMAC_DESC_RX_OWN) == 0) {
|
||||
while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
|
||||
|
||||
if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 == EMAC_DESC_RX_OWN) {
|
||||
if (emac_dma_rx_chain_buf[emac_config.dirty_rx]->basic.desc0 == EMAC_DESC_RX_OWN) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -543,18 +579,21 @@ static void emac_process_rx(void)
|
||||
ESP_LOGE(TAG, "emac rx buf err!!!\n");
|
||||
}
|
||||
uint32_t tmp_dirty = emac_config.dirty_rx;
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
|
||||
emac_config.dirty_rx = (emac_config.dirty_rx + 1) %
|
||||
DMA_RX_BUF_NUM;
|
||||
|
||||
//copy data to lwip
|
||||
emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
|
||||
(((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
|
||||
|
||||
}
|
||||
emac_config.emac_tcpip_input((emac_dma_rx_buf[tmp_dirty]),
|
||||
(((emac_dma_rx_chain_buf[tmp_dirty]->basic.desc0) >>
|
||||
EMAC_DESC_FRAME_LENGTH_S) &
|
||||
EMAC_DESC_FRAME_LENGTH),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
emac_enable_rx_intr();
|
||||
xSemaphoreGiveRecursive( emac_rx_xMutex );
|
||||
xSemaphoreGiveRecursive(emac_rx_xMutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -570,7 +609,8 @@ static void IRAM_ATTR emac_process_intr(void *arg)
|
||||
if (event & EMAC_RECV_INT) {
|
||||
emac_disable_rx_intr();
|
||||
if (emac_config.emac_flow_ctrl_partner_support == true) {
|
||||
if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && pause_send == false ) {
|
||||
if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK &&
|
||||
pause_send == false) {
|
||||
pause_send = true;
|
||||
emac_send_pause_frame_enable();
|
||||
}
|
||||
@@ -591,7 +631,9 @@ static void IRAM_ATTR emac_process_intr(void *arg)
|
||||
static void emac_set_macaddr_reg(void)
|
||||
{
|
||||
REG_SET_FIELD(EMAC_ADDR0HIGH_REG, EMAC_ADDRESS0_HI, (emac_config.macaddr[0] << 8) | (emac_config.macaddr[1]));
|
||||
REG_WRITE(EMAC_ADDR0LOW_REG, (emac_config.macaddr[2] << 24) | (emac_config.macaddr[3] << 16) | (emac_config.macaddr[4] << 8) | (emac_config.macaddr[5]));
|
||||
REG_WRITE(EMAC_ADDR0LOW_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)
|
||||
@@ -612,7 +654,8 @@ static void emac_check_phy_init(void)
|
||||
emac_config.emac_flow_ctrl_partner_support = false;
|
||||
#else
|
||||
if (emac_config.emac_flow_ctrl_enable == true) {
|
||||
if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
|
||||
if (emac_config.emac_phy_get_partner_pause_enable() == true &&
|
||||
emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
|
||||
emac_enable_flowctrl();
|
||||
emac_config.emac_flow_ctrl_partner_support = true;
|
||||
} else {
|
||||
@@ -635,7 +678,7 @@ static void emac_process_link_updown(bool link_status)
|
||||
|
||||
if (link_status == true) {
|
||||
emac_check_phy_init();
|
||||
ESP_LOGI(TAG, "eth link_up!!!");
|
||||
ESP_LOGD(TAG, "eth link_up");
|
||||
emac_enable_dma_tx();
|
||||
emac_enable_dma_rx();
|
||||
for (i = 0; i < PHY_LINK_CHECK_NUM; i++) {
|
||||
@@ -644,7 +687,7 @@ static void emac_process_link_updown(bool link_status)
|
||||
|
||||
evt.event_id = SYSTEM_EVENT_ETH_CONNECTED;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "eth link_down!!!");
|
||||
ESP_LOGD(TAG, "eth link_down");
|
||||
emac_disable_dma_tx();
|
||||
emac_disable_dma_rx();
|
||||
evt.event_id = SYSTEM_EVENT_ETH_DISCONNECTED;
|
||||
@@ -667,31 +710,32 @@ esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
if (emac_config.emac_status != EMAC_RUNTIME_START || emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
|
||||
ESP_LOGI(TAG, "tx netif close");
|
||||
if (emac_config.emac_status != EMAC_RUNTIME_START) {
|
||||
ESP_LOGE(TAG, "tx netif is not ready, emac_status=%d",
|
||||
emac_config.emac_status);
|
||||
ret = ERR_IF;
|
||||
return ret;
|
||||
}
|
||||
|
||||
xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
|
||||
xSemaphoreTakeRecursive(emac_tx_xMutex, portMAX_DELAY);
|
||||
if (emac_config.cnt_tx == DMA_TX_BUF_NUM - 1) {
|
||||
ESP_LOGD(TAG, "tx buf full");
|
||||
ret = ERR_MEM;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
memcpy((uint8_t *)(emac_config.dma_etx[emac_config.cur_tx].basic.desc2), (uint8_t *)buf, size);
|
||||
memcpy(emac_dma_tx_buf[emac_config.cur_tx], buf, size);
|
||||
|
||||
emac_setup_tx_desc(&(emac_config.dma_etx[emac_config.cur_tx]), size);
|
||||
emac_setup_tx_desc(emac_dma_tx_chain_buf[emac_config.cur_tx], size);
|
||||
|
||||
emac_config.cnt_tx ++;
|
||||
emac_config.cur_tx = (emac_config.cur_tx + 1) % DMA_TX_BUF_NUM ;
|
||||
emac_config.cnt_tx++;
|
||||
emac_config.cur_tx = (emac_config.cur_tx + 1) % DMA_TX_BUF_NUM;
|
||||
|
||||
emac_poll_tx_cmd();
|
||||
|
||||
_exit:
|
||||
|
||||
xSemaphoreGiveRecursive( emac_tx_xMutex );
|
||||
xSemaphoreGiveRecursive(emac_tx_xMutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -702,17 +746,16 @@ static void emac_init_default_data(void)
|
||||
|
||||
void emac_process_link_check(void)
|
||||
{
|
||||
if (emac_config.emac_status != EMAC_RUNTIME_START ||
|
||||
emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
|
||||
if (emac_config.emac_status != EMAC_RUNTIME_START) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (emac_config.emac_phy_check_link() == true ) {
|
||||
if (emac_config.phy_link_up == false) {
|
||||
if (emac_config.emac_phy_check_link()) {
|
||||
if (!emac_config.phy_link_up) {
|
||||
emac_process_link_updown(true);
|
||||
}
|
||||
} else {
|
||||
if (emac_config.phy_link_up == true) {
|
||||
if (emac_config.phy_link_up) {
|
||||
emac_process_link_updown(false);
|
||||
}
|
||||
}
|
||||
@@ -725,8 +768,12 @@ void emac_link_check_func(void *pv_parameters)
|
||||
|
||||
static bool emac_link_check_timer_init(void)
|
||||
{
|
||||
emac_timer = xTimerCreate("emac_timer", (2000 / portTICK_PERIOD_MS),
|
||||
pdTRUE, (void *)rand(), emac_link_check_func);
|
||||
emac_timer = xTimerCreate("emac_timer",
|
||||
(CONFIG_EMAC_CHECK_LINK_PERIOD_MS /
|
||||
portTICK_PERIOD_MS),
|
||||
pdTRUE,
|
||||
NULL,
|
||||
emac_link_check_func);
|
||||
if (emac_timer == NULL) {
|
||||
return false;
|
||||
} else {
|
||||
@@ -761,10 +808,10 @@ static bool emac_link_check_timer_delete(void)
|
||||
|
||||
static void emac_start(void *param)
|
||||
{
|
||||
struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)param;
|
||||
struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)param;
|
||||
struct emac_open_cmd *cmd = (struct emac_open_cmd *)(post_cmd->cmd);
|
||||
|
||||
ESP_LOGI(TAG , "emac start !!!\n");
|
||||
ESP_LOGD(TAG, "emac start");
|
||||
cmd->err = EMAC_CMD_OK;
|
||||
emac_enable_clk(true);
|
||||
|
||||
@@ -803,7 +850,7 @@ static void emac_start(void *param)
|
||||
xSemaphoreGive(emac_g_sem);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "emac start success !!!");
|
||||
ESP_LOGD(TAG, "emac start success");
|
||||
}
|
||||
|
||||
esp_err_t esp_eth_enable(void)
|
||||
@@ -849,8 +896,8 @@ cleanup:
|
||||
|
||||
static void emac_stop(void *param)
|
||||
{
|
||||
struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)param;
|
||||
ESP_LOGI(TAG, "emac stop");
|
||||
struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)param;
|
||||
ESP_LOGD(TAG, "emac stop");
|
||||
|
||||
emac_link_check_timer_stop();
|
||||
emac_link_check_timer_delete();
|
||||
@@ -871,7 +918,7 @@ static void emac_stop(void *param)
|
||||
xSemaphoreGive(emac_g_sem);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "emac stop success !!!");
|
||||
ESP_LOGD(TAG, "emac stop success");
|
||||
}
|
||||
|
||||
esp_err_t esp_eth_disable(void)
|
||||
@@ -906,7 +953,7 @@ esp_err_t esp_eth_disable(void)
|
||||
static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)par;
|
||||
struct emac_post_cmd *post_cmd = (struct emac_post_cmd *)par;
|
||||
xTaskHandle task_hdl = xTaskGetCurrentTaskHandle();
|
||||
|
||||
if (emac_task_hdl != task_hdl) {
|
||||
@@ -948,7 +995,7 @@ void emac_task(void *pv)
|
||||
emac_event_t e;
|
||||
|
||||
for (;;) {
|
||||
if (xQueueReceive(emac_xqueue, &e, (portTickType)portMAX_DELAY) == pdTRUE) {
|
||||
if (xQueueReceive(emac_xqueue, &e, portMAX_DELAY) == pdTRUE) {
|
||||
portENTER_CRITICAL(&g_emac_mux);
|
||||
emac_sig_cnt[e.sig]--;
|
||||
portEXIT_CRITICAL(&g_emac_mux);
|
||||
@@ -1020,8 +1067,18 @@ esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
|
||||
|
||||
esp_err_t esp_eth_init(eth_config_t *config)
|
||||
{
|
||||
esp_event_set_default_eth_handlers();
|
||||
return esp_eth_init_internal(config);
|
||||
/* dynamically alloc memory for ethernet dma */
|
||||
for (int i = 0; i < DMA_RX_BUF_NUM; i++) {
|
||||
emac_dma_rx_chain_buf[i] = (struct dma_extended_desc *)heap_caps_malloc(sizeof(struct dma_extended_desc), MALLOC_CAP_DMA);
|
||||
emac_dma_rx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_RX_BUF_SIZE, MALLOC_CAP_DMA);
|
||||
}
|
||||
for (int i = 0; i < DMA_TX_BUF_NUM; i++) {
|
||||
emac_dma_tx_chain_buf[i] = (struct dma_extended_desc *)heap_caps_malloc(sizeof(struct dma_extended_desc), MALLOC_CAP_DMA);
|
||||
emac_dma_tx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_TX_BUF_SIZE, MALLOC_CAP_DMA);
|
||||
}
|
||||
|
||||
esp_event_set_default_eth_handlers();
|
||||
return esp_eth_init_internal(config);
|
||||
}
|
||||
|
||||
esp_err_t esp_eth_init_internal(eth_config_t *config)
|
||||
@@ -1033,7 +1090,7 @@ esp_err_t esp_eth_init_internal(eth_config_t *config)
|
||||
|
||||
emac_init_default_data();
|
||||
|
||||
if (config != NULL ) {
|
||||
if (config != NULL) {
|
||||
emac_set_user_config_data(config);
|
||||
}
|
||||
|
||||
@@ -1051,31 +1108,28 @@ esp_err_t esp_eth_init_internal(eth_config_t *config)
|
||||
if (emac_config.clock_mode != ETH_CLOCK_GPIO0_IN) {
|
||||
// 50 MHz = 40MHz * (6 + 4) / (2 * (2 + 2) = 400MHz / 8
|
||||
rtc_clk_apll_enable(1, 0, 0, 6, 2);
|
||||
// the next to values have to be set AFTER "periph_module_enable" is called
|
||||
REG_SET_FIELD(EMAC_EX_CLKOUT_CONF_REG, EMAC_EX_CLK_OUT_H_DIV_NUM, 0);
|
||||
REG_SET_FIELD(EMAC_EX_CLKOUT_CONF_REG, EMAC_EX_CLK_OUT_DIV_NUM, 0);
|
||||
|
||||
if (emac_config.clock_mode == ETH_CLOCK_GPIO0_OUT) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
|
||||
REG_WRITE(PIN_CTRL, 6);
|
||||
ESP_LOGD(TAG, "EMAC 50MHz clock output on GPIO0");
|
||||
} else if (emac_config.clock_mode == ETH_CLOCK_GPIO16_OUT) {
|
||||
if (emac_config.clock_mode == ETH_CLOCK_GPIO16_OUT) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
|
||||
ESP_LOGD(TAG, "EMAC 50MHz clock output on GPIO16");
|
||||
} else if (emac_config.clock_mode == ETH_CLOCK_GPIO17_OUT) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U,
|
||||
FUNC_GPIO17_EMAC_CLK_OUT_180);
|
||||
ESP_LOGD(TAG, "EMAC 50MHz inverted clock output on GPIO17");
|
||||
}
|
||||
}
|
||||
|
||||
emac_enable_clk(true);
|
||||
REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, EMAC_EX_PHY_INTF_RMII);
|
||||
REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL,
|
||||
EMAC_EX_PHY_INTF_RMII);
|
||||
emac_dma_init();
|
||||
|
||||
if (emac_config.clock_mode == ETH_CLOCK_GPIO0_IN) {
|
||||
// external clock on GPIO0
|
||||
REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_EXT_OSC_EN);
|
||||
REG_CLR_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_INT_OSC_EN);
|
||||
REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_EXT_OSC_EN);
|
||||
REG_CLR_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_INT_OSC_EN);
|
||||
REG_SET_BIT(EMAC_EX_OSCCLK_CONF_REG, EMAC_EX_OSC_CLK_SEL);
|
||||
ESP_LOGD(TAG, "External clock input 50MHz on GPIO0");
|
||||
if (emac_config.mac_mode == ETH_MODE_MII) {
|
||||
@@ -1084,8 +1138,8 @@ esp_err_t esp_eth_init_internal(eth_config_t *config)
|
||||
}
|
||||
} else {
|
||||
// internal clock by APLL
|
||||
REG_CLR_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_EXT_OSC_EN);
|
||||
REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_INT_OSC_EN);
|
||||
REG_CLR_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_EXT_OSC_EN);
|
||||
REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_INT_OSC_EN);
|
||||
REG_CLR_BIT(EMAC_EX_OSCCLK_CONF_REG, EMAC_EX_OSC_CLK_SEL);
|
||||
}
|
||||
|
||||
@@ -1101,7 +1155,8 @@ esp_err_t esp_eth_init_internal(eth_config_t *config)
|
||||
emac_rx_xMutex = xSemaphoreCreateRecursiveMutex();
|
||||
emac_tx_xMutex = xSemaphoreCreateRecursiveMutex();
|
||||
emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t));
|
||||
xTaskCreate(emac_task, "emacT", 2048, NULL, EMAC_TASK_PRIORITY, &emac_task_hdl);
|
||||
xTaskCreate(emac_task, "emacT", 2048, NULL, EMAC_TASK_PRIORITY,
|
||||
&emac_task_hdl);
|
||||
|
||||
emac_enable_clk(false);
|
||||
esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
|
||||
@@ -1111,3 +1166,43 @@ esp_err_t esp_eth_init_internal(eth_config_t *config)
|
||||
_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_eth_deinit(void)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
if (!emac_task_hdl) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
vTaskDelete(emac_task_hdl);
|
||||
emac_task_hdl = NULL;
|
||||
|
||||
vQueueDelete(emac_xqueue);
|
||||
vSemaphoreDelete(emac_tx_xMutex);
|
||||
vSemaphoreDelete(emac_rx_xMutex);
|
||||
vSemaphoreDelete(emac_g_sem);
|
||||
emac_reset_dma_chain();
|
||||
emac_config.emac_phy_power_enable(false);
|
||||
periph_module_disable(PERIPH_EMAC_MODULE);
|
||||
emac_config.emac_status = EMAC_RUNTIME_NOT_INIT;
|
||||
|
||||
/* free memory that dynamically allocted */
|
||||
for (int i = 0; i < DMA_RX_BUF_NUM; i++) {
|
||||
free(emac_dma_rx_chain_buf[i]);
|
||||
free(emac_dma_rx_buf[i]);
|
||||
emac_dma_rx_chain_buf[i] = NULL;
|
||||
emac_dma_rx_buf[i] = NULL;
|
||||
}
|
||||
for (int i = 0; i < DMA_TX_BUF_NUM; i++) {
|
||||
free(emac_dma_tx_chain_buf[i]);
|
||||
free(emac_dma_tx_buf[i]);
|
||||
emac_dma_tx_chain_buf[i] = NULL;
|
||||
emac_dma_tx_buf[i] = NULL;
|
||||
}
|
||||
ret = ESP_OK;
|
||||
|
||||
_exit:
|
||||
return ret;
|
||||
}
|
||||
|
Reference in New Issue
Block a user