| NUC472_NUC442_BSP V3.04.000 The Board Support Package for NUC472/NUC442

emac.c
Go to the documentation of this file.
1/**************************************************************************/
12#include <stdio.h>
13#include <string.h>
14#include "NUC472_442.h"
15
24int32_t g_EMAC_i32ErrCode = 0;
26// Below are structure, definitions, static variables used locally by EMAC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined
28
32// Un-comment to print EMAC debug message
33#define EMAC_DBG
34#ifndef EMAC_DBG
35#define printf(...)
36#endif
37
38// PHY Register Description
39#define PHY_CNTL_REG 0x00
40#define PHY_STATUS_REG 0x01
41#define PHY_ID1_REG 0x02
42#define PHY_ID2_REG 0x03
43#define PHY_ANA_REG 0x04
44#define PHY_ANLPA_REG 0x05
45#define PHY_ANE_REG 0x06
46
47//PHY Control Register
48#define PHY_CNTL_RESET_PHY (1 << 15)
49#define PHY_CNTL_DR_100MB (1 << 13)
50#define PHY_CNTL_ENABLE_AN (1 << 12)
51#define PHY_CNTL_POWER_DOWN (1 << 11)
52#define PHY_CNTL_RESTART_AN (1 << 9)
53#define PHY_CNTL_FULLDUPLEX (1 << 8)
54
55// PHY Status Register
56#define PHY_STATUS_AN_COMPLETE (1 << 5)
57#define PHY_STATUS_LINK_VALID (1 << 2)
58
59// PHY Auto-negotiation Advertisement Register
60#define PHY_ANA_DR100_TX_FULL (1 << 8)
61#define PHY_ANA_DR100_TX_HALF (1 << 7)
62#define PHY_ANA_DR10_TX_FULL (1 << 6)
63#define PHY_ANA_DR10_TX_HALF (1 << 5)
64#define PHY_ANA_IEEE_802_3_CSMA_CD (1 << 0)
65
66// PHY Auto-negotiation Link Partner Advertisement Register
67#define PHY_ANLPA_DR100_TX_FULL (1 << 8)
68#define PHY_ANLPA_DR100_TX_HALF (1 << 7)
69#define PHY_ANLPA_DR10_TX_FULL (1 << 6)
70#define PHY_ANLPA_DR10_TX_HALF (1 << 5)
71
72// EMAC Tx/Rx descriptor's owner bit
73#define EMAC_DESC_OWN_EMAC 0x80000000
74#define EMAC_DESC_OWN_CPU 0x00000000
75
76// Rx Frame Descriptor Status
77#define EMAC_RXFD_RTSAS 0x0080
78#define EMAC_RXFD_RP 0x0040
79#define EMAC_RXFD_ALIE 0x0020
80#define EMAC_RXFD_RXGD 0x0010
81#define EMAC_RXFD_PTLE 0x0008
82#define EMAC_RXFD_CRCE 0x0002
83#define EMAC_RXFD_RXINTR 0x0001
84
85// Tx Frame Descriptor's Control bits
86#define EMAC_TXFD_TTSEN 0x08
87#define EMAC_TXFD_INTEN 0x04
88#define EMAC_TXFD_CRCAPP 0x02
89#define EMAC_TXFD_PADEN 0x01
90
91// Tx Frame Descriptor Status
92#define EMAC_TXFD_TXINTR 0x0001
93#define EMAC_TXFD_DEF 0x0002
94#define EMAC_TXFD_TXCP 0x0008
95#define EMAC_TXFD_EXDEF 0x0010
96#define EMAC_TXFD_NCS 0x0020
97#define EMAC_TXFD_TXABT 0x0040
98#define EMAC_TXFD_LC 0x0080
99#define EMAC_TXFD_TXHA 0x0100
100#define EMAC_TXFD_PAU 0x0200
101#define EMAC_TXFD_SQE 0x0400
102#define EMAC_TXFD_TTSAS 0x0800
103 /* end of group NUC472_442_EMAC_EXPORTED_CONSTANTS */
105
111typedef struct
112{
113 uint32_t u32Status1;
114 uint32_t u32Data;
115 uint32_t u32Status2;
116 uint32_t u32Next;
117 uint32_t u32Backup1;
118 uint32_t u32Backup2;
119} EMAC_DESCRIPTOR_T;
120
122typedef struct
123{
124 uint8_t au8Buf[1520];
125} EMAC_FRAME_T;
126 /* end of group NUC472_442_EMAC_EXPORTED_TYPEDEF */
128
129// local variables
130static volatile EMAC_DESCRIPTOR_T rx_desc[EMAC_RX_DESC_SIZE];
131static volatile EMAC_FRAME_T rx_buf[EMAC_RX_DESC_SIZE];
132static volatile EMAC_DESCRIPTOR_T tx_desc[EMAC_TX_DESC_SIZE];
133static volatile EMAC_FRAME_T tx_buf[EMAC_TX_DESC_SIZE];
134
135
136static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc;
137static uint32_t s_u32EnableTs = 0;
138
148#define EMAC_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
149
155#define EMAC_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
156
164static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data)
165{
166 // From preamble to idle is 64-bit transfer, MDC shouldn't be slower than 1MHz
167 uint32_t u32Delay = SystemCoreClock / 1000000 * 64;
168 // Set data register
169 EMAC->MIIMDAT = u32Data ;
170 // Set PHY address, PHY register address, busy bit and write bit
171 EMAC->MIIMCTL = u32Reg | (u32Addr << 8) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
172
173 // Wait write complete by polling busy bit.
174 while ((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) && (--u32Delay))
175 {
176 ;
177 }
178 g_EMAC_i32ErrCode = u32Delay > 0 ? 0 :EMAC_TIMEOUT_ERR;
179}
180
187static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr)
188{
189 // From preamble to idle is 64-bit transfer, MDC shouldn't be slower than 1MHz
190 uint32_t u32Delay = SystemCoreClock / 1000000 * 64;
191 // Set PHY address, PHY register address, busy bit
192 EMAC->MIIMCTL = u32Reg | (u32Addr << EMAC_MIIMCTL_PHYADDR_Pos) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
193 // Wait read complete by polling busy bit
194 while ((EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk) && (--u32Delay))
195 {
196 ;
197 }
198 g_EMAC_i32ErrCode = u32Delay > 0 ? 0 :EMAC_TIMEOUT_ERR;
199 // Get return data
200 return EMAC->MIIMDAT;
201}
202
203
211int32_t EMAC_PhyInit(void)
212{
213 uint32_t u32Delay;
214 uint32_t reg;
215
216 // Reset Phy Chip
217 EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY);
218
219 // Wait until reset complete
220 //Report error if the reset status is not cleared for more than 0.1 second
221 u32Delay = SystemCoreClock / 10;
222 while (--u32Delay)
223 {
224 reg = EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) ;
225 if ((reg & PHY_CNTL_RESET_PHY)==0)
226 break;
227 }
228 if(u32Delay == 0)
229 {
230 goto error;
231 }
232
233 u32Delay = SystemCoreClock; // Wait 1 second. Report error if link valid is not set
234 while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
235 {
236 if (--u32Delay == 0) /* Cable not connected */
237 {
238 goto error;
239 }
240 }
241 // Configure auto negotiation capability
242 EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL |
243 PHY_ANA_DR100_TX_HALF |
244 PHY_ANA_DR10_TX_FULL |
245 PHY_ANA_DR10_TX_HALF |
246 PHY_ANA_IEEE_802_3_CSMA_CD);
247 // Restart auto negotiation
248 EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN);
249
250 // Wait for auto-negotiation complete
251 // Report error if auto-negotiation is not complete in 2 seconds
252 u32Delay = SystemCoreClock * 2;
253 while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE))
254 {
255 if (--u32Delay == 0)
256 {
257 goto error;
258 }
259 }
260
261 // Check link valid again. Some PHYs needs to check result after link valid bit set
262 // Report error if link valid is not set after 1 second
263 u32Delay = SystemCoreClock;
264 while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
265 {
266 if (--u32Delay == 0)
267 {
268 goto error;
269 }
270 }
271
272 // Check link partner capability
273 reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
274 if (reg & PHY_ANLPA_DR100_TX_FULL)
275 {
276 printf("100F\n");
277 EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
278 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
279 }
280 else if (reg & PHY_ANLPA_DR100_TX_HALF)
281 {
282 printf("100H\n");
283 EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
284 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
285 }
286 else if (reg & PHY_ANLPA_DR10_TX_FULL)
287 {
288 printf("10F\n");
289 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
290 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
291 }
292 else
293 {
294 printf("10H\n");
295 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
296 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
297 }
298 return 0;
299
300error:
301 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
302 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
303 return EMAC_TIMEOUT_ERR;
304}
305
311static void EMAC_TxDescInit(void)
312{
313 uint32_t i;
314
315 // Get Frame descriptor's base address.
316 EMAC->TXDSA = (uint32_t)&tx_desc[0];
317 u32NextTxDesc = u32CurrentTxDesc = (uint32_t)&tx_desc[0];
318
319 for(i = 0; i < EMAC_TX_DESC_SIZE; i++)
320 {
321
322 if(s_u32EnableTs)
323 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN;
324 else
325 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN;
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 = 0;
330 tx_desc[i].u32Next = (uint32_t)&tx_desc[(i + 1) % 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=0; 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 = 0;
358 rx_desc[i].u32Next = (uint32_t)&rx_desc[(i + 1) % 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 = 1000000000ll * subsec;
374 i >>= 31;
375 return(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 = (1ll << 31) * nsec;
388 i /= 1000000000;
389 return(i);
390}
391
392 /* end of group NUC472_442_EMAC_EXPORTED_FUNCTIONS */
394
395
396
398
399
405// Basic configuration functions
417 int32_t EMAC_Open(uint8_t *pu8MacAddr)
418{
419 // Enable transmit and receive descriptor
420 EMAC_TxDescInit();
421 EMAC_RxDescInit();
422
423 // Set the CAM Control register and the MAC address value
424 EMAC_SetMacAddr(pu8MacAddr);
425
426 // Configure the MAC interrupt enable register.
427 EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
428 EMAC_INTEN_TXIEN_Msk |
429 EMAC_INTEN_RXGDIEN_Msk |
430 EMAC_INTEN_TXCPIEN_Msk |
431 EMAC_INTEN_RXBEIEN_Msk |
432 EMAC_INTEN_TXBEIEN_Msk |
433 EMAC_INTEN_RDUIEN_Msk |
434 EMAC_INTEN_TSALMIEN_Msk |
435 EMAC_INTEN_WOLIEN_Msk;
436
437 // Configure the MAC control register.
438 EMAC->CTL = EMAC_CTL_STRIPCRC_Msk |
439 EMAC_CTL_RMIIEN_Msk |
440 EMAC_CTL_RMIIRXCTL_Msk;
441
442 //Accept packets for us and all broadcast and multicast packets
443 EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
444 EMAC_CAMCTL_AMP_Msk |
445 EMAC_CAMCTL_ABP_Msk;
446
447 return (EMAC_PhyInit());
448}
449
456 void EMAC_Close(void)
457{
458 EMAC->CTL |= EMAC_CTL_RST_Msk;
459}
460
466 void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
467{
468 EMAC_EnableCamEntry(0, pu8MacAddr);
469
470}
471
478 void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t *pu8MacAddr)
479{
480 uint32_t u32Lsw, u32Msw;
481
482 u32Lsw = (pu8MacAddr[4] << 24) |
483 (pu8MacAddr[5] << 16);
484 u32Msw = (pu8MacAddr[0] << 24)|
485 (pu8MacAddr[1] << 16)|
486 (pu8MacAddr[2] << 8)|
487 pu8MacAddr[3];
488
489 *(uint32_t volatile *)(&EMAC->CAM0M + u32Entry * 2) = u32Msw;
490 *(uint32_t volatile *)(&EMAC->CAM0L + u32Entry * 2) = u32Lsw;
491
492 EMAC->CAMEN |= (1 << u32Entry);
493}
494
500 void EMAC_DisableCamEntry(uint32_t u32Entry)
501{
502 EMAC->CAMEN &= ~(1 << u32Entry);
503}
504
505// Receive functions
516 uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
517{
518 EMAC_DESCRIPTOR_T *desc;
519 uint32_t status, reg;
520 uint32_t u32Count = 0;
521
522 // Clear Rx interrupt flags
523 reg = EMAC->INTSTS;
524 EMAC->INTSTS = reg & 0xFFFF; // Clear all RX related interrupt status
525
526 if (reg & EMAC_INTSTS_RXBEIF_Msk)
527 {
528 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
529 printf("RX bus error\n");
530 return (uint32_t)EMAC_BUS_ERR;
531 }
532 else
533 {
534
535 // Get Rx Frame Descriptor
536 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
537
538 // If we reach last recv Rx descriptor, leave the loop
539 //if(EMAC->CRXDSA == (uint32_t)desc)
540 // return(0);
541 if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) // ownership=CPU
542 {
543
544 status = desc->u32Status1 >> 16;
545
546 // If Rx frame is good, process received frame
547 if(status & EMAC_RXFD_RXGD)
548 {
549 // lower 16 bit in descriptor status1 stores the Rx packet length
550 *pu32Size = desc->u32Status1 & 0xffff;
551 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
552 u32Count = 1;
553 }
554 else
555 {
556 // Save Error status if necessary
557 if (status & EMAC_RXFD_RP) {}
558
559 if (status & EMAC_RXFD_ALIE) {}
560
561 if (status & EMAC_RXFD_PTLE) {}
562
563 if (status & EMAC_RXFD_CRCE) {}
564 }
565 }
566 }
567 return(u32Count);
568}
569
584uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
585{
586 EMAC_DESCRIPTOR_T *desc;
587 uint32_t status, reg;
588 uint32_t u32Count = 0;
589
590 // Clear Rx interrupt flags
591 reg = EMAC->INTSTS;
592 EMAC->INTSTS = reg & 0xFFFF; // Clear all Rx related interrupt status
593
594 if (reg & EMAC_INTSTS_RXBEIF_Msk)
595 {
596 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
597 printf("RX bus error\n");
598 return (uint32_t)EMAC_BUS_ERR;
599 }
600 else
601 {
602
603 // Get Rx Frame Descriptor
604 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
605
606 // If we reach last recv Rx descriptor, leave the loop
607 if(EMAC->CRXDSA == (uint32_t)desc)
608 return(0);
609 if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) // ownership=CPU
610 {
611
612 status = desc->u32Status1 >> 16;
613
614 // If Rx frame is good, process received frame
615 if(status & EMAC_RXFD_RXGD)
616 {
617 // lower 16 bit in descriptor status1 stores the Rx packet length
618 *pu32Size = desc->u32Status1 & 0xffff;
619 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
620
621 *pu32Sec = desc->u32Next; // second stores in descriptor's NEXT field
622 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); // Sub nano second store in DATA field
623
624 u32Count = 1;
625 }
626 else
627 {
628 // Save Error status if necessary
629 if (status & EMAC_RXFD_RP) {}
630
631 if (status & EMAC_RXFD_ALIE) {}
632
633 if (status & EMAC_RXFD_PTLE) {}
634
635 if (status & EMAC_RXFD_CRCE) {}
636 }
637 }
638 }
639 return(u32Count);
640}
641
649 void EMAC_RecvPktDone(void)
650{
651 EMAC_DESCRIPTOR_T *desc;
652 // Get Rx Frame Descriptor
653 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
654
655 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
656 desc->u32Data = desc->u32Backup1;
657 desc->u32Next = desc->u32Backup2;
658
659 // Change ownership to DMA for next use
660 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
661
662 // Get Next Frame Descriptor pointer to process
663 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
664
665 // Save last processed Rx descriptor
666 u32CurrentRxDesc = (uint32_t)desc;
667
668 EMAC_TRIGGER_RX();
669}
670
671// Transmit functions
672
682uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
683{
684 EMAC_DESCRIPTOR_T *desc;
685 uint32_t status;
686
687 // Get Tx frame descriptor & data pointer
688 desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
689
690 status = desc->u32Status1;
691
692 // Check descriptor ownership
693 if((status & EMAC_DESC_OWN_EMAC))
694 return(0);
695
696 memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size);
697
698 // Set Tx descriptor transmit byte count
699 desc->u32Status2 = u32Size;
700
701 // Change descriptor ownership to EMAC
702 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
703
704 // Get next Tx descriptor
705 u32NextTxDesc = (uint32_t)(desc->u32Next);
706
707 // Trigger EMAC to send the packet
708 EMAC_TRIGGER_TX();
709
710 return(1);
711}
712
713
723uint32_t EMAC_SendPktDone(void)
724{
725 EMAC_DESCRIPTOR_T *desc;
726 uint32_t status, reg;
727 uint32_t last_tx_desc;
728 uint32_t u32Count = 0;
729
730 reg = EMAC->INTSTS;
731 // Clear Tx interrupt flags
732 EMAC->INTSTS = reg & (0xFFFF0000 & ~EMAC_INTSTS_TSALMIF_Msk);
733
734
735 if (reg & EMAC_INTSTS_TXBEIF_Msk)
736 {
737 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
738 printf("TX bus error\n");
739 return (uint32_t)EMAC_BUS_ERR;
740 }
741 else
742 {
743 // Process the descriptor(s).
744 last_tx_desc = EMAC->CTXDSA ;
745 // Get our first descriptor to process
746 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
747 do
748 {
749 // Descriptor ownership is still EMAC, so this packet haven't been send.
750 if(desc->u32Status1 & EMAC_DESC_OWN_EMAC)
751 break;
752 // Get Tx status stored in descriptor
753 status = desc->u32Status2 >> 16;
754 if (status & EMAC_TXFD_TXCP)
755 {
756 u32Count++;
757 }
758 else
759 {
760 // Do nothing here on error.
761 if (status & EMAC_TXFD_TXABT) {}
762
763 if (status & EMAC_TXFD_DEF) {}
764
765 if (status & EMAC_TXFD_PAU) {}
766
767 if (status & EMAC_TXFD_EXDEF) {}
768
769 if (status & EMAC_TXFD_NCS) {}
770
771 if (status & EMAC_TXFD_SQE) {}
772
773 if (status & EMAC_TXFD_LC) {}
774
775 if (status & EMAC_TXFD_TXHA) {}
776 }
777
778 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
779 desc->u32Data = desc->u32Backup1;
780 desc->u32Next = desc->u32Backup2;
781 // go to next descriptor in link
782 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
783 }
784 while (last_tx_desc != (uint32_t)desc); // If we reach last sent Tx descriptor, leave the loop
785 // Save last processed Tx descriptor
786 u32CurrentTxDesc = (uint32_t)desc;
787 }
788 return(u32Count);
789}
790
802uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec)
803{
804
805 EMAC_DESCRIPTOR_T *desc;
806 uint32_t status, reg;
807 uint32_t u32Count = 0;
808
809 reg = EMAC->INTSTS;
810 // Clear Tx interrupt flags
811 EMAC->INTSTS = reg & (0xFFFF0000 & ~EMAC_INTSTS_TSALMIF_Msk);
812
813
814 if (reg & EMAC_INTSTS_TXBEIF_Msk)
815 {
816 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
817 printf("TX bus error\n");
818 return (uint32_t)EMAC_BUS_ERR;
819 }
820 else
821 {
822 // Process the descriptor.
823 // Get our first descriptor to process
824 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
825
826 // Descriptor ownership is still EMAC, so this packet haven't been send.
827 if(desc->u32Status1 & EMAC_DESC_OWN_EMAC)
828 return(0);
829 // Get Tx status stored in descriptor
830 status = desc->u32Status2 >> 16;
831 if (status & EMAC_TXFD_TXCP)
832 {
833 u32Count = 1;
834 *pu32Sec = desc->u32Next; // second stores in descriptor's NEXT field
835 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); // Sub nano second store in DATA field
836 }
837 else
838 {
839 // Do nothing here on error.
840 if (status & EMAC_TXFD_TXABT) {}
841
842 if (status & EMAC_TXFD_DEF) {}
843
844 if (status & EMAC_TXFD_PAU) {}
845
846 if (status & EMAC_TXFD_EXDEF) {}
847
848 if (status & EMAC_TXFD_NCS) {}
849
850 if (status & EMAC_TXFD_SQE) {}
851
852 if (status & EMAC_TXFD_LC) {}
853
854 if (status & EMAC_TXFD_TXHA) {}
855 }
856
857 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
858 desc->u32Data = desc->u32Backup1;
859 desc->u32Next = desc->u32Backup2;
860 // go to next descriptor in link
861 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
862
863 // Save last processed Tx descriptor
864 u32CurrentTxDesc = (uint32_t)desc;
865 }
866
867 return(u32Count);
868}
869
870// IEEE 1588 functions
877 void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
878{
879 double f;
880 uint32_t reg;
881 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
882 EMAC->UPDSEC = u32Sec; // Assume current time is 0 sec + 0 nano sec
883 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
884
885 // PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
886 // Assume we want to set each tick to 100ns.
887 // Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
888 // Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
889 // From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
890 // So:
891 // EMAC->TSIR = 0xD7;
892 // EMAC->TSAR = 0x1E70C600;
893 f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5;
894 EMAC->TSINC = (reg = (uint32_t)f);
895 f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg);
896 EMAC->TSADDEND = (uint32_t)f;
897 EMAC->TSCTL |= (EMAC_TSCTL_TSUPDATE_Msk | EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); // Fine update
898}
899
905 void EMAC_DisableTS(void)
906{
907 EMAC->TSCTL = 0;
908}
909
916 void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
917{
918 // Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read.
919 *pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC);
920 *pu32Sec = EMAC->TSSEC;
921}
922
929 void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
930{
931 // Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk)
932 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
933 EMAC->UPDSEC = u32Sec;
934 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
935 EMAC->TSCTL |= (EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk);
936
937}
938
945 void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
946{
947
948 EMAC->ALMSEC = u32Sec;
949 EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
950 EMAC->TSCTL |= EMAC_TSCTL_TSALMEN_Msk;
951
952}
953
959 void EMAC_DisableAlarm(void)
960{
961
962 EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
963
964}
965
973 void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
974{
975 EMAC->UPDSEC = u32Sec;
976 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
977 if(u32Neg)
978 EMAC->UPDSUBSEC |= BIT31; // Set bit 31 indicates this is a negative value
979
980 EMAC->TSCTL |= EMAC_TSCTL_TSUPDATE_Msk;
981
982}
983
984 /* end of group NUC472_442_EMAC_EXPORTED_FUNCTIONS */
986 /* end of group NUC472_442_EMAC_Driver */
988 /* end of group NUC472_442_Device_Driver */
990
991/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
NUC472_442.h
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
EMAC_INTEN_RXBEIEN_Msk
#define EMAC_INTEN_RXBEIEN_Msk
Definition: NUC472_442.h:13725
EMAC_TSCTL_TSIEN_Msk
#define EMAC_TSCTL_TSIEN_Msk
Definition: NUC472_442.h:13887
EMAC_INTSTS_RXBEIF_Msk
#define EMAC_INTSTS_RXBEIF_Msk
Definition: NUC472_442.h:13797
EMAC_MIIMCTL_PHYADDR_Pos
#define EMAC_MIIMCTL_PHYADDR_Pos
Definition: NUC472_442.h:13658
EMAC_TSCTL_TSEN_Msk
#define EMAC_TSCTL_TSEN_Msk
Definition: NUC472_442.h:13884
EMAC_CTL_RST_Msk
#define EMAC_CTL_RST_Msk
Definition: NUC472_442.h:13650
EMAC_CAMCTL_AMP_Msk
#define EMAC_CAMCTL_AMP_Msk
Definition: NUC472_442.h:13260
EMAC_INTEN_TSALMIEN_Msk
#define EMAC_INTEN_TSALMIEN_Msk
Definition: NUC472_442.h:13761
EMAC_INTEN_TXCPIEN_Msk
#define EMAC_INTEN_TXCPIEN_Msk
Definition: NUC472_442.h:13740
EMAC_CTL_RMIIRXCTL_Msk
#define EMAC_CTL_RMIIRXCTL_Msk
Definition: NUC472_442.h:13641
EMAC_CTL_OPMODE_Msk
#define EMAC_CTL_OPMODE_Msk
Definition: NUC472_442.h:13644
EMAC_INTSTS_TXBEIF_Msk
#define EMAC_INTSTS_TXBEIF_Msk
Definition: NUC472_442.h:13830
EMAC_CAMCTL_ABP_Msk
#define EMAC_CAMCTL_ABP_Msk
Definition: NUC472_442.h:13263
EMAC_INTEN_TXBEIEN_Msk
#define EMAC_INTEN_TXBEIEN_Msk
Definition: NUC472_442.h:13758
EMAC_CTL_FUDUP_Msk
#define EMAC_CTL_FUDUP_Msk
Definition: NUC472_442.h:13638
EMAC_TSCTL_TSALMEN_Msk
#define EMAC_TSCTL_TSALMEN_Msk
Definition: NUC472_442.h:13896
EMAC_INTEN_RXGDIEN_Msk
#define EMAC_INTEN_RXGDIEN_Msk
Definition: NUC472_442.h:13704
EMAC_INTEN_TXIEN_Msk
#define EMAC_INTEN_TXIEN_Msk
Definition: NUC472_442.h:13734
EMAC_CAMCTL_CMPEN_Msk
#define EMAC_CAMCTL_CMPEN_Msk
Definition: NUC472_442.h:13269
EMAC_INTEN_RXIEN_Msk
#define EMAC_INTEN_RXIEN_Msk
Definition: NUC472_442.h:13692
EMAC_CTL_STRIPCRC_Msk
#define EMAC_CTL_STRIPCRC_Msk
Definition: NUC472_442.h:13620
EMAC_TSCTL_TSUPDATE_Msk
#define EMAC_TSCTL_TSUPDATE_Msk
Definition: NUC472_442.h:13893
EMAC_MIIMCTL_MDCON_Msk
#define EMAC_MIIMCTL_MDCON_Msk
Definition: NUC472_442.h:13671
EMAC_MIIMCTL_WRITE_Msk
#define EMAC_MIIMCTL_WRITE_Msk
Definition: NUC472_442.h:13662
EMAC_MIIMCTL_BUSY_Msk
#define EMAC_MIIMCTL_BUSY_Msk
Definition: NUC472_442.h:13665
EMAC_CTL_RMIIEN_Msk
#define EMAC_CTL_RMIIEN_Msk
Definition: NUC472_442.h:13647
EMAC_TSCTL_TSMODE_Msk
#define EMAC_TSCTL_TSMODE_Msk
Definition: NUC472_442.h:13890
EMAC_INTEN_WOLIEN_Msk
#define EMAC_INTEN_WOLIEN_Msk
Definition: NUC472_442.h:13731
EMAC_INTEN_RDUIEN_Msk
#define EMAC_INTEN_RDUIEN_Msk
Definition: NUC472_442.h:13722
CLK_GetHCLKFreq
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
Definition: clk.c:145
g_EMAC_i32ErrCode
int32_t g_EMAC_i32ErrCode
Definition: emac.c:24
EMAC_PHY_ADDR
#define EMAC_PHY_ADDR
PHY address, this address is board dependent.
Definition: emac.h:33
EMAC_TIMEOUT_ERR
#define EMAC_TIMEOUT_ERR
Definition: emac.h:38
EMAC_BUS_ERR
#define EMAC_BUS_ERR
Definition: emac.h:39
EMAC_RX_DESC_SIZE
#define EMAC_RX_DESC_SIZE
Number of Rx Descriptors, should be 2 at least.
Definition: emac.h:35
EMAC_TX_DESC_SIZE
#define EMAC_TX_DESC_SIZE
Number of Tx Descriptors, should be 2 at least.
Definition: emac.h:36
EMAC_SetTime
void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
Set current time stamp.
Definition: emac.c:929
EMAC_DisableTS
void EMAC_DisableTS(void)
Disable IEEE1588 time stamp function.
Definition: emac.c:905
EMAC_DisableAlarm
void EMAC_DisableAlarm(void)
Disable alarm function.
Definition: emac.c:959
EMAC_SendPktDoneTS
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:802
EMAC_Close
void EMAC_Close(void)
This function stop all receive and transmit activity and disable MAC interface.
Definition: emac.c:456
EMAC_RecvPktDone
void EMAC_RecvPktDone(void)
Clean up process after a packet is received.
Definition: emac.c:649
EMAC_EnableCamEntry
void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t *pu8MacAddr)
Fill a CAM entry for MAC address comparison.
Definition: emac.c:478
EMAC_DisableCamEntry
void EMAC_DisableCamEntry(uint32_t u32Entry)
Disable a specified CAM entry.
Definition: emac.c:500
EMAC_SendPktDone
uint32_t EMAC_SendPktDone(void)
Clean up process after packet(s) are sent.
Definition: emac.c:723
EMAC_SetMacAddr
void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
Set the device MAC address.
Definition: emac.c:466
EMAC_RecvPktTS
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:584
EMAC_Open
int32_t EMAC_Open(uint8_t *pu8MacAddr)
Initialize EMAC interface, including descriptors, MAC address, and PHY.
Definition: emac.c:417
EMAC_GetTime
void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
Get current time stamp.
Definition: emac.c:916
EMAC_RecvPkt
uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
Receive an Ethernet packet.
Definition: emac.c:516
EMAC_SendPkt
uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
Send an Ethernet packet.
Definition: emac.c:682
EMAC_UpdateTime
void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
Add a offset to current time.
Definition: emac.c:973
EMAC_EnableAlarm
void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
Enable alarm function and set alarm time.
Definition: emac.c:945
EMAC_EnableTS
void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
Enable IEEE1588 time stamp function and set current time.
Definition: emac.c:877
EMAC
#define EMAC
Definition: NUC472_442.h:28819
BIT31
#define BIT31
Bit 31 mask of an 32 bit integer.
Definition: NUC472_442.h:29059
SystemCoreClock
uint32_t SystemCoreClock
Definition: system_NUC472_442.c:17