M480 BSP V3.05.005
The Board Support Package for M480 Series
emac.c
Go to the documentation of this file.
1/**************************************************************************/
9#include <stdio.h>
10#include <string.h>
11#include "NuMicro.h"
12
13
22int32_t g_EMAC_i32ErrCode = 0;
24/* Below are structure, definitions, static variables used locally by EMAC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined */
31/* PHY Register Description */
32#define PHY_CNTL_REG 0x00UL
33#define PHY_STATUS_REG 0x01UL
34#define PHY_ID1_REG 0x02UL
35#define PHY_ID2_REG 0x03UL
36#define PHY_ANA_REG 0x04UL
37#define PHY_ANLPA_REG 0x05UL
38#define PHY_ANE_REG 0x06UL
40/* PHY Control Register */
41#define PHY_CNTL_RESET_PHY (1UL << 15UL)
42#define PHY_CNTL_DR_100MB (1UL << 13UL)
43#define PHY_CNTL_ENABLE_AN (1UL << 12UL)
44#define PHY_CNTL_POWER_DOWN (1UL << 11UL)
45#define PHY_CNTL_RESTART_AN (1UL << 9UL)
46#define PHY_CNTL_FULLDUPLEX (1UL << 8UL)
47
48/* PHY Status Register */
49#define PHY_STATUS_AN_COMPLETE (1UL << 5UL)
50#define PHY_STATUS_LINK_VALID (1UL << 2UL)
51
52/* PHY Auto-negotiation Advertisement Register */
53#define PHY_ANA_DR100_TX_FULL (1UL << 8UL)
54#define PHY_ANA_DR100_TX_HALF (1UL << 7UL)
55#define PHY_ANA_DR10_TX_FULL (1UL << 6UL)
56#define PHY_ANA_DR10_TX_HALF (1UL << 5UL)
57#define PHY_ANA_IEEE_802_3_CSMA_CD (1UL << 0UL)
58
59/* PHY Auto-negotiation Link Partner Advertisement Register */
60#define PHY_ANLPA_DR100_TX_FULL (1UL << 8UL)
61#define PHY_ANLPA_DR100_TX_HALF (1UL << 7UL)
62#define PHY_ANLPA_DR10_TX_FULL (1UL << 6UL)
63#define PHY_ANLPA_DR10_TX_HALF (1UL << 5UL)
64
65/* EMAC Tx/Rx descriptor's owner bit */
66#define EMAC_DESC_OWN_EMAC 0x80000000UL
67#define EMAC_DESC_OWN_CPU 0x00000000UL
69/* Rx Frame Descriptor Status */
70#define EMAC_RXFD_RTSAS 0x0080UL
71#define EMAC_RXFD_RP 0x0040UL
72#define EMAC_RXFD_ALIE 0x0020UL
73#define EMAC_RXFD_RXGD 0x0010UL
74#define EMAC_RXFD_PTLE 0x0008UL
75#define EMAC_RXFD_CRCE 0x0002UL
76#define EMAC_RXFD_RXINTR 0x0001UL
78/* Tx Frame Descriptor's Control bits */
79#define EMAC_TXFD_TTSEN 0x08UL
80#define EMAC_TXFD_INTEN 0x04UL
81#define EMAC_TXFD_CRCAPP 0x02UL
82#define EMAC_TXFD_PADEN 0x01UL
84/* Tx Frame Descriptor Status */
85#define EMAC_TXFD_TXINTR 0x0001UL
86#define EMAC_TXFD_DEF 0x0002UL
87#define EMAC_TXFD_TXCP 0x0008UL
88#define EMAC_TXFD_EXDEF 0x0010UL
89#define EMAC_TXFD_NCS 0x0020UL
90#define EMAC_TXFD_TXABT 0x0040UL
91#define EMAC_TXFD_LC 0x0080UL
92#define EMAC_TXFD_TXHA 0x0100UL
93#define EMAC_TXFD_PAU 0x0200UL
94#define EMAC_TXFD_SQE 0x0400UL
95#define EMAC_TXFD_TTSAS 0x0800UL /* end of group EMAC_EXPORTED_CONSTANTS */
98
104typedef struct
105{
106 uint32_t u32Status1;
107 uint32_t u32Data;
108 uint32_t u32Status2;
109 uint32_t u32Next;
110 uint32_t u32Backup1;
111 uint32_t u32Backup2;
112} EMAC_DESCRIPTOR_T;
113
115typedef struct
116{
117 uint8_t au8Buf[EMAC_MAX_PKT_SIZE];
118} EMAC_FRAME_T;
119 /* end of group EMAC_EXPORTED_TYPEDEF */
121
122/* local variables */
123static volatile EMAC_DESCRIPTOR_T rx_desc[EMAC_RX_DESC_SIZE];
124static volatile EMAC_FRAME_T rx_buf[EMAC_RX_DESC_SIZE];
125static volatile EMAC_DESCRIPTOR_T tx_desc[EMAC_TX_DESC_SIZE];
126static volatile EMAC_FRAME_T tx_buf[EMAC_TX_DESC_SIZE];
127
128
129static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc;
130static uint32_t s_u32EnableTs = 0UL;
131
132static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data);
133static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr);
134static void EMAC_TxDescInit(void);
135static void EMAC_RxDescInit(void);
136static uint32_t EMAC_Subsec2Nsec(uint32_t subsec);
137static uint32_t EMAC_Nsec2Subsec(uint32_t nsec);
138
153static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data)
154{
155 /* From preamble to idle is 64-bit transfer, MDC shouldn't be slower than 1MHz */
156 uint32_t u32Delay = SystemCoreClock / 1000000 * 64;
157 /* Set data register */
158 EMAC->MIIMDAT = u32Data ;
159 /* Set PHY address, PHY register address, busy bit and write bit */
160 EMAC->MIIMCTL = u32Reg | (u32Addr << 8) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
161
162 /* Wait write complete by polling busy bit. */
163 while ((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) && (--u32Delay))
164 {
165 ;
166 }
167 g_EMAC_i32ErrCode = u32Delay > 0 ? 0 :EMAC_TIMEOUT_ERR;
168}
169
178static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr)
179{
180
181 /* From preamble to idle is 64-bit transfer, MDC shouldn't be slower than 1MHz */
182 uint32_t u32Delay = SystemCoreClock / 1000000 * 64;
183 /* Set PHY address, PHY register address, busy bit */
185
186 /* Wait read complete by polling busy bit */
187 while ((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) && (--u32Delay))
188 {
189 ;
190 }
191 g_EMAC_i32ErrCode = u32Delay > 0 ? 0 :EMAC_TIMEOUT_ERR;
192 /* Get return data */
193 return EMAC->MIIMDAT;
194}
195
203int32_t EMAC_PhyInit(void)
204{
205 uint32_t u32Reg;
206 uint32_t u32Delay;
207
209
210 /* Reset Phy Chip */
211 EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY);
212
213 /* Wait until PHY reset complete.
214 Report error if the reset status is not cleared for more than 0.1 second */
215 u32Delay = SystemCoreClock / 10;
216 while (--u32Delay)
217 {
218 u32Reg = EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) ;
219
220 if ((u32Reg & PHY_CNTL_RESET_PHY) == 0UL)
221 {
222 break;
223 }
224 }
225 if(u32Delay == 0)
226 {
227 goto error;
228 }
229
230 u32Delay = SystemCoreClock; // Wait 1 second. Report error if link valid is not set
231 while (!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
232 {
233 if (--u32Delay == 0) /* Cable not connected */
234 {
235 goto error;
236 }
237 }
238
239 /* Configure auto negotiation capability */
240 EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL |
241 PHY_ANA_DR100_TX_HALF |
242 PHY_ANA_DR10_TX_FULL |
243 PHY_ANA_DR10_TX_HALF |
244 PHY_ANA_IEEE_802_3_CSMA_CD);
245 /* Restart auto negotiation */
246 EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN);
247
248 /* Wait for auto-negotiation complete
249 Report error if auto-negotiation is not complete in 2 seconds */
250 u32Delay = SystemCoreClock * 2;
251 while (!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE))
252 {
253 if (--u32Delay == 0)
254 {
255 goto error;
256 }
257 }
258
259 /* Check link valid again. There're some PHY chips need to re-check link valid
260 bit set after auto-t-negotiation complete before check partner capability.
261 Report error if link valid is not set after 1 second */
262 u32Delay = SystemCoreClock;
263 while (!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
264 {
265 if (--u32Delay == 0)
266 {
267 goto error;
268 }
269 }
270
271 /* Check link partner capability */
272 u32Reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
273
274 if (u32Reg & PHY_ANLPA_DR100_TX_FULL)
275 {
277 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
278 }
279 else if (u32Reg & PHY_ANLPA_DR100_TX_HALF)
280 {
282 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
283 }
284 else if (u32Reg & PHY_ANLPA_DR10_TX_FULL)
285 {
286 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
287 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
288 }
289 else
290 {
291 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
292 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
293 }
294 return 0;
295
296error:
297 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
298 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
299 return EMAC_TIMEOUT_ERR;
300}
301
307static void EMAC_TxDescInit(void)
308{
309 uint32_t i;
310
311 /* Get Frame descriptor's base address. */
312 EMAC->TXDSA = (uint32_t)&tx_desc[0];
313 u32NextTxDesc = u32CurrentTxDesc = (uint32_t)&tx_desc[0];
314
315 for (i = 0UL; i < EMAC_TX_DESC_SIZE; i++)
316 {
317
318 if (s_u32EnableTs)
319 {
320 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN;
321 }
322 else
323 {
324 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN;
325 }
326
327 tx_desc[i].u32Data = (uint32_t)((uint32_t)&tx_buf[i]);
328 tx_desc[i].u32Backup1 = tx_desc[i].u32Data;
329 tx_desc[i].u32Status2 = 0UL;
330 tx_desc[i].u32Next = (uint32_t)&tx_desc[(i + 1UL) % EMAC_TX_DESC_SIZE];
331 tx_desc[i].u32Backup2 = tx_desc[i].u32Next;
332
333 }
334
335}
336
337
343static void EMAC_RxDescInit(void)
344{
345
346 uint32_t i;
347
348 /* Get Frame descriptor's base address. */
349 EMAC->RXDSA = (uint32_t)&rx_desc[0];
350 u32CurrentRxDesc = (uint32_t)&rx_desc[0];
351
352 for (i = 0UL; i < EMAC_RX_DESC_SIZE; i++)
353 {
354 rx_desc[i].u32Status1 = EMAC_DESC_OWN_EMAC;
355 rx_desc[i].u32Data = (uint32_t)((uint32_t)&rx_buf[i]);
356 rx_desc[i].u32Backup1 = rx_desc[i].u32Data;
357 rx_desc[i].u32Status2 = 0UL;
358 rx_desc[i].u32Next = (uint32_t)&rx_desc[(i + 1UL) % EMAC_RX_DESC_SIZE];
359 rx_desc[i].u32Backup2 = rx_desc[i].u32Next;
360 }
361
362}
363
369static uint32_t EMAC_Subsec2Nsec(uint32_t subsec)
370{
371 /* 2^31 subsec == 10^9 ns */
372 uint64_t i;
373 i = 1000000000ull * (uint64_t)subsec;
374 i >>= 31;
375 return ((uint32_t)i);
376}
377
383static uint32_t EMAC_Nsec2Subsec(uint32_t nsec)
384{
385 /* 10^9 ns = 2^31 subsec */
386 uint64_t i;
387 i = (1ull << 31) * nsec;
388 i /= 1000000000ull;
389 return ((uint32_t)i);
390}
391
392 /* end of group EMAC_EXPORTED_FUNCTIONS */
394
395
396
414void EMAC_Open(uint8_t *pu8MacAddr)
415{
416 /* Enable transmit and receive descriptor */
417 EMAC_TxDescInit();
418 EMAC_RxDescInit();
419
420 /* Set the CAM Control register and the MAC address value */
421 EMAC_SetMacAddr(pu8MacAddr);
422
423 /* Configure the MAC interrupt enable register. */
424 EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
433
434 /* Configure the MAC control register. */
437
438 /* Accept packets for us and all broadcast and multicast packets */
439 EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
442
443 /* Limit the max receive frame length to 1514 + 4 */
444 EMAC->MRFL = EMAC_MAX_PKT_SIZE;
445}
446
455int32_t EMAC_Close(void)
456{
457 // It takes a few ECLK for the reset bit to be auto-cleared. Add a small counter if something goes wrong.
458 uint32_t u32Delay = 10;
459 EMAC->CTL |= EMAC_CTL_RST_Msk;
460
461 while ((EMAC->CTL & EMAC_CTL_RST_Msk) && (--u32Delay))
462 {
463 ;
464 }
465 return u32Delay > 0 ? 0 : EMAC_TIMEOUT_ERR;
466}
467
473void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
474{
475 EMAC_EnableCamEntry(0UL, pu8MacAddr);
476
477}
478
485void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[])
486{
487 uint32_t u32Lsw, u32Msw;
488 uint32_t reg;
489 u32Lsw = (uint32_t)(((uint32_t)pu8MacAddr[4] << 24) |
490 ((uint32_t)pu8MacAddr[5] << 16));
491 u32Msw = (uint32_t)(((uint32_t)pu8MacAddr[0] << 24) |
492 ((uint32_t)pu8MacAddr[1] << 16) |
493 ((uint32_t)pu8MacAddr[2] << 8) |
494 (uint32_t)pu8MacAddr[3]);
495
496 reg = (uint32_t)&EMAC->CAM0M + u32Entry * 2UL * 4UL;
497 *(uint32_t volatile *)reg = u32Msw;
498 reg = (uint32_t)&EMAC->CAM0L + u32Entry * 2UL * 4UL;
499 *(uint32_t volatile *)reg = u32Lsw;
500
501 EMAC->CAMEN |= (1UL << u32Entry);
502}
503
509void EMAC_DisableCamEntry(uint32_t u32Entry)
510{
511 EMAC->CAMEN &= ~(1UL << u32Entry);
512}
513
514
525uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
526{
527 EMAC_DESCRIPTOR_T *desc;
528 uint32_t status, reg;
529 uint32_t u32Count = 0UL;
530
531 /* Clear Rx interrupt flags */
532 reg = EMAC->INTSTS;
533 EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all RX related interrupt status */
534
535 if (reg & EMAC_INTSTS_RXBEIF_Msk)
536 {
537 /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
538 return (uint32_t)EMAC_BUS_ERR;
539 }
540 else
541 {
542
543 /* Get Rx Frame Descriptor */
544 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
545
546 /* If we reach last recv Rx descriptor, leave the loop */
547 if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */
548 {
549
550 status = desc->u32Status1 >> 16;
551
552 /* If Rx frame is good, process received frame */
553 if (status & EMAC_RXFD_RXGD)
554 {
555 /* lower 16 bit in descriptor status1 stores the Rx packet length */
556 *pu32Size = desc->u32Status1 & 0xFFFFUL;
557 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
558 u32Count = 1UL;
559 }
560 else
561 {
562 /* Save Error status if necessary */
563 if (status & EMAC_RXFD_RP) {}
564
565 if (status & EMAC_RXFD_ALIE) {}
566
567 if (status & EMAC_RXFD_PTLE) {}
568
569 if (status & EMAC_RXFD_CRCE) {}
570 }
571 }
572 }
573
574 return (u32Count);
575}
576
591uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
592{
593 EMAC_DESCRIPTOR_T *desc;
594 uint32_t status, reg;
595 uint32_t u32Count = 0UL;
596
597 /* Clear Rx interrupt flags */
598 reg = EMAC->INTSTS;
599 EMAC->INTSTS = reg & 0xFFFFUL; /* Clear all Rx related interrupt status */
600
601 if (reg & EMAC_INTSTS_RXBEIF_Msk)
602 {
603 /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
604 return (uint32_t)EMAC_BUS_ERR;
605 }
606 else
607 {
608
609 /* Get Rx Frame Descriptor */
610 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
611
612 /* If we reach last recv Rx descriptor, leave the loop */
613 if (EMAC->CRXDSA != (uint32_t)desc)
614 {
615 if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */
616 {
617
618 status = desc->u32Status1 >> 16;
619
620 /* If Rx frame is good, process received frame */
621 if (status & EMAC_RXFD_RXGD)
622 {
623 /* lower 16 bit in descriptor status1 stores the Rx packet length */
624 *pu32Size = desc->u32Status1 & 0xFFFFUL;
625 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
626
627 *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */
628 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */
629
630 u32Count = 1UL;
631 }
632 else
633 {
634 /* Save Error status if necessary */
635 if (status & EMAC_RXFD_RP) {}
636
637 if (status & EMAC_RXFD_ALIE) {}
638
639 if (status & EMAC_RXFD_PTLE) {}
640
641 if (status & EMAC_RXFD_CRCE) {}
642 }
643 }
644 }
645 }
646
647 return (u32Count);
648}
649
658{
659 EMAC_DESCRIPTOR_T *desc;
660 /* Get Rx Frame Descriptor */
661 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
662
663 /* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
664 desc->u32Data = desc->u32Backup1;
665 desc->u32Next = desc->u32Backup2;
666
667 /* Change ownership to DMA for next use */
668 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
669
670 /* Get Next Frame Descriptor pointer to process */
671 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
672
673 /* Save last processed Rx descriptor */
674 u32CurrentRxDesc = (uint32_t)desc;
675
677}
678
679
689uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
690{
691 EMAC_DESCRIPTOR_T *desc;
692 uint32_t status;
693 uint32_t ret = 0UL;
694 /* Get Tx frame descriptor & data pointer */
695 desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
696
697 status = desc->u32Status1;
698
699 /* Check descriptor ownership */
700 if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
701 {
702 memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size);
703
704 /* Set Tx descriptor transmit byte count */
705 desc->u32Status2 = u32Size;
706
707 /* Change descriptor ownership to EMAC */
708 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
709
710 /* Get next Tx descriptor */
711 u32NextTxDesc = (uint32_t)(desc->u32Next);
712
713 /* Trigger EMAC to send the packet */
715 ret = 1UL;
716 }
717
718 return (ret);
719}
720
721
731uint32_t EMAC_SendPktDone(void)
732{
733 EMAC_DESCRIPTOR_T *desc;
734 uint32_t status, reg;
735 uint32_t last_tx_desc;
736 uint32_t u32Count = 0UL;
737
738 reg = EMAC->INTSTS;
739 /* Clear Tx interrupt flags */
740 EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
741
742
743 if (reg & EMAC_INTSTS_TXBEIF_Msk)
744 {
745 /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
746 return (uint32_t)EMAC_BUS_ERR;
747 }
748 else
749 {
750 /* Process the descriptor(s). */
751 last_tx_desc = EMAC->CTXDSA ;
752 /* Get our first descriptor to process */
753 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
754
755 do
756 {
757 /* Descriptor ownership is still EMAC, so this packet haven't been send. */
758 if (desc->u32Status1 & EMAC_DESC_OWN_EMAC)
759 {
760 break;
761 }
762
763 /* Get Tx status stored in descriptor */
764 status = desc->u32Status2 >> 16UL;
765
766 if (status & EMAC_TXFD_TXCP)
767 {
768 u32Count++;
769 }
770 else
771 {
772 /* Do nothing here on error. */
773 if (status & EMAC_TXFD_TXABT) {}
774
775 if (status & EMAC_TXFD_DEF) {}
776
777 if (status & EMAC_TXFD_PAU) {}
778
779 if (status & EMAC_TXFD_EXDEF) {}
780
781 if (status & EMAC_TXFD_NCS) {}
782
783 if (status & EMAC_TXFD_SQE) {}
784
785 if (status & EMAC_TXFD_LC) {}
786
787 if (status & EMAC_TXFD_TXHA) {}
788 }
789
790 /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
791 desc->u32Data = desc->u32Backup1;
792 desc->u32Next = desc->u32Backup2;
793 /* go to next descriptor in link */
794 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
795 } while (last_tx_desc != (uint32_t)desc); /* If we reach last sent Tx descriptor, leave the loop */
796
797 /* Save last processed Tx descriptor */
798 u32CurrentTxDesc = (uint32_t)desc;
799 }
800
801 return (u32Count);
802}
803
815uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec)
816{
817
818 EMAC_DESCRIPTOR_T *desc;
819 uint32_t status, reg;
820 uint32_t u32Count = 0UL;
821
822 reg = EMAC->INTSTS;
823 /* Clear Tx interrupt flags */
824 EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
825
826
827 if (reg & EMAC_INTSTS_TXBEIF_Msk)
828 {
829 /* Bus error occurred, this is usually a bad sign about software bug and will occur again... */
830 return (uint32_t)EMAC_BUS_ERR;
831 }
832 else
833 {
834 /* Process the descriptor.
835 Get our first descriptor to process */
836 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
837
838 /* Descriptor ownership is still EMAC, so this packet haven't been send. */
839 if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
840 {
841 /* Get Tx status stored in descriptor */
842 status = desc->u32Status2 >> 16UL;
843
844 if (status & EMAC_TXFD_TXCP)
845 {
846 u32Count = 1UL;
847 *pu32Sec = desc->u32Next; /* second stores in descriptor's NEXT field */
848 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); /* Sub nano second store in DATA field */
849 }
850 else
851 {
852 /* Do nothing here on error. */
853 if (status & EMAC_TXFD_TXABT) {}
854
855 if (status & EMAC_TXFD_DEF) {}
856
857 if (status & EMAC_TXFD_PAU) {}
858
859 if (status & EMAC_TXFD_EXDEF) {}
860
861 if (status & EMAC_TXFD_NCS) {}
862
863 if (status & EMAC_TXFD_SQE) {}
864
865 if (status & EMAC_TXFD_LC) {}
866
867 if (status & EMAC_TXFD_TXHA) {}
868 }
869
870 /* restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
871 desc->u32Data = desc->u32Backup1;
872 desc->u32Next = desc->u32Backup2;
873 /* go to next descriptor in link */
874 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
875
876 /* Save last processed Tx descriptor */
877 u32CurrentTxDesc = (uint32_t)desc;
878 }
879 }
880
881 return (u32Count);
882}
883
890void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
891{
892 double f;
893 uint32_t reg;
894 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
895 EMAC->UPDSEC = u32Sec; /* Assume current time is 0 sec + 0 nano sec */
896 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
897
898 /* PTP source clock is 160MHz (Real chip using PLL). Each tick is 6.25ns
899 Assume we want to set each tick to 100ns.
900 Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
901 Addend register = 2^32 * tick_freq / (160MHz), where tick_freq = (2^31 / 215) MHz
902 From above equation, addend register = 2^63 / (160M * 215) ~= 268121280 = 0xFFB34C0
903 So:
904 EMAC->TSIR = 0xD7;
905 EMAC->TSAR = 0x1E70C600; */
906 f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5;
907 EMAC->TSINC = (reg = (uint32_t)f);
908 f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg);
909 EMAC->TSADDEND = (uint32_t)f;
911}
912
919{
920 EMAC->TSCTL = 0UL;
921}
922
929void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
930{
931 /* Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read. */
932 *pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC);
933 *pu32Sec = EMAC->TSSEC;
934}
935
942void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
943{
944 /* Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk) */
945 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
946 EMAC->UPDSEC = u32Sec;
947 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
949
950}
951
958void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
959{
960
961 EMAC->ALMSEC = u32Sec;
962 EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
964
965}
966
973{
974
975 EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
976
977}
978
986void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
987{
988 EMAC->UPDSEC = u32Sec;
989 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
990
991 if (u32Neg)
992 {
993 EMAC->UPDSUBSEC |= BIT31; /* Set bit 31 indicates this is a negative value */
994 }
995
997
998}
999
1012{
1013 uint32_t reg, ret = EMAC_LINK_DOWN;
1014
1015 /* Check link valid again */
1016 if (EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)
1017 {
1018 /* Check link partner capability */
1019 reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
1020
1021 if (reg & PHY_ANLPA_DR100_TX_FULL)
1022 {
1023 EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
1024 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
1025 ret = EMAC_LINK_100F;
1026 }
1027 else if (reg & PHY_ANLPA_DR100_TX_HALF)
1028 {
1029 EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
1030 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
1031 ret = EMAC_LINK_100H;
1032 }
1033 else if (reg & PHY_ANLPA_DR10_TX_FULL)
1034 {
1035 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
1036 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
1037 ret = EMAC_LINK_10F;
1038 }
1039 else
1040 {
1041 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
1042 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
1043 ret = EMAC_LINK_10H;
1044 }
1045 }
1046
1047 return ret;
1048}
1049
1057int32_t EMAC_FillCamEntry(uint8_t pu8MacAddr[])
1058{
1059 uint32_t *EMAC_CAMxM;
1060 uint32_t *EMAC_CAMxL;
1061 int32_t index;
1062 uint8_t mac[6];
1063
1064 for (index = 0; index < EMAC_CAMENTRY_NB; index ++)
1065 {
1066 EMAC_CAMxM = (uint32_t *)((uint32_t)&EMAC->CAM0M + (index * 8));
1067 EMAC_CAMxL = (uint32_t *)((uint32_t)&EMAC->CAM0L + (index * 8));
1068
1069 mac[0] = (*EMAC_CAMxM >> 24) & 0xff;
1070 mac[1] = (*EMAC_CAMxM >> 16) & 0xff;
1071 mac[2] = (*EMAC_CAMxM >> 8) & 0xff;
1072 mac[3] = (*EMAC_CAMxM) & 0xff;
1073 mac[4] = (*EMAC_CAMxL >> 24) & 0xff;
1074 mac[5] = (*EMAC_CAMxL >> 16) & 0xff;
1075
1076 if (memcmp(mac, pu8MacAddr, sizeof(mac)) == 0)
1077 {
1078 goto exit_emac_fillcamentry;
1079 }
1080
1081 if (*EMAC_CAMxM == 0 && *EMAC_CAMxL == 0)
1082 {
1083 break;
1084 }
1085 }
1086
1087 if (index < EMAC_CAMENTRY_NB)
1088 {
1089 EMAC_EnableCamEntry(index, pu8MacAddr);
1090 goto exit_emac_fillcamentry;
1091 }
1092
1093 return -1;
1094
1095exit_emac_fillcamentry:
1096
1097 return index;
1098}
1099
1108uint32_t EMAC_SendPktWoCopy(uint32_t u32Size)
1109{
1110 EMAC_DESCRIPTOR_T *desc;
1111 uint32_t status;
1112 uint32_t ret = 0UL;
1113 /* Get Tx frame descriptor & data pointer */
1114 desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
1115
1116 status = desc->u32Status1;
1117
1118 /* Check descriptor ownership */
1119 if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
1120 {
1121 /* Set Tx descriptor transmit byte count */
1122 desc->u32Status2 = u32Size;
1123
1124 /* Change descriptor ownership to EMAC */
1125 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
1126
1127 /* Get next Tx descriptor */
1128 u32NextTxDesc = (uint32_t)(desc->u32Next);
1129
1130 /* Trigger EMAC to send the packet */
1132 ret = 1UL;
1133 }
1134
1135 return (ret);
1136}
1137
1145{
1146 EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
1147
1148 if (desc->u32Status1 & EMAC_DESC_OWN_EMAC)
1149 {
1150 return (NULL);
1151 }
1152 else
1153 {
1154 return (uint8_t *)desc->u32Data;
1155 }
1156}
1157
1165{
1166 EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
1167
1168 if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) /* ownership=CPU */
1169 {
1170 uint32_t status = desc->u32Status1 >> 16;
1171
1172 /* It is good and no CRC error. */
1173 if ((status & EMAC_RXFD_RXGD) && !(status & EMAC_RXFD_CRCE))
1174 {
1175 return desc->u32Status1 & 0xFFFFUL;
1176 }
1177 else
1178 {
1179 // Drop it
1181 }
1182 }
1183
1184 return 0;
1185}
1186
1187
1197{
1198 EMAC_DESCRIPTOR_T *desc;
1199 /* Get Rx Frame Descriptor */
1200 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
1201
1202 /* Restore descriptor link list and data pointer they will be overwrite if time stamp enabled */
1203 desc->u32Data = desc->u32Backup1;
1204 desc->u32Next = desc->u32Backup2;
1205
1206 /* Change ownership to DMA for next use */
1207 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
1208
1209 /* Get Next Frame Descriptor pointer to process */
1210 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
1211
1212 /* Save last processed Rx descriptor */
1213 u32CurrentRxDesc = (uint32_t)desc;
1214}
1215
1216 /* end of group EMAC_EXPORTED_FUNCTIONS */
1218 /* end of group EMAC_Driver */
1220 /* end of group Standard_Driver */
NuMicro peripheral access layer header file.
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
Definition: clk.c:246
int32_t g_EMAC_i32ErrCode
Definition: emac.c:22
#define EMAC_PHY_ADDR
Definition: emac.h:31
#define EMAC_TIMEOUT_ERR
Definition: emac.h:43
#define EMAC_BUS_ERR
Definition: emac.h:44
#define EMAC_LINK_100F
Definition: emac.h:38
#define EMAC_LINK_10H
Definition: emac.h:41
#define EMAC_MAX_PKT_SIZE
Definition: emac.h:35
#define EMAC_LINK_DOWN
Definition: emac.h:37
#define EMAC_RX_DESC_SIZE
Definition: emac.h:32
#define EMAC_LINK_10F
Definition: emac.h:40
#define EMAC_TX_DESC_SIZE
Definition: emac.h:33
#define EMAC_LINK_100H
Definition: emac.h:39
#define EMAC_CAMENTRY_NB
Definition: emac.h:34
uint32_t EMAC_CheckLinkStatus(void)
Check Ethernet link status.
Definition: emac.c:1011
void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
Set current time stamp.
Definition: emac.c:942
uint32_t EMAC_GetAvailRXBufSize(void)
Get data length of avaiable RX buffer.
Definition: emac.c:1164
void EMAC_DisableTS(void)
Disable IEEE1588 time stamp function.
Definition: emac.c:918
void EMAC_DisableAlarm(void)
Disable alarm function.
Definition: emac.c:972
uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec)
Clean up process after a packet is sent, and get the time stamp while packet is sent.
Definition: emac.c:815
uint8_t * EMAC_ClaimFreeTXBuf(void)
Get avaiable TX buffer address.
Definition: emac.c:1144
void EMAC_RecvPktDoneWoRxTrigger(void)
Clean up process after a packet is received.
Definition: emac.c:1196
void EMAC_RecvPktDone(void)
Clean up process after a packet is received.
Definition: emac.c:657
void EMAC_DisableCamEntry(uint32_t u32Entry)
Disable a specified CAM entry.
Definition: emac.c:509
uint32_t EMAC_SendPktDone(void)
Clean up process after packet(s) are sent.
Definition: emac.c:731
void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
Set the device MAC address.
Definition: emac.c:473
uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
Receive an Ethernet packet and the time stamp while it's received.
Definition: emac.c:591
int32_t EMAC_PhyInit(void)
void EMAC_Open(uint8_t *pu8MacAddr)
Initialize EMAC interface, including descriptors, MAC address, and PHY.
Definition: emac.c:414
void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
Get current time stamp.
Definition: emac.c:929
#define EMAC_TRIGGER_RX()
Trigger EMAC Rx function.
Definition: emac.h:160
uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
Receive an Ethernet packet.
Definition: emac.c:525
uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
Send an Ethernet packet.
Definition: emac.c:689
int32_t EMAC_FillCamEntry(uint8_t pu8MacAddr[])
Fill a MAC address to list and enable.
Definition: emac.c:1057
void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[])
Fill a CAM entry for MAC address comparison.
Definition: emac.c:485
void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
Add a offset to current time.
Definition: emac.c:986
void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
Enable alarm function and set alarm time.
Definition: emac.c:958
int32_t EMAC_Close(void)
This function stop all receive and transmit activity and disable MAC interface.
Definition: emac.c:455
void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
Enable IEEE1588 time stamp function and set current time.
Definition: emac.c:890
#define EMAC_TRIGGER_TX()
Trigger EMAC Tx function.
Definition: emac.h:167
uint32_t EMAC_SendPktWoCopy(uint32_t u32Size)
Send an Ethernet packet.
Definition: emac.c:1108
#define NULL
NULL pointer.
Definition: M480.h:605
#define BIT31
Bit 31 mask of an 32 bit integer.
Definition: M480.h:646
#define EMAC
Definition: M480.h:390
#define EMAC_INTEN_RXBEIEN_Msk
Definition: emac_reg.h:3576
#define EMAC_TSCTL_TSIEN_Msk
Definition: emac_reg.h:3738
#define EMAC_INTSTS_RXBEIF_Msk
Definition: emac_reg.h:3648
#define EMAC_MIIMCTL_PHYADDR_Pos
Definition: emac_reg.h:3509
#define EMAC_TSCTL_TSEN_Msk
Definition: emac_reg.h:3735
#define EMAC_CTL_RST_Msk
Definition: emac_reg.h:3501
#define EMAC_CAMCTL_AMP_Msk
Definition: emac_reg.h:3156
#define EMAC_INTEN_TSALMIEN_Msk
Definition: emac_reg.h:3612
#define EMAC_INTEN_TXCPIEN_Msk
Definition: emac_reg.h:3591
#define EMAC_CTL_OPMODE_Msk
Definition: emac_reg.h:3495
#define EMAC_INTSTS_TXBEIF_Msk
Definition: emac_reg.h:3681
#define EMAC_CAMCTL_ABP_Msk
Definition: emac_reg.h:3159
#define EMAC_INTEN_TXBEIEN_Msk
Definition: emac_reg.h:3609
#define EMAC_CTL_FUDUP_Msk
Definition: emac_reg.h:3489
#define EMAC_TSCTL_TSALMEN_Msk
Definition: emac_reg.h:3747
#define EMAC_INTEN_RXGDIEN_Msk
Definition: emac_reg.h:3555
#define EMAC_INTEN_TXIEN_Msk
Definition: emac_reg.h:3585
#define EMAC_CAMCTL_CMPEN_Msk
Definition: emac_reg.h:3165
#define EMAC_INTEN_RXIEN_Msk
Definition: emac_reg.h:3543
#define EMAC_CTL_STRIPCRC_Msk
Definition: emac_reg.h:3471
#define EMAC_TSCTL_TSUPDATE_Msk
Definition: emac_reg.h:3744
#define EMAC_MIIMCTL_MDCON_Msk
Definition: emac_reg.h:3522
#define EMAC_MIIMCTL_WRITE_Msk
Definition: emac_reg.h:3513
#define EMAC_MIIMCTL_BUSY_Msk
Definition: emac_reg.h:3516
#define EMAC_CTL_RMIIEN_Msk
Definition: emac_reg.h:3498
#define EMAC_TSCTL_TSMODE_Msk
Definition: emac_reg.h:3741
#define EMAC_INTEN_WOLIEN_Msk
Definition: emac_reg.h:3582
#define EMAC_INTEN_RDUIEN_Msk
Definition: emac_reg.h:3573
uint32_t SystemCoreClock
Definition: system_M480.c:21