esp_eth_mac_esp.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <sys/cdefs.h>
  9. #include <stdarg.h>
  10. #include "esp_private/periph_ctrl.h"
  11. #include "driver/gpio.h"
  12. #include "esp_attr.h"
  13. #include "esp_log.h"
  14. #include "esp_check.h"
  15. #include "esp_eth_driver.h"
  16. #include "esp_pm.h"
  17. #include "esp_mac.h"
  18. #include "esp_cpu.h"
  19. #include "esp_heap_caps.h"
  20. #include "esp_intr_alloc.h"
  21. #include "esp_private/esp_clk.h"
  22. #include "freertos/FreeRTOS.h"
  23. #include "freertos/task.h"
  24. #include "freertos/semphr.h"
  25. #include "hal/emac_hal.h"
  26. #include "hal/gpio_hal.h"
  27. #include "soc/soc.h"
  28. #include "clk_ctrl_os.h"
  29. #include "sdkconfig.h"
  30. #include "esp_rom_gpio.h"
  31. #include "esp_rom_sys.h"
  32. #include "hal/emac_ll.h"
  33. static const char *TAG = "esp.emac";
  34. #define PHY_OPERATION_TIMEOUT_US (1000)
  35. #define MAC_STOP_TIMEOUT_US (250)
  36. #define FLOW_CONTROL_LOW_WATER_MARK (CONFIG_ETH_DMA_RX_BUFFER_NUM / 3)
  37. #define FLOW_CONTROL_HIGH_WATER_MARK (FLOW_CONTROL_LOW_WATER_MARK * 2)
  38. typedef struct {
  39. esp_eth_mac_t parent;
  40. esp_eth_mediator_t *eth;
  41. emac_hal_context_t hal;
  42. intr_handle_t intr_hdl;
  43. TaskHandle_t rx_task_hdl;
  44. uint32_t sw_reset_timeout_ms;
  45. uint32_t frames_remain;
  46. uint32_t free_rx_descriptor;
  47. uint32_t flow_control_high_water_mark;
  48. uint32_t flow_control_low_water_mark;
  49. int smi_mdc_gpio_num;
  50. int smi_mdio_gpio_num;
  51. eth_mac_clock_config_t clock_config;
  52. uint8_t addr[6];
  53. uint8_t *rx_buf[CONFIG_ETH_DMA_RX_BUFFER_NUM];
  54. uint8_t *tx_buf[CONFIG_ETH_DMA_TX_BUFFER_NUM];
  55. bool isr_need_yield;
  56. bool flow_ctrl_enabled; // indicates whether the user want to do flow control
  57. bool do_flow_ctrl; // indicates whether we need to do software flow control
  58. bool use_apll; // Only use APLL in EMAC_DATA_INTERFACE_RMII && EMAC_CLK_OUT
  59. #ifdef CONFIG_PM_ENABLE
  60. esp_pm_lock_handle_t pm_lock;
  61. #endif
  62. eth_mac_dma_burst_len_t dma_burst_len;
  63. } emac_esp32_t;
  64. static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl, void **out_descriptors);
  65. static void esp_emac_free_driver_obj(emac_esp32_t *emac, void *descriptors);
  66. static esp_err_t emac_esp32_start(esp_eth_mac_t *mac);
  67. static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac);
  68. static esp_err_t emac_esp32_set_mediator(esp_eth_mac_t *mac, esp_eth_mediator_t *eth)
  69. {
  70. esp_err_t ret = ESP_OK;
  71. ESP_GOTO_ON_FALSE(eth, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac's mediator to null");
  72. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  73. emac->eth = eth;
  74. return ESP_OK;
  75. err:
  76. return ret;
  77. }
  78. static esp_err_t emac_esp32_write_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t reg_value)
  79. {
  80. esp_err_t ret = ESP_OK;
  81. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  82. ESP_GOTO_ON_FALSE(!emac_ll_is_mii_busy(emac->hal.mac_regs), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
  83. emac_ll_set_phy_data(emac->hal.mac_regs, reg_value);
  84. emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, true);
  85. /* polling the busy flag */
  86. uint32_t to = 0;
  87. bool busy = true;
  88. do {
  89. esp_rom_delay_us(100);
  90. busy = emac_ll_is_mii_busy(emac->hal.mac_regs);
  91. to += 100;
  92. } while (busy && to < PHY_OPERATION_TIMEOUT_US);
  93. ESP_GOTO_ON_FALSE(!busy, ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
  94. return ESP_OK;
  95. err:
  96. return ret;
  97. }
  98. static esp_err_t emac_esp32_read_phy_reg(esp_eth_mac_t *mac, uint32_t phy_addr, uint32_t phy_reg, uint32_t *reg_value)
  99. {
  100. esp_err_t ret = ESP_OK;
  101. ESP_GOTO_ON_FALSE(reg_value, ESP_ERR_INVALID_ARG, err, TAG, "can't set reg_value to null");
  102. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  103. ESP_GOTO_ON_FALSE(!emac_ll_is_mii_busy(emac->hal.mac_regs), ESP_ERR_INVALID_STATE, err, TAG, "phy is busy");
  104. emac_hal_set_phy_cmd(&emac->hal, phy_addr, phy_reg, false);
  105. /* polling the busy flag */
  106. uint32_t to = 0;
  107. bool busy = true;
  108. do {
  109. esp_rom_delay_us(100);
  110. busy = emac_ll_is_mii_busy(emac->hal.mac_regs);
  111. to += 100;
  112. } while (busy && to < PHY_OPERATION_TIMEOUT_US);
  113. ESP_GOTO_ON_FALSE(!busy, ESP_ERR_TIMEOUT, err, TAG, "phy is busy");
  114. /* Store value */
  115. *reg_value = emac_ll_get_phy_data(emac->hal.mac_regs);
  116. return ESP_OK;
  117. err:
  118. return ret;
  119. }
  120. static esp_err_t emac_esp32_set_addr(esp_eth_mac_t *mac, uint8_t *addr)
  121. {
  122. esp_err_t ret = ESP_OK;
  123. ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
  124. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  125. memcpy(emac->addr, addr, 6);
  126. emac_hal_set_address(&emac->hal, emac->addr);
  127. return ESP_OK;
  128. err:
  129. return ret;
  130. }
  131. static esp_err_t emac_esp32_get_addr(esp_eth_mac_t *mac, uint8_t *addr)
  132. {
  133. esp_err_t ret = ESP_OK;
  134. ESP_GOTO_ON_FALSE(addr, ESP_ERR_INVALID_ARG, err, TAG, "can't set mac addr to null");
  135. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  136. memcpy(addr, emac->addr, 6);
  137. return ESP_OK;
  138. err:
  139. return ret;
  140. }
  141. static esp_err_t emac_esp32_set_link(esp_eth_mac_t *mac, eth_link_t link)
  142. {
  143. esp_err_t ret = ESP_OK;
  144. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  145. switch (link) {
  146. case ETH_LINK_UP:
  147. ESP_GOTO_ON_ERROR(esp_intr_enable(emac->intr_hdl), err, TAG, "enable interrupt failed");
  148. emac_esp32_start(mac);
  149. break;
  150. case ETH_LINK_DOWN:
  151. ESP_GOTO_ON_ERROR(esp_intr_disable(emac->intr_hdl), err, TAG, "disable interrupt failed");
  152. emac_esp32_stop(mac);
  153. break;
  154. default:
  155. ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unknown link status");
  156. break;
  157. }
  158. return ESP_OK;
  159. err:
  160. return ret;
  161. }
  162. static esp_err_t emac_esp32_set_speed(esp_eth_mac_t *mac, eth_speed_t speed)
  163. {
  164. esp_err_t ret = ESP_ERR_INVALID_ARG;
  165. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  166. if (speed >= ETH_SPEED_10M && speed < ETH_SPEED_MAX) {
  167. emac_ll_set_port_speed(emac->hal.mac_regs, speed);
  168. ESP_LOGD(TAG, "working in %dMbps", speed == ETH_SPEED_10M ? 10 : 100);
  169. return ESP_OK;
  170. }
  171. return ret;
  172. }
  173. static esp_err_t emac_esp32_set_duplex(esp_eth_mac_t *mac, eth_duplex_t duplex)
  174. {
  175. esp_err_t ret = ESP_ERR_INVALID_ARG;
  176. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  177. if (duplex == ETH_DUPLEX_HALF || duplex == ETH_DUPLEX_FULL) {
  178. emac_ll_set_duplex(emac->hal.mac_regs, duplex);
  179. ESP_LOGD(TAG, "working in %s duplex", duplex == ETH_DUPLEX_HALF ? "half" : "full");
  180. return ESP_OK;
  181. }
  182. return ret;
  183. }
  184. static esp_err_t emac_esp32_set_promiscuous(esp_eth_mac_t *mac, bool enable)
  185. {
  186. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  187. emac_ll_promiscuous_mode_enable(emac->hal.mac_regs, enable);
  188. return ESP_OK;
  189. }
  190. static esp_err_t emac_esp32_enable_flow_ctrl(esp_eth_mac_t *mac, bool enable)
  191. {
  192. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  193. emac->flow_ctrl_enabled = enable;
  194. return ESP_OK;
  195. }
  196. static esp_err_t emac_esp32_set_peer_pause_ability(esp_eth_mac_t *mac, uint32_t ability)
  197. {
  198. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  199. // we want to enable flow control, and peer does support pause function
  200. // then configure the MAC layer to enable flow control feature
  201. if (emac->flow_ctrl_enabled && ability) {
  202. emac_hal_enable_flow_ctrl(&emac->hal, true);
  203. emac->do_flow_ctrl = true;
  204. } else {
  205. emac_hal_enable_flow_ctrl(&emac->hal, false);
  206. emac->do_flow_ctrl = false;
  207. ESP_LOGD(TAG, "Flow control not enabled for the link");
  208. }
  209. return ESP_OK;
  210. }
  211. static esp_err_t emac_esp32_transmit(esp_eth_mac_t *mac, uint8_t *buf, uint32_t length)
  212. {
  213. esp_err_t ret = ESP_OK;
  214. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  215. uint32_t sent_len = emac_hal_transmit_frame(&emac->hal, buf, length);
  216. ESP_GOTO_ON_FALSE(sent_len == length, ESP_ERR_NO_MEM, err, TAG, "insufficient TX buffer size");
  217. return ESP_OK;
  218. err:
  219. return ret;
  220. }
  221. static esp_err_t emac_esp32_transmit_multiple_bufs(esp_eth_mac_t *mac, uint32_t argc, va_list args)
  222. {
  223. esp_err_t ret = ESP_OK;
  224. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  225. uint8_t *bufs[argc];
  226. uint32_t len[argc];
  227. uint32_t exp_len = 0;
  228. for (int i = 0; i < argc; i++) {
  229. bufs[i] = va_arg(args, uint8_t*);
  230. len[i] = va_arg(args, uint32_t);
  231. exp_len += len[i];
  232. }
  233. uint32_t sent_len = emac_hal_transmit_multiple_buf_frame(&emac->hal, bufs, len, argc);
  234. ESP_GOTO_ON_FALSE(sent_len == exp_len, ESP_ERR_INVALID_SIZE, err, TAG, "insufficient TX buffer size");
  235. return ESP_OK;
  236. err:
  237. return ret;
  238. }
  239. static esp_err_t emac_esp32_receive(esp_eth_mac_t *mac, uint8_t *buf, uint32_t *length)
  240. {
  241. esp_err_t ret = ESP_OK;
  242. uint32_t expected_len = *length;
  243. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  244. ESP_GOTO_ON_FALSE(buf && length, ESP_ERR_INVALID_ARG, err, TAG, "can't set buf and length to null");
  245. uint32_t receive_len = emac_hal_receive_frame(&emac->hal, buf, expected_len, &emac->frames_remain, &emac->free_rx_descriptor);
  246. /* we need to check the return value in case the buffer size is not enough */
  247. ESP_LOGD(TAG, "receive len= %d", receive_len);
  248. ESP_GOTO_ON_FALSE(expected_len >= receive_len, ESP_ERR_INVALID_SIZE, err, TAG, "received buffer longer than expected");
  249. *length = receive_len;
  250. return ESP_OK;
  251. err:
  252. *length = expected_len;
  253. return ret;
  254. }
  255. static void emac_esp32_rx_task(void *arg)
  256. {
  257. emac_esp32_t *emac = (emac_esp32_t *)arg;
  258. uint8_t *buffer = NULL;
  259. uint32_t length = 0;
  260. while (1) {
  261. // block indefinitely until got notification from underlay event
  262. ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
  263. do {
  264. length = ETH_MAX_PACKET_SIZE;
  265. buffer = malloc(length);
  266. if (!buffer) {
  267. ESP_LOGE(TAG, "no mem for receive buffer");
  268. } else if (emac_esp32_receive(&emac->parent, buffer, &length) == ESP_OK) {
  269. /* pass the buffer to stack (e.g. TCP/IP layer) */
  270. if (length) {
  271. emac->eth->stack_input(emac->eth, buffer, length);
  272. } else {
  273. free(buffer);
  274. }
  275. } else {
  276. free(buffer);
  277. }
  278. #if CONFIG_ETH_SOFT_FLOW_CONTROL
  279. // we need to do extra checking of remained frames in case there are no unhandled frames left, but pause frame is still undergoing
  280. if ((emac->free_rx_descriptor < emac->flow_control_low_water_mark) && emac->do_flow_ctrl && emac->frames_remain) {
  281. emac_ll_pause_frame_enable(emac->hal.ext_regs, true);
  282. } else if ((emac->free_rx_descriptor > emac->flow_control_high_water_mark) || !emac->frames_remain) {
  283. emac_ll_pause_frame_enable(emac->hal.ext_regs, false);
  284. }
  285. #endif
  286. } while (emac->frames_remain);
  287. }
  288. vTaskDelete(NULL);
  289. }
  290. static void emac_esp32_init_smi_gpio(emac_esp32_t *emac)
  291. {
  292. if (emac->smi_mdc_gpio_num >= 0) {
  293. /* Setup SMI MDC GPIO */
  294. gpio_set_direction(emac->smi_mdc_gpio_num, GPIO_MODE_OUTPUT);
  295. esp_rom_gpio_connect_out_signal(emac->smi_mdc_gpio_num, EMAC_MDC_O_IDX, false, false);
  296. gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[emac->smi_mdc_gpio_num], PIN_FUNC_GPIO);
  297. }
  298. if (emac->smi_mdio_gpio_num >= 0) {
  299. /* Setup SMI MDIO GPIO */
  300. gpio_set_direction(emac->smi_mdio_gpio_num, GPIO_MODE_INPUT_OUTPUT);
  301. esp_rom_gpio_connect_out_signal(emac->smi_mdio_gpio_num, EMAC_MDO_O_IDX, false, false);
  302. esp_rom_gpio_connect_in_signal(emac->smi_mdio_gpio_num, EMAC_MDI_I_IDX, false);
  303. gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[emac->smi_mdio_gpio_num], PIN_FUNC_GPIO);
  304. }
  305. }
  306. static esp_err_t emac_config_apll_clock(void)
  307. {
  308. uint32_t expt_freq = 50000000; // 50MHz
  309. uint32_t real_freq = 0;
  310. esp_err_t ret = periph_rtc_apll_freq_set(expt_freq, &real_freq);
  311. ESP_RETURN_ON_FALSE(ret != ESP_ERR_INVALID_ARG, ESP_FAIL, TAG, "Set APLL clock coefficients failed");
  312. if (ret == ESP_ERR_INVALID_STATE) {
  313. ESP_LOGW(TAG, "APLL is occupied already, it is working at %d Hz", real_freq);
  314. }
  315. // If the difference of real APLL frequency is not within 50 ppm, i.e. 2500 Hz, the APLL is unavailable
  316. ESP_RETURN_ON_FALSE(abs((int)real_freq - (int)expt_freq) <= 2500,
  317. ESP_ERR_INVALID_STATE, TAG, "The APLL is working at an unusable frequency");
  318. return ESP_OK;
  319. }
  320. static esp_err_t emac_esp32_init(esp_eth_mac_t *mac)
  321. {
  322. esp_err_t ret = ESP_OK;
  323. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  324. esp_eth_mediator_t *eth = emac->eth;
  325. /* init gpio used by smi interface */
  326. emac_esp32_init_smi_gpio(emac);
  327. ESP_GOTO_ON_ERROR(eth->on_state_changed(eth, ETH_STATE_LLINIT, NULL), err, TAG, "lowlevel init failed");
  328. /* software reset */
  329. emac_ll_reset(emac->hal.dma_regs);
  330. uint32_t to = 0;
  331. for (to = 0; to < emac->sw_reset_timeout_ms / 10; to++) {
  332. if (emac_ll_is_reset_done(emac->hal.dma_regs)) {
  333. break;
  334. }
  335. vTaskDelay(pdMS_TO_TICKS(10));
  336. }
  337. ESP_GOTO_ON_FALSE(to < emac->sw_reset_timeout_ms / 10, ESP_ERR_TIMEOUT, err, TAG, "reset timeout");
  338. /* set smi clock */
  339. emac_hal_set_csr_clock_range(&emac->hal, esp_clk_apb_freq());
  340. /* reset descriptor chain */
  341. emac_hal_reset_desc_chain(&emac->hal);
  342. /* init mac registers by default */
  343. emac_hal_init_mac_default(&emac->hal);
  344. /* init dma registers with selected EMAC-DMA configuration */
  345. emac_hal_dma_config_t dma_config = { .dma_burst_len = emac->dma_burst_len };
  346. emac_hal_init_dma_default(&emac->hal, &dma_config);
  347. /* get emac address from efuse */
  348. ESP_GOTO_ON_ERROR(esp_read_mac(emac->addr, ESP_MAC_ETH), err, TAG, "fetch ethernet mac address failed");
  349. /* set MAC address to emac register */
  350. emac_hal_set_address(&emac->hal, emac->addr);
  351. #ifdef CONFIG_PM_ENABLE
  352. esp_pm_lock_acquire(emac->pm_lock);
  353. #endif
  354. return ESP_OK;
  355. err:
  356. eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
  357. periph_module_disable(PERIPH_EMAC_MODULE);
  358. return ret;
  359. }
  360. static esp_err_t emac_esp32_deinit(esp_eth_mac_t *mac)
  361. {
  362. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  363. esp_eth_mediator_t *eth = emac->eth;
  364. #ifdef CONFIG_PM_ENABLE
  365. esp_pm_lock_release(emac->pm_lock);
  366. #endif
  367. emac_hal_stop(&emac->hal);
  368. eth->on_state_changed(eth, ETH_STATE_DEINIT, NULL);
  369. return ESP_OK;
  370. }
  371. static esp_err_t emac_esp32_start(esp_eth_mac_t *mac)
  372. {
  373. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  374. emac_hal_reset_desc_chain(&emac->hal);
  375. emac_hal_start(&emac->hal);
  376. return ESP_OK;
  377. }
  378. static esp_err_t emac_esp32_stop(esp_eth_mac_t *mac)
  379. {
  380. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  381. esp_err_t ret = ESP_OK;
  382. int32_t to = 0;
  383. do {
  384. if ((ret = emac_hal_stop(&emac->hal)) == ESP_OK) {
  385. break;
  386. }
  387. to += 25;
  388. esp_rom_delay_us(25);
  389. } while (to < MAC_STOP_TIMEOUT_US);
  390. return ret;
  391. }
  392. static esp_err_t emac_esp32_del(esp_eth_mac_t *mac)
  393. {
  394. emac_esp32_t *emac = __containerof(mac, emac_esp32_t, parent);
  395. esp_emac_free_driver_obj(emac, emac->hal.descriptors);
  396. periph_module_disable(PERIPH_EMAC_MODULE);
  397. return ESP_OK;
  398. }
  399. // To achieve a better performance, we put the ISR always in IRAM
  400. IRAM_ATTR void emac_isr_default_handler(void *args)
  401. {
  402. emac_hal_context_t *hal = (emac_hal_context_t *)args;
  403. emac_esp32_t *emac = __containerof(hal, emac_esp32_t, hal);
  404. BaseType_t high_task_wakeup = pdFALSE;
  405. uint32_t intr_stat = emac_ll_get_intr_status(hal->dma_regs);
  406. emac_ll_clear_corresponding_intr(hal->dma_regs, intr_stat);
  407. #if EMAC_LL_CONFIG_ENABLE_INTR_MASK & EMAC_LL_INTR_RECEIVE_ENABLE
  408. if (intr_stat & EMAC_LL_DMA_RECEIVE_FINISH_INTR) {
  409. /* notify receive task */
  410. vTaskNotifyGiveFromISR(emac->rx_task_hdl, &high_task_wakeup);
  411. if (high_task_wakeup == pdTRUE) {
  412. portYIELD_FROM_ISR();
  413. }
  414. }
  415. #endif
  416. }
  417. static void esp_emac_free_driver_obj(emac_esp32_t *emac, void *descriptors)
  418. {
  419. if (emac) {
  420. if (emac->rx_task_hdl) {
  421. vTaskDelete(emac->rx_task_hdl);
  422. }
  423. if (emac->intr_hdl) {
  424. esp_intr_free(emac->intr_hdl);
  425. }
  426. if (emac->use_apll) {
  427. periph_rtc_apll_release();
  428. }
  429. for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
  430. free(emac->tx_buf[i]);
  431. }
  432. for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
  433. free(emac->rx_buf[i]);
  434. }
  435. #ifdef CONFIG_PM_ENABLE
  436. if (emac->pm_lock) {
  437. esp_pm_lock_delete(emac->pm_lock);
  438. }
  439. #endif
  440. free(emac);
  441. }
  442. if (descriptors) {
  443. free(descriptors);
  444. }
  445. }
  446. static esp_err_t esp_emac_alloc_driver_obj(const eth_mac_config_t *config, emac_esp32_t **emac_out_hdl, void **out_descriptors)
  447. {
  448. esp_err_t ret = ESP_OK;
  449. emac_esp32_t *emac = NULL;
  450. void *descriptors = NULL;
  451. if (config->flags & ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE) {
  452. emac = heap_caps_calloc(1, sizeof(emac_esp32_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
  453. } else {
  454. emac = calloc(1, sizeof(emac_esp32_t));
  455. }
  456. ESP_GOTO_ON_FALSE(emac, ESP_ERR_NO_MEM, err, TAG, "no mem for esp emac object");
  457. /* alloc memory for ethernet dma descriptor */
  458. uint32_t desc_size = CONFIG_ETH_DMA_RX_BUFFER_NUM * sizeof(eth_dma_rx_descriptor_t) +
  459. CONFIG_ETH_DMA_TX_BUFFER_NUM * sizeof(eth_dma_tx_descriptor_t);
  460. descriptors = heap_caps_calloc(1, desc_size, MALLOC_CAP_DMA);
  461. ESP_GOTO_ON_FALSE(descriptors, ESP_ERR_NO_MEM, err, TAG, "no mem for descriptors");
  462. /* alloc memory for ethernet dma buffer */
  463. for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
  464. emac->rx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA);
  465. ESP_GOTO_ON_FALSE(emac->rx_buf[i], ESP_ERR_NO_MEM, err, TAG, "no mem for RX DMA buffers");
  466. }
  467. for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
  468. emac->tx_buf[i] = heap_caps_calloc(1, CONFIG_ETH_DMA_BUFFER_SIZE, MALLOC_CAP_DMA);
  469. ESP_GOTO_ON_FALSE(emac->tx_buf[i], ESP_ERR_NO_MEM, err, TAG, "no mem for TX DMA buffers");
  470. }
  471. /* alloc PM lock */
  472. #ifdef CONFIG_PM_ENABLE
  473. ESP_GOTO_ON_ERROR(esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "emac_esp32", &emac->pm_lock), err, TAG, "create pm lock failed");
  474. #endif
  475. /* create rx task */
  476. BaseType_t core_num = tskNO_AFFINITY;
  477. if (config->flags & ETH_MAC_FLAG_PIN_TO_CORE) {
  478. core_num = esp_cpu_get_core_id();
  479. }
  480. BaseType_t xReturned = xTaskCreatePinnedToCore(emac_esp32_rx_task, "emac_rx", config->rx_task_stack_size, emac,
  481. config->rx_task_prio, &emac->rx_task_hdl, core_num);
  482. ESP_GOTO_ON_FALSE(xReturned == pdPASS, ESP_FAIL, err, TAG, "create emac_rx task failed");
  483. *out_descriptors = descriptors;
  484. *emac_out_hdl = emac;
  485. return ESP_OK;
  486. err:
  487. esp_emac_free_driver_obj(emac, descriptors);
  488. return ret;
  489. }
  490. static esp_err_t esp_emac_config_data_interface(const eth_esp32_emac_config_t *esp32_emac_config, emac_esp32_t *emac)
  491. {
  492. esp_err_t ret = ESP_OK;
  493. switch (esp32_emac_config->interface) {
  494. case EMAC_DATA_INTERFACE_MII:
  495. emac->clock_config = esp32_emac_config->clock_config;
  496. /* MII interface GPIO initialization */
  497. emac_hal_iomux_init_mii();
  498. /* Enable MII clock */
  499. emac_ll_clock_enable_mii(emac->hal.ext_regs);
  500. break;
  501. case EMAC_DATA_INTERFACE_RMII:
  502. // by default, the clock mode is selected at compile time (by Kconfig)
  503. if (esp32_emac_config->clock_config.rmii.clock_mode == EMAC_CLK_DEFAULT) {
  504. #if CONFIG_ETH_RMII_CLK_INPUT
  505. #if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
  506. emac->clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
  507. emac->clock_config.rmii.clock_gpio = CONFIG_ETH_RMII_CLK_IN_GPIO;
  508. #else
  509. #error "ESP32 EMAC only support input RMII clock to GPIO0"
  510. #endif // CONFIG_ETH_RMII_CLK_IN_GPIO == 0
  511. #elif CONFIG_ETH_RMII_CLK_OUTPUT
  512. emac->clock_config.rmii.clock_mode = EMAC_CLK_OUT;
  513. #if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
  514. emac->clock_config.rmii.clock_gpio = 0;
  515. #elif CONFIG_ETH_RMII_CLK_OUT_GPIO
  516. emac->clock_config.rmii.clock_gpio = CONFIG_ETH_RMII_CLK_OUT_GPIO;
  517. #endif // CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
  518. #else
  519. #error "Unsupported RMII clock mode"
  520. #endif
  521. } else {
  522. emac->clock_config = esp32_emac_config->clock_config;
  523. }
  524. /* RMII interface GPIO initialization */
  525. emac_hal_iomux_init_rmii();
  526. /* If ref_clk is configured as input */
  527. if (emac->clock_config.rmii.clock_mode == EMAC_CLK_EXT_IN) {
  528. ESP_GOTO_ON_FALSE(emac->clock_config.rmii.clock_gpio == EMAC_CLK_IN_GPIO,
  529. ESP_ERR_INVALID_ARG, err, TAG, "ESP32 EMAC only support input RMII clock to GPIO0");
  530. emac_hal_iomux_rmii_clk_input();
  531. emac_ll_clock_enable_rmii_input(emac->hal.ext_regs);
  532. } else if (emac->clock_config.rmii.clock_mode == EMAC_CLK_OUT) {
  533. ESP_GOTO_ON_FALSE(emac->clock_config.rmii.clock_gpio == EMAC_APPL_CLK_OUT_GPIO ||
  534. emac->clock_config.rmii.clock_gpio == EMAC_CLK_OUT_GPIO ||
  535. emac->clock_config.rmii.clock_gpio == EMAC_CLK_OUT_180_GPIO,
  536. ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC clock output GPIO");
  537. emac_hal_iomux_rmii_clk_ouput(emac->clock_config.rmii.clock_gpio);
  538. if (emac->clock_config.rmii.clock_gpio == EMAC_APPL_CLK_OUT_GPIO) {
  539. REG_SET_FIELD(PIN_CTRL, CLK_OUT1, 6);
  540. }
  541. /* Enable RMII clock */
  542. emac_ll_clock_enable_rmii_output(emac->hal.ext_regs);
  543. // Power up APLL clock
  544. periph_rtc_apll_acquire();
  545. ESP_GOTO_ON_ERROR(emac_config_apll_clock(), err, TAG, "Configure APLL for RMII failed");
  546. emac->use_apll = true;
  547. } else {
  548. ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC clock mode");
  549. }
  550. break;
  551. default:
  552. ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid EMAC Data Interface:%d", esp32_emac_config->interface);
  553. }
  554. err:
  555. return ret;
  556. }
  557. esp_eth_mac_t *esp_eth_mac_new_esp32(const eth_esp32_emac_config_t *esp32_config, const eth_mac_config_t *config)
  558. {
  559. esp_err_t ret_code = ESP_OK;
  560. esp_eth_mac_t *ret = NULL;
  561. void *descriptors = NULL;
  562. emac_esp32_t *emac = NULL;
  563. ESP_GOTO_ON_FALSE(config, NULL, err, TAG, "can't set mac config to null");
  564. ret_code = esp_emac_alloc_driver_obj(config, &emac, &descriptors);
  565. ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "alloc driver object failed");
  566. /* enable APB to access Ethernet peripheral registers */
  567. periph_module_enable(PERIPH_EMAC_MODULE);
  568. /* initialize hal layer driver */
  569. emac_hal_init(&emac->hal, descriptors, emac->rx_buf, emac->tx_buf);
  570. /* alloc interrupt */
  571. if (config->flags & ETH_MAC_FLAG_WORK_WITH_CACHE_DISABLE) {
  572. ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, ESP_INTR_FLAG_IRAM,
  573. emac_isr_default_handler, &emac->hal, &(emac->intr_hdl));
  574. } else {
  575. ret_code = esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0,
  576. emac_isr_default_handler, &emac->hal, &(emac->intr_hdl));
  577. }
  578. ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err, TAG, "alloc emac interrupt failed");
  579. ret_code = esp_emac_config_data_interface(esp32_config, emac);
  580. ESP_GOTO_ON_FALSE(ret_code == ESP_OK, NULL, err_interf, TAG, "config emac interface failed");
  581. emac->dma_burst_len = esp32_config->dma_burst_len;
  582. emac->sw_reset_timeout_ms = config->sw_reset_timeout_ms;
  583. emac->smi_mdc_gpio_num = esp32_config->smi_mdc_gpio_num;
  584. emac->smi_mdio_gpio_num = esp32_config->smi_mdio_gpio_num;
  585. emac->flow_control_high_water_mark = FLOW_CONTROL_HIGH_WATER_MARK;
  586. emac->flow_control_low_water_mark = FLOW_CONTROL_LOW_WATER_MARK;
  587. emac->use_apll = false;
  588. emac->parent.set_mediator = emac_esp32_set_mediator;
  589. emac->parent.init = emac_esp32_init;
  590. emac->parent.deinit = emac_esp32_deinit;
  591. emac->parent.start = emac_esp32_start;
  592. emac->parent.stop = emac_esp32_stop;
  593. emac->parent.del = emac_esp32_del;
  594. emac->parent.write_phy_reg = emac_esp32_write_phy_reg;
  595. emac->parent.read_phy_reg = emac_esp32_read_phy_reg;
  596. emac->parent.set_addr = emac_esp32_set_addr;
  597. emac->parent.get_addr = emac_esp32_get_addr;
  598. emac->parent.set_speed = emac_esp32_set_speed;
  599. emac->parent.set_duplex = emac_esp32_set_duplex;
  600. emac->parent.set_link = emac_esp32_set_link;
  601. emac->parent.set_promiscuous = emac_esp32_set_promiscuous;
  602. emac->parent.set_peer_pause_ability = emac_esp32_set_peer_pause_ability;
  603. emac->parent.enable_flow_ctrl = emac_esp32_enable_flow_ctrl;
  604. emac->parent.transmit = emac_esp32_transmit;
  605. emac->parent.transmit_vargs = emac_esp32_transmit_multiple_bufs;
  606. emac->parent.receive = emac_esp32_receive;
  607. return &(emac->parent);
  608. err_interf:
  609. periph_module_disable(PERIPH_EMAC_MODULE);
  610. err:
  611. esp_emac_free_driver_obj(emac, descriptors);
  612. return ret;
  613. }