nu_emac.c 36 KB

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