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
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)
49#define PHY_STATUS_AN_COMPLETE (1UL << 5UL)
50#define PHY_STATUS_LINK_VALID (1UL << 2UL)
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)
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)
66#define EMAC_DESC_OWN_EMAC 0x80000000UL
67#define EMAC_DESC_OWN_CPU 0x00000000UL
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
79#define EMAC_TXFD_TTSEN 0x08UL
80#define EMAC_TXFD_INTEN 0x04UL
81#define EMAC_TXFD_CRCAPP 0x02UL
82#define EMAC_TXFD_PADEN 0x01UL
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
129static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc;
130static uint32_t s_u32EnableTs = 0UL;
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);
153static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data)
158 EMAC->MIIMDAT = u32Data ;
178static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr)
193 return EMAC->MIIMDAT;
211 EMAC_MdioWrite(PHY_CNTL_REG,
EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY);
220 if ((u32Reg & PHY_CNTL_RESET_PHY) == 0UL)
231 while (!(EMAC_MdioRead(PHY_STATUS_REG,
EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
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);
251 while (!(EMAC_MdioRead(PHY_STATUS_REG,
EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE))
263 while (!(EMAC_MdioRead(PHY_STATUS_REG,
EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID))
274 if (u32Reg & PHY_ANLPA_DR100_TX_FULL)
279 else if (u32Reg & PHY_ANLPA_DR100_TX_HALF)
282 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
284 else if (u32Reg & PHY_ANLPA_DR10_TX_FULL)
286 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
291 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
292 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
297 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
298 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
307static void EMAC_TxDescInit(
void)
312 EMAC->TXDSA = (uint32_t)&tx_desc[0];
313 u32NextTxDesc = u32CurrentTxDesc = (uint32_t)&tx_desc[0];
320 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN;
324 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN;
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;
331 tx_desc[i].u32Backup2 = tx_desc[i].u32Next;
343static void EMAC_RxDescInit(
void)
349 EMAC->RXDSA = (uint32_t)&rx_desc[0];
350 u32CurrentRxDesc = (uint32_t)&rx_desc[0];
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;
359 rx_desc[i].u32Backup2 = rx_desc[i].u32Next;
369static uint32_t EMAC_Subsec2Nsec(uint32_t subsec)
373 i = 1000000000ull * (uint64_t)subsec;
375 return ((uint32_t)i);
383static uint32_t EMAC_Nsec2Subsec(uint32_t nsec)
387 i = (1ull << 31) * nsec;
389 return ((uint32_t)i);
458 uint32_t u32Delay = 10;
487 uint32_t u32Lsw, u32Msw;
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]);
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;
501 EMAC->CAMEN |= (1UL << u32Entry);
511 EMAC->CAMEN &= ~(1UL << u32Entry);
527 EMAC_DESCRIPTOR_T *desc;
528 uint32_t status, reg;
529 uint32_t u32Count = 0UL;
533 EMAC->INTSTS = reg & 0xFFFFUL;
544 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
547 if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
550 status = desc->u32Status1 >> 16;
553 if (status & EMAC_RXFD_RXGD)
556 *pu32Size = desc->u32Status1 & 0xFFFFUL;
557 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
563 if (status & EMAC_RXFD_RP) {}
565 if (status & EMAC_RXFD_ALIE) {}
567 if (status & EMAC_RXFD_PTLE) {}
569 if (status & EMAC_RXFD_CRCE) {}
591uint32_t
EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
593 EMAC_DESCRIPTOR_T *desc;
594 uint32_t status, reg;
595 uint32_t u32Count = 0UL;
599 EMAC->INTSTS = reg & 0xFFFFUL;
610 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
613 if (
EMAC->CRXDSA != (uint32_t)desc)
615 if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
618 status = desc->u32Status1 >> 16;
621 if (status & EMAC_RXFD_RXGD)
624 *pu32Size = desc->u32Status1 & 0xFFFFUL;
625 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
627 *pu32Sec = desc->u32Next;
628 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data);
635 if (status & EMAC_RXFD_RP) {}
637 if (status & EMAC_RXFD_ALIE) {}
639 if (status & EMAC_RXFD_PTLE) {}
641 if (status & EMAC_RXFD_CRCE) {}
659 EMAC_DESCRIPTOR_T *desc;
661 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
664 desc->u32Data = desc->u32Backup1;
665 desc->u32Next = desc->u32Backup2;
668 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
671 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
674 u32CurrentRxDesc = (uint32_t)desc;
691 EMAC_DESCRIPTOR_T *desc;
695 desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
697 status = desc->u32Status1;
700 if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
702 memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size);
705 desc->u32Status2 = u32Size;
708 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
711 u32NextTxDesc = (uint32_t)(desc->u32Next);
733 EMAC_DESCRIPTOR_T *desc;
734 uint32_t status, reg;
735 uint32_t last_tx_desc;
736 uint32_t u32Count = 0UL;
740 EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
751 last_tx_desc =
EMAC->CTXDSA ;
753 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
758 if (desc->u32Status1 & EMAC_DESC_OWN_EMAC)
764 status = desc->u32Status2 >> 16UL;
766 if (status & EMAC_TXFD_TXCP)
773 if (status & EMAC_TXFD_TXABT) {}
775 if (status & EMAC_TXFD_DEF) {}
777 if (status & EMAC_TXFD_PAU) {}
779 if (status & EMAC_TXFD_EXDEF) {}
781 if (status & EMAC_TXFD_NCS) {}
783 if (status & EMAC_TXFD_SQE) {}
785 if (status & EMAC_TXFD_LC) {}
787 if (status & EMAC_TXFD_TXHA) {}
791 desc->u32Data = desc->u32Backup1;
792 desc->u32Next = desc->u32Backup2;
794 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
795 }
while (last_tx_desc != (uint32_t)desc);
798 u32CurrentTxDesc = (uint32_t)desc;
818 EMAC_DESCRIPTOR_T *desc;
819 uint32_t status, reg;
820 uint32_t u32Count = 0UL;
824 EMAC->INTSTS = reg & (0xFFFF0000UL & ~EMAC_INTSTS_TSALMIF_Msk);
836 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
839 if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
842 status = desc->u32Status2 >> 16UL;
844 if (status & EMAC_TXFD_TXCP)
847 *pu32Sec = desc->u32Next;
848 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data);
853 if (status & EMAC_TXFD_TXABT) {}
855 if (status & EMAC_TXFD_DEF) {}
857 if (status & EMAC_TXFD_PAU) {}
859 if (status & EMAC_TXFD_EXDEF) {}
861 if (status & EMAC_TXFD_NCS) {}
863 if (status & EMAC_TXFD_SQE) {}
865 if (status & EMAC_TXFD_LC) {}
867 if (status & EMAC_TXFD_TXHA) {}
871 desc->u32Data = desc->u32Backup1;
872 desc->u32Next = desc->u32Backup2;
874 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
877 u32CurrentTxDesc = (uint32_t)desc;
895 EMAC->UPDSEC = u32Sec;
896 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
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;
932 *pu32Nsec = EMAC_Subsec2Nsec(
EMAC->TSSUBSEC);
933 *pu32Sec =
EMAC->TSSEC;
946 EMAC->UPDSEC = u32Sec;
947 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
961 EMAC->ALMSEC = u32Sec;
962 EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
975 EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
988 EMAC->UPDSEC = u32Sec;
989 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
1016 if (EMAC_MdioRead(PHY_STATUS_REG,
EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID)
1021 if (reg & PHY_ANLPA_DR100_TX_FULL)
1027 else if (reg & PHY_ANLPA_DR100_TX_HALF)
1030 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
1033 else if (reg & PHY_ANLPA_DR10_TX_FULL)
1035 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
1041 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
1042 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
1059 uint32_t *EMAC_CAMxM;
1060 uint32_t *EMAC_CAMxL;
1066 EMAC_CAMxM = (uint32_t *)((uint32_t)&
EMAC->CAM0M + (index * 8));
1067 EMAC_CAMxL = (uint32_t *)((uint32_t)&
EMAC->CAM0L + (index * 8));
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;
1076 if (memcmp(mac, pu8MacAddr,
sizeof(mac)) == 0)
1078 goto exit_emac_fillcamentry;
1081 if (*EMAC_CAMxM == 0 && *EMAC_CAMxL == 0)
1090 goto exit_emac_fillcamentry;
1095exit_emac_fillcamentry:
1110 EMAC_DESCRIPTOR_T *desc;
1114 desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
1116 status = desc->u32Status1;
1119 if ((status & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
1122 desc->u32Status2 = u32Size;
1125 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
1128 u32NextTxDesc = (uint32_t)(desc->u32Next);
1146 EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
1148 if (desc->u32Status1 & EMAC_DESC_OWN_EMAC)
1154 return (uint8_t *)desc->u32Data;
1166 EMAC_DESCRIPTOR_T *desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
1168 if ((desc->u32Status1 & EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC)
1170 uint32_t status = desc->u32Status1 >> 16;
1173 if ((status & EMAC_RXFD_RXGD) && !(status & EMAC_RXFD_CRCE))
1175 return desc->u32Status1 & 0xFFFFUL;
1198 EMAC_DESCRIPTOR_T *desc;
1200 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
1203 desc->u32Data = desc->u32Backup1;
1204 desc->u32Next = desc->u32Backup2;
1207 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
1210 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
1213 u32CurrentRxDesc = (uint32_t)desc;
NuMicro peripheral access layer header file.
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
int32_t g_EMAC_i32ErrCode
#define EMAC_MAX_PKT_SIZE
#define EMAC_RX_DESC_SIZE
#define EMAC_TX_DESC_SIZE
uint32_t EMAC_CheckLinkStatus(void)
Check Ethernet link status.
void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
Set current time stamp.
uint32_t EMAC_GetAvailRXBufSize(void)
Get data length of avaiable RX buffer.
void EMAC_DisableTS(void)
Disable IEEE1588 time stamp function.
void EMAC_DisableAlarm(void)
Disable alarm function.
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.
uint8_t * EMAC_ClaimFreeTXBuf(void)
Get avaiable TX buffer address.
void EMAC_RecvPktDoneWoRxTrigger(void)
Clean up process after a packet is received.
void EMAC_RecvPktDone(void)
Clean up process after a packet is received.
void EMAC_DisableCamEntry(uint32_t u32Entry)
Disable a specified CAM entry.
uint32_t EMAC_SendPktDone(void)
Clean up process after packet(s) are sent.
void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
Set the device MAC address.
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.
int32_t EMAC_PhyInit(void)
void EMAC_Open(uint8_t *pu8MacAddr)
Initialize EMAC interface, including descriptors, MAC address, and PHY.
void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
Get current time stamp.
#define EMAC_TRIGGER_RX()
Trigger EMAC Rx function.
uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
Receive an Ethernet packet.
uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
Send an Ethernet packet.
int32_t EMAC_FillCamEntry(uint8_t pu8MacAddr[])
Fill a MAC address to list and enable.
void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t pu8MacAddr[])
Fill a CAM entry for MAC address comparison.
void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
Add a offset to current time.
void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
Enable alarm function and set alarm time.
int32_t EMAC_Close(void)
This function stop all receive and transmit activity and disable MAC interface.
void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
Enable IEEE1588 time stamp function and set current time.
#define EMAC_TRIGGER_TX()
Trigger EMAC Tx function.
uint32_t EMAC_SendPktWoCopy(uint32_t u32Size)
Send an Ethernet packet.
#define NULL
NULL pointer.
#define BIT31
Bit 31 mask of an 32 bit integer.
#define EMAC_INTEN_RXBEIEN_Msk
#define EMAC_TSCTL_TSIEN_Msk
#define EMAC_INTSTS_RXBEIF_Msk
#define EMAC_MIIMCTL_PHYADDR_Pos
#define EMAC_TSCTL_TSEN_Msk
#define EMAC_CAMCTL_AMP_Msk
#define EMAC_INTEN_TSALMIEN_Msk
#define EMAC_INTEN_TXCPIEN_Msk
#define EMAC_CTL_OPMODE_Msk
#define EMAC_INTSTS_TXBEIF_Msk
#define EMAC_CAMCTL_ABP_Msk
#define EMAC_INTEN_TXBEIEN_Msk
#define EMAC_CTL_FUDUP_Msk
#define EMAC_TSCTL_TSALMEN_Msk
#define EMAC_INTEN_RXGDIEN_Msk
#define EMAC_INTEN_TXIEN_Msk
#define EMAC_CAMCTL_CMPEN_Msk
#define EMAC_INTEN_RXIEN_Msk
#define EMAC_CTL_STRIPCRC_Msk
#define EMAC_TSCTL_TSUPDATE_Msk
#define EMAC_MIIMCTL_MDCON_Msk
#define EMAC_MIIMCTL_WRITE_Msk
#define EMAC_MIIMCTL_BUSY_Msk
#define EMAC_CTL_RMIIEN_Msk
#define EMAC_TSCTL_TSMODE_Msk
#define EMAC_INTEN_WOLIEN_Msk
#define EMAC_INTEN_RDUIEN_Msk