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