emac_hal.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. // Copyright 2021 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 "sdkconfig.h"
  16. #include "esp_attr.h"
  17. #include "hal/emac_hal.h"
  18. #include "hal/emac_ll.h"
  19. #include "hal/gpio_ll.h"
  20. #define ETH_CRC_LENGTH (4)
  21. void emac_hal_iomux_init_mii(void)
  22. {
  23. /* TX_CLK to GPIO0 */
  24. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
  25. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
  26. /* TX_EN to GPIO21 */
  27. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
  28. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
  29. /* TXD0 to GPIO19 */
  30. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
  31. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
  32. /* TXD1 to GPIO22 */
  33. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
  34. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
  35. /* TXD2 to MTMS */
  36. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTMS_U, FUNC_MTMS_EMAC_TXD2);
  37. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[14]);
  38. /* TXD3 to MTDI */
  39. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTDI_U, FUNC_MTDI_EMAC_TXD3);
  40. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[12]);
  41. /* RX_CLK to GPIO5 */
  42. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5_EMAC_RX_CLK);
  43. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[5]);
  44. /* RX_DV to GPIO27 */
  45. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
  46. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
  47. /* RXD0 to GPIO25 */
  48. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
  49. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
  50. /* RXD1 to GPIO26 */
  51. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
  52. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
  53. /* RXD2 to U0TXD */
  54. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_EMAC_RXD2);
  55. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[1]);
  56. /* RXD3 to MTDO */
  57. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTDO_U, FUNC_MTDO_EMAC_RXD3);
  58. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[15]);
  59. }
  60. void emac_hal_iomux_rmii_clk_input(void)
  61. {
  62. /* REF_CLK(RMII mode) to GPIO0 */
  63. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
  64. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
  65. }
  66. void emac_hal_iomux_rmii_clk_ouput(int num)
  67. {
  68. switch (num) {
  69. case 0:
  70. /* APLL clock output to GPIO0 (must be configured to 50MHz!) */
  71. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
  72. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
  73. break;
  74. case 16:
  75. /* RMII CLK (50MHz) output to GPIO16 */
  76. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
  77. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
  78. break;
  79. case 17:
  80. /* RMII CLK (50MHz) output to GPIO17 */
  81. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
  82. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
  83. break;
  84. default:
  85. break;
  86. }
  87. }
  88. void emac_hal_iomux_init_rmii(void)
  89. {
  90. /* TX_EN to GPIO21 */
  91. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
  92. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
  93. /* TXD0 to GPIO19 */
  94. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
  95. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
  96. /* TXD1 to GPIO22 */
  97. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
  98. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
  99. /* CRS_DV to GPIO27 */
  100. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
  101. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
  102. /* RXD0 to GPIO25 */
  103. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
  104. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
  105. /* RXD1 to GPIO26 */
  106. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
  107. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
  108. }
  109. void emac_hal_iomux_init_tx_er(void)
  110. {
  111. /* TX_ER to GPIO4 */
  112. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4_EMAC_TX_ER);
  113. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[4]);
  114. }
  115. void emac_hal_iomux_init_rx_er(void)
  116. {
  117. /* RX_ER to MTCK */
  118. gpio_ll_iomux_func_sel(PERIPHS_IO_MUX_MTCK_U, FUNC_MTCK_EMAC_RX_ER);
  119. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[13]);
  120. }
  121. void emac_hal_init(emac_hal_context_t *hal, void *descriptors,
  122. uint8_t **rx_buf, uint8_t **tx_buf)
  123. {
  124. hal->dma_regs = &EMAC_DMA;
  125. hal->mac_regs = &EMAC_MAC;
  126. hal->ext_regs = &EMAC_EXT;
  127. hal->descriptors = descriptors;
  128. hal->rx_buf = rx_buf;
  129. hal->tx_buf = tx_buf;
  130. }
  131. void emac_hal_set_csr_clock_range(emac_hal_context_t *hal, int freq)
  132. {
  133. /* Tell MAC system clock Frequency in MHz, which will determine the frequency range of MDC(1MHz~2.5MHz) */
  134. if (freq >= 20000000 && freq < 35000000) {
  135. emac_ll_set_csr_clock_division(hal->mac_regs, 2); // CSR clock/16
  136. } else if (freq >= 35000000 && freq < 60000000) {
  137. emac_ll_set_csr_clock_division(hal->mac_regs, 3); // CSR clock/26
  138. } else if (freq >= 60000000 && freq < 100000000) {
  139. emac_ll_set_csr_clock_division(hal->mac_regs, 0); // CSR clock/42
  140. } else if (freq >= 100000000 && freq < 150000000) {
  141. emac_ll_set_csr_clock_division(hal->mac_regs, 1); // CSR clock/62
  142. } else if (freq >= 150000000 && freq < 250000000) {
  143. emac_ll_set_csr_clock_division(hal->mac_regs, 4); // CSR clock/102
  144. } else {
  145. emac_ll_set_csr_clock_division(hal->mac_regs, 5); // CSR clock/124
  146. }
  147. }
  148. void emac_hal_reset_desc_chain(emac_hal_context_t *hal)
  149. {
  150. /* reset DMA descriptors */
  151. hal->rx_desc = (eth_dma_rx_descriptor_t *)(hal->descriptors);
  152. hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->descriptors +
  153. sizeof(eth_dma_rx_descriptor_t) * CONFIG_ETH_DMA_RX_BUFFER_NUM);
  154. /* init rx chain */
  155. for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
  156. /* Set Own bit of the Rx descriptor Status: DMA */
  157. hal->rx_desc[i].RDES0.Own = 1;
  158. /* Set Buffer1 size and Second Address Chained bit */
  159. hal->rx_desc[i].RDES1.SecondAddressChained = 1;
  160. hal->rx_desc[i].RDES1.ReceiveBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  161. /* Enable Ethernet DMA Rx Descriptor interrupt */
  162. hal->rx_desc[i].RDES1.DisableInterruptOnComplete = 0;
  163. /* point to the buffer */
  164. hal->rx_desc[i].Buffer1Addr = (uint32_t)(hal->rx_buf[i]);
  165. /* point to next descriptor */
  166. hal->rx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc + i + 1);
  167. }
  168. /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
  169. hal->rx_desc[CONFIG_ETH_DMA_RX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc);
  170. /* init tx chain */
  171. for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
  172. /* Set Second Address Chained bit */
  173. hal->tx_desc[i].TDES0.SecondAddressChained = 1;
  174. hal->tx_desc[i].TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  175. /* Enable Ethernet DMA Tx Descriptor interrupt */
  176. hal->tx_desc[1].TDES0.InterruptOnComplete = 1;
  177. /* Enable Transmit Timestamp */
  178. hal->tx_desc[i].TDES0.TransmitTimestampEnable = 1;
  179. /* point to the buffer */
  180. hal->tx_desc[i].Buffer1Addr = (uint32_t)(hal->tx_buf[i]);
  181. /* point to next descriptor */
  182. hal->tx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc + i + 1);
  183. }
  184. /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
  185. hal->tx_desc[CONFIG_ETH_DMA_TX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc);
  186. /* set base address of the first descriptor */
  187. emac_ll_set_rx_desc_addr(hal->dma_regs, (uint32_t)hal->rx_desc);
  188. emac_ll_set_tx_desc_addr(hal->dma_regs, (uint32_t)hal->tx_desc);
  189. }
  190. void emac_hal_init_mac_default(emac_hal_context_t *hal)
  191. {
  192. /* MACCR Configuration */
  193. /* Enable the watchdog on the receiver, frame longer than 2048 Bytes is not allowed */
  194. emac_ll_watchdog_enable(hal->mac_regs, true);
  195. /* Enable the jabber timer on the transmitter, frame longer than 2048 Bytes is not allowed */
  196. emac_ll_jabber_enable(hal->mac_regs, true);
  197. /* minimum IFG between frames during transmission is 96 bit times */
  198. emac_ll_set_inter_frame_gap(hal->mac_regs, EMAC_LL_INTERFRAME_GAP_96BIT);
  199. /* Enable Carrier Sense During Transmission */
  200. emac_ll_carrier_sense_enable(hal->mac_regs, true);
  201. /* Select speed: port: 10/100 Mbps, here set default 100M, afterwards, will reset by auto-negotiation */
  202. emac_ll_set_port_speed(hal->mac_regs, ETH_SPEED_100M);;
  203. /* Allow the reception of frames when the TX_EN signal is asserted in Half-Duplex mode */
  204. emac_ll_recv_own_enable(hal->mac_regs, true);
  205. /* Disable internal loopback mode */
  206. emac_ll_loopback_enable(hal->mac_regs, false);
  207. /* Select duplex mode: here set default full duplex, afterwards, will reset by auto-negotiation */
  208. emac_ll_set_duplex(hal->mac_regs, ETH_DUPLEX_FULL);
  209. /* Select the checksum mode for received frame payload's TCP/UDP/ICMP headers */
  210. emac_ll_checksum_offload_mode(hal->mac_regs, ETH_CHECKSUM_HW);
  211. /* Enable MAC retry transmission when a colision occurs in half duplex mode */
  212. emac_ll_retry_enable(hal->mac_regs, true);
  213. /* MAC passes all incoming frames to host, without modifying them */
  214. emac_ll_auto_pad_crc_strip_enable(hal->mac_regs, false);
  215. /* Set Back-Off limit time before retry a transmittion after a collision */
  216. emac_ll_set_back_off_limit(hal->mac_regs, EMAC_LL_BACKOFF_LIMIT_10);
  217. /* Disable deferral check, MAC defers until the CRS signal goes inactive */
  218. emac_ll_deferral_check_enable(hal->mac_regs, false);
  219. /* Set preamble length 7 Bytes */
  220. emac_ll_set_preamble_length(hal->mac_regs, EMAC_LL_PREAMBLE_LENGTH_7);
  221. /* MACFFR Configuration */
  222. /* Receiver module passes only those frames to the Application that pass the SA or DA address filter */
  223. emac_ll_receive_all_enable(hal->mac_regs, false);
  224. /* Disable source address filter */
  225. emac_ll_set_src_addr_filter(hal->mac_regs, EMAC_LL_SOURCE_ADDR_FILTER_DISABLE);
  226. emac_ll_sa_inverse_filter_enable(hal->mac_regs, false);
  227. /* MAC blocks all control frames */
  228. emac_ll_set_pass_ctrl_frame_mode(hal->mac_regs, EMAC_LL_CONTROL_FRAME_BLOCKALL);
  229. /* AFM module passes all received broadcast frames and multicast frames */
  230. emac_ll_broadcast_frame_enable(hal->mac_regs, true);
  231. emac_ll_pass_all_multicast_enable(hal->mac_regs, true);
  232. /* Address Check block operates in normal filtering mode for the DA address */
  233. emac_ll_da_inverse_filter_enable(hal->mac_regs, false);
  234. /* Disable Promiscuous Mode */
  235. emac_ll_promiscuous_mode_enable(hal->mac_regs, false);
  236. }
  237. void emac_hal_enable_flow_ctrl(emac_hal_context_t *hal, bool enable)
  238. {
  239. /* MACFCR Configuration */
  240. if (enable) {
  241. /* Pause time */
  242. emac_ll_set_pause_time(hal->mac_regs, EMAC_LL_PAUSE_TIME);
  243. /* Enable generation of Zero-Quanta Pause Control frames */
  244. emac_ll_zero_quanta_pause_enable(hal->mac_regs, true);
  245. /* Threshold of the PAUSE to be checked for automatic retransmission of PAUSE Frame */
  246. emac_ll_set_pause_low_threshold(hal->mac_regs, EMAC_LL_PAUSE_LOW_THRESHOLD_MINUS_28);
  247. /* Don't allow MAC detect Pause frames with MAC address0 unicast address and unique multicast address */
  248. emac_ll_unicast_pause_frame_detect_enable(hal->mac_regs, false);
  249. /* Enable MAC to decode the received Pause frame and disable its transmitter for a specific time */
  250. emac_ll_receive_flow_ctrl_enable(hal->mac_regs, true);
  251. /* Enable MAC to transmit Pause frames in full duplex mode or the MAC back-pressure operation in half duplex mode */
  252. emac_ll_transmit_flow_ctrl_enable(hal->mac_regs, true);
  253. } else {
  254. emac_ll_clear(hal->mac_regs);
  255. }
  256. }
  257. void emac_hal_init_dma_default(emac_hal_context_t *hal)
  258. {
  259. /* DMAOMR Configuration */
  260. /* Enable Dropping of TCP/IP Checksum Error Frames */
  261. emac_ll_drop_tcp_err_frame_enable(hal->dma_regs, true);
  262. /* Enable Receive Store Forward */
  263. emac_ll_recv_store_forward_enable(hal->dma_regs, true);
  264. /* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */
  265. emac_ll_flush_recv_frame_enable(hal->dma_regs, true);
  266. /* Disable Transmit Store Forward */
  267. emac_ll_trans_store_forward_enable(hal->dma_regs, false);
  268. /* Flush Transmit FIFO */
  269. emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
  270. /* Transmit Threshold Control */
  271. emac_ll_set_transmit_threshold(hal->dma_regs, EMAC_LL_TRANSMIT_THRESHOLD_CONTROL_64);
  272. /* Disable Forward Error Frame */
  273. emac_ll_forward_err_frame_enable(hal->dma_regs, false);
  274. /* Disable forward undersized good frame */
  275. emac_ll_forward_undersized_good_frame_enable(hal->dma_regs, false);
  276. /* Receive Threshold Control */
  277. emac_ll_set_recv_threshold(hal->dma_regs, EMAC_LL_RECEIVE_THRESHOLD_CONTROL_64);
  278. /* Allow the DMA to process a second frame of Transmit data even before obtaining the status for the first frame */
  279. emac_ll_opt_second_frame_enable(hal->dma_regs, true);;
  280. /* DMABMR Configuration */
  281. /* Enable Mixed Burst */
  282. emac_ll_mixed_burst_enable(hal->dma_regs, true);
  283. /* Enable Address Aligned Beates */
  284. emac_ll_addr_align_enable(hal->dma_regs, true);
  285. /* Use Separate PBL */
  286. emac_ll_use_separate_pbl_enable(hal->dma_regs, true);
  287. /* Set Rx/Tx DMA Burst Length */
  288. emac_ll_set_rx_dma_pbl(hal->dma_regs, EMAC_LL_DMA_BURST_LENGTH_32BEAT);
  289. emac_ll_set_prog_burst_len(hal->dma_regs, EMAC_LL_DMA_BURST_LENGTH_32BEAT);
  290. /* Enable Enhanced Descriptor,8 Words(32 Bytes) */
  291. emac_ll_enhance_desc_enable(hal->dma_regs, true);
  292. /* Specifies the number of word to skip between two unchained descriptors (Ring mode) */
  293. emac_ll_set_desc_skip_len(hal->dma_regs, 0);
  294. /* DMA Arbitration Scheme */
  295. emac_ll_fixed_arbitration_enable(hal->dma_regs, false);
  296. /* Set priority ratio in the weighted round-robin arbitration between Rx DMA and Tx DMA */
  297. emac_ll_set_priority_ratio(hal->dma_regs, EMAC_LL_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1);
  298. }
  299. void emac_hal_set_phy_cmd(emac_hal_context_t *hal, uint32_t phy_addr, uint32_t phy_reg, bool write)
  300. {
  301. /* Write the result value into the MII Address register */
  302. emac_ll_set_phy_addr(hal->mac_regs, phy_addr);
  303. /* Set the PHY register address */
  304. emac_ll_set_phy_reg(hal->mac_regs, phy_reg);
  305. /* Set as write mode */
  306. emac_ll_write_enable(hal->mac_regs, write);
  307. /* Set MII busy bit */
  308. emac_ll_set_busy(hal->mac_regs, true);
  309. }
  310. void emac_hal_set_address(emac_hal_context_t *hal, uint8_t *mac_addr)
  311. {
  312. /* Make sure mac address is unicast type */
  313. if (!(mac_addr[0] & 0x01)) {
  314. emac_ll_set_addr(hal->mac_regs, mac_addr);
  315. }
  316. }
  317. void emac_hal_start(emac_hal_context_t *hal)
  318. {
  319. /* Enable Ethernet MAC and DMA Interrupt */
  320. emac_ll_enable_corresponding_intr(hal->dma_regs, EMAC_LL_CONFIG_ENABLE_INTR_MASK);
  321. /* Enable transmit state machine of the MAC for transmission on the MII */
  322. emac_ll_transmit_enable(hal->mac_regs, true);
  323. /* Enable receive state machine of the MAC for reception from the MII */
  324. emac_ll_receive_enable(hal->mac_regs, true);
  325. /* Flush Transmit FIFO */
  326. emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
  327. /* Start DMA transmission */
  328. emac_ll_start_stop_dma_transmit(hal->dma_regs, true);
  329. /* Start DMA reception */
  330. emac_ll_start_stop_dma_receive(hal->dma_regs, true);
  331. /* Clear all pending interrupts */
  332. emac_ll_clear_all_pending_intr(hal->dma_regs);
  333. }
  334. void emac_hal_stop(emac_hal_context_t *hal)
  335. {
  336. /* Flush Transmit FIFO */
  337. emac_ll_flush_trans_fifo_enable(hal->dma_regs, true);
  338. /* Stop DMA transmission */
  339. emac_ll_start_stop_dma_transmit(hal->dma_regs, false);
  340. /* Stop DMA reception */
  341. emac_ll_start_stop_dma_receive(hal->dma_regs, false);
  342. /* Disable receive state machine of the MAC for reception from the MII */
  343. emac_ll_transmit_enable(hal->mac_regs, false);
  344. /* Disable transmit state machine of the MAC for transmission on the MII */
  345. emac_ll_receive_enable(hal->mac_regs, false);
  346. /* Disable Ethernet MAC and DMA Interrupt */
  347. emac_ll_disable_all_intr(hal->dma_regs);
  348. }
  349. uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal)
  350. {
  351. return hal->tx_desc->TDES0.Own;
  352. }
  353. uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
  354. {
  355. /* Get the number of Tx buffers to use for the frame */
  356. uint32_t bufcount = 0;
  357. uint32_t lastlen = length;
  358. uint32_t sentout = 0;
  359. while (lastlen > CONFIG_ETH_DMA_BUFFER_SIZE) {
  360. lastlen -= CONFIG_ETH_DMA_BUFFER_SIZE;
  361. bufcount++;
  362. }
  363. if (lastlen) {
  364. bufcount++;
  365. }
  366. if (bufcount > CONFIG_ETH_DMA_TX_BUFFER_NUM) {
  367. goto err;
  368. }
  369. eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc;
  370. /* A frame is transmitted in multiple descriptor */
  371. for (size_t i = 0; i < bufcount; i++) {
  372. /* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
  373. if (desc_iter->TDES0.Own != EMAC_LL_DMADESC_OWNER_CPU) {
  374. goto err;
  375. }
  376. /* Clear FIRST and LAST segment bits */
  377. desc_iter->TDES0.FirstSegment = 0;
  378. desc_iter->TDES0.LastSegment = 0;
  379. desc_iter->TDES0.InterruptOnComplete = 0;
  380. if (i == 0) {
  381. /* Setting the first segment bit */
  382. desc_iter->TDES0.FirstSegment = 1;
  383. }
  384. if (i == (bufcount - 1)) {
  385. /* Setting the last segment bit */
  386. desc_iter->TDES0.LastSegment = 1;
  387. /* Enable transmit interrupt */
  388. desc_iter->TDES0.InterruptOnComplete = 1;
  389. /* Program size */
  390. desc_iter->TDES1.TransmitBuffer1Size = lastlen;
  391. /* copy data from uplayer stack buffer */
  392. memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen);
  393. sentout += lastlen;
  394. } else {
  395. /* Program size */
  396. desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  397. /* copy data from uplayer stack buffer */
  398. memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
  399. sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
  400. }
  401. /* Point to next descriptor */
  402. desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  403. }
  404. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  405. for (size_t i = 0; i < bufcount; i++) {
  406. hal->tx_desc->TDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  407. hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
  408. }
  409. emac_ll_transmit_poll_demand(hal->dma_regs, 0);
  410. return sentout;
  411. err:
  412. return 0;
  413. }
  414. 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)
  415. {
  416. eth_dma_rx_descriptor_t *desc_iter = NULL;
  417. eth_dma_rx_descriptor_t *first_desc = NULL;
  418. uint32_t used_descs = 0;
  419. uint32_t seg_count = 0;
  420. uint32_t ret_len = 0;
  421. uint32_t copy_len = 0;
  422. uint32_t write_len = 0;
  423. uint32_t frame_count = 0;
  424. first_desc = hal->rx_desc;
  425. desc_iter = hal->rx_desc;
  426. /* Traverse descriptors owned by CPU */
  427. while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM) && !frame_count) {
  428. used_descs++;
  429. seg_count++;
  430. /* Last segment in frame */
  431. if (desc_iter->RDES0.LastDescriptor) {
  432. /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  433. ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
  434. /* packets larger than expected will be truncated */
  435. copy_len = ret_len > size ? size : ret_len;
  436. /* update unhandled frame count */
  437. frame_count++;
  438. }
  439. /* First segment in frame */
  440. if (desc_iter->RDES0.FirstDescriptor) {
  441. first_desc = desc_iter;
  442. }
  443. /* point to next descriptor */
  444. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  445. }
  446. /* there's at least one frame to process */
  447. if (frame_count) {
  448. /* check how many frames left to handle */
  449. while ((desc_iter->RDES0.Own != EMAC_LL_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
  450. used_descs++;
  451. if (desc_iter->RDES0.LastDescriptor) {
  452. frame_count++;
  453. }
  454. /* point to next descriptor */
  455. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  456. }
  457. desc_iter = first_desc;
  458. for (size_t i = 0; i < seg_count - 1; i++) {
  459. used_descs--;
  460. write_len = copy_len < CONFIG_ETH_DMA_BUFFER_SIZE ? copy_len : CONFIG_ETH_DMA_BUFFER_SIZE;
  461. /* copy data to buffer */
  462. memcpy(buf, (void *)(desc_iter->Buffer1Addr), write_len);
  463. buf += write_len;
  464. copy_len -= write_len;
  465. /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
  466. desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  467. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  468. }
  469. memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
  470. desc_iter->RDES0.Own = EMAC_LL_DMADESC_OWNER_DMA;
  471. /* update rxdesc */
  472. hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  473. /* poll rx demand */
  474. emac_ll_receive_poll_demand(hal->dma_regs, 0);
  475. frame_count--;
  476. used_descs--;
  477. }
  478. *frames_remain = frame_count;
  479. *free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
  480. return ret_len;
  481. }