esp_eth_mac_esp.c 24 KB

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