emac_hal.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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 "sdkconfig.h"
  16. #include "esp_attr.h"
  17. #include "soc/gpio_periph.h"
  18. #include "soc/rtc.h"
  19. #include "hal/emac.h"
  20. #include "hal/gpio_hal.h"
  21. #define ETH_CRC_LENGTH (4)
  22. #if CONFIG_ETH_RMII_CLK_OUTPUT
  23. static void emac_config_apll_clock(void)
  24. {
  25. /* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2) */
  26. rtc_xtal_freq_t rtc_xtal_freq = rtc_clk_xtal_freq_get();
  27. switch (rtc_xtal_freq) {
  28. case RTC_XTAL_FREQ_40M: // Recommended
  29. /* 50 MHz = 40MHz * (4 + 6) / (2 * (2 + 2) = 50.000 */
  30. /* sdm0 = 0, sdm1 = 0, sdm2 = 6, o_div = 2 */
  31. rtc_clk_apll_enable(true, 0, 0, 6, 2);
  32. break;
  33. case RTC_XTAL_FREQ_26M:
  34. /* 50 MHz = 26MHz * (4 + 15 + 118 / 256 + 39/65536) / ((3 + 2) * 2) = 49.999992 */
  35. /* sdm0 = 39, sdm1 = 118, sdm2 = 15, o_div = 3 */
  36. rtc_clk_apll_enable(true, 39, 118, 15, 3);
  37. break;
  38. case RTC_XTAL_FREQ_24M:
  39. /* 50 MHz = 24MHz * (4 + 12 + 255 / 256 + 255/65536) / ((2 + 2) * 2) = 49.499977 */
  40. /* sdm0 = 255, sdm1 = 255, sdm2 = 12, o_div = 2 */
  41. rtc_clk_apll_enable(true, 255, 255, 12, 2);
  42. break;
  43. default: // Assume we have a 40M xtal
  44. rtc_clk_apll_enable(true, 0, 0, 6, 2);
  45. break;
  46. }
  47. }
  48. #endif
  49. void emac_hal_init(emac_hal_context_t *hal, void *descriptors,
  50. uint8_t **rx_buf, uint8_t **tx_buf)
  51. {
  52. hal->dma_regs = &EMAC_DMA;
  53. hal->mac_regs = &EMAC_MAC;
  54. hal->ext_regs = &EMAC_EXT;
  55. hal->descriptors = descriptors;
  56. hal->rx_buf = rx_buf;
  57. hal->tx_buf = tx_buf;
  58. }
  59. void emac_hal_lowlevel_init(emac_hal_context_t *hal)
  60. {
  61. /* GPIO configuration */
  62. /* TX_EN to GPIO21 */
  63. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
  64. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[21]);
  65. /* TXD0 to GPIO19 */
  66. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
  67. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[19]);
  68. /* TXD1 to GPIO22 */
  69. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
  70. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[22]);
  71. /* RXD0 to GPIO25 */
  72. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO25_U, FUNC_GPIO25_EMAC_RXD0);
  73. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[25]);
  74. /* RXD1 to GPIO26 */
  75. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO26_U, FUNC_GPIO26_EMAC_RXD1);
  76. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[26]);
  77. /* CRS_DV to GPIO27 */
  78. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
  79. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[27]);
  80. #if CONFIG_ETH_RMII_CLK_INPUT
  81. #if CONFIG_ETH_RMII_CLK_IN_GPIO == 0
  82. /* RMII clock (50MHz) input to GPIO0 */
  83. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_EMAC_TX_CLK);
  84. PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[0]);
  85. #else
  86. #error "ESP32 EMAC only support input RMII clock to GPIO0"
  87. #endif
  88. #endif
  89. #if CONFIG_ETH_RMII_CLK_OUTPUT
  90. #if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
  91. /* APLL clock output to GPIO0 (must be configured to 50MHz!) */
  92. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
  93. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[0]);
  94. #elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 16
  95. /* RMII CLK (50MHz) output to GPIO16 */
  96. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
  97. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[16]);
  98. #elif CONFIG_ETH_RMII_CLK_OUT_GPIO == 17
  99. /* RMII CLK (50MHz) output to GPIO17 */
  100. gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
  101. PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[17]);
  102. #endif
  103. #endif // CONFIG_ETH_RMII_CLK_OUTPUT
  104. /* Clock configuration */
  105. #if CONFIG_ETH_PHY_INTERFACE_MII
  106. hal->ext_regs->ex_phyinf_conf.phy_intf_sel = 0;
  107. hal->ext_regs->ex_clk_ctrl.mii_clk_rx_en = 1;
  108. hal->ext_regs->ex_clk_ctrl.mii_clk_tx_en = 1;
  109. #elif CONFIG_ETH_PHY_INTERFACE_RMII
  110. hal->ext_regs->ex_phyinf_conf.phy_intf_sel = 4;
  111. #if CONFIG_ETH_RMII_CLK_INPUT
  112. hal->ext_regs->ex_clk_ctrl.ext_en = 1;
  113. hal->ext_regs->ex_clk_ctrl.int_en = 0;
  114. hal->ext_regs->ex_oscclk_conf.clk_sel = 1;
  115. #elif CONFIG_ETH_RMII_CLK_OUTPUT
  116. hal->ext_regs->ex_clk_ctrl.ext_en = 0;
  117. hal->ext_regs->ex_clk_ctrl.int_en = 1;
  118. hal->ext_regs->ex_oscclk_conf.clk_sel = 0;
  119. emac_config_apll_clock();
  120. hal->ext_regs->ex_clkout_conf.div_num = 0;
  121. hal->ext_regs->ex_clkout_conf.h_div_num = 0;
  122. #if CONFIG_ETH_RMII_CLK_OUTPUT_GPIO0
  123. /* Choose the APLL clock to output on GPIO */
  124. REG_WRITE(PIN_CTRL, 6);
  125. #endif // CONFIG_RMII_CLK_OUTPUT_GPIO0
  126. #endif // CONFIG_ETH_RMII_CLK_INPUT
  127. #endif // CONFIG_ETH_PHY_INTERFACE_MII
  128. }
  129. void emac_hal_reset(emac_hal_context_t *hal)
  130. {
  131. hal->dma_regs->dmabusmode.sw_rst = 1;
  132. }
  133. bool emac_hal_is_reset_done(emac_hal_context_t *hal)
  134. {
  135. return hal->dma_regs->dmabusmode.sw_rst ? false : true;
  136. }
  137. void emac_hal_set_csr_clock_range(emac_hal_context_t *hal)
  138. {
  139. /* Tell MAC system clock Frequency, which will determin the frequency range of MDC(1MHz~2.5MHz) */
  140. if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 20 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 35) {
  141. hal->mac_regs->emacgmiiaddr.miicsrclk = 2;
  142. } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 35 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 60) {
  143. hal->mac_regs->emacgmiiaddr.miicsrclk = 3;
  144. } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 60 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 100) {
  145. hal->mac_regs->emacgmiiaddr.miicsrclk = 0;
  146. } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ >= 100 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 150) {
  147. hal->mac_regs->emacgmiiaddr.miicsrclk = 1;
  148. } else if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ > 150 && CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ < 250) {
  149. hal->mac_regs->emacgmiiaddr.miicsrclk = 4;
  150. } else {
  151. hal->mac_regs->emacgmiiaddr.miicsrclk = 5;
  152. }
  153. }
  154. void emac_hal_reset_desc_chain(emac_hal_context_t *hal)
  155. {
  156. /* reset DMA descriptors */
  157. hal->rx_desc = (eth_dma_rx_descriptor_t *)(hal->descriptors);
  158. hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->descriptors +
  159. sizeof(eth_dma_rx_descriptor_t) * CONFIG_ETH_DMA_RX_BUFFER_NUM);
  160. /* init rx chain */
  161. for (int i = 0; i < CONFIG_ETH_DMA_RX_BUFFER_NUM; i++) {
  162. /* Set Own bit of the Rx descriptor Status: DMA */
  163. hal->rx_desc[i].RDES0.Own = 1;
  164. /* Set Buffer1 size and Second Address Chained bit */
  165. hal->rx_desc[i].RDES1.SecondAddressChained = 1;
  166. hal->rx_desc[i].RDES1.ReceiveBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  167. /* Enable Ethernet DMA Rx Descriptor interrupt */
  168. hal->rx_desc[i].RDES1.DisableInterruptOnComplete = 0;
  169. /* point to the buffer */
  170. hal->rx_desc[i].Buffer1Addr = (uint32_t)(hal->rx_buf[i]);
  171. /* point to next descriptor */
  172. hal->rx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc + i + 1);
  173. }
  174. /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
  175. hal->rx_desc[CONFIG_ETH_DMA_RX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->rx_desc);
  176. /* init tx chain */
  177. for (int i = 0; i < CONFIG_ETH_DMA_TX_BUFFER_NUM; i++) {
  178. /* Set Second Address Chained bit */
  179. hal->tx_desc[i].TDES0.SecondAddressChained = 1;
  180. hal->tx_desc[i].TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  181. /* Enable Ethernet DMA Tx Descriptor interrupt */
  182. hal->tx_desc[1].TDES0.InterruptOnComplete = 1;
  183. /* Enable Transmit Timestamp */
  184. hal->tx_desc[i].TDES0.TransmitTimestampEnable = 1;
  185. /* point to the buffer */
  186. hal->tx_desc[i].Buffer1Addr = (uint32_t)(hal->tx_buf[i]);
  187. /* point to next descriptor */
  188. hal->tx_desc[i].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc + i + 1);
  189. }
  190. /* For last descriptor, set next descriptor address register equal to the first descriptor base address */
  191. hal->tx_desc[CONFIG_ETH_DMA_TX_BUFFER_NUM - 1].Buffer2NextDescAddr = (uint32_t)(hal->tx_desc);
  192. /* set base address of the first descriptor */
  193. hal->dma_regs->dmarxbaseaddr = (uint32_t)hal->rx_desc;
  194. hal->dma_regs->dmatxbaseaddr = (uint32_t)hal->tx_desc;
  195. }
  196. void emac_hal_init_mac_default(emac_hal_context_t *hal)
  197. {
  198. /* MACCR Configuration */
  199. typeof(hal->mac_regs->gmacconfig) maccr = hal->mac_regs->gmacconfig;
  200. /* Enable the watchdog on the receiver, frame longer than 2048 Bytes is not allowed */
  201. maccr.watchdog = EMAC_WATCHDOG_ENABLE;
  202. /* Enable the jabber timer on the transmitter, frame longer than 2048 Bytes is not allowed */
  203. maccr.jabber = EMAC_JABBER_ENABLE;
  204. /* minimum IFG between frames during transmission is 96 bit times */
  205. maccr.interframegap = EMAC_INTERFRAME_GAP_96BIT;
  206. /* Enable Carrier Sense During Transmission */
  207. maccr.disablecrs = EMAC_CARRIERSENSE_ENABLE;
  208. /* Select port: 10/100 Mbps */
  209. maccr.mii = EMAC_PORT_10_100MBPS;
  210. /* Select speed: here set default 100M, afterwards, will reset by auto-negotiation */
  211. maccr.fespeed = EMAC_SPEED_100M;
  212. /* Allow the reception of frames when the TX_EN signal is asserted in Half-Duplex mode */
  213. maccr.rxown = EMAC_RECEIVE_OWN_ENABLE;
  214. /* Disable internal loopback mode */
  215. maccr.loopback = EMAC_LOOPBACK_DISABLE;
  216. /* Select duplex mode: here set default full duplex, afterwards, will reset by auto-negotiation */
  217. maccr.duplex = EMAC_DUPLEX_FULL;
  218. /* Select the checksum mode for received frame payload's TCP/UDP/ICMP headers */
  219. maccr.rxipcoffload = EMAC_CHECKSUM_HW;
  220. /* Enable MAC retry transmission when a colision occurs in half duplex mode */
  221. maccr.retry = EMAC_RETRY_TRANSMISSION_ENABLE;
  222. /* MAC passes all incoming frames to host, without modifying them */
  223. maccr.padcrcstrip = EMAC_AUTO_PAD_CRC_STRIP_DISABLE;
  224. /* Set Back-Off limit time before retry a transmittion after a collision */
  225. maccr.backofflimit = EMAC_BACKOFF_LIMIT_10;
  226. /* Disable deferral check, MAC defers until the CRS signal goes inactive */
  227. maccr.deferralcheck = EMAC_DEFERRAL_CHECK_DISABLE;
  228. /* Set preamble length 7 Bytes */
  229. maccr.pltf = EMAC_PREAMBLE_LENGTH_7;
  230. hal->mac_regs->gmacconfig = maccr;
  231. /* MACFFR Configuration */
  232. typeof(hal->mac_regs->gmacff) macffr = hal->mac_regs->gmacff;
  233. /* Receiver module passes only those frames to the Application that pass the SA or DA address filter */
  234. macffr.receive_all = EMAC_RECEIVE_ALL_DISABLE;
  235. /* Disable source address filter */
  236. macffr.safe = EMAC_SOURCE_ADDR_FILTER_DISABLE;
  237. macffr.saif = 0;
  238. /* MAC blocks all control frames */
  239. macffr.pcf = EMAC_CONTROL_FRAME_BLOCKALL;
  240. /* AFM module passes all received broadcast frames and multicast frames */
  241. macffr.dbf = EMAC_RECEPT_BROADCAST_ENABLE;
  242. macffr.pam = 1;
  243. /* Address Check block operates in normal filtering mode for the DA address */
  244. macffr.daif = EMAC_DEST_ADDR_FILTER_NORMAL;
  245. /* Disable Promiscuous Mode */
  246. macffr.pmode = EMAC_PROMISCUOUS_DISABLE;
  247. hal->mac_regs->gmacff = macffr;
  248. }
  249. void emac_hal_enable_flow_ctrl(emac_hal_context_t *hal, bool enable)
  250. {
  251. /* MACFCR Configuration */
  252. typeof(hal->mac_regs->gmacfc) macfcr = hal->mac_regs->gmacfc;
  253. if (enable) {
  254. /* Pause time */
  255. macfcr.pause_time = EMAC_PAUSE_TIME;
  256. /* Enable generation of Zero-Quanta Pause Control frames */
  257. macfcr.dzpq = EMAC_ZERO_QUANTA_PAUSE_ENABLE;
  258. /* Threshold of the PAUSE to be checked for automatic retransmission of PAUSE Frame */
  259. macfcr.plt = EMAC_PAUSE_LOW_THRESHOLD_MINUS_28;
  260. /* Don't allow MAC detect Pause frames with MAC address0 unicast address and unique multicast address */
  261. macfcr.upfd = EMAC_UNICAST_PAUSE_DETECT_DISABLE;
  262. /* Enable MAC to decode the received Pause frame and disable its transmitter for a specific time */
  263. macfcr.rfce = EMAC_RECEIVE_FLOW_CONTROL_ENABLE;
  264. /* Enable MAC to transmit Pause frames in full duplex mode or the MAC back-pressure operation in half duplex mode */
  265. macfcr.tfce = EMAC_TRANSMIT_FLOW_CONTROL_ENABLE;
  266. } else {
  267. macfcr.val = 0;
  268. }
  269. hal->mac_regs->gmacfc = macfcr;
  270. }
  271. void emac_hal_init_dma_default(emac_hal_context_t *hal)
  272. {
  273. /* DMAOMR Configuration */
  274. typeof(hal->dma_regs->dmaoperation_mode) dmaomr = hal->dma_regs->dmaoperation_mode;
  275. /* Enable Dropping of TCP/IP Checksum Error Frames */
  276. dmaomr.dis_drop_tcpip_err_fram = EMAC_DROP_TCPIP_CHECKSUM_ERROR_ENABLE;
  277. /* Enable Receive Store Forward */
  278. dmaomr.rx_store_forward = EMAC_RECEIVE_STORE_FORWARD_ENABLE;
  279. /* Enable Flushing of Received Frames because of the unavailability of receive descriptors or buffers */
  280. dmaomr.dis_flush_recv_frames = EMAC_FLUSH_RECEIVED_FRAME_ENABLE;
  281. /* Enable Transmit Store Forward */
  282. dmaomr.tx_str_fwd = EMAC_TRANSMIT_STORE_FORWARD_ENABLE;
  283. /* Flush Transmit FIFO */
  284. dmaomr.flush_tx_fifo = 1;
  285. /* Transmit Threshold Control */
  286. dmaomr.tx_thresh_ctrl = EMAC_TRANSMIT_THRESHOLD_CONTROL_64;
  287. /* Disable Forward Error Frame */
  288. dmaomr.fwd_err_frame = EMAC_FORWARD_ERROR_FRAME_DISABLE;
  289. /* Disable forward undersized good frame */
  290. dmaomr.fwd_under_gf = EMAC_FORWARD_UNDERSIZED_GOOD_FRAME_DISABLE;
  291. /* Receive Threshold Control */
  292. dmaomr.rx_thresh_ctrl = EMAC_RECEIVE_THRESHOLD_CONTROL_64;
  293. /* Allow the DMA to process a second frame of Transmit data even before obtaining the status for the first frame */
  294. dmaomr.opt_second_frame = EMAC_OPERATE_SECOND_FRAME_ENABLE;
  295. hal->dma_regs->dmaoperation_mode = dmaomr;
  296. /* DMABMR Configuration */
  297. typeof(hal->dma_regs->dmabusmode) dmabmr = hal->dma_regs->dmabusmode;
  298. /* Enable Mixed Burst */
  299. dmabmr.dmamixedburst = EMAC_MIXED_BURST_ENABLE;
  300. /* Enable Address Aligned Beates */
  301. dmabmr.dmaaddralibea = EMAC_ADDR_ALIGN_BEATS_ENABLE;
  302. /* Use Separate PBL */
  303. dmabmr.use_sep_pbl = EMAC_USE_SEPARATE_PBL;
  304. /* Set Rx/Tx DMA Burst Length */
  305. dmabmr.rx_dma_pbl = EMAC_DMA_BURST_LENGTH_32BEAT;
  306. dmabmr.prog_burst_len = EMAC_DMA_BURST_LENGTH_32BEAT;
  307. /* Enable Enhanced Descriptor,8 Words(32 Bytes) */
  308. dmabmr.alt_desc_size = EMAC_ENHANCED_DESCRIPTOR_ENABLE;
  309. /* Specifies the number of word to skip between two unchained descriptors (Ring mode) */
  310. dmabmr.desc_skip_len = 0;
  311. /* DMA Arbitration Scheme */
  312. dmabmr.dma_arb_sch = EMAC_DMA_ARBITRATION_SCHEME_ROUNDROBIN;
  313. /* Set priority ratio in the weighted round-robin arbitration between Rx DMA and Tx DMA */
  314. dmabmr.pri_ratio = EMAC_DMA_ARBITRATION_ROUNDROBIN_RXTX_1_1;
  315. hal->dma_regs->dmabusmode = dmabmr;
  316. }
  317. void emac_hal_set_speed(emac_hal_context_t *hal, uint32_t speed)
  318. {
  319. hal->mac_regs->gmacconfig.fespeed = speed;
  320. }
  321. void emac_hal_set_duplex(emac_hal_context_t *hal, uint32_t duplex)
  322. {
  323. hal->mac_regs->gmacconfig.duplex = duplex;
  324. }
  325. void emac_hal_set_promiscuous(emac_hal_context_t *hal, bool enable)
  326. {
  327. if (enable) {
  328. hal->mac_regs->gmacff.pmode = 1;
  329. } else {
  330. hal->mac_regs->gmacff.pmode = 0;
  331. }
  332. }
  333. void emac_hal_send_pause_frame(emac_hal_context_t *hal, bool enable)
  334. {
  335. if (enable) {
  336. hal->ext_regs->ex_phyinf_conf.sbd_flowctrl = 1;
  337. } else {
  338. hal->ext_regs->ex_phyinf_conf.sbd_flowctrl = 0;
  339. }
  340. }
  341. bool emac_hal_is_mii_busy(emac_hal_context_t *hal)
  342. {
  343. return hal->mac_regs->emacgmiiaddr.miibusy ? true : false;
  344. }
  345. void emac_hal_set_phy_cmd(emac_hal_context_t *hal, uint32_t phy_addr, uint32_t phy_reg, bool write)
  346. {
  347. typeof(hal->mac_regs->emacgmiiaddr) macmiiar = hal->mac_regs->emacgmiiaddr;
  348. macmiiar.miidev = phy_addr;
  349. /* Set the PHY register address */
  350. macmiiar.miireg = phy_reg;
  351. if (write) {
  352. /* Set write mode */
  353. macmiiar.miiwrite = 1;
  354. } else {
  355. /* Set read mode */
  356. macmiiar.miiwrite = 0;
  357. }
  358. /* Set MII busy bit */
  359. macmiiar.miibusy = 1;
  360. /* Write the result value into the MII Address register */
  361. hal->mac_regs->emacgmiiaddr = macmiiar;
  362. }
  363. void emac_hal_set_phy_data(emac_hal_context_t *hal, uint32_t reg_value)
  364. {
  365. hal->mac_regs->emacmiidata.mii_data = reg_value;
  366. }
  367. uint32_t emac_hal_get_phy_data(emac_hal_context_t *hal)
  368. {
  369. return hal->mac_regs->emacmiidata.mii_data;
  370. }
  371. void emac_hal_set_address(emac_hal_context_t *hal, uint8_t *mac_addr)
  372. {
  373. /* Make sure mac address is unicast type */
  374. if (!(mac_addr[0] & 0x01)) {
  375. hal->mac_regs->emacaddr0high.address0_hi = (mac_addr[5] << 8) | mac_addr[4];
  376. hal->mac_regs->emacaddr0low = (mac_addr[3] << 24) | (mac_addr[2] << 16) | (mac_addr[1] << 8) | (mac_addr[0]);
  377. }
  378. }
  379. void emac_hal_start(emac_hal_context_t *hal)
  380. {
  381. typeof(hal->dma_regs->dmaoperation_mode) opm = hal->dma_regs->dmaoperation_mode;
  382. typeof(hal->mac_regs->gmacconfig) cfg = hal->mac_regs->gmacconfig;
  383. /* Enable Ethernet MAC and DMA Interrupt */
  384. hal->dma_regs->dmain_en.val = 0xFFFFFFFF;
  385. /* Flush Transmit FIFO */
  386. opm.flush_tx_fifo = 1;
  387. /* Start DMA transmission */
  388. opm.start_stop_transmission_command = 1;
  389. /* Start DMA reception */
  390. opm.start_stop_rx = 1;
  391. /* Enable transmit state machine of the MAC for transmission on the MII */
  392. cfg.tx = 1;
  393. /* Enable receive state machine of the MAC for reception from the MII */
  394. cfg.rx = 1;
  395. hal->dma_regs->dmaoperation_mode = opm;
  396. hal->mac_regs->gmacconfig = cfg;
  397. /* Clear all pending interrupts */
  398. hal->dma_regs->dmastatus.val = 0xFFFFFFFF;
  399. }
  400. void emac_hal_stop(emac_hal_context_t *hal)
  401. {
  402. typeof(hal->dma_regs->dmaoperation_mode) opm = hal->dma_regs->dmaoperation_mode;
  403. typeof(hal->mac_regs->gmacconfig) cfg = hal->mac_regs->gmacconfig;
  404. /* Flush Transmit FIFO */
  405. opm.flush_tx_fifo = 1;
  406. /* Stop DMA transmission */
  407. opm.start_stop_transmission_command = 0;
  408. /* Stop DMA reception */
  409. opm.start_stop_rx = 0;
  410. /* Disable receive state machine of the MAC for reception from the MII */
  411. cfg.rx = 0;
  412. /* Disable transmit state machine of the MAC for transmission on the MII */
  413. cfg.tx = 0;
  414. hal->dma_regs->dmaoperation_mode = opm;
  415. hal->mac_regs->gmacconfig = cfg;
  416. /* Disable Ethernet MAC and DMA Interrupt */
  417. hal->dma_regs->dmain_en.val = 0x0;
  418. }
  419. uint32_t emac_hal_get_tx_desc_owner(emac_hal_context_t *hal)
  420. {
  421. return hal->tx_desc->TDES0.Own;
  422. }
  423. uint32_t emac_hal_transmit_frame(emac_hal_context_t *hal, uint8_t *buf, uint32_t length)
  424. {
  425. /* Get the number of Tx buffers to use for the frame */
  426. uint32_t bufcount = 0;
  427. uint32_t lastlen = length;
  428. uint32_t sentout = 0;
  429. while (lastlen > CONFIG_ETH_DMA_BUFFER_SIZE) {
  430. lastlen -= CONFIG_ETH_DMA_BUFFER_SIZE;
  431. bufcount++;
  432. }
  433. if (lastlen) {
  434. bufcount++;
  435. }
  436. if (bufcount > CONFIG_ETH_DMA_TX_BUFFER_NUM) {
  437. goto err;
  438. }
  439. eth_dma_tx_descriptor_t *desc_iter = hal->tx_desc;
  440. /* A frame is transmitted in multiple descriptor */
  441. for (size_t i = 0; i < bufcount; i++) {
  442. /* Check if the descriptor is owned by the Ethernet DMA (when 1) or CPU (when 0) */
  443. if (desc_iter->TDES0.Own != EMAC_DMADESC_OWNER_CPU) {
  444. goto err;
  445. }
  446. /* Clear FIRST and LAST segment bits */
  447. desc_iter->TDES0.FirstSegment = 0;
  448. desc_iter->TDES0.LastSegment = 0;
  449. desc_iter->TDES0.InterruptOnComplete = 0;
  450. if (i == 0) {
  451. /* Setting the first segment bit */
  452. desc_iter->TDES0.FirstSegment = 1;
  453. }
  454. if (i == (bufcount - 1)) {
  455. /* Setting the last segment bit */
  456. desc_iter->TDES0.LastSegment = 1;
  457. /* Enable transmit interrupt */
  458. desc_iter->TDES0.InterruptOnComplete = 1;
  459. /* Program size */
  460. desc_iter->TDES1.TransmitBuffer1Size = lastlen;
  461. /* copy data from uplayer stack buffer */
  462. memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, lastlen);
  463. sentout += lastlen;
  464. } else {
  465. /* Program size */
  466. desc_iter->TDES1.TransmitBuffer1Size = CONFIG_ETH_DMA_BUFFER_SIZE;
  467. /* copy data from uplayer stack buffer */
  468. memcpy((void *)(desc_iter->Buffer1Addr), buf + i * CONFIG_ETH_DMA_BUFFER_SIZE, CONFIG_ETH_DMA_BUFFER_SIZE);
  469. sentout += CONFIG_ETH_DMA_BUFFER_SIZE;
  470. }
  471. /* Point to next descriptor */
  472. desc_iter = (eth_dma_tx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  473. }
  474. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  475. for (size_t i = 0; i < bufcount; i++) {
  476. hal->tx_desc->TDES0.Own = EMAC_DMADESC_OWNER_DMA;
  477. hal->tx_desc = (eth_dma_tx_descriptor_t *)(hal->tx_desc->Buffer2NextDescAddr);
  478. }
  479. hal->dma_regs->dmatxpolldemand = 0;
  480. return sentout;
  481. err:
  482. return 0;
  483. }
  484. 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)
  485. {
  486. eth_dma_rx_descriptor_t *desc_iter = NULL;
  487. eth_dma_rx_descriptor_t *first_desc = NULL;
  488. uint32_t used_descs = 0;
  489. uint32_t seg_count = 0;
  490. uint32_t ret_len = 0;
  491. uint32_t copy_len = 0;
  492. uint32_t write_len = 0;
  493. uint32_t frame_count = 0;
  494. first_desc = hal->rx_desc;
  495. desc_iter = hal->rx_desc;
  496. /* Traverse descriptors owned by CPU */
  497. while ((desc_iter->RDES0.Own != EMAC_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM) && !frame_count) {
  498. used_descs++;
  499. seg_count++;
  500. /* Last segment in frame */
  501. if (desc_iter->RDES0.LastDescriptor) {
  502. /* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
  503. ret_len = desc_iter->RDES0.FrameLength - ETH_CRC_LENGTH;
  504. /* packets larger than expected will be truncated */
  505. copy_len = ret_len > size ? size : ret_len;
  506. /* update unhandled frame count */
  507. frame_count++;
  508. }
  509. /* First segment in frame */
  510. if (desc_iter->RDES0.FirstDescriptor) {
  511. first_desc = desc_iter;
  512. }
  513. /* point to next descriptor */
  514. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  515. }
  516. /* there's at least one frame to process */
  517. if (frame_count) {
  518. /* check how many frames left to handle */
  519. while ((desc_iter->RDES0.Own != EMAC_DMADESC_OWNER_DMA) && (used_descs < CONFIG_ETH_DMA_RX_BUFFER_NUM)) {
  520. used_descs++;
  521. if (desc_iter->RDES0.LastDescriptor) {
  522. frame_count++;
  523. }
  524. /* point to next descriptor */
  525. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  526. }
  527. desc_iter = first_desc;
  528. for (size_t i = 0; i < seg_count - 1; i++) {
  529. used_descs--;
  530. write_len = copy_len < CONFIG_ETH_DMA_BUFFER_SIZE ? copy_len : CONFIG_ETH_DMA_BUFFER_SIZE;
  531. /* copy data to buffer */
  532. memcpy(buf, (void *)(desc_iter->Buffer1Addr), write_len);
  533. buf += write_len;
  534. copy_len -= write_len;
  535. /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
  536. desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
  537. desc_iter = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  538. }
  539. memcpy(buf, (void *)(desc_iter->Buffer1Addr), copy_len);
  540. desc_iter->RDES0.Own = EMAC_DMADESC_OWNER_DMA;
  541. /* update rxdesc */
  542. hal->rx_desc = (eth_dma_rx_descriptor_t *)(desc_iter->Buffer2NextDescAddr);
  543. /* poll rx demand */
  544. hal->dma_regs->dmarxpolldemand = 0;
  545. frame_count--;
  546. used_descs--;
  547. }
  548. *frames_remain = frame_count;
  549. *free_desc = CONFIG_ETH_DMA_RX_BUFFER_NUM - used_descs;
  550. return ret_len;
  551. }
  552. IRAM_ATTR void emac_hal_isr(void *arg)
  553. {
  554. emac_hal_context_t *hal = (emac_hal_context_t *)arg;
  555. typeof(hal->dma_regs->dmastatus) dma_status = hal->dma_regs->dmastatus;
  556. hal->dma_regs->dmastatus.val = dma_status.val;
  557. /* DMA Normal Interrupt */
  558. if (dma_status.norm_int_summ) {
  559. /* Transmit Interrupt */
  560. if (dma_status.trans_int) {
  561. emac_hal_tx_complete_cb(arg);
  562. }
  563. /* Transmit Buffer Unavailable */
  564. if (dma_status.trans_buf_unavail) {
  565. emac_hal_tx_unavail_cb(arg);
  566. }
  567. /* Receive Interrupt */
  568. if (dma_status.recv_int) {
  569. emac_hal_rx_complete_cb(arg);
  570. }
  571. /* Early Receive Interrupt */
  572. if (dma_status.early_recv_int) {
  573. emac_hal_rx_early_cb(arg);
  574. }
  575. }
  576. /* DMA Abnormal Interrupt */
  577. if (dma_status.abn_int_summ) {
  578. /* Transmit Process Stopped */
  579. if (dma_status.trans_proc_stop) {
  580. }
  581. /* Transmit Jabber Timeout */
  582. if (dma_status.trans_jabber_to) {
  583. }
  584. /* Receive FIFO Overflow */
  585. if (dma_status.recv_ovflow) {
  586. }
  587. /* Transmit Underflow */
  588. if (dma_status.trans_undflow) {
  589. }
  590. /* Receive Buffer Unavailable */
  591. if (dma_status.recv_buf_unavail) {
  592. emac_hal_rx_unavail_cb(arg);
  593. }
  594. /* Receive Process Stopped */
  595. if (dma_status.recv_proc_stop) {
  596. }
  597. /* Receive Watchdog Timeout */
  598. if (dma_status.recv_wdt_to) {
  599. }
  600. /* Early Transmit Interrupt */
  601. if (dma_status.early_trans_int) {
  602. }
  603. /* Fatal Bus Error */
  604. if (dma_status.fatal_bus_err_int) {
  605. }
  606. }
  607. }
  608. IRAM_ATTR __attribute__((weak)) void emac_hal_tx_complete_cb(void *arg)
  609. {
  610. // This is a weak function, do nothing by default
  611. // Upper code can rewrite this function
  612. // Note: you're in the interrupt context
  613. return;
  614. }
  615. IRAM_ATTR __attribute__((weak)) void emac_hal_tx_unavail_cb(void *arg)
  616. {
  617. // This is a weak function, do nothing by default
  618. // Upper code can rewrite this function
  619. // Note: you're in the interrupt context
  620. return;
  621. }
  622. IRAM_ATTR __attribute__((weak)) void emac_hal_rx_complete_cb(void *arg)
  623. {
  624. // This is a weak function, do nothing by default
  625. // Upper code can rewrite this function
  626. // Note: you're in the interrupt context
  627. return;
  628. }
  629. IRAM_ATTR __attribute__((weak)) void emac_hal_rx_early_cb(void *arg)
  630. {
  631. // This is a weak function, do nothing by default
  632. // Upper code can rewrite this function
  633. // Note: you're in the interrupt context
  634. return;
  635. }
  636. IRAM_ATTR __attribute__((weak)) void emac_hal_rx_unavail_cb(void *arg)
  637. {
  638. // This is a weak function, do nothing by default
  639. // Upper code can rewrite this function
  640. // Note: you're in the interrupt context
  641. return;
  642. }