| NUC472_NUC442_BSP V3.03.003 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
111 typedef 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
122 typedef struct
123{
124 uint8_t au8Buf[1520];
125} EMAC_FRAME_T;
126 /* end of group NUC472_442_EMAC_EXPORTED_TYPEDEF */
128
129// local variables
130 static volatile EMAC_DESCRIPTOR_T rx_desc[EMAC_RX_DESC_SIZE];
131 static volatile EMAC_FRAME_T rx_buf[EMAC_RX_DESC_SIZE];
132 static volatile EMAC_DESCRIPTOR_T tx_desc[EMAC_TX_DESC_SIZE];
133 static volatile EMAC_FRAME_T tx_buf[EMAC_TX_DESC_SIZE];
134
135
136 static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc;
137 static 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
164 static 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
187 static 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
311 static 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
343 static 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
369 static 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
383 static 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 if (status & EMAC_RXFD_ALIE);
559 if (status & EMAC_RXFD_PTLE);
560 if (status & EMAC_RXFD_CRCE);
561 }
562 }
563 }
564 return(u32Count);
565}
566
581uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
582{
583 EMAC_DESCRIPTOR_T *desc;
584 uint32_t status, reg;
585 uint32_t u32Count = 0;
586
587 // Clear Rx interrupt flags
588 reg = EMAC->INTSTS;
589 EMAC->INTSTS = reg & 0xFFFF; // Clear all Rx related interrupt status
590
591 if (reg & EMAC_INTSTS_RXBEIF_Msk)
592 {
593 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
594 printf("RX bus error\n");
595 return (uint32_t)EMAC_BUS_ERR;
596 }
597 else
598 {
599
600 // Get Rx Frame Descriptor
601 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
602
603 // If we reach last recv Rx descriptor, leave the loop
604 if(EMAC->CRXDSA == (uint32_t)desc)
605 return(0);
606 if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) // ownership=CPU
607 {
608
609 status = desc->u32Status1 >> 16;
610
611 // If Rx frame is good, process received frame
612 if(status & EMAC_RXFD_RXGD)
613 {
614 // lower 16 bit in descriptor status1 stores the Rx packet length
615 *pu32Size = desc->u32Status1 & 0xffff;
616 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
617
618 *pu32Sec = desc->u32Next; // second stores in descriptor's NEXT field
619 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); // Sub nano second store in DATA field
620
621 u32Count = 1;
622 }
623 else
624 {
625 // Save Error status if necessary
626 if (status & EMAC_RXFD_RP);
627 if (status & EMAC_RXFD_ALIE);
628 if (status & EMAC_RXFD_PTLE);
629 if (status & EMAC_RXFD_CRCE);
630 }
631 }
632 }
633 return(u32Count);
634}
635
643 void EMAC_RecvPktDone(void)
644{
645 EMAC_DESCRIPTOR_T *desc;
646 // Get Rx Frame Descriptor
647 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
648
649 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
650 desc->u32Data = desc->u32Backup1;
651 desc->u32Next = desc->u32Backup2;
652
653 // Change ownership to DMA for next use
654 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
655
656 // Get Next Frame Descriptor pointer to process
657 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
658
659 // Save last processed Rx descriptor
660 u32CurrentRxDesc = (uint32_t)desc;
661
662 EMAC_TRIGGER_RX();
663}
664
665// Transmit functions
666
676uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
677{
678 EMAC_DESCRIPTOR_T *desc;
679 uint32_t status;
680
681 // Get Tx frame descriptor & data pointer
682 desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
683
684 status = desc->u32Status1;
685
686 // Check descriptor ownership
687 if((status & EMAC_DESC_OWN_EMAC))
688 return(0);
689
690 memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size);
691
692 // Set Tx descriptor transmit byte count
693 desc->u32Status2 = u32Size;
694
695 // Change descriptor ownership to EMAC
696 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
697
698 // Get next Tx descriptor
699 u32NextTxDesc = (uint32_t)(desc->u32Next);
700
701 // Trigger EMAC to send the packet
702 EMAC_TRIGGER_TX();
703
704 return(1);
705}
706
707
717uint32_t EMAC_SendPktDone(void)
718{
719 EMAC_DESCRIPTOR_T *desc;
720 uint32_t status, reg;
721 uint32_t last_tx_desc;
722 uint32_t u32Count = 0;
723
724 reg = EMAC->INTSTS;
725 // Clear Tx interrupt flags
726 EMAC->INTSTS = reg & (0xFFFF0000 & ~EMAC_INTSTS_TSALMIF_Msk);
727
728
729 if (reg & EMAC_INTSTS_TXBEIF_Msk)
730 {
731 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
732 printf("TX bus error\n");
733 return (uint32_t)EMAC_BUS_ERR;
734 }
735 else
736 {
737 // Process the descriptor(s).
738 last_tx_desc = EMAC->CTXDSA ;
739 // Get our first descriptor to process
740 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
741 do
742 {
743 // Descriptor ownership is still EMAC, so this packet haven't been send.
744 if(desc->u32Status1 & EMAC_DESC_OWN_EMAC)
745 break;
746 // Get Tx status stored in descriptor
747 status = desc->u32Status2 >> 16;
748 if (status & EMAC_TXFD_TXCP)
749 {
750 u32Count++;
751 }
752 else
753 {
754 // Do nothing here on error.
755 if (status & EMAC_TXFD_TXABT);
756 if (status & EMAC_TXFD_DEF);
757 if (status & EMAC_TXFD_PAU);
758 if (status & EMAC_TXFD_EXDEF);
759 if (status & EMAC_TXFD_NCS);
760 if (status & EMAC_TXFD_SQE);
761 if (status & EMAC_TXFD_LC);
762 if (status & EMAC_TXFD_TXHA);
763 }
764
765 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
766 desc->u32Data = desc->u32Backup1;
767 desc->u32Next = desc->u32Backup2;
768 // go to next descriptor in link
769 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
770 }
771 while (last_tx_desc != (uint32_t)desc); // If we reach last sent Tx descriptor, leave the loop
772 // Save last processed Tx descriptor
773 u32CurrentTxDesc = (uint32_t)desc;
774 }
775 return(u32Count);
776}
777
789uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec)
790{
791
792 EMAC_DESCRIPTOR_T *desc;
793 uint32_t status, reg;
794 uint32_t u32Count = 0;
795
796 reg = EMAC->INTSTS;
797 // Clear Tx interrupt flags
798 EMAC->INTSTS = reg & (0xFFFF0000 & ~EMAC_INTSTS_TSALMIF_Msk);
799
800
801 if (reg & EMAC_INTSTS_TXBEIF_Msk)
802 {
803 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
804 printf("TX bus error\n");
805 return (uint32_t)EMAC_BUS_ERR;
806 }
807 else
808 {
809 // Process the descriptor.
810 // Get our first descriptor to process
811 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
812
813 // Descriptor ownership is still EMAC, so this packet haven't been send.
814 if(desc->u32Status1 & EMAC_DESC_OWN_EMAC)
815 return(0);
816 // Get Tx status stored in descriptor
817 status = desc->u32Status2 >> 16;
818 if (status & EMAC_TXFD_TXCP)
819 {
820 u32Count = 1;
821 *pu32Sec = desc->u32Next; // second stores in descriptor's NEXT field
822 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); // Sub nano second store in DATA field
823 }
824 else
825 {
826 // Do nothing here on error.
827 if (status & EMAC_TXFD_TXABT);
828 if (status & EMAC_TXFD_DEF);
829 if (status & EMAC_TXFD_PAU);
830 if (status & EMAC_TXFD_EXDEF);
831 if (status & EMAC_TXFD_NCS);
832 if (status & EMAC_TXFD_SQE);
833 if (status & EMAC_TXFD_LC);
834 if (status & EMAC_TXFD_TXHA);
835 }
836
837 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
838 desc->u32Data = desc->u32Backup1;
839 desc->u32Next = desc->u32Backup2;
840 // go to next descriptor in link
841 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
842
843 // Save last processed Tx descriptor
844 u32CurrentTxDesc = (uint32_t)desc;
845 }
846
847 return(u32Count);
848}
849
850// IEEE 1588 functions
857 void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
858{
859 double f;
860 uint32_t reg;
861 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
862 EMAC->UPDSEC = u32Sec; // Assume current time is 0 sec + 0 nano sec
863 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
864
865 // PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
866 // Assume we want to set each tick to 100ns.
867 // Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
868 // Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
869 // From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
870 // So:
871 // EMAC->TSIR = 0xD7;
872 // EMAC->TSAR = 0x1E70C600;
873 f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5;
874 EMAC->TSINC = (reg = (uint32_t)f);
875 f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg);
876 EMAC->TSADDEND = (uint32_t)f;
877 EMAC->TSCTL |= (EMAC_TSCTL_TSUPDATE_Msk | EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); // Fine update
878}
879
885 void EMAC_DisableTS(void)
886{
887 EMAC->TSCTL = 0;
888}
889
896 void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
897{
898 // Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read.
899 *pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC);
900 *pu32Sec = EMAC->TSSEC;
901}
902
909 void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
910{
911 // Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk)
912 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
913 EMAC->UPDSEC = u32Sec;
914 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
915 EMAC->TSCTL |= (EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk);
916
917}
918
925 void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
926{
927
928 EMAC->ALMSEC = u32Sec;
929 EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
930 EMAC->TSCTL |= EMAC_TSCTL_TSALMEN_Msk;
931
932}
933
939 void EMAC_DisableAlarm(void)
940{
941
942 EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
943
944}
945
953 void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
954{
955 EMAC->UPDSEC = u32Sec;
956 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
957 if(u32Neg)
958 EMAC->UPDSUBSEC |= BIT31; // Set bit 31 indicates this is a negative value
959
960 EMAC->TSCTL |= EMAC_TSCTL_TSUPDATE_Msk;
961
962}
963
964 /* end of group NUC472_442_EMAC_EXPORTED_FUNCTIONS */
966 /* end of group NUC472_442_EMAC_Driver */
968 /* end of group NUC472_442_Device_Driver */
970
971/*** (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:909
EMAC_DisableTS
void EMAC_DisableTS(void)
Disable IEEE1588 time stamp function.
Definition: emac.c:885
EMAC_DisableAlarm
void EMAC_DisableAlarm(void)
Disable alarm function.
Definition: emac.c:939
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:789
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:643
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:717
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:581
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:896
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:676
EMAC_UpdateTime
void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
Add a offset to current time.
Definition: emac.c:953
EMAC_EnableAlarm
void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
Enable alarm function and set alarm time.
Definition: emac.c:925
EMAC_EnableTS
void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
Enable IEEE1588 time stamp function and set current time.
Definition: emac.c:857
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