nu_emac.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  1. /**************************************************************************//**
  2. * @file emac.c
  3. * @version V1.00
  4. * @brief M480 EMAC driver source file
  5. *
  6. * SPDX-License-Identifier: Apache-2.0
  7. * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include "NuMicro.h"
  12. /** @addtogroup Standard_Driver Standard Driver
  13. @{
  14. */
  15. /** @addtogroup EMAC_Driver EMAC Driver
  16. @{
  17. */
  18. /* Below are structure, definitions, static variables used locally by EMAC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */
  19. /** @cond HIDDEN_SYMBOLS */
  20. /** @addtogroup EMAC_EXPORTED_CONSTANTS EMAC Exported Constants
  21. @{
  22. */
  23. /* PHY Register Description */
  24. #define PHY_CNTL_REG 0x00UL /*!< PHY control register address */
  25. #define PHY_STATUS_REG 0x01UL /*!< PHY status register address */
  26. #define PHY_ID1_REG 0x02UL /*!< PHY ID1 register */
  27. #define PHY_ID2_REG 0x03UL /*!< PHY ID2 register */
  28. #define PHY_ANA_REG 0x04UL /*!< PHY auto-negotiation advertisement register */
  29. #define PHY_ANLPA_REG 0x05UL /*!< PHY auto-negotiation link partner availability register */
  30. #define PHY_ANE_REG 0x06UL /*!< PHY auto-negotiation expansion register */
  31. /* PHY Control Register */
  32. #define PHY_CNTL_RESET_PHY (1UL << 15UL)
  33. #define PHY_CNTL_DR_100MB (1UL << 13UL)
  34. #define PHY_CNTL_ENABLE_AN (1UL << 12UL)
  35. #define PHY_CNTL_POWER_DOWN (1UL << 11UL)
  36. #define PHY_CNTL_RESTART_AN (1UL << 9UL)
  37. #define PHY_CNTL_FULLDUPLEX (1UL << 8UL)
  38. /* PHY Status Register */
  39. #define PHY_STATUS_AN_COMPLETE (1UL << 5UL)
  40. #define PHY_STATUS_LINK_VALID (1UL << 2UL)
  41. /* PHY Auto-negotiation Advertisement Register */
  42. #define PHY_ANA_DR100_TX_FULL (1UL << 8UL)
  43. #define PHY_ANA_DR100_TX_HALF (1UL << 7UL)
  44. #define PHY_ANA_DR10_TX_FULL (1UL << 6UL)
  45. #define PHY_ANA_DR10_TX_HALF (1UL << 5UL)
  46. #define PHY_ANA_IEEE_802_3_CSMA_CD (1UL << 0UL)
  47. /* PHY Auto-negotiation Link Partner Advertisement Register */
  48. #define PHY_ANLPA_DR100_TX_FULL (1UL << 8UL)
  49. #define PHY_ANLPA_DR100_TX_HALF (1UL << 7UL)
  50. #define PHY_ANLPA_DR10_TX_FULL (1UL << 6UL)
  51. #define PHY_ANLPA_DR10_TX_HALF (1UL << 5UL)
  52. /* EMAC Tx/Rx descriptor's owner bit */
  53. #define EMAC_DESC_OWN_EMAC 0x80000000UL /*!< Set owner to EMAC */
  54. #define EMAC_DESC_OWN_CPU 0x00000000UL /*!< Set owner to CPU */
  55. /* Rx Frame Descriptor Status */
  56. #define EMAC_RXFD_RTSAS 0x0080UL /*!< Time Stamp Available */
  57. #define EMAC_RXFD_RP 0x0040UL /*!< Runt Packet */
  58. #define EMAC_RXFD_ALIE 0x0020UL /*!< Alignment Error */
  59. #define EMAC_RXFD_RXGD 0x0010UL /*!< Receiving Good packet received */
  60. #define EMAC_RXFD_PTLE 0x0008UL /*!< Packet Too Long Error */
  61. #define EMAC_RXFD_CRCE 0x0002UL /*!< CRC Error */
  62. #define EMAC_RXFD_RXINTR 0x0001UL /*!< Interrupt on receive */
  63. /* Tx Frame Descriptor's Control bits */
  64. #define EMAC_TXFD_TTSEN 0x08UL /*!< Tx time stamp enable */
  65. #define EMAC_TXFD_INTEN 0x04UL /*!< Tx interrupt enable */
  66. #define EMAC_TXFD_CRCAPP 0x02UL /*!< Append CRC */
  67. #define EMAC_TXFD_PADEN 0x01UL /*!< Padding mode enable */
  68. /* Tx Frame Descriptor Status */
  69. #define EMAC_TXFD_TXINTR 0x0001UL /*!< Interrupt on Transmit */
  70. #define EMAC_TXFD_DEF 0x0002UL /*!< Transmit deferred */
  71. #define EMAC_TXFD_TXCP 0x0008UL /*!< Transmission Completion */
  72. #define EMAC_TXFD_EXDEF 0x0010UL /*!< Exceed Deferral */
  73. #define EMAC_TXFD_NCS 0x0020UL /*!< No Carrier Sense Error */
  74. #define EMAC_TXFD_TXABT 0x0040UL /*!< Transmission Abort */
  75. #define EMAC_TXFD_LC 0x0080UL /*!< Late Collision */
  76. #define EMAC_TXFD_TXHA 0x0100UL /*!< Transmission halted */
  77. #define EMAC_TXFD_PAU 0x0200UL /*!< Paused */
  78. #define EMAC_TXFD_SQE 0x0400UL /*!< SQE error */
  79. #define EMAC_TXFD_TTSAS 0x0800UL /*!< Time Stamp available */
  80. /*@}*/ /* end of group EMAC_EXPORTED_CONSTANTS */
  81. /** @addtogroup EMAC_EXPORTED_TYPEDEF EMAC Exported Type Defines
  82. @{
  83. */
  84. /** Tx/Rx buffer descriptor structure */
  85. typedef struct
  86. {
  87. uint32_t u32Status1; /*!< Status word 1 */
  88. uint32_t u32Data; /*!< Pointer to data buffer */
  89. uint32_t u32Status2; /*!< Status word 2 */
  90. uint32_t u32Next; /*!< Pointer to next descriptor */
  91. uint32_t u32Backup1; /*!< For backup descriptor fields over written by time stamp */
  92. uint32_t u32Backup2; /*!< For backup descriptor fields over written by time stamp */
  93. } EMAC_DESCRIPTOR_T;
  94. /** Tx/Rx buffer structure */
  95. typedef struct
  96. {
  97. uint8_t au8Buf[EMAC_MAX_PKT_SIZE];
  98. } EMAC_FRAME_T;
  99. /*@}*/ /* end of group EMAC_EXPORTED_TYPEDEF */
  100. /* local variables */
  101. static volatile EMAC_DESCRIPTOR_T rx_desc[EMAC_RX_DESC_SIZE];
  102. static volatile EMAC_FRAME_T rx_buf[EMAC_RX_DESC_SIZE];
  103. static volatile EMAC_DESCRIPTOR_T tx_desc[EMAC_TX_DESC_SIZE];
  104. static volatile EMAC_FRAME_T tx_buf[EMAC_TX_DESC_SIZE];
  105. static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc;
  106. static uint32_t s_u32EnableTs = 0UL;
  107. static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data);
  108. static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr);
  109. static void EMAC_TxDescInit(void);
  110. static void EMAC_RxDescInit(void);
  111. static uint32_t EMAC_Subsec2Nsec(uint32_t subsec);
  112. static uint32_t EMAC_Nsec2Subsec(uint32_t nsec);
  113. /** @addtogroup EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions
  114. @{
  115. */
  116. /**
  117. * @brief Write PHY register
  118. * @param[in] u32Reg PHY register number
  119. * @param[in] u32Addr PHY address, this address is board dependent
  120. * @param[in] u32Data data to write to PHY register
  121. * @return None
  122. */
  123. static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data)
  124. {
  125. /* Set data register */
  126. EMAC->MIIMDAT = u32Data ;
  127. /* Set PHY address, PHY register address, busy bit and write bit */
  128. EMAC->MIIMCTL = u32Reg | (u32Addr << 8) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
  129. /* Wait write complete by polling busy bit. */
  130. while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk)
  131. {
  132. ;
  133. }
  134. }
  135. /**
  136. * @brief Read PHY register
  137. * @param[in] u32Reg PHY register number
  138. * @param[in] u32Addr PHY address, this address is board dependent
  139. * @return Value read from PHY register
  140. */
  141. static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr)
  142. {
  143. /* Set PHY address, PHY register address, busy bit */
  144. EMAC->MIIMCTL = u32Reg | (u32Addr << EMAC_MIIMCTL_PHYADDR_Pos) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
  145. /* Wait read complete by polling busy bit */
  146. while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk)
  147. {
  148. ;
  149. }
  150. /* Get return data */
  151. return EMAC->MIIMDAT;
  152. }
  153. /**
  154. * @brief Initialize PHY chip, check for the auto-negotiation result.
  155. * @param None
  156. * @return None
  157. */
  158. void EMAC_PhyInit(void)
  159. {
  160. uint32_t reg;
  161. uint32_t i = 0UL;
  162. /* Reset Phy Chip */
  163. EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY);
  164. /* Wait until reset complete */
  165. while (1)
  166. {
  167. reg = EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) ;
  168. if ((reg & PHY_CNTL_RESET_PHY) == 0UL)
  169. {
  170. break;
  171. }
  172. }
  173. while (!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
  174. {
  175. if (i++ > 10000UL) /* Cable not connected */
  176. {
  177. EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
  178. EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
  179. break;
  180. }
  181. }
  182. if (i <= 10000UL)
  183. {
  184. /* Configure auto negotiation capability */
  185. EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL |
  186. PHY_ANA_DR100_TX_HALF |
  187. PHY_ANA_DR10_TX_FULL |
  188. PHY_ANA_DR10_TX_HALF |
  189. PHY_ANA_IEEE_802_3_CSMA_CD);
  190. /* Restart auto negotiation */
  191. EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN);
  192. /* Wait for auto-negotiation complete */
  193. while (!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE))
  194. {
  195. ;
  196. }
  197. /* Check link valid again. Some PHYs needs to check result after link valid bit set */
  198. while (!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
  199. {
  200. ;
  201. }
  202. /* Check link partner capability */
  203. reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
  204. if (reg & PHY_ANLPA_DR100_TX_FULL)
  205. {
  206. EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
  207. EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
  208. }
  209. else if (reg & PHY_ANLPA_DR100_TX_HALF)
  210. {
  211. EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
  212. EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
  213. }
  214. else if (reg & PHY_ANLPA_DR10_TX_FULL)
  215. {
  216. EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
  217. EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
  218. }
  219. else
  220. {
  221. EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
  222. EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
  223. }
  224. }
  225. }
  226. /**
  227. * @brief Initial EMAC Tx descriptors and get Tx descriptor base address
  228. * @param None
  229. * @return None
  230. */
  231. static void EMAC_TxDescInit(void)
  232. {
  233. uint32_t i;
  234. /* Get Frame descriptor's base address. */
  235. EMAC->TXDSA = (uint32_t)&tx_desc[0];
  236. u32NextTxDesc = u32CurrentTxDesc = (uint32_t)&tx_desc[0];
  237. for (i = 0UL; i < EMAC_TX_DESC_SIZE; i++)
  238. {
  239. if (s_u32EnableTs)
  240. {
  241. tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN;
  242. }
  243. else
  244. {
  245. tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN;
  246. }
  247. tx_desc[i].u32Data = (uint32_t)((uint32_t)&tx_buf[i]);
  248. tx_desc[i].u32Backup1 = tx_desc[i].u32Data;
  249. tx_desc[i].u32Status2 = 0UL;
  250. tx_desc[i].u32Next = (uint32_t)&tx_desc[(i + 1UL) % EMAC_TX_DESC_SIZE];
  251. tx_desc[i].u32Backup2 = tx_desc[i].u32Next;
  252. }
  253. }
  254. /**
  255. * @brief Initial EMAC Rx descriptors and get Rx descriptor base address
  256. * @param None
  257. * @return None
  258. */
  259. static void EMAC_RxDescInit(void)
  260. {
  261. uint32_t i;
  262. /* Get Frame descriptor's base address. */
  263. EMAC->RXDSA = (uint32_t)&rx_desc[0];
  264. u32CurrentRxDesc = (uint32_t)&rx_desc[0];
  265. for (i = 0UL; i < EMAC_RX_DESC_SIZE; i++)
  266. {
  267. rx_desc[i].u32Status1 = EMAC_DESC_OWN_EMAC;
  268. rx_desc[i].u32Data = (uint32_t)((uint32_t)&rx_buf[i]);
  269. rx_desc[i].u32Backup1 = rx_desc[i].u32Data;
  270. rx_desc[i].u32Status2 = 0UL;
  271. rx_desc[i].u32Next = (uint32_t)&rx_desc[(i + 1UL) % EMAC_RX_DESC_SIZE];
  272. rx_desc[i].u32Backup2 = rx_desc[i].u32Next;
  273. }
  274. }
  275. /**
  276. * @brief Convert subsecond value to nano second
  277. * @param[in] subsec Subsecond value to be convert
  278. * @return Nano second
  279. */
  280. static uint32_t EMAC_Subsec2Nsec(uint32_t subsec)
  281. {
  282. /* 2^31 subsec == 10^9 ns */
  283. uint64_t i;
  284. i = 1000000000ull * (uint64_t)subsec;
  285. i >>= 31;
  286. return ((uint32_t)i);
  287. }
  288. /**
  289. * @brief Convert nano second to subsecond value
  290. * @param[in] nsec Nano second to be convert
  291. * @return Subsecond
  292. */
  293. static uint32_t EMAC_Nsec2Subsec(uint32_t nsec)
  294. {
  295. /* 10^9 ns = 2^31 subsec */
  296. uint64_t i;
  297. i = (1ull << 31) * nsec;
  298. i /= 1000000000ull;
  299. return ((uint32_t)i);
  300. }
  301. /*@}*/ /* end of group EMAC_EXPORTED_FUNCTIONS */
  302. /** @endcond HIDDEN_SYMBOLS */
  303. /** @addtogroup EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions
  304. @{
  305. */
  306. /**
  307. * @brief Initialize EMAC interface, including descriptors, MAC address, and PHY.
  308. * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
  309. * @return None
  310. * @note This API configures EMAC to receive all broadcast and multicast packets, but could configure to other settings with
  311. * \ref EMAC_ENABLE_RECV_BCASTPKT, \ref EMAC_DISABLE_RECV_BCASTPKT, \ref EMAC_ENABLE_RECV_MCASTPKT, and \ref EMAC_DISABLE_RECV_MCASTPKT
  312. * @note Receive(RX) and transmit(TX) are not enabled yet, application must call \ref EMAC_ENABLE_RX and \ref EMAC_ENABLE_TX to
  313. * enable receive and transmit function.
  314. */
  315. void EMAC_Open(uint8_t *pu8MacAddr)
  316. {
  317. /* Enable transmit and receive descriptor */
  318. EMAC_TxDescInit();
  319. EMAC_RxDescInit();
  320. /* Set the CAM Control register and the MAC address value */
  321. EMAC_SetMacAddr(pu8MacAddr);
  322. /* Configure the MAC interrupt enable register. */
  323. EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
  324. EMAC_INTEN_TXIEN_Msk |
  325. EMAC_INTEN_RXGDIEN_Msk |
  326. EMAC_INTEN_TXCPIEN_Msk |
  327. EMAC_INTEN_RXBEIEN_Msk |
  328. EMAC_INTEN_TXBEIEN_Msk |
  329. EMAC_INTEN_RDUIEN_Msk |
  330. EMAC_INTEN_TSALMIEN_Msk |
  331. EMAC_INTEN_WOLIEN_Msk;
  332. /* Configure the MAC control register. */
  333. EMAC->CTL = EMAC_CTL_STRIPCRC_Msk |
  334. EMAC_CTL_RMIIEN_Msk;
  335. /* Accept packets for us and all broadcast and multicast packets */
  336. EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
  337. EMAC_CAMCTL_AMP_Msk |
  338. EMAC_CAMCTL_ABP_Msk;
  339. /* Limit the max receive frame length to 1514 + 4 */
  340. EMAC->MRFL = EMAC_MAX_PKT_SIZE;
  341. }
  342. /**
  343. * @brief This function stop all receive and transmit activity and disable MAC interface
  344. * @param None
  345. * @return None
  346. */
  347. void EMAC_Close(void)
  348. {
  349. EMAC->CTL |= EMAC_CTL_RST_Msk;
  350. while (EMAC->CTL & EMAC_CTL_RST_Msk) {}
  351. }
  352. /**
  353. * @brief Set the device MAC address
  354. * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
  355. * @return None
  356. */
  357. void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
  358. {
  359. EMAC_EnableCamEntry(0UL, pu8MacAddr);
  360. }
  361. /**
  362. * @brief Fill a CAM entry for MAC address comparison.
  363. * @param[in] u32Entry MAC entry to fill. Entry 0 is used to store device MAC address, do not overwrite the setting in it.
  364. * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
  365. * @return None
  366. */
  367. void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[])
  368. {
  369. uint32_t u32Lsw, u32Msw;
  370. uint32_t reg;
  371. u32Lsw = (uint32_t)(((uint32_t)pu8MacAddr[4] << 24) |
  372. ((uint32_t)pu8MacAddr[5] << 16));
  373. u32Msw = (uint32_t)(((uint32_t)pu8MacAddr[0] << 24) |
  374. ((uint32_t)pu8MacAddr[1] << 16) |
  375. ((uint32_t)pu8MacAddr[2] << 8) |
  376. (uint32_t)pu8MacAddr[3]);
  377. reg = (uint32_t)&EMAC->CAM0M + u32Entry * 2UL * 4UL;
  378. *(uint32_t volatile *)reg = u32Msw;
  379. reg = (uint32_t)&EMAC->CAM0L + u32Entry * 2UL * 4UL;
  380. *(uint32_t volatile *)reg = u32Lsw;
  381. EMAC->CAMEN |= (1UL << u32Entry);
  382. }
  383. /**
  384. * @brief Disable a specified CAM entry
  385. * @param[in] u32Entry CAM entry to be disabled
  386. * @return None
  387. */
  388. void EMAC_DisableCamEntry(uint32_t u32Entry)
  389. {
  390. EMAC->CAMEN &= ~(1UL << u32Entry);
  391. }
  392. /**
  393. * @brief Receive an Ethernet packet
  394. * @param[in] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed)
  395. * @param[in] pu32Size Received packet size (without 4 byte CRC).
  396. * @return Packet receive success or not
  397. * @retval 0 No packet available for receive
  398. * @retval 1 A packet is received
  399. * @note Return 0 doesn't guarantee the packet will be sent and received successfully.
  400. */
  401. uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
  402. {
  403. EMAC_DESCRIPTOR_T *desc;
  404. uint32_t status, reg;
  405. uint32_t u32Count = 0UL;
  406. /* Clear Rx interrupt flags */
  407. reg = EMAC->INTSTS;
  408. EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all RX related interrupt status */
  409. if (reg & EMAC_INTSTS_RXBEIF_Msk)
  410. {
  411. /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
  412. while (1) {}
  413. }
  414. else
  415. {
  416. /* Get Rx Frame Descriptor */
  417. desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
  418. /* If we reach last recv Rx descriptor, leave the loop */
  419. if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */
  420. {
  421. status = desc->u32Status1 >> 16;
  422. /* If Rx frame is good, process received frame */
  423. if (status & EMAC_RXFD_RXGD)
  424. {
  425. /* lower 16 bit in descriptor status1 stores the Rx packet length */
  426. *pu32Size = desc->u32Status1 & 0xFFFFUL;
  427. memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
  428. u32Count = 1UL;
  429. }
  430. else
  431. {
  432. /* Save Error status if necessary */
  433. if (status & EMAC_RXFD_RP) {}
  434. if (status & EMAC_RXFD_ALIE) {}
  435. if (status & EMAC_RXFD_PTLE) {}
  436. if (status & EMAC_RXFD_CRCE) {}
  437. }
  438. }
  439. }
  440. return (u32Count);
  441. }
  442. /**
  443. * @brief Receive an Ethernet packet and the time stamp while it's received
  444. * @param[out] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed)
  445. * @param[out] pu32Size Received packet size (without 4 byte CRC).
  446. * @param[out] pu32Sec Second value while packet received
  447. * @param[out] pu32Nsec Nano second value while packet received
  448. * @return Packet receive success or not
  449. * @retval 0 No packet available for receive
  450. * @retval 1 A packet is received
  451. * @note Return 0 doesn't guarantee the packet will be sent and received successfully.
  452. * @note Largest Ethernet packet is 1514 bytes after stripped CRC, application must give
  453. * a buffer large enough to store such packet
  454. */
  455. uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
  456. {
  457. EMAC_DESCRIPTOR_T *desc;
  458. uint32_t status, reg;
  459. uint32_t u32Count = 0UL;
  460. /* Clear Rx interrupt flags */
  461. reg = EMAC->INTSTS;
  462. EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all Rx related interrupt status */
  463. if (reg & EMAC_INTSTS_RXBEIF_Msk)
  464. {
  465. /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
  466. while (1) {}
  467. }
  468. else
  469. {
  470. /* Get Rx Frame Descriptor */
  471. desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
  472. /* If we reach last recv Rx descriptor, leave the loop */
  473. if (EMAC->CRXDSA != (uint32_t)desc)
  474. {
  475. if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */
  476. {
  477. status = desc->u32Status1 >> 16;
  478. /* If Rx frame is good, process received frame */
  479. if (status & EMAC_RXFD_RXGD)
  480. {
  481. /* lower 16 bit in descriptor status1 stores the Rx packet length */
  482. *pu32Size = desc->u32Status1 & 0xFFFFUL;
  483. memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
  484. *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */
  485. *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */
  486. u32Count = 1UL;
  487. }
  488. else
  489. {
  490. /* Save Error status if necessary */
  491. if (status & EMAC_RXFD_RP) {}
  492. if (status & EMAC_RXFD_ALIE) {}
  493. if (status & EMAC_RXFD_PTLE) {}
  494. if (status & EMAC_RXFD_CRCE) {}
  495. }
  496. }
  497. }
  498. }
  499. return (u32Count);
  500. }
  501. /**
  502. * @brief Clean up process after a packet is received
  503. * @param None
  504. * @return None
  505. * @details EMAC Rx interrupt service routine \b must call this API to release the resource use by receive process
  506. * @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1
  507. */
  508. void EMAC_RecvPktDone(void)
  509. {
  510. EMAC_DESCRIPTOR_T *desc;
  511. /* Get Rx Frame Descriptor */
  512. desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
  513. /* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
  514. desc->u32Data = desc->u32Backup1;
  515. desc->u32Next = desc->u32Backup2;
  516. /* Change ownership to DMA for next use */
  517. desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
  518. /* Get Next Frame Descriptor pointer to process */
  519. desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
  520. /* Save last processed Rx descriptor */
  521. u32CurrentRxDesc = (uint32_t)desc;
  522. EMAC_TRIGGER_RX();
  523. }
  524. /**
  525. * @brief Send an Ethernet packet
  526. * @param[in] pu8Data Pointer to a buffer holds the packet to transmit
  527. * @param[in] u32Size Packet size (without 4 byte CRC).
  528. * @return Packet transmit success or not
  529. * @retval 0 Transmit failed due to descriptor unavailable.
  530. * @retval 1 Packet is copied to descriptor and triggered to transmit.
  531. * @note Return 1 doesn't guarantee the packet will be sent and received successfully.
  532. */
  533. uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
  534. {
  535. EMAC_DESCRIPTOR_T *desc;
  536. uint32_t status;
  537. uint32_t ret = 0UL;
  538. /* Get Tx frame descriptor & data pointer */
  539. desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
  540. status = desc->u32Status1;
  541. /* Check descriptor ownership */
  542. if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
  543. {
  544. memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size);
  545. /* Set Tx descriptor transmit byte count */
  546. desc->u32Status2 = u32Size;
  547. /* Change descriptor ownership to EMAC */
  548. desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
  549. /* Get next Tx descriptor */
  550. u32NextTxDesc = (uint32_t)(desc->u32Next);
  551. /* Trigger EMAC to send the packet */
  552. EMAC_TRIGGER_TX();
  553. ret = 1UL;
  554. }
  555. return (ret);
  556. }
  557. /**
  558. * @brief Clean up process after packet(s) are sent
  559. * @param None
  560. * @return Number of packet sent between two function calls
  561. * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDoneTS to
  562. * release the resource use by transmit process
  563. */
  564. uint32_t EMAC_SendPktDone(void)
  565. {
  566. EMAC_DESCRIPTOR_T *desc;
  567. uint32_t status, reg;
  568. uint32_t last_tx_desc;
  569. uint32_t u32Count = 0UL;
  570. reg = EMAC->INTSTS;
  571. /* Clear Tx interrupt flags */
  572. EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
  573. if (reg & EMAC_INTSTS_TXBEIF_Msk)
  574. {
  575. /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
  576. while (1) {}
  577. }
  578. else
  579. {
  580. /* Process the descriptor(s). */
  581. last_tx_desc = EMAC->CTXDSA ;
  582. /* Get our first descriptor to process */
  583. desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
  584. do
  585. {
  586. /* Descriptor ownership is still EMAC, so this packet haven't been send. */
  587. if (desc->u32Status1 & EMAC_DESC_OWN_EMAC)
  588. {
  589. break;
  590. }
  591. /* Get Tx status stored in descriptor */
  592. status = desc->u32Status2 >> 16UL;
  593. if (status & EMAC_TXFD_TXCP)
  594. {
  595. u32Count++;
  596. }
  597. else
  598. {
  599. /* Do nothing here on error. */
  600. if (status & EMAC_TXFD_TXABT) {}
  601. if (status & EMAC_TXFD_DEF) {}
  602. if (status & EMAC_TXFD_PAU) {}
  603. if (status & EMAC_TXFD_EXDEF) {}
  604. if (status & EMAC_TXFD_NCS) {}
  605. if (status & EMAC_TXFD_SQE) {}
  606. if (status & EMAC_TXFD_LC) {}
  607. if (status & EMAC_TXFD_TXHA) {}
  608. }
  609. /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
  610. desc->u32Data = desc->u32Backup1;
  611. desc->u32Next = desc->u32Backup2;
  612. /* go to next descriptor in link */
  613. desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
  614. }
  615. while (last_tx_desc != (uint32_t)desc); /* If we reach last sent Tx descriptor, leave the loop */
  616. /* Save last processed Tx descriptor */
  617. u32CurrentTxDesc = (uint32_t)desc;
  618. }
  619. return (u32Count);
  620. }
  621. /**
  622. * @brief Clean up process after a packet is sent, and get the time stamp while packet is sent
  623. * @param[in] pu32Sec Second value while packet sent
  624. * @param[in] pu32Nsec Nano second value while packet sent
  625. * @return If a packet sent successfully
  626. * @retval 0 No packet sent successfully, and the value in *pu32Sec and *pu32Nsec are meaningless
  627. * @retval 1 A packet sent successfully, and the value in *pu32Sec and *pu32Nsec is the time stamp while packet sent
  628. * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDone to
  629. * release the resource use by transmit process
  630. */
  631. uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec)
  632. {
  633. EMAC_DESCRIPTOR_T *desc;
  634. uint32_t status, reg;
  635. uint32_t u32Count = 0UL;
  636. reg = EMAC->INTSTS;
  637. /* Clear Tx interrupt flags */
  638. EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
  639. if (reg & EMAC_INTSTS_TXBEIF_Msk)
  640. {
  641. /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
  642. while (1) {}
  643. }
  644. else
  645. {
  646. /* Process the descriptor.
  647. Get our first descriptor to process */
  648. desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
  649. /* Descriptor ownership is still EMAC, so this packet haven't been send. */
  650. if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
  651. {
  652. /* Get Tx status stored in descriptor */
  653. status = desc->u32Status2 >> 16UL;
  654. if (status & EMAC_TXFD_TXCP)
  655. {
  656. u32Count = 1UL;
  657. *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */
  658. *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */
  659. }
  660. else
  661. {
  662. /* Do nothing here on error. */
  663. if (status & EMAC_TXFD_TXABT) {}
  664. if (status & EMAC_TXFD_DEF) {}
  665. if (status & EMAC_TXFD_PAU) {}
  666. if (status & EMAC_TXFD_EXDEF) {}
  667. if (status & EMAC_TXFD_NCS) {}
  668. if (status & EMAC_TXFD_SQE) {}
  669. if (status & EMAC_TXFD_LC) {}
  670. if (status & EMAC_TXFD_TXHA) {}
  671. }
  672. /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
  673. desc->u32Data = desc->u32Backup1;
  674. desc->u32Next = desc->u32Backup2;
  675. /* go to next descriptor in link */
  676. desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
  677. /* Save last processed Tx descriptor */
  678. u32CurrentTxDesc = (uint32_t)desc;
  679. }
  680. }
  681. return (u32Count);
  682. }
  683. /**
  684. * @brief Enable IEEE1588 time stamp function and set current time
  685. * @param[in] u32Sec Second value
  686. * @param[in] u32Nsec Nano second value
  687. * @return None
  688. */
  689. void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
  690. {
  691. double f;
  692. uint32_t reg;
  693. EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
  694. EMAC->UPDSEC = u32Sec; /* Assume current time is 0 sec + 0 nano sec */
  695. EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
  696. /* PTP source clock is 160MHz (Real chip using PLL). Each tick is 6.25ns
  697. Assume we want to set each tick to 100ns.
  698. Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
  699. Addend register = 2^32 * tick_freq / (160MHz), where tick_freq = (2^31 / 215) MHz
  700. From above equation, addend register = 2^63 / (160M * 215) ~= 268121280 = 0xFFB34C0
  701. So:
  702. EMAC->TSIR = 0xD7;
  703. EMAC->TSAR = 0x1E70C600; */
  704. f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5;
  705. EMAC->TSINC = (reg = (uint32_t)f);
  706. f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg);
  707. EMAC->TSADDEND = (uint32_t)f;
  708. EMAC->TSCTL |= (EMAC_TSCTL_TSUPDATE_Msk | EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); /* Fine update */
  709. }
  710. /**
  711. * @brief Disable IEEE1588 time stamp function
  712. * @param None
  713. * @return None
  714. */
  715. void EMAC_DisableTS(void)
  716. {
  717. EMAC->TSCTL = 0UL;
  718. }
  719. /**
  720. * @brief Get current time stamp
  721. * @param[out] pu32Sec Current second value
  722. * @param[out] pu32Nsec Current nano second value
  723. * @return None
  724. */
  725. void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
  726. {
  727. /* Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read. */
  728. *pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC);
  729. *pu32Sec = EMAC->TSSEC;
  730. }
  731. /**
  732. * @brief Set current time stamp
  733. * @param[in] u32Sec Second value
  734. * @param[in] u32Nsec Nano second value
  735. * @return None
  736. */
  737. void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
  738. {
  739. /* Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk) */
  740. EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
  741. EMAC->UPDSEC = u32Sec;
  742. EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
  743. EMAC->TSCTL |= (EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk);
  744. }
  745. /**
  746. * @brief Enable alarm function and set alarm time
  747. * @param[in] u32Sec Second value to trigger alarm
  748. * @param[in] u32Nsec Nano second value to trigger alarm
  749. * @return None
  750. */
  751. void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
  752. {
  753. EMAC->ALMSEC = u32Sec;
  754. EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
  755. EMAC->TSCTL |= EMAC_TSCTL_TSALMEN_Msk;
  756. }
  757. /**
  758. * @brief Disable alarm function
  759. * @param None
  760. * @return None
  761. */
  762. void EMAC_DisableAlarm(void)
  763. {
  764. EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
  765. }
  766. /**
  767. * @brief Add a offset to current time
  768. * @param[in] u32Neg Offset is negative value (u32Neg == 1) or positive value (u32Neg == 0).
  769. * @param[in] u32Sec Second value to add to current time
  770. * @param[in] u32Nsec Nano second value to add to current time
  771. * @return None
  772. */
  773. void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
  774. {
  775. EMAC->UPDSEC = u32Sec;
  776. EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
  777. if (u32Neg)
  778. {
  779. EMAC->UPDSUBSEC |= BIT31; /* Set bit 31 indicates this is a negative value */
  780. }
  781. EMAC->TSCTL |= EMAC_TSCTL_TSUPDATE_Msk;
  782. }
  783. /**
  784. * @brief Check Ethernet link status
  785. * @param None
  786. * @return Current link status, could be one of following value.
  787. * - \ref EMAC_LINK_DOWN
  788. * - \ref EMAC_LINK_100F
  789. * - \ref EMAC_LINK_100H
  790. * - \ref EMAC_LINK_10F
  791. * - \ref EMAC_LINK_10H
  792. * @note This API should be called regularly to sync EMAC setting with real connection status
  793. */
  794. uint32_t EMAC_CheckLinkStatus(void)
  795. {
  796. uint32_t reg, ret = EMAC_LINK_DOWN;
  797. /* Check link valid again */
  798. if (EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)
  799. {
  800. /* Check link partner capability */
  801. reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
  802. if (reg & PHY_ANLPA_DR100_TX_FULL)
  803. {
  804. EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
  805. EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
  806. ret = EMAC_LINK_100F;
  807. }
  808. else if (reg & PHY_ANLPA_DR100_TX_HALF)
  809. {
  810. EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
  811. EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
  812. ret = EMAC_LINK_100H;
  813. }
  814. else if (reg & PHY_ANLPA_DR10_TX_FULL)
  815. {
  816. EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
  817. EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
  818. ret = EMAC_LINK_10F;
  819. }
  820. else
  821. {
  822. EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
  823. EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
  824. ret = EMAC_LINK_10H;
  825. }
  826. }
  827. return ret;
  828. }
  829. /**
  830. * @brief Fill a MAC address to list and enable.
  831. * @param A MAC address
  832. * @return The CAM index
  833. * @retval -1 Failed to fill the MAC address.
  834. * @retval 0~(EMAC_CAMENTRY_NB-1) The index number of entry location.
  835. */
  836. int32_t EMAC_FillCamEntry(uint8_t pu8MacAddr[])
  837. {
  838. uint32_t *EMAC_CAMxM;
  839. uint32_t *EMAC_CAMxL;
  840. int32_t index;
  841. uint8_t mac[6];
  842. for (index = 0; index < EMAC_CAMENTRY_NB; index ++)
  843. {
  844. EMAC_CAMxM = (uint32_t *)((uint32_t)&EMAC->CAM0M + (index * 8));
  845. EMAC_CAMxL = (uint32_t *)((uint32_t)&EMAC->CAM0L + (index * 8));
  846. mac[0] = (*EMAC_CAMxM >> 24) & 0xff;
  847. mac[1] = (*EMAC_CAMxM >> 16) & 0xff;
  848. mac[2] = (*EMAC_CAMxM >> 8) & 0xff;
  849. mac[3] = (*EMAC_CAMxM) & 0xff;
  850. mac[4] = (*EMAC_CAMxL >> 24) & 0xff;
  851. mac[5] = (*EMAC_CAMxL >> 16) & 0xff;
  852. if (memcmp(mac, pu8MacAddr, sizeof(mac)) == 0)
  853. {
  854. goto exit_emac_fillcamentry;
  855. }
  856. if (*EMAC_CAMxM == 0 && *EMAC_CAMxL == 0)
  857. {
  858. break;
  859. }
  860. }
  861. if (index < EMAC_CAMENTRY_NB)
  862. {
  863. EMAC_EnableCamEntry(index, pu8MacAddr);
  864. goto exit_emac_fillcamentry;
  865. }
  866. return -1;
  867. exit_emac_fillcamentry:
  868. return index;
  869. }
  870. /**
  871. * @brief Send an Ethernet packet
  872. * @param[in] u32Size Packet size (without 4 byte CRC).
  873. * @return Packet transmit success or not
  874. * @retval 0 Transmit failed due to descriptor unavailable.
  875. * @retval 1 Triggered to transmit.
  876. * @note Return 1 doesn't guarantee the packet will be sent and received successfully.
  877. */
  878. uint32_t EMAC_SendPktWoCopy(uint32_t u32Size)
  879. {
  880. EMAC_DESCRIPTOR_T *desc;
  881. uint32_t status;
  882. uint32_t ret = 0UL;
  883. /* Get Tx frame descriptor & data pointer */
  884. desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
  885. status = desc->u32Status1;
  886. /* Check descriptor ownership */
  887. if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
  888. {
  889. /* Set Tx descriptor transmit byte count */
  890. desc->u32Status2 = u32Size;
  891. /* Change descriptor ownership to EMAC */
  892. desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
  893. /* Get next Tx descriptor */
  894. u32NextTxDesc = (uint32_t)(desc->u32Next);
  895. /* Trigger EMAC to send the packet */
  896. EMAC_TRIGGER_TX();
  897. ret = 1UL;
  898. }
  899. return (ret);
  900. }
  901. /**
  902. * @brief Get avaiable TX buffer address
  903. * @param None
  904. * @return An avaiable TX buffer.
  905. * @note This API should be called before EMAC_SendPkt_WoCopy calling. Caller will do data-copy.
  906. */
  907. uint8_t *EMAC_ClaimFreeTXBuf(void)
  908. {
  909. EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
  910. if (desc->u32Status1 & EMAC_DESC_OWN_EMAC)
  911. {
  912. return (NULL);
  913. }
  914. else
  915. {
  916. return (uint8_t *)desc->u32Data;
  917. }
  918. }
  919. /**
  920. * @brief Get data length of avaiable RX buffer.
  921. * @param None
  922. * @return An data length of avaiable RX buffer.
  923. * @note This API should be called before EMAC_RecvPktDone_WoTrigger calling. Caller will do data-copy.
  924. */
  925. uint32_t EMAC_GetAvailRXBufSize(uint8_t **ppuDataBuf)
  926. {
  927. EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
  928. if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */
  929. {
  930. uint32_t status = desc->u32Status1 >> 16;
  931. /* It is good and no CRC error. */
  932. if ((status & EMAC_RXFD_RXGD) && !(status & EMAC_RXFD_CRCE))
  933. {
  934. *ppuDataBuf = (uint8_t *)desc->u32Backup1;
  935. return desc->u32Status1 & 0xFFFFUL;
  936. }
  937. else
  938. {
  939. // Drop it
  940. EMAC_RecvPktDone();
  941. }
  942. }
  943. return 0;
  944. }
  945. /**
  946. * @brief Clean up process after a packet is received.
  947. * @param None
  948. * @return None
  949. * @details Caller must call the function to release the resource.
  950. * @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1
  951. * @note This function is without doing EMAC_TRIGGER_RX.
  952. */
  953. void EMAC_RecvPktDoneWoRxTrigger(void)
  954. {
  955. EMAC_DESCRIPTOR_T *desc;
  956. /* Get Rx Frame Descriptor */
  957. desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
  958. /* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
  959. desc->u32Data = desc->u32Backup1;
  960. desc->u32Next = desc->u32Backup2;
  961. /* Change ownership to DMA for next use */
  962. desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
  963. /* Get Next Frame Descriptor pointer to process */
  964. desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
  965. /* Save last processed Rx descriptor */
  966. u32CurrentRxDesc = (uint32_t)desc;
  967. }
  968. /*@}*/ /* end of group EMAC_EXPORTED_FUNCTIONS */
  969. /*@}*/ /* end of group EMAC_Driver */
  970. /*@}*/ /* end of group Standard_Driver */
  971. /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/