| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240 |
- // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "rom/ets_sys.h"
- #include "rom/gpio.h"
- #include "soc/dport_reg.h"
- #include "soc/io_mux_reg.h"
- #include "soc/rtc.h"
- #include "soc/rtc_cntl_reg.h"
- #include "soc/gpio_reg.h"
- #include "soc/dport_reg.h"
- #include "soc/emac_ex_reg.h"
- #include "soc/emac_reg_v2.h"
- #include "soc/soc.h"
- #include "tcpip_adapter.h"
- #include "sdkconfig.h"
- #include "esp_task_wdt.h"
- #include "esp_event.h"
- #include "esp_system.h"
- #include "esp_err.h"
- #include "esp_log.h"
- #include "esp_eth.h"
- #include "esp_intr_alloc.h"
- #include "esp_pm.h"
- #include "esp_spiram.h"
- #include "driver/periph_ctrl.h"
- #include "emac_common.h"
- #include "emac_desc.h"
- #include "freertos/xtensa_api.h"
- #include "freertos/FreeRTOS.h"
- #include "freertos/task.h"
- #include "freertos/queue.h"
- #include "freertos/semphr.h"
- #include "freertos/timers.h"
- #include "lwip/err.h"
- #define EMAC_EVT_QNUM 200
- #define EMAC_SIG_MAX 50
- static struct emac_config_data emac_config;
- static dma_extended_desc_t *emac_dma_rx_chain_buf;
- static dma_extended_desc_t *emac_dma_tx_chain_buf;
- static uint8_t *emac_dma_rx_buf[DMA_RX_BUF_NUM];
- static uint8_t *emac_dma_tx_buf[DMA_TX_BUF_NUM];
- static SemaphoreHandle_t emac_g_sem = NULL;
- static portMUX_TYPE g_emac_mux = portMUX_INITIALIZER_UNLOCKED;
- 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;
- static SemaphoreHandle_t emac_tx_xMutex = NULL;
- static intr_handle_t eth_intr_handle = NULL;
- static const char *TAG = "emac";
- static bool pause_send = false;
- #ifdef CONFIG_PM_ENABLE
- static esp_pm_lock_handle_t s_pm_lock;
- #endif
- static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par);
- esp_err_t emac_post(emac_sig_t sig, emac_par_t par);
- static void emac_macaddr_init(void)
- {
- esp_read_mac(&(emac_config.macaddr[0]), ESP_MAC_ETH);
- }
- void esp_eth_get_mac(uint8_t mac[6])
- {
- memcpy(mac, &(emac_config.macaddr[0]), 6);
- }
- esp_err_t esp_eth_set_mac(const uint8_t mac[6])
- {
- if (!(mac[0] & 0x01)) {
- memcpy(&(emac_config.macaddr[0]), mac, 6);
- return ESP_OK;
- } else {
- return ESP_ERR_INVALID_MAC;
- }
- }
- eth_speed_mode_t esp_eth_get_speed(void)
- {
- return emac_config.emac_phy_get_speed_mode();
- }
- static void emac_setup_tx_desc(dma_extended_desc_t *tx_desc, uint32_t size)
- {
- tx_desc->basic.desc1 = size & 0xfff;
- tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT |
- EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
- }
- static void emac_clean_tx_desc(dma_extended_desc_t *tx_desc)
- {
- tx_desc->basic.desc1 = 0;
- tx_desc->basic.desc0 = 0;
- }
- static void emac_clean_rx_desc(dma_extended_desc_t *rx_desc, uint32_t buf_ptr)
- {
- 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.desc0 = EMAC_DESC_RX_OWN;
- }
- static void emac_set_tx_base_reg(void)
- {
- REG_WRITE(EMAC_DMATXBASEADDR_REG, (uint32_t)(emac_config.dma_etx));
- }
- static void emac_set_rx_base_reg(void)
- {
- REG_WRITE(EMAC_DMARXBASEADDR_REG, (uint32_t)(emac_config.dma_erx));
- }
- /*
- * 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;
- *
- * 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.
- *
- * (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
- * 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 --.
- *
- * (5) Cycle from Step 2 to Step 4 without break and build up circular linked
- * list handling.
- */
- static void emac_reset_dma_chain(void)
- {
- emac_config.cnt_tx = 0;
- emac_config.cur_tx = 0;
- emac_config.dirty_tx = 0;
- emac_config.cnt_rx = 0;
- emac_config.cur_rx = 0;
- emac_config.dirty_rx = 0;
- }
- static void emac_init_dma_chain(void)
- {
- int i;
- uint32_t dma_phy;
- dma_extended_desc_t *p = NULL;
- //init tx chain
- emac_config.dma_etx = emac_dma_tx_chain_buf;
- 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(dma_extended_desc_t);
- emac_clean_tx_desc(p);
- p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]);
- p->basic.desc3 = dma_phy;
- p++;
- }
- emac_clean_tx_desc(p);
- p->basic.desc2 = (uint32_t)(emac_dma_tx_buf[i]);
- p->basic.desc3 = (uint32_t)(emac_config.dma_etx);
- //init rx chain
- emac_config.dma_erx = emac_dma_rx_chain_buf;
- 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(dma_extended_desc_t);
- emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i]));
- p->basic.desc3 = dma_phy;
- p++;
- }
- emac_clean_rx_desc(p, (uint32_t)(emac_dma_rx_buf[i]));
- p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
- }
- 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) {
- }
- REG_WRITE(EMAC_MIIDATA_REG, value);
- 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) {
- }
- }
- 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) {
- }
- 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)
- {
- unsigned start = xTaskGetTickCount();
- 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)) {
- current_value = esp_eth_smi_read(reg_num);
- if ((current_value & value_mask) == (value & value_mask)) {
- return ESP_OK;
- }
- 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",
- reg_num, value, value_mask, current_value);
- return ESP_ERR_TIMEOUT;
- }
- esp_err_t emac_reset(void)
- {
- REG_SET_BIT(EMAC_DMABUSMODE_REG, EMAC_SW_RST);
- if (emac_config.reset_timeout_ms) {
- int start = xTaskGetTickCount();
- uint32_t timeout_ticks = (emac_config.reset_timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS;
- while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) {
- if (REG_GET_BIT(EMAC_DMABUSMODE_REG, EMAC_SW_RST) != EMAC_SW_RST) {
- goto reset_ok;
- }
- vTaskDelay(1);
- }
- ESP_LOGE(TAG, "Reset EMAC Timeout");
- return ESP_ERR_TIMEOUT;
- }
- /* infinite wait loop */
- else {
- while (REG_GET_BIT(EMAC_DMABUSMODE_REG, EMAC_SW_RST) == EMAC_SW_RST) {
- //nothing to do ,if stop here,maybe emac have not clk input.
- ESP_LOGI(TAG, "emac resetting ....");
- }
- }
- reset_ok:
- ESP_LOGI(TAG, "emac reset done");
- return ESP_OK;
- }
- 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;
- emac_config.clock_mode = config->clock_mode;
- emac_config.phy_init = config->phy_init;
- emac_config.emac_tcpip_input = config->tcpip_input;
- 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;
- emac_config.reset_timeout_ms = config->reset_timeout_ms;
- #if DMA_RX_BUF_NUM > 9
- emac_config.emac_flow_ctrl_enable = config->flow_ctrl_enable;
- #else
- if (config->flow_ctrl_enable == true) {
- ESP_LOGE(TAG, "Can only configure flow_ctrl_enable==true if DMA_RX_BUF_NUM in menuconfig is >9. Disabling flow control.");
- }
- 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_power_enable = config->phy_power_enable;
- }
- static void emac_enable_intr()
- {
- REG_WRITE(EMAC_DMAIN_EN_REG, EMAC_INTR_ENABLE_BIT);
- }
- static void emac_disable_intr()
- {
- REG_WRITE(EMAC_DMAIN_EN_REG, 0);
- }
- static esp_err_t emac_verify_args(void)
- {
- esp_err_t ret = ESP_OK;
- if (emac_config.phy_addr > PHY31) {
- ESP_LOGE(TAG, "phy addr err");
- ret = ESP_FAIL;
- }
- if (emac_config.mac_mode != ETH_MODE_RMII) {
- ESP_LOGE(TAG, "mac mode err, currently only support for RMII");
- ret = ESP_FAIL;
- }
- if (emac_config.clock_mode > ETH_CLOCK_GPIO17_OUT) {
- ESP_LOGE(TAG, "emac clock mode err");
- ret = ESP_FAIL;
- }
- if (emac_config.phy_init == NULL) {
- ESP_LOGE(TAG, "phy_init func is null");
- ret = ESP_FAIL;
- }
- if (emac_config.emac_tcpip_input == NULL) {
- ESP_LOGE(TAG, "tcpip_input func is null");
- ret = ESP_FAIL;
- }
- if (emac_config.emac_gpio_config == NULL) {
- ESP_LOGE(TAG, "gpio config func is null");
- 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;
- }
- if (emac_config.emac_flow_ctrl_enable && !emac_config.emac_phy_get_partner_pause_enable) {
- ESP_LOGE(TAG, "phy get partner pause enable func is null");
- ret = ESP_FAIL;
- }
- if (emac_config.emac_phy_power_enable == NULL) {
- ESP_LOGE(TAG, "phy power enable func is null");
- ret = ESP_FAIL;
- }
- return ret;
- }
- static void emac_process_tx(void)
- {
- uint32_t cur_tx_desc = emac_read_tx_cur_reg();
- if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
- return;
- }
- xSemaphoreTakeRecursive(emac_tx_xMutex, portMAX_DELAY);
- while (((uint32_t) & (emac_config.dma_etx[emac_config.dirty_tx])) != cur_tx_desc) {
- emac_clean_tx_desc(&(emac_config.dma_etx[emac_config.dirty_tx]));
- emac_config.dirty_tx = (emac_config.dirty_tx + 1) % DMA_TX_BUF_NUM;
- emac_config.cnt_tx--;
- if (emac_config.cnt_tx < 0) {
- 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, 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");
- }
- emac_poll_rx_cmd();
- xSemaphoreGiveRecursive(emac_rx_xMutex);
- if (emac_config.emac_flow_ctrl_partner_support) {
- portENTER_CRITICAL(&g_emac_mux);
- if (pause_send && emac_config.cnt_rx < FLOW_CONTROL_LOW_WATERMARK) {
- emac_send_pause_zero_frame_enable();
- pause_send = false;
- }
- portEXIT_CRITICAL(&g_emac_mux);
- }
- }
- static uint32_t IRAM_ATTR emac_get_rxbuf_count_in_intr(void)
- {
- uint32_t cnt = 0;
- uint32_t cur_rx_desc = emac_read_rx_cur_reg();
- dma_extended_desc_t *cur_desc = (dma_extended_desc_t *)cur_rx_desc;
- while (cur_desc->basic.desc0 == EMAC_DESC_RX_OWN && cnt < DMA_RX_BUF_NUM) {
- cnt++;
- cur_desc = (dma_extended_desc_t *)cur_desc->basic.desc3;
- }
- return cnt;
- }
- #if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
- static void emac_process_rx(void)
- {
- if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
- return;
- }
- uint32_t cur_rx_desc = emac_read_rx_cur_reg();
- while (((uint32_t) & (emac_config.dma_erx[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_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;
- 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, 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) {
- break;
- }
- emac_config.cnt_rx++;
- if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
- ESP_LOGE(TAG, "emac rx buf full");
- }
- uint32_t tmp_dirty = emac_config.dirty_rx;
- emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
- //copy data to lwip
- emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
- (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
- EMAC_DESC_FRAME_LENGTH), NULL);
- }
- emac_enable_rx_intr();
- emac_enable_rx_unavail_intr();
- 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, portMAX_DELAY);
- if ((((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx])) != cur_rx_desc)) {
- while ((((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx])) != cur_rx_desc) &&
- emac_config.cnt_rx < DMA_RX_BUF_NUM) {
- emac_config.cnt_rx++;
- if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
- ESP_LOGE(TAG, "emac rx buf full");
- }
- uint32_t tmp_dirty = emac_config.dirty_rx;
- emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
- //copy data to lwip
- emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
- (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
- EMAC_DESC_FRAME_LENGTH), NULL);
- cur_rx_desc = emac_read_rx_cur_reg();
- }
- } else {
- if (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
- if (!(emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN)) {
- while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
- if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) {
- break;
- }
- emac_config.cnt_rx++;
- if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
- ESP_LOGE(TAG, "emac rx buf full");
- }
- uint32_t tmp_dirty = emac_config.dirty_rx;
- emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
- //copy data to lwip
- emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
- (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) &
- EMAC_DESC_FRAME_LENGTH), NULL);
- }
- }
- }
- }
- emac_enable_rx_intr();
- xSemaphoreGiveRecursive(emac_rx_xMutex);
- }
- #endif
- //TODO other events need to do something
- static void IRAM_ATTR emac_process_intr(void *arg)
- {
- uint32_t event;
- event = REG_READ(EMAC_DMASTATUS_REG);
- //clr intrs
- REG_WRITE(EMAC_DMASTATUS_REG, event);
- if (event & EMAC_RECV_INT) {
- emac_disable_rx_intr();
- if (emac_config.emac_flow_ctrl_partner_support) {
- if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && !pause_send) {
- pause_send = true;
- emac_send_pause_frame_enable();
- }
- }
- 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_set_macaddr_reg(void)
- {
- REG_SET_FIELD(EMAC_ADDR0HIGH_REG, EMAC_ADDRESS0_HI, (emac_config.macaddr[5] << 8) | (emac_config.macaddr[4]));
- REG_WRITE(EMAC_ADDR0LOW_REG, (emac_config.macaddr[3] << 24) | (emac_config.macaddr[2] << 16) |
- (emac_config.macaddr[1] << 8) | (emac_config.macaddr[0]));
- }
- static void emac_check_phy_init(void)
- {
- emac_config.emac_phy_check_init();
- if (emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
- REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX);
- } else {
- REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX);
- }
- if (emac_config.emac_phy_get_speed_mode() == ETH_SPEED_MODE_100M) {
- REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED);
- } else {
- REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED);
- }
- #if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
- emac_disable_flowctrl();
- emac_config.emac_flow_ctrl_partner_support = false;
- #else
- if (emac_config.emac_flow_ctrl_enable) {
- if (emac_config.emac_phy_get_partner_pause_enable() &&
- emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
- emac_enable_flowctrl();
- emac_config.emac_flow_ctrl_partner_support = true;
- } else {
- emac_disable_flowctrl();
- emac_config.emac_flow_ctrl_partner_support = false;
- }
- } else {
- emac_disable_flowctrl();
- emac_config.emac_flow_ctrl_partner_support = false;
- }
- #endif
- emac_mac_enable_txrx();
- }
- static void emac_process_link_updown(bool link_status)
- {
- system_event_t evt;
- uint8_t i = 0;
- emac_config.phy_link_up = link_status;
- if (link_status) {
- emac_check_phy_init();
- ESP_LOGD(TAG, "eth link_up");
- emac_enable_dma_tx();
- emac_enable_dma_rx();
- for (i = 0; i < PHY_LINK_CHECK_NUM; i++) {
- emac_check_phy_init();
- }
- evt.event_id = SYSTEM_EVENT_ETH_CONNECTED;
- } else {
- ESP_LOGD(TAG, "eth link_down");
- emac_disable_dma_tx();
- emac_disable_dma_rx();
- evt.event_id = SYSTEM_EVENT_ETH_DISCONNECTED;
- }
- esp_event_send(&evt);
- }
- static void emac_hw_init(void)
- {
- //init chain
- emac_init_dma_chain();
- //get hw features TODO
- //ipc TODO
- }
- esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
- {
- esp_err_t ret = ESP_OK;
- if (emac_config.emac_status != EMAC_RUNTIME_START) {
- ESP_LOGE(TAG, "tx netif is not ready, emac_status=%d", emac_config.emac_status);
- ret = ESP_ERR_INVALID_STATE;
- return ret;
- }
- xSemaphoreTakeRecursive(emac_tx_xMutex, portMAX_DELAY);
- if (emac_config.cnt_tx == DMA_TX_BUF_NUM - 1) {
- ESP_LOGD(TAG, "tx buf full");
- ret = ESP_ERR_NO_MEM;
- goto _exit;
- }
- memcpy((void *)(emac_config.dma_etx[emac_config.cur_tx].basic.desc2), buf, size);
- emac_setup_tx_desc(&(emac_config.dma_etx[emac_config.cur_tx]), size);
- emac_config.cnt_tx++;
- emac_config.cur_tx = (emac_config.cur_tx + 1) % DMA_TX_BUF_NUM;
- emac_poll_tx_cmd();
- _exit:
- xSemaphoreGiveRecursive(emac_tx_xMutex);
- return ret;
- }
- static void emac_init_default_data(void)
- {
- memset((void *)&emac_config, 0, sizeof(struct emac_config_data));
- }
- void emac_process_link_check(void)
- {
- if (emac_config.emac_status != EMAC_RUNTIME_START) {
- return;
- }
- 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) {
- emac_process_link_updown(false);
- }
- }
- }
- void emac_link_check_func(void *pv_parameters)
- {
- emac_post(SIG_EMAC_CHECK_LINK, 0);
- }
- static bool emac_link_check_timer_init(void)
- {
- 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 {
- return true;
- }
- }
- static bool emac_link_check_timer_start(void)
- {
- if (xTimerStart(emac_timer, portMAX_DELAY) != pdPASS) {
- return false;
- } else {
- return true;
- }
- }
- static bool emac_link_check_timer_stop(void)
- {
- if (xTimerStop(emac_timer, portMAX_DELAY) != pdPASS) {
- return false;
- } else {
- return true;
- }
- }
- static bool emac_link_check_timer_delete(void)
- {
- xTimerDelete(emac_timer, portMAX_DELAY);
- emac_timer = NULL;
- return true;
- }
- static void emac_start(void *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_LOGD(TAG, "emac start");
- cmd->err = EMAC_CMD_OK;
- if (emac_reset() != ESP_OK) {
- return;
- }
- emac_reset_dma_chain();
- emac_dma_init();
- emac_set_macaddr_reg();
- emac_set_tx_base_reg();
- emac_set_rx_base_reg();
- emac_mac_init();
- emac_enable_intr();
- emac_config.emac_status = EMAC_RUNTIME_START;
- system_event_t evt;
- evt.event_id = SYSTEM_EVENT_ETH_START;
- esp_event_send(&evt);
- //set a timer to check link up status
- if (emac_link_check_timer_init()) {
- if (!emac_link_check_timer_start()) {
- cmd->err = EMAC_CMD_FAIL;
- emac_link_check_timer_delete();
- }
- } else {
- cmd->err = EMAC_CMD_FAIL;
- }
- if (post_cmd->post_type == EMAC_POST_SYNC) {
- xSemaphoreGive(emac_g_sem);
- }
- ESP_LOGD(TAG, "emac start success");
- }
- esp_err_t esp_eth_enable(void)
- {
- struct emac_post_cmd post_cmd;
- struct emac_open_cmd open_cmd;
- post_cmd.cmd = (void *)(&open_cmd);
- open_cmd.err = EMAC_CMD_OK;
- if (emac_config.emac_status == EMAC_RUNTIME_START) {
- open_cmd.err = EMAC_CMD_OK;
- return open_cmd.err;
- }
- #ifdef CONFIG_PM_ENABLE
- esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "ethernet", &s_pm_lock);
- if (err != ESP_OK) {
- return err;
- }
- esp_pm_lock_acquire(s_pm_lock);
- #endif //CONFIG_PM_ENABLE
- emac_enable_clk(true);
- /* init phy device */
- if (emac_config.phy_init() != ESP_OK) {
- ESP_LOGE(TAG, "Initialise PHY device Timeout");
- return ESP_FAIL;
- }
- if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) {
- if (emac_ioctl(SIG_EMAC_START, (emac_par_t)(&post_cmd))) {
- open_cmd.err = EMAC_CMD_FAIL;
- goto cleanup;
- }
- } else {
- open_cmd.err = EMAC_CMD_FAIL;
- goto cleanup;
- }
- return EMAC_CMD_OK;
- cleanup:
- #ifdef CONFIG_PM_ENABLE
- esp_pm_lock_release(s_pm_lock);
- esp_pm_lock_delete(s_pm_lock);
- s_pm_lock = NULL;
- #endif //CONFIG_PM_ENABLE
- return open_cmd.err;
- }
- static void emac_stop(void *param)
- {
- 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();
- emac_process_link_updown(false);
- emac_disable_intr();
- emac_enable_clk(false);
- emac_config.emac_status = EMAC_RUNTIME_STOP;
- system_event_t evt;
- evt.event_id = SYSTEM_EVENT_ETH_STOP;
- esp_event_send(&evt);
- if (post_cmd->post_type == EMAC_POST_SYNC) {
- xSemaphoreGive(emac_g_sem);
- }
- ESP_LOGD(TAG, "emac stop success");
- }
- esp_err_t esp_eth_disable(void)
- {
- struct emac_post_cmd post_cmd;
- struct emac_close_cmd close_cmd;
- post_cmd.cmd = (void *)(&close_cmd);
- close_cmd.err = EMAC_CMD_OK;
- if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
- close_cmd.err = EMAC_CMD_OK;
- return close_cmd.err;
- }
- #ifdef CONFIG_PM_ENABLE
- esp_pm_lock_release(s_pm_lock);
- esp_pm_lock_delete(s_pm_lock);
- s_pm_lock = NULL;
- #endif // CONFIG_PM_ENABLE
- if (emac_config.emac_status == EMAC_RUNTIME_START) {
- if (emac_ioctl(SIG_EMAC_STOP, (emac_par_t)(&post_cmd)) != 0) {
- close_cmd.err = EMAC_CMD_FAIL;
- }
- } else {
- close_cmd.err = EMAC_CMD_FAIL;
- }
- return close_cmd.err;
- }
- 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;
- xTaskHandle task_hdl = xTaskGetCurrentTaskHandle();
- if (emac_task_hdl != task_hdl) {
- post_cmd->post_type = EMAC_POST_SYNC;
- if (emac_post(sig, par) != ESP_OK) {
- ret = ESP_FAIL;
- return ret;
- };
- if (xSemaphoreTake(emac_g_sem, portMAX_DELAY) == pdTRUE) {
- return ret;
- }
- } else {
- post_cmd->post_type = EMAC_POST_ASYNC;
- switch (sig) {
- case SIG_EMAC_RX_DONE:
- emac_process_rx();
- break;
- case SIG_EMAC_TX_DONE:
- emac_process_tx();
- break;
- case SIG_EMAC_START:
- emac_start((void *)par);
- break;
- case SIG_EMAC_STOP:
- emac_stop((void *)par);
- break;
- default:
- ESP_LOGE(TAG, "unexpect sig %d", sig);
- break;
- }
- }
- return ret;
- }
- void emac_task(void *pv)
- {
- emac_event_t e;
- for (;;) {
- if (xQueueReceive(emac_xqueue, &e, portMAX_DELAY) == pdTRUE) {
- portENTER_CRITICAL(&g_emac_mux);
- emac_sig_cnt[e.sig]--;
- portEXIT_CRITICAL(&g_emac_mux);
- switch (e.sig) {
- case SIG_EMAC_RX_DONE:
- emac_process_rx();
- break;
- case SIG_EMAC_RX_UNAVAIL:
- emac_process_rx_unavail();
- break;
- case SIG_EMAC_TX_DONE:
- emac_process_tx();
- break;
- case SIG_EMAC_START:
- emac_start((void *)e.par);
- break;
- case SIG_EMAC_STOP:
- emac_stop((void *)e.par);
- break;
- case SIG_EMAC_CHECK_LINK:
- emac_process_link_check();
- break;
- default:
- ESP_LOGE(TAG, "unexpect sig %d", e.sig);
- break;
- }
- }
- }
- }
- esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
- {
- if (sig <= SIG_EMAC_RX_DONE) {
- if (emac_sig_cnt[sig]) {
- return ESP_OK;
- } else {
- emac_sig_cnt[sig]++;
- 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 {
- portENTER_CRITICAL(&g_emac_mux);
- emac_sig_cnt[sig]++;
- portEXIT_CRITICAL(&g_emac_mux);
- emac_event_t evt;
- evt.sig = sig;
- evt.par = par;
- if (xQueueSend(emac_xqueue, &evt, 10 / portTICK_PERIOD_MS) != pdTRUE) {
- return ESP_FAIL;
- }
- }
- return ESP_OK;
- }
- esp_err_t esp_eth_init(eth_config_t *config)
- {
- esp_event_set_default_eth_handlers();
- return esp_eth_init_internal(config);
- }
- esp_err_t esp_eth_init_internal(eth_config_t *config)
- {
- int i = 0;
- esp_err_t ret = ESP_OK;
- if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) {
- goto _initialised;
- }
- /* dynamically alloc memory for ethernet dma */
- emac_dma_rx_chain_buf = (dma_extended_desc_t *)heap_caps_malloc(sizeof(dma_extended_desc_t) * DMA_RX_BUF_NUM, MALLOC_CAP_DMA);
- emac_dma_tx_chain_buf = (dma_extended_desc_t *)heap_caps_malloc(sizeof(dma_extended_desc_t) * DMA_TX_BUF_NUM, MALLOC_CAP_DMA);
- for (i = 0; i < DMA_RX_BUF_NUM; i++) {
- emac_dma_rx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_RX_BUF_SIZE, MALLOC_CAP_DMA);
- }
- for (i = 0; i < DMA_TX_BUF_NUM; i++) {
- emac_dma_tx_buf[i] = (uint8_t *)heap_caps_malloc(DMA_TX_BUF_SIZE, MALLOC_CAP_DMA);
- }
- emac_init_default_data();
- if (config) {
- emac_set_user_config_data(config);
- }
- ret = emac_verify_args();
- if (ret != ESP_OK) {
- goto _verify_err;
- }
- emac_config.emac_phy_power_enable(true);
- //before set emac reg must enable clk
- periph_module_enable(PERIPH_EMAC_MODULE);
- if (emac_config.clock_mode != ETH_CLOCK_GPIO0_IN) {
- #if CONFIG_SPIRAM_SUPPORT
- if (esp_spiram_is_initialized()) {
- ESP_LOGE(TAG, "GPIO16 and GPIO17 has been occupied by PSRAM, Only ETH_CLOCK_GPIO_IN is supported!");
- ret = ESP_FAIL;
- goto _verify_err;
- } else {
- ESP_LOGW(TAG, "GPIO16/17 is used for clock of EMAC, Please Make Sure you're not using PSRAM.");
- }
- #endif
- // 50 MHz = 40MHz * (6 + 4) / (2 * (2 + 2) = 400MHz / 8
- rtc_clk_apll_enable(1, 0, 0, 6, 2);
- REG_SET_FIELD(EMAC_EX_CLKOUT_CONF_REG, EMAC_EX_CLK_OUT_H_DIV_NUM, 0);
- REG_SET_FIELD(EMAC_EX_CLKOUT_CONF_REG, EMAC_EX_CLK_OUT_DIV_NUM, 0);
- 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);
- 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);
- 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_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) {
- REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_MII_CLK_RX_EN);
- REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_MII_CLK_TX_EN);
- }
- } 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_OSCCLK_CONF_REG, EMAC_EX_OSC_CLK_SEL);
- }
- emac_config.emac_gpio_config();
- emac_hw_init();
- emac_macaddr_init();
- //watchdog TODO
- //init task for emac
- emac_g_sem = xSemaphoreCreateBinary();
- emac_rx_xMutex = xSemaphoreCreateRecursiveMutex();
- emac_tx_xMutex = xSemaphoreCreateRecursiveMutex();
- emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t));
- xTaskCreate(emac_task,
- "emacT",
- EMAC_TASK_STACK_SIZE,
- NULL,
- EMAC_TASK_PRIORITY,
- &emac_task_hdl);
- esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, ð_intr_handle);
- emac_config.emac_status = EMAC_RUNTIME_INIT;
- return ESP_OK;
- _verify_err:
- free(emac_dma_rx_chain_buf);
- free(emac_dma_tx_chain_buf);
- emac_dma_rx_chain_buf = NULL;
- emac_dma_tx_chain_buf = NULL;
- for (i = 0; i < DMA_RX_BUF_NUM; i++) {
- free(emac_dma_rx_buf[i]);
- emac_dma_rx_buf[i] = NULL;
- }
- for (i = 0; i < DMA_TX_BUF_NUM; i++) {
- free(emac_dma_tx_buf[i]);
- emac_dma_tx_buf[i] = NULL;
- }
- _initialised:
- return ret;
- }
- esp_err_t esp_eth_deinit(void)
- {
- esp_err_t ret = ESP_OK;
- int i = 0;
- if (emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
- goto _exit;
- }
- if (emac_config.emac_status == EMAC_RUNTIME_START) {
- esp_eth_disable();
- }
- if (!emac_task_hdl) {
- ret = ESP_ERR_INVALID_STATE;
- goto _exit;
- }
- 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 */
- free(emac_dma_rx_chain_buf);
- free(emac_dma_tx_chain_buf);
- emac_dma_rx_chain_buf = NULL;
- emac_dma_tx_chain_buf = NULL;
- for (i = 0; i < DMA_RX_BUF_NUM; i++) {
- free(emac_dma_rx_buf[i]);
- emac_dma_rx_buf[i] = NULL;
- }
- for (i = 0; i < DMA_TX_BUF_NUM; i++) {
- free(emac_dma_tx_buf[i]);
- emac_dma_tx_buf[i] = NULL;
- }
- esp_intr_free(eth_intr_handle);
- _exit:
- return ret;
- }
|