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