emac_hal.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <string.h>
  7. #include "sdkconfig.h"
  8. #include "esp_attr.h"
  9. #include "hal/emac_hal.h"
  10. #include "hal/emac_ll.h"
  11. #include "hal/gpio_ll.h"
  12. #define ETH_CRC_LENGTH (4)
  13. #ifndef NDEBUG
  14. #define EMAC_HAL_BUF_MAGIC_ID 0x1E1C8416
  15. #endif // NDEBUG
  16. typedef struct {
  17. #ifndef NDEBUG
  18. uint32_t magic_id;
  19. #endif // NDEBUG
  20. uint32_t copy_len;
  21. }__attribute__((packed)) emac_hal_auto_buf_info_t;
  22. void emac_hal_iomux_init_mii(void)
  23. {
  24. /* TX_CLK to GPIO0 */
  25. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
  26. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
  27. /* TX_EN to GPIO21 */
  28. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
  29. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
  30. /* TXD0 to GPIO19 */
  31. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
  32. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
  33. /* TXD1 to GPIO22 */
  34. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
  35. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
  36. /* TXD2 to MTMS */
  37. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTMS_U, FUNC_MTMS_EMAC_TXD2);
  38. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[14]);
  39. /* TXD3 to MTDI */
  40. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTDI_U, FUNC_MTDI_EMAC_TXD3);
  41. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[12]);
  42. /* RX_CLK to GPIO5 */
  43. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5_EMAC_RX_CLK);
  44. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[5]);
  45. /* RX_DV to GPIO27 */
  46. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
  47. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
  48. /* RXD0 to GPIO25 */
  49. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
  50. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
  51. /* RXD1 to GPIO26 */
  52. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
  53. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
  54. /* RXD2 to U0TXD */
  55. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_EMAC_RXD2);
  56. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[1]);
  57. /* RXD3 to MTDO */
  58. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTDO_U, FUNC_MTDO_EMAC_RXD3);
  59. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[15]);
  60. }
  61. void emac_hal_iomux_rmii_clk_input(void)
  62. {
  63. /* REF_CLK(RMII mode) to GPIO0 */
  64. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
  65. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
  66. }
  67. void emac_hal_iomux_rmii_clk_ouput(int num)
  68. {
  69. switch (num) {
  70. case 0:
  71. /* APLL clock output to GPIO0 (must be configured to 50MHz!) */
  72. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
  73. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
  74. break;
  75. case 16:
  76. /* RMII CLK (50MHz) output to GPIO16 */
  77. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
  78. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
  79. break;
  80. case 17:
  81. /* RMII CLK (50MHz) output to GPIO17 */
  82. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
  83. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
  84. break;
  85. default:
  86. break;
  87. }
  88. }
  89. void emac_hal_iomux_init_rmii(void)
  90. {
  91. /* TX_EN to GPIO21 */
  92. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
  93. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
  94. /* TXD0 to GPIO19 */
  95. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
  96. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
  97. /* TXD1 to GPIO22 */
  98. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
  99. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
  100. /* CRS_DV to GPIO27 */
  101. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
  102. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
  103. /* RXD0 to GPIO25 */
  104. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
  105. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
  106. /* RXD1 to GPIO26 */
  107. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
  108. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
  109. }
  110. void emac_hal_iomux_init_tx_er(void)
  111. {
  112. /* TX_ER to GPIO4 */
  113. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4_EMAC_TX_ER);
  114. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[4]);
  115. }
  116. void emac_hal_iomux_init_rx_er(void)
  117. {
  118. /* RX_ER to MTCK */
  119. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTCK_U, FUNC_MTCK_EMAC_RX_ER);
  120. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[13]);
  121. }
  122. void emac_hal_init(emac_hal_context_t *hal, void *descriptors,
  123. uint8_t **rx_buf, uint8_t **tx_buf)
  124. {
  125. hal->dma_regs = &EMAC_DMA;
  126. hal->mac_regs = &EMAC_MAC;
  127. hal->ext_regs = &EMAC_EXT;
  128. hal->descriptors = descriptors;
  129. hal->rx_buf = rx_buf;
  130. hal->tx_buf = tx_buf;
  131. }
  132. void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq)
  133. {
  134. /* Tell MAC system clock Frequency in MHz, which will determine the frequency range of MDC(1MHz~2.5MHz) */
  135. if (freq >= 20000000 && freq < 35000000) {
  136. emac_ll_set_csr_clock_division(hal->mac_regs, 2); // CSR clock/16
  137. } else if (freq >= 35000000 && freq < 60000000) {
  138. emac_ll_set_csr_clock_division(hal->mac_regs, 3); // CSR clock/26
  139. } else if (freq >= 60000000 && freq < 100000000) {
  140. emac_ll_set_csr_clock_division(hal->mac_regs, 0); // CSR clock/42
  141. } else if (freq >= 100000000 && freq < 150000000) {
  142. emac_ll_set_csr_clock_division(hal->mac_regs, 1); // CSR clock/62
  143. } else if (freq >= 150000000 && freq < 250000000) {
  144. emac_ll_set_csr_clock_division(hal->mac_regs, 4); // CSR clock/102
  145. } else {
  146. emac_ll_set_csr_clock_division(hal->mac_regs, 5); // CSR clock/124
  147. }
  148. }
  149. void emac_hal_reset_desc_chain(emac_hal_context_t *hal)
  150. {
  151. /* reset DMA descriptors */
  152. hal->rx_desc = (eth_dma_rx_descriptor_t *)(hal->descriptors);
  153. hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->descriptors +
  154. sizeof(eth_dma_rx_descriptor_t) * CONFIG_ETH_DMA_RX_BUFFER_NUM);
  155. /* init rx chain */
  156. for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
  157. /* Set Own bit of the Rx descriptor Status: DMA */
  158. hal->rx_desc[i].RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  159. /* Set Buffer1 size and Second Address Chained bit */
  160. hal->rx_desc[i].RDES1.SecondAddressChained = 1;
  161. hal->rx_desc[i].RDES1.ReceiveBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  162. /* Enable Ethernet DMA Rx Descriptor interrupt */
  163. hal->rx_desc[i].RDES1.DisableInterruptOnComplete = 0;
  164. /* point to the buffer */
  165. hal->rx_desc[i].Buffer1Addr = (uint32_t)(hal->rx_buf[i]);
  166. /* point to next descriptor */
  167. hal->rx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc + i + 1);
  168. }
  169. /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
  170. hal->rx_desc[CONFIG_ETH_DMA_RX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc);
  171. /* init tx chain */
  172. for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
  173. /* Set Own bit of the Tx descriptor Status: CPU */
  174. hal->tx_desc[i].TDES0.Own = EMAC_LL_DMADESC_OWNER_CPU;
  175. hal->tx_desc[i].TDES0.SecondAddressChained = 1;
  176. hal->tx_desc[i].TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  177. /* Enable Ethernet DMA Tx Descriptor interrupt */
  178. hal->tx_desc[1].TDES0.InterruptOnComplete = 1;
  179. /* Enable Transmit Timestamp */
  180. hal->tx_desc[i].TDES0.TransmitTimestampEnable = 1;
  181. /* point to the buffer */
  182. hal->tx_desc[i].Buffer1Addr = (uint32_t)(hal->tx_buf[i]);
  183. /* point to next descriptor */
  184. hal->tx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc + i + 1);
  185. }
  186. /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
  187. hal->tx_desc[CONFIG_ETH_DMA_TX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc);
  188. /* set base address of the first descriptor */
  189. emac_ll_set_rx_desc_addr(hal->dma_regs, (uint32_t)hal->rx_desc);
  190. emac_ll_set_tx_desc_addr(hal->dma_regs, (uint32_t)hal->tx_desc);
  191. }
  192. void emac_hal_init_mac_default(emac_hal_context_t *hal)
  193. {
  194. /* MACCR Configuration */
  195. /* Enable the watchdog on the receiver, frame longer than 2048 Bytes is not allowed */
  196. emac_ll_watchdog_enable(hal->mac_regs, true);
  197. /* Enable the jabber timer on the transmitter, frame longer than 2048 Bytes is not allowed */
  198. emac_ll_jabber_enable(hal->mac_regs, true);
  199. /* minimum IFG between frames during transmission is 96 bit times */
  200. emac_ll_set_inter_frame_gap(hal->mac_regs, EMAC_LL_INTERFRAME_GAP_96BIT);
  201. /* Enable Carrier Sense During Transmission */
  202. emac_ll_carrier_sense_enable(hal->mac_regs, true);
  203. /* Select speed: port: 10/100 Mbps, here set default 100M, afterwards, will reset by auto-negotiation */
  204. emac_ll_set_port_speed(hal->mac_regs, ETH_SPEED_100M);;
  205. /* Allow the reception of frames when the TX_EN signal is asserted in Half-Duplex mode */
  206. emac_ll_recv_own_enable(hal->mac_regs, true);
  207. /* Disable internal loopback mode */
  208. emac_ll_loopback_enable(hal->mac_regs, false);
  209. /* Select duplex mode: here set default full duplex, afterwards, will reset by auto-negotiation */
  210. emac_ll_set_duplex(hal->mac_regs, ETH_DUPLEX_FULL);
  211. /* Select the checksum mode for received frame payload's TCP/UDP/ICMP headers */
  212. emac_ll_checksum_offload_mode(hal->mac_regs, ETH_CHECKSUM_HW);
  213. /* Enable MAC retry transmission when a colision occurs in half duplex mode */
  214. emac_ll_retry_enable(hal->mac_regs, true);
  215. /* MAC passes all incoming frames to host, without modifying them */
  216. emac_ll_auto_pad_crc_strip_enable(hal->mac_regs, false);
  217. /* Set Back-Off limit time before retry a transmittion after a collision */
  218. emac_ll_set_back_off_limit(hal->mac_regs, EMAC_LL_BACKOFF_LIMIT_10);
  219. /* Disable deferral check, MAC defers until the CRS signal goes inactive */
  220. emac_ll_deferral_check_enable(hal->mac_regs, false);
  221. /* Set preamble length 7 Bytes */
  222. emac_ll_set_preamble_length(hal->mac_regs, EMAC_LL_PREAMBLE_LENGTH_7);
  223. /* MACFFR Configuration */
  224. /* Receiver module passes only those frames to the Application that pass the SA or DA address filter */
  225. emac_ll_receive_all_enable(hal->mac_regs, false);
  226. /* Disable source address filter */
  227. emac_ll_set_src_addr_filter(hal->mac_regs, EMAC_LL_SOURCE_ADDR_FILTER_DISABLE);
  228. emac_ll_sa_inverse_filter_enable(hal->mac_regs, false);
  229. /* MAC blocks all control frames */
  230. emac_ll_set_pass_ctrl_frame_mode(hal->mac_regs, EMAC_LL_CONTROL_FRAME_BLOCKALL);
  231. /* AFM module passes all received broadcast frames and multicast frames */
  232. emac_ll_broadcast_frame_enable(hal->mac_regs, true);
  233. emac_ll_pass_all_multicast_enable(hal->mac_regs, true);
  234. /* Address Check block operates in normal filtering mode for the DA address */
  235. emac_ll_da_inverse_filter_enable(hal->mac_regs, false);
  236. /* Disable Promiscuous Mode */
  237. emac_ll_promiscuous_mode_enable(hal->mac_regs, false);
  238. }
  239. void emac_hal_enable_flow_ctrl(emac_hal_context_t *hal, bool enable)
  240. {
  241. /* MACFCR Configuration */
  242. if (enable) {
  243. /* Pause time */
  244. emac_ll_set_pause_time(hal->mac_regs, EMAC_LL_PAUSE_TIME);
  245. /* Enable generation of Zero-Quanta Pause Control frames */
  246. emac_ll_zero_quanta_pause_enable(hal->mac_regs, true);
  247. /* Threshold of the PAUSE to be checked for automatic retransmission of PAUSE Frame */
  248. emac_ll_set_pause_low_threshold(hal->mac_regs, EMAC_LL_PAUSE_LOW_THRESHOLD_MINUS_28);
  249. /* Don't allow MAC detect Pause frames with MAC address0 unicast address and unique multicast address */
  250. emac_ll_unicast_pause_frame_detect_enable(hal->mac_regs, false);
  251. /* Enable MAC to decode the received Pause frame and disable its transmitter for a specific time */
  252. emac_ll_receive_flow_ctrl_enable(hal->mac_regs, true);
  253. /* Enable MAC to transmit Pause frames in full duplex mode or the MAC back-pressure operation in half duplex mode */
  254. emac_ll_transmit_flow_ctrl_enable(hal->mac_regs, true);
  255. } else {
  256. emac_ll_clear(hal->mac_regs);
  257. }
  258. }
  259. void emac_hal_init_dma_default(emac_hal_context_t *hal, emac_hal_dma_config_t *hal_config)
  260. {
  261. /* DMAOMR Configuration */
  262. /* Enable Dropping of TCP/IP Checksum Error Frames */
  263. emac_ll_drop_tcp_err_frame_enable(hal->dma_regs, true);
  264. /* Enable Receive Store Forward */
  265. emac_ll_recv_store_forward_enable(hal->dma_regs, true);
  266. /* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */
  267. emac_ll_flush_recv_frame_enable(hal->dma_regs, true);
  268. /* Disable Transmit Store Forward */
  269. emac_ll_trans_store_forward_enable(hal->dma_regs, false);
  270. /* Flush Transmit FIFO */
  271. emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
  272. /* Transmit Threshold Control */
  273. emac_ll_set_transmit_threshold(hal->dma_regs, EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_64);
  274. /* Disable Forward Error Frame */
  275. emac_ll_forward_err_frame_enable(hal->dma_regs, false);
  276. /* Disable forward undersized good frame */
  277. emac_ll_forward_undersized_good_frame_enable(hal->dma_regs, false);
  278. /* Receive Threshold Control */
  279. emac_ll_set_recv_threshold(hal->dma_regs, EMAC_LL_RECEIVE_THRESHOLD_CONTROL_64);
  280. /* Allow the DMA to process a second frame of Transmit data even before obtaining the status for the first frame */
  281. emac_ll_opt_second_frame_enable(hal->dma_regs, true);
  282. /* DMABMR Configuration */
  283. /* Enable Mixed Burst */
  284. emac_ll_mixed_burst_enable(hal->dma_regs, true);
  285. /* Enable Address Aligned Beates */
  286. emac_ll_addr_align_enable(hal->dma_regs, true);
  287. /* Don't use Separate PBL */
  288. emac_ll_use_separate_pbl_enable(hal->dma_regs, false);
  289. /* Set Rx/Tx DMA Burst Length */
  290. emac_ll_set_prog_burst_len(hal->dma_regs, hal_config->dma_burst_len);
  291. /* Enable Enhanced Descriptor,8 Words(32 Bytes) */
  292. emac_ll_enhance_desc_enable(hal->dma_regs, true);
  293. /* Specifies the number of word to skip between two unchained descriptors (Ring mode) */
  294. emac_ll_set_desc_skip_len(hal->dma_regs, 0);
  295. /* DMA Arbitration Scheme */
  296. emac_ll_fixed_arbitration_enable(hal->dma_regs, false);
  297. /* Set priority ratio in the weighted round-robin arbitration between Rx DMA and Tx DMA */
  298. emac_ll_set_priority_ratio(hal->dma_regs, EMAC_LL_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1);
  299. }
  300. void emac_hal_set_phy_cmd(emac_hal_context_t *hal, uint32_t phy_addr, uint32_t phy_reg, bool write)
  301. {
  302. /* Write the result value into the MII Address register */
  303. emac_ll_set_phy_addr(hal->mac_regs, phy_addr);
  304. /* Set the PHY register address */
  305. emac_ll_set_phy_reg(hal->mac_regs, phy_reg);
  306. /* Set as write mode */
  307. emac_ll_write_enable(hal->mac_regs, write);
  308. /* Set MII busy bit */
  309. emac_ll_set_busy(hal->mac_regs, true);
  310. }
  311. void emac_hal_set_address(emac_hal_context_t *hal, uint8_t *mac_addr)
  312. {
  313. /* Make sure mac address is unicast type */
  314. if (!(mac_addr[0] & 0x01)) {
  315. emac_ll_set_addr(hal->mac_regs, mac_addr);
  316. }
  317. }
  318. void emac_hal_start(emac_hal_context_t *hal)
  319. {
  320. /* Enable Ethernet MAC and DMA Interrupt */
  321. emac_ll_enable_corresponding_intr(hal->dma_regs, EMAC_LL_CONFIG_ENABLE_INTR_MASK);
  322. /* Flush Transmit FIFO */
  323. emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
  324. /* Start DMA transmission */
  325. emac_ll_start_stop_dma_transmit(hal->dma_regs, true);
  326. /* Start DMA reception */
  327. emac_ll_start_stop_dma_receive(hal->dma_regs, true);
  328. /* Enable transmit state machine of the MAC for transmission on the MII */
  329. emac_ll_transmit_enable(hal->mac_regs, true);
  330. /* Enable receive state machine of the MAC for reception from the MII */
  331. emac_ll_receive_enable(hal->mac_regs, true);
  332. /* Clear all pending interrupts */
  333. emac_ll_clear_all_pending_intr(hal->dma_regs);
  334. }
  335. esp_err_t emac_hal_stop(emac_hal_context_t *hal)
  336. {
  337. /* Stop DMA transmission */
  338. emac_ll_start_stop_dma_transmit(hal->dma_regs, false);
  339. if (emac_ll_transmit_frame_ctrl_status(hal->mac_regs) != 0x0) {
  340. /* Previous transmit in progress */
  341. return ESP_ERR_INVALID_STATE;
  342. }
  343. /* Disable transmit state machine of the MAC for transmission on the MII */
  344. emac_ll_receive_enable(hal->mac_regs, false);
  345. /* Disable receive state machine of the MAC for reception from the MII */
  346. emac_ll_transmit_enable(hal->mac_regs, false);
  347. if (emac_ll_receive_read_ctrl_state(hal->mac_regs) != 0x0) {
  348. /* Previous receive copy in progress */
  349. return ESP_ERR_INVALID_STATE;
  350. }
  351. /* Stop DMA reception */
  352. emac_ll_start_stop_dma_receive(hal->dma_regs, false);
  353. /* Disable Ethernet MAC and DMA Interrupt */
  354. emac_ll_disable_all_intr(hal->dma_regs);
  355. return ESP_OK;
  356. }
  357. uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
  358. {
  359. /* Get the number of Tx buffers to use for the frame */
  360. uint32_t bufcount = 0;
  361. uint32_t lastlen = length;
  362. uint32_t sentout = 0;
  363. while (lastlen > CONFIG_ETH_DMA_BUFFER_SIZE) {
  364. lastlen -= CONFIG_ETH_DMA_BUFFER_SIZE;
  365. bufcount++;
  366. }
  367. if (lastlen) {
  368. bufcount++;
  369. }
  370. if (bufcount > CONFIG_ETH_DMA_TX_BUFFER_NUM) {
  371. goto err;
  372. }
  373. eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc;
  374. /* A frame is transmitted in multiple descriptor */
  375. for (size_t i = 0; i < bufcount; i++) {
  376. /* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
  377. if (desc_iter->TDES0.Own != EMAC_LL_DMADESC_OWNER_CPU) {
  378. goto err;
  379. }
  380. /* Clear FIRST and LAST segment bits */
  381. desc_iter->TDES0.FirstSegment = 0;
  382. desc_iter->TDES0.LastSegment = 0;
  383. desc_iter->TDES0.InterruptOnComplete = 0;
  384. if (i == 0) {
  385. /* Setting the first segment bit */
  386. desc_iter->TDES0.FirstSegment = 1;
  387. }
  388. if (i == (bufcount - 1)) {
  389. /* Setting the last segment bit */
  390. desc_iter->TDES0.LastSegment = 1;
  391. /* Enable transmit interrupt */
  392. desc_iter->TDES0.InterruptOnComplete = 1;
  393. /* Program size */
  394. desc_iter->TDES1.TransmitBuffer1Size = lastlen;
  395. /* copy data from uplayer stack buffer */
  396. memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen);
  397. sentout += lastlen;
  398. } else {
  399. /* Program size */
  400. desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  401. /* copy data from uplayer stack buffer */
  402. memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
  403. sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
  404. }
  405. /* Point to next descriptor */
  406. desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  407. }
  408. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  409. for (size_t i = 0; i < bufcount; i++) {
  410. hal->tx_desc->TDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  411. hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
  412. }
  413. emac_ll_transmit_poll_demand(hal->dma_regs, 0);
  414. return sentout;
  415. err:
  416. return 0;
  417. }
  418. uint32_t emac_hal_transmit_multiple_buf_frame(emac_hal_context_t *hal, uint8_t **buffs, uint32_t *lengths, uint32_t buffs_cnt)
  419. {
  420. /* Get the number of Tx buffers to use for the frame */
  421. uint32_t dma_bufcount = 0;
  422. uint32_t sentout = 0;
  423. uint8_t *ptr = buffs[0];
  424. uint32_t lastlen = lengths[0];
  425. uint32_t avail_len = CONFIG_ETH_DMA_BUFFER_SIZE;
  426. eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc;
  427. /* A frame is transmitted in multiple descriptor */
  428. while (dma_bufcount < CONFIG_ETH_DMA_TX_BUFFER_NUM) {
  429. /* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
  430. if (desc_iter->TDES0.Own != EMAC_LL_DMADESC_OWNER_CPU) {
  431. goto err;
  432. }
  433. /* Clear FIRST and LAST segment bits */
  434. desc_iter->TDES0.FirstSegment = 0;
  435. desc_iter->TDES0.LastSegment = 0;
  436. desc_iter->TDES0.InterruptOnComplete = 0;
  437. desc_iter->TDES1.TransmitBuffer1Size = 0;
  438. if (dma_bufcount == 0) {
  439. /* Setting the first segment bit */
  440. desc_iter->TDES0.FirstSegment = 1;
  441. }
  442. while (buffs_cnt > 0) {
  443. /* Check if input buff data fits to currently available space in the descriptor */
  444. if (lastlen < avail_len) {
  445. /* copy data from uplayer stack buffer */
  446. memcpy((void *)(desc_iter->Buffer1Addr + (CONFIG_ETH_DMA_BUFFER_SIZE - avail_len)), ptr, lastlen);
  447. sentout += lastlen;
  448. avail_len -= lastlen;
  449. desc_iter->TDES1.TransmitBuffer1Size += lastlen;
  450. /* Update processed input buffers info */
  451. buffs_cnt--;
  452. ptr = *(++buffs);
  453. lastlen = *(++lengths);
  454. /* There is only limited available space in the current descriptor, use it all */
  455. } else {
  456. /* copy data from uplayer stack buffer */
  457. memcpy((void *)(desc_iter->Buffer1Addr + (CONFIG_ETH_DMA_BUFFER_SIZE - avail_len)), ptr, avail_len);
  458. sentout += avail_len;
  459. lastlen -= avail_len;
  460. /* If lastlen is not zero, input buff will be fragmented over multiple descriptors */
  461. if (lastlen > 0) {
  462. ptr += avail_len;
  463. /* Input buff fully fits the descriptor, move to the next input buff */
  464. } else {
  465. /* Update processed input buffers info */
  466. buffs_cnt--;
  467. ptr = *(++buffs);
  468. lastlen = *(++lengths);
  469. }
  470. avail_len = CONFIG_ETH_DMA_BUFFER_SIZE;
  471. desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  472. /* The descriptor is full here so exit and use the next descriptor */
  473. break;
  474. }
  475. }
  476. /* Increase counter of utilized DMA buffers */
  477. dma_bufcount++;
  478. /* If all input buffers processed, mark as LAST segment and finish the coping */
  479. if (buffs_cnt == 0) {
  480. /* Setting the last segment bit */
  481. desc_iter->TDES0.LastSegment = 1;
  482. /* Enable transmit interrupt */
  483. desc_iter->TDES0.InterruptOnComplete = 1;
  484. break;
  485. }
  486. /* Point to next descriptor */
  487. desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  488. }
  489. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  490. for (size_t i = 0; i < dma_bufcount; i++) {
  491. hal->tx_desc->TDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  492. hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
  493. }
  494. emac_ll_transmit_poll_demand(hal->dma_regs, 0);
  495. return sentout;
  496. err:
  497. return 0;
  498. }
  499. uint8_t *emac_hal_alloc_recv_buf(emac_hal_context_t *hal, uint32_t *size)
  500. {
  501. eth_dma_rx_descriptor_t *desc_iter = hal->rx_desc;
  502. uint32_t used_descs = 0;
  503. uint32_t ret_len = 0;
  504. uint32_t copy_len = 0;
  505. uint8_t *buf = NULL;
  506. /* Traverse descriptors owned by CPU */
  507. while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
  508. used_descs++;
  509. /* Last segment in frame */
  510. if (desc_iter->RDES0.LastDescriptor) {
  511. /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  512. ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
  513. /* packets larger than expected will be truncated */
  514. copy_len = ret_len > *size ? *size : ret_len;
  515. break;
  516. }
  517. /* point to next descriptor */
  518. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  519. }
  520. if (copy_len > 0) {
  521. buf = malloc(copy_len);
  522. if (buf != NULL) {
  523. emac_hal_auto_buf_info_t *buff_info = (emac_hal_auto_buf_info_t *)buf;
  524. /* no need to check allocated buffer min lenght prior writing since we know that EMAC DMA is configured to
  525. not forward erroneous or undersized frames (less than 64B), see emac_hal_init_dma_default */
  526. #ifndef NDEBUG
  527. buff_info->magic_id = EMAC_HAL_BUF_MAGIC_ID;
  528. #endif // NDEBUG
  529. buff_info->copy_len = copy_len;
  530. }
  531. }
  532. /* indicate actual size of received frame */
  533. *size = ret_len;
  534. return buf;
  535. }
  536. uint32_t emac_hal_receive_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t size, uint32_t *frames_remain, uint32_t *free_desc)
  537. {
  538. eth_dma_rx_descriptor_t *desc_iter = hal->rx_desc;
  539. eth_dma_rx_descriptor_t *first_desc = hal->rx_desc;
  540. uint32_t used_descs = 0;
  541. uint32_t ret_len = 0;
  542. uint32_t copy_len = 0;
  543. uint32_t frame_count = 0;
  544. if (size != EMAC_HAL_BUF_SIZE_AUTO) {
  545. /* Traverse descriptors owned by CPU */
  546. while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM) && !frame_count) {
  547. used_descs++;
  548. /* Last segment in frame */
  549. if (desc_iter->RDES0.LastDescriptor) {
  550. /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  551. ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
  552. /* packets larger than expected will be truncated */
  553. copy_len = ret_len > size ? size : ret_len;
  554. /* update unhandled frame count */
  555. frame_count++;
  556. }
  557. /* First segment in frame */
  558. if (desc_iter->RDES0.FirstDescriptor) {
  559. first_desc = desc_iter;
  560. }
  561. /* point to next descriptor */
  562. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  563. }
  564. } else {
  565. emac_hal_auto_buf_info_t *buff_info = (emac_hal_auto_buf_info_t *)buf;
  566. #ifndef NDEBUG
  567. /* check that buffer was allocated by emac_hal_alloc_recv_buf */
  568. assert(buff_info->magic_id == EMAC_HAL_BUF_MAGIC_ID);
  569. #endif // NDEBUG
  570. copy_len = buff_info->copy_len;
  571. ret_len = copy_len;
  572. }
  573. if (copy_len) {
  574. /* check how many frames left to handle */
  575. while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
  576. used_descs++;
  577. if (desc_iter->RDES0.LastDescriptor) {
  578. frame_count++;
  579. }
  580. /* point to next descriptor */
  581. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  582. }
  583. desc_iter = first_desc;
  584. while(copy_len > CONFIG_ETH_DMA_BUFFER_SIZE) {
  585. used_descs--;
  586. memcpy(buf, (void *)(desc_iter->Buffer1Addr), CONFIG_ETH_DMA_BUFFER_SIZE);
  587. buf += CONFIG_ETH_DMA_BUFFER_SIZE;
  588. copy_len -= CONFIG_ETH_DMA_BUFFER_SIZE;
  589. /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
  590. desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  591. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  592. }
  593. memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
  594. desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  595. used_descs--;
  596. /* `copy_len` does not include CRC, hence check if we reached the last descriptor */
  597. while (!desc_iter->RDES0.LastDescriptor) {
  598. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  599. desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  600. used_descs--;
  601. }
  602. /* update rxdesc */
  603. hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  604. /* poll rx demand */
  605. emac_ll_receive_poll_demand(hal->dma_regs, 0);
  606. frame_count--;
  607. }
  608. *frames_remain = frame_count;
  609. *free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
  610. return ret_len;
  611. }
  612. uint32_t emac_hal_flush_recv_frame(emac_hal_context_t *hal, uint32_t *frames_remain, uint32_t *free_desc)
  613. {
  614. eth_dma_rx_descriptor_t *desc_iter = hal->rx_desc;
  615. eth_dma_rx_descriptor_t *first_desc = hal->rx_desc;
  616. uint32_t used_descs = 0;
  617. uint32_t frame_len = 0;
  618. uint32_t frame_count = 0;
  619. /* Traverse descriptors owned by CPU */
  620. while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM) && !frame_count) {
  621. used_descs++;
  622. /* Last segment in frame */
  623. if (desc_iter->RDES0.LastDescriptor) {
  624. /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  625. frame_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
  626. /* update unhandled frame count */
  627. frame_count++;
  628. }
  629. /* First segment in frame */
  630. if (desc_iter->RDES0.FirstDescriptor) {
  631. first_desc = desc_iter;
  632. }
  633. /* point to next descriptor */
  634. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  635. }
  636. /* if there is at least one frame waiting */
  637. if (frame_len) {
  638. /* check how many frames left to handle */
  639. while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
  640. used_descs++;
  641. if (desc_iter->RDES0.LastDescriptor) {
  642. frame_count++;
  643. }
  644. /* point to next descriptor */
  645. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  646. }
  647. desc_iter = first_desc;
  648. /* return descriptors to DMA */
  649. while (!desc_iter->RDES0.LastDescriptor) {
  650. desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  651. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  652. used_descs--;
  653. }
  654. desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  655. used_descs--;
  656. /* update rxdesc */
  657. hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  658. /* poll rx demand */
  659. emac_ll_receive_poll_demand(hal->dma_regs, 0);
  660. frame_count--;
  661. }
  662. *frames_remain = frame_count;
  663. *free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
  664. return frame_len;
  665. }