M480 BSP  V3.05.001
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 
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 */
30 /* PHY Register Description */
31 #define PHY_CNTL_REG 0x00UL
32 #define PHY_STATUS_REG 0x01UL
33 #define PHY_ID1_REG 0x02UL
34 #define PHY_ID2_REG 0x03UL
35 #define PHY_ANA_REG 0x04UL
36 #define PHY_ANLPA_REG 0x05UL
37 #define PHY_ANE_REG 0x06UL
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
66 #define EMAC_DESC_OWN_CPU 0x00000000UL
68 /* Rx Frame Descriptor Status */
69 #define EMAC_RXFD_RTSAS 0x0080UL
70 #define EMAC_RXFD_RP 0x0040UL
71 #define EMAC_RXFD_ALIE 0x0020UL
72 #define EMAC_RXFD_RXGD 0x0010UL
73 #define EMAC_RXFD_PTLE 0x0008UL
74 #define EMAC_RXFD_CRCE 0x0002UL
75 #define EMAC_RXFD_RXINTR 0x0001UL
77 /* Tx Frame Descriptor's Control bits */
78 #define EMAC_TXFD_TTSEN 0x08UL
79 #define EMAC_TXFD_INTEN 0x04UL
80 #define EMAC_TXFD_CRCAPP 0x02UL
81 #define EMAC_TXFD_PADEN 0x01UL
83 /* Tx Frame Descriptor Status */
84 #define EMAC_TXFD_TXINTR 0x0001UL
85 #define EMAC_TXFD_DEF 0x0002UL
86 #define EMAC_TXFD_TXCP 0x0008UL
87 #define EMAC_TXFD_EXDEF 0x0010UL
88 #define EMAC_TXFD_NCS 0x0020UL
89 #define EMAC_TXFD_TXABT 0x0040UL
90 #define EMAC_TXFD_LC 0x0080UL
91 #define EMAC_TXFD_TXHA 0x0100UL
92 #define EMAC_TXFD_PAU 0x0200UL
93 #define EMAC_TXFD_SQE 0x0400UL
94 #define EMAC_TXFD_TTSAS 0x0800UL
96  /* end of group EMAC_EXPORTED_CONSTANTS */
97 
103 typedef struct
104 {
105  uint32_t u32Status1;
106  uint32_t u32Data;
107  uint32_t u32Status2;
108  uint32_t u32Next;
109  uint32_t u32Backup1;
110  uint32_t u32Backup2;
111 } EMAC_DESCRIPTOR_T;
112 
114 typedef struct
115 {
116  uint8_t au8Buf[EMAC_MAX_PKT_SIZE];
117 } EMAC_FRAME_T;
118  /* 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 
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 
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 
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 
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 
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 
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 
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  /* end of group EMAC_EXPORTED_FUNCTIONS */
361 
362 
363 
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 |
400 
401  /* Configure the MAC control register. */
402  EMAC->CTL = EMAC_CTL_STRIPCRC_Msk |
404 
405  /* Accept packets for us and all broadcast and multicast packets */
406  EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
409 
410  /* Limit the max receive frame length to 1514 + 4 */
411  EMAC->MRFL = EMAC_MAX_PKT_SIZE;
412 }
413 
420 void EMAC_Close(void)
421 {
422  EMAC->CTL |= EMAC_CTL_RST_Msk;
423 
424  while (EMAC->CTL & EMAC_CTL_RST_Msk) {}
425 }
426 
432 void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
433 {
434  EMAC_EnableCamEntry(0UL, pu8MacAddr);
435 
436 }
437 
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 
468 void EMAC_DisableCamEntry(uint32_t u32Entry)
469 {
470  EMAC->CAMEN &= ~(1UL << u32Entry);
471 }
472 
473 
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 
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 
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 
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 
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 
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 
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;
865 }
866 
872 void EMAC_DisableTS(void)
873 {
874  EMAC->TSCTL = 0UL;
875 }
876 
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 
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);
903 
904 }
905 
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 
927 {
928 
929  EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
930 
931 }
932 
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 
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 
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 
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 
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 
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 
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  /* end of group EMAC_EXPORTED_FUNCTIONS */
1172  /* end of group EMAC_Driver */
1174  /* end of group Standard_Driver */
1176 
1177 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
#define EMAC_INTEN_TSALMIEN_Msk
Definition: emac_reg.h:3612
int32_t EMAC_FillCamEntry(uint8_t pu8MacAddr[])
Fill a MAC address to list and enable.
Definition: emac.c:1011
void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
Set current time stamp.
Definition: emac.c:896
#define EMAC
Definition: M480.h:390
#define BIT31
Bit 31 mask of an 32 bit integer.
Definition: M480.h:645
#define EMAC_MIIMCTL_WRITE_Msk
Definition: emac_reg.h:3513
void EMAC_PhyInit(void)
#define EMAC_TX_DESC_SIZE
Definition: emac.h:33
void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
Set the device MAC address.
Definition: emac.c:432
#define EMAC_MIIMCTL_BUSY_Msk
Definition: emac_reg.h:3516
void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
Get current time stamp.
Definition: emac.c:883
#define EMAC_LINK_DOWN
Definition: emac.h:37
#define EMAC_CAMCTL_AMP_Msk
Definition: emac_reg.h:3156
#define EMAC_INTEN_RXBEIEN_Msk
Definition: emac_reg.h:3576
#define EMAC_LINK_10H
Definition: emac.h:41
void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
Enable alarm function and set alarm time.
Definition: emac.c:912
void EMAC_DisableTS(void)
Disable IEEE1588 time stamp function.
Definition: emac.c:872
#define EMAC_CTL_STRIPCRC_Msk
Definition: emac_reg.h:3471
NuMicro peripheral access layer header file.
#define EMAC_CTL_OPMODE_Msk
Definition: emac_reg.h:3495
#define EMAC_PHY_ADDR
Definition: emac.h:31
#define EMAC_CAMCTL_ABP_Msk
Definition: emac_reg.h:3159
#define EMAC_TSCTL_TSEN_Msk
Definition: emac_reg.h:3735
#define EMAC_INTEN_TXBEIEN_Msk
Definition: emac_reg.h:3609
void EMAC_DisableAlarm(void)
Disable alarm function.
Definition: emac.c:926
#define EMAC_INTEN_TXIEN_Msk
Definition: emac_reg.h:3585
void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
Enable IEEE1588 time stamp function and set current time.
Definition: emac.c:844
void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[])
Fill a CAM entry for MAC address comparison.
Definition: emac.c:444
#define EMAC_RX_DESC_SIZE
Definition: emac.h:32
uint32_t EMAC_CheckLinkStatus(void)
Check Ethernet link status.
Definition: emac.c:965
#define EMAC_INTEN_RXGDIEN_Msk
Definition: emac_reg.h:3555
#define EMAC_TSCTL_TSMODE_Msk
Definition: emac_reg.h:3741
#define EMAC_CAMENTRY_NB
Definition: emac.h:34
#define EMAC_INTEN_TXCPIEN_Msk
Definition: emac_reg.h:3591
uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
Receive an Ethernet packet.
Definition: emac.c:483
#define EMAC_LINK_100F
Definition: emac.h:38
#define EMAC_INTEN_RXIEN_Msk
Definition: emac_reg.h:3543
#define EMAC_TRIGGER_TX()
Trigger EMAC Tx function.
Definition: emac.h:163
uint32_t EMAC_SendPktDone(void)
Clean up process after packet(s) are sent.
Definition: emac.c:686
void EMAC_Close(void)
This function stop all receive and transmit activity and disable MAC interface.
Definition: emac.c:420
void EMAC_DisableCamEntry(uint32_t u32Entry)
Disable a specified CAM entry.
Definition: emac.c:468
void EMAC_Open(uint8_t *pu8MacAddr)
Initialize EMAC interface, including descriptors, MAC address, and PHY.
Definition: emac.c:381
#define EMAC_LINK_10F
Definition: emac.h:40
void EMAC_RecvPktDone(void)
Clean up process after a packet is received.
Definition: emac.c:614
#define EMAC_TSCTL_TSUPDATE_Msk
Definition: emac_reg.h:3744
#define EMAC_INTSTS_TXBEIF_Msk
Definition: emac_reg.h:3681
void EMAC_RecvPktDoneWoRxTrigger(void)
Clean up process after a packet is received.
Definition: emac.c:1150
void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
Add a offset to current time.
Definition: emac.c:940
uint32_t EMAC_SendPktWoCopy(uint32_t u32Size)
Send an Ethernet packet.
Definition: emac.c:1062
#define EMAC_MAX_PKT_SIZE
Definition: emac.h:35
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:769
#define EMAC_CTL_RMIIEN_Msk
Definition: emac_reg.h:3498
#define EMAC_INTEN_RDUIEN_Msk
Definition: emac_reg.h:3573
#define EMAC_CTL_FUDUP_Msk
Definition: emac_reg.h:3489
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
Definition: clk.c:244
#define EMAC_INTSTS_TSALMIF_Msk
Definition: emac_reg.h:3684
uint32_t EMAC_GetAvailRXBufSize(void)
Get data length of avaiable RX buffer.
Definition: emac.c:1118
#define EMAC_INTSTS_RXBEIF_Msk
Definition: emac_reg.h:3648
#define EMAC_MIIMCTL_PHYADDR_Pos
Definition: emac_reg.h:3509
#define NULL
NULL pointer.
Definition: M480.h:604
#define EMAC_TRIGGER_RX()
Trigger EMAC Rx function.
Definition: emac.h:156
#define EMAC_INTEN_WOLIEN_Msk
Definition: emac_reg.h:3582
uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
Send an Ethernet packet.
Definition: emac.c:646
#define EMAC_CTL_RST_Msk
Definition: emac_reg.h:3501
#define EMAC_CAMCTL_CMPEN_Msk
Definition: emac_reg.h:3165
#define EMAC_TSCTL_TSIEN_Msk
Definition: emac_reg.h:3738
#define EMAC_LINK_100H
Definition: emac.h:39
#define EMAC_MIIMCTL_MDCON_Msk
Definition: emac_reg.h:3522
#define EMAC_TSCTL_TSALMEN_Msk
Definition: emac_reg.h:3747
uint8_t * EMAC_ClaimFreeTXBuf(void)
Get avaiable TX buffer address.
Definition: emac.c:1098
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:548