mbed official / mbed-dev

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
153:fa9ff456f731
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
<> 144:ef7eb2e8f9f7 1 /**************************************************************************//**
<> 144:ef7eb2e8f9f7 2 * @file emac.c
<> 144:ef7eb2e8f9f7 3 * @version V1.00
<> 144:ef7eb2e8f9f7 4 * $Revision: 14 $
<> 144:ef7eb2e8f9f7 5 * $Date: 14/05/29 1:13p $
<> 144:ef7eb2e8f9f7 6 * @brief NUC472/NUC442 EMAC driver source file
<> 144:ef7eb2e8f9f7 7 *
<> 144:ef7eb2e8f9f7 8 * @note
<> 144:ef7eb2e8f9f7 9 * Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
<> 144:ef7eb2e8f9f7 10 *****************************************************************************/
<> 144:ef7eb2e8f9f7 11 #include <stdio.h>
<> 144:ef7eb2e8f9f7 12 #include <string.h>
<> 144:ef7eb2e8f9f7 13 #include "NUC472_442.h"
<> 144:ef7eb2e8f9f7 14
<> 144:ef7eb2e8f9f7 15 /** @addtogroup NUC472_442_Device_Driver NUC472/NUC442 Device Driver
<> 144:ef7eb2e8f9f7 16 @{
<> 144:ef7eb2e8f9f7 17 */
<> 144:ef7eb2e8f9f7 18
<> 144:ef7eb2e8f9f7 19 /** @addtogroup NUC472_442_EMAC_Driver EMAC Driver
<> 144:ef7eb2e8f9f7 20 @{
<> 144:ef7eb2e8f9f7 21 */
<> 144:ef7eb2e8f9f7 22
<> 144:ef7eb2e8f9f7 23
<> 144:ef7eb2e8f9f7 24 // Below are structure, definitions, static variables used locally by EMAC driver and does not want to parse by doxygen unless HIDDEN_SYMBOLS is defined
<> 144:ef7eb2e8f9f7 25 /// @cond HIDDEN_SYMBOLS
<> 144:ef7eb2e8f9f7 26
<> 144:ef7eb2e8f9f7 27 /** @addtogroup NUC472_442_EMAC_EXPORTED_CONSTANTS EMAC Exported Constants
<> 144:ef7eb2e8f9f7 28 @{
<> 144:ef7eb2e8f9f7 29 */
<> 144:ef7eb2e8f9f7 30 // Un-comment to print EMAC debug message
<> 144:ef7eb2e8f9f7 31 //#define EMAC_DBG
<> 144:ef7eb2e8f9f7 32 #ifndef EMAC_DBG
<> 144:ef7eb2e8f9f7 33 #define printf(...)
<> 144:ef7eb2e8f9f7 34 #endif
<> 144:ef7eb2e8f9f7 35
<> 144:ef7eb2e8f9f7 36 // PHY Register Description
<> 144:ef7eb2e8f9f7 37 #define PHY_CNTL_REG 0x00 ///< PHY control register address
<> 144:ef7eb2e8f9f7 38 #define PHY_STATUS_REG 0x01 ///< PHY status register address
<> 144:ef7eb2e8f9f7 39 #define PHY_ID1_REG 0x02 ///< PHY ID1 register
<> 144:ef7eb2e8f9f7 40 #define PHY_ID2_REG 0x03 ///< PHY ID2 register
<> 144:ef7eb2e8f9f7 41 #define PHY_ANA_REG 0x04 ///< PHY auto-negotiation advertisement register
<> 144:ef7eb2e8f9f7 42 #define PHY_ANLPA_REG 0x05 ///< PHY auto-negotiation link partner availability register
<> 144:ef7eb2e8f9f7 43 #define PHY_ANE_REG 0x06 ///< PHY auto-negotiation expansion register
<> 144:ef7eb2e8f9f7 44
<> 144:ef7eb2e8f9f7 45 //PHY Control Register
<> 144:ef7eb2e8f9f7 46 #define PHY_CNTL_RESET_PHY (1 << 15)
<> 144:ef7eb2e8f9f7 47 #define PHY_CNTL_DR_100MB (1 << 13)
<> 144:ef7eb2e8f9f7 48 #define PHY_CNTL_ENABLE_AN (1 << 12)
<> 144:ef7eb2e8f9f7 49 #define PHY_CNTL_POWER_DOWN (1 << 11)
<> 144:ef7eb2e8f9f7 50 #define PHY_CNTL_RESTART_AN (1 << 9)
<> 144:ef7eb2e8f9f7 51 #define PHY_CNTL_FULLDUPLEX (1 << 8)
<> 144:ef7eb2e8f9f7 52
<> 144:ef7eb2e8f9f7 53 // PHY Status Register
<> 144:ef7eb2e8f9f7 54 #define PHY_STATUS_AN_COMPLETE (1 << 5)
<> 144:ef7eb2e8f9f7 55 #define PHY_STATUS_LINK_VALID (1 << 3)
<> 144:ef7eb2e8f9f7 56
<> 144:ef7eb2e8f9f7 57 // PHY Auto-negotiation Advertisement Register
<> 144:ef7eb2e8f9f7 58 #define PHY_ANA_DR100_TX_FULL (1 << 8)
<> 144:ef7eb2e8f9f7 59 #define PHY_ANA_DR100_TX_HALF (1 << 7)
<> 144:ef7eb2e8f9f7 60 #define PHY_ANA_DR10_TX_FULL (1 << 6)
<> 144:ef7eb2e8f9f7 61 #define PHY_ANA_DR10_TX_HALF (1 << 5)
<> 144:ef7eb2e8f9f7 62 #define PHY_ANA_IEEE_802_3_CSMA_CD (1 << 0)
<> 144:ef7eb2e8f9f7 63
<> 144:ef7eb2e8f9f7 64 // PHY Auto-negotiation Link Partner Advertisement Register
<> 144:ef7eb2e8f9f7 65 #define PHY_ANLPA_DR100_TX_FULL (1 << 8)
<> 144:ef7eb2e8f9f7 66 #define PHY_ANLPA_DR100_TX_HALF (1 << 7)
<> 144:ef7eb2e8f9f7 67 #define PHY_ANLPA_DR10_TX_FULL (1 << 6)
<> 144:ef7eb2e8f9f7 68 #define PHY_ANLPA_DR10_TX_HALF (1 << 5)
<> 144:ef7eb2e8f9f7 69
<> 144:ef7eb2e8f9f7 70 // EMAC Tx/Rx descriptor's owner bit
<> 144:ef7eb2e8f9f7 71 #define EMAC_DESC_OWN_EMAC 0x80000000 ///< Set owner to EMAC
<> 144:ef7eb2e8f9f7 72 #define EMAC_DESC_OWN_CPU 0x00000000 ///< Set owner to CPU
<> 144:ef7eb2e8f9f7 73
<> 144:ef7eb2e8f9f7 74 // Rx Frame Descriptor Status
<> 144:ef7eb2e8f9f7 75 #define EMAC_RXFD_RTSAS 0x0080 ///< Time Stamp Available
<> 144:ef7eb2e8f9f7 76 #define EMAC_RXFD_RP 0x0040 ///< Runt Packet
<> 144:ef7eb2e8f9f7 77 #define EMAC_RXFD_ALIE 0x0020 ///< Alignment Error
<> 144:ef7eb2e8f9f7 78 #define EMAC_RXFD_RXGD 0x0010 ///< Receiving Good packet received
<> 144:ef7eb2e8f9f7 79 #define EMAC_RXFD_PTLE 0x0008 ///< Packet Too Long Error
<> 144:ef7eb2e8f9f7 80 #define EMAC_RXFD_CRCE 0x0002 ///< CRC Error
<> 144:ef7eb2e8f9f7 81 #define EMAC_RXFD_RXINTR 0x0001 ///< Interrupt on receive
<> 144:ef7eb2e8f9f7 82
<> 144:ef7eb2e8f9f7 83 // Tx Frame Descriptor's Control bits
<> 144:ef7eb2e8f9f7 84 #define EMAC_TXFD_TTSEN 0x08 ///< Tx time stamp enable
<> 144:ef7eb2e8f9f7 85 #define EMAC_TXFD_INTEN 0x04 ///< Tx interrupt enable
<> 144:ef7eb2e8f9f7 86 #define EMAC_TXFD_CRCAPP 0x02 ///< Append CRC
<> 144:ef7eb2e8f9f7 87 #define EMAC_TXFD_PADEN 0x01 ///< Padding mode enable
<> 144:ef7eb2e8f9f7 88
<> 144:ef7eb2e8f9f7 89 // Tx Frame Descriptor Status
<> 144:ef7eb2e8f9f7 90 #define EMAC_TXFD_TXINTR 0x0001 ///< Interrupt on Transmit
<> 144:ef7eb2e8f9f7 91 #define EMAC_TXFD_DEF 0x0002 ///< Transmit deferred
<> 144:ef7eb2e8f9f7 92 #define EMAC_TXFD_TXCP 0x0008 ///< Transmission Completion
<> 144:ef7eb2e8f9f7 93 #define EMAC_TXFD_EXDEF 0x0010 ///< Exceed Deferral
<> 144:ef7eb2e8f9f7 94 #define EMAC_TXFD_NCS 0x0020 ///< No Carrier Sense Error
<> 144:ef7eb2e8f9f7 95 #define EMAC_TXFD_TXABT 0x0040 ///< Transmission Abort
<> 144:ef7eb2e8f9f7 96 #define EMAC_TXFD_LC 0x0080 ///< Late Collision
<> 144:ef7eb2e8f9f7 97 #define EMAC_TXFD_TXHA 0x0100 ///< Transmission halted
<> 144:ef7eb2e8f9f7 98 #define EMAC_TXFD_PAU 0x0200 ///< Paused
<> 144:ef7eb2e8f9f7 99 #define EMAC_TXFD_SQE 0x0400 ///< SQE error
<> 144:ef7eb2e8f9f7 100 #define EMAC_TXFD_TTSAS 0x0800 ///< Time Stamp available
<> 144:ef7eb2e8f9f7 101
<> 144:ef7eb2e8f9f7 102 /*@}*/ /* end of group NUC472_442_EMAC_EXPORTED_CONSTANTS */
<> 144:ef7eb2e8f9f7 103
<> 144:ef7eb2e8f9f7 104 /** @addtogroup NUC472_442_EMAC_EXPORTED_TYPEDEF EMAC Exported Type Defines
<> 144:ef7eb2e8f9f7 105 @{
<> 144:ef7eb2e8f9f7 106 */
<> 144:ef7eb2e8f9f7 107
<> 144:ef7eb2e8f9f7 108 /** Tx/Rx buffer descriptor structure */
<> 144:ef7eb2e8f9f7 109 typedef struct {
<> 144:ef7eb2e8f9f7 110 uint32_t u32Status1; ///< Status word 1
<> 144:ef7eb2e8f9f7 111 uint32_t u32Data; ///< Pointer to data buffer
<> 144:ef7eb2e8f9f7 112 uint32_t u32Status2; ///< Status word 2
<> 144:ef7eb2e8f9f7 113 uint32_t u32Next; ///< Pointer to next descriptor
<> 144:ef7eb2e8f9f7 114 uint32_t u32Backup1; ///< For backup descriptor fields over written by time stamp
<> 144:ef7eb2e8f9f7 115 uint32_t u32Backup2; ///< For backup descriptor fields over written by time stamp
<> 144:ef7eb2e8f9f7 116 } EMAC_DESCRIPTOR_T;
<> 144:ef7eb2e8f9f7 117
<> 144:ef7eb2e8f9f7 118 /** Tx/Rx buffer structure */
<> 144:ef7eb2e8f9f7 119 typedef struct {
<> 144:ef7eb2e8f9f7 120 uint8_t au8Buf[1520];
<> 144:ef7eb2e8f9f7 121 } EMAC_FRAME_T;
<> 144:ef7eb2e8f9f7 122
<> 144:ef7eb2e8f9f7 123 /*@}*/ /* end of group NUC472_442_EMAC_EXPORTED_TYPEDEF */
<> 144:ef7eb2e8f9f7 124
<> 144:ef7eb2e8f9f7 125 // local variables
<> 144:ef7eb2e8f9f7 126 static volatile EMAC_DESCRIPTOR_T rx_desc[EMAC_RX_DESC_SIZE];
<> 144:ef7eb2e8f9f7 127 static volatile EMAC_FRAME_T rx_buf[EMAC_RX_DESC_SIZE];
<> 144:ef7eb2e8f9f7 128 static volatile EMAC_DESCRIPTOR_T tx_desc[EMAC_TX_DESC_SIZE];
<> 144:ef7eb2e8f9f7 129 static volatile EMAC_FRAME_T tx_buf[EMAC_TX_DESC_SIZE];
<> 144:ef7eb2e8f9f7 130
<> 144:ef7eb2e8f9f7 131
<> 144:ef7eb2e8f9f7 132 static uint32_t u32CurrentTxDesc, u32NextTxDesc, u32CurrentRxDesc;
<> 144:ef7eb2e8f9f7 133 static uint32_t s_u32EnableTs = 0;
<> 144:ef7eb2e8f9f7 134
<> 144:ef7eb2e8f9f7 135 /** @addtogroup NUC472_442_EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions
<> 144:ef7eb2e8f9f7 136 @{
<> 144:ef7eb2e8f9f7 137 */
<> 144:ef7eb2e8f9f7 138
<> 144:ef7eb2e8f9f7 139 /**
<> 144:ef7eb2e8f9f7 140 * @brief Trigger EMAC Rx function
<> 144:ef7eb2e8f9f7 141 * @param None
<> 144:ef7eb2e8f9f7 142 * @return None
<> 144:ef7eb2e8f9f7 143 */
<> 144:ef7eb2e8f9f7 144 #define EMAC_TRIGGER_RX() do{EMAC->RXST = 0;}while(0)
<> 144:ef7eb2e8f9f7 145
<> 144:ef7eb2e8f9f7 146 /**
<> 144:ef7eb2e8f9f7 147 * @brief Trigger EMAC Tx function
<> 144:ef7eb2e8f9f7 148 * @param None
<> 144:ef7eb2e8f9f7 149 * @return None
<> 144:ef7eb2e8f9f7 150 */
<> 144:ef7eb2e8f9f7 151 #define EMAC_TRIGGER_TX() do{EMAC->TXST = 0;}while(0)
<> 144:ef7eb2e8f9f7 152
<> 144:ef7eb2e8f9f7 153 /**
<> 144:ef7eb2e8f9f7 154 * @brief Write PHY register
<> 144:ef7eb2e8f9f7 155 * @param[in] u32Reg PHY register number
<> 144:ef7eb2e8f9f7 156 * @param[in] u32Addr PHY address, this address is board dependent
<> 144:ef7eb2e8f9f7 157 * @param[in] u32Data data to write to PHY register
<> 144:ef7eb2e8f9f7 158 * @return None
<> 144:ef7eb2e8f9f7 159 */
<> 144:ef7eb2e8f9f7 160 static void EMAC_MdioWrite(uint32_t u32Reg, uint32_t u32Addr, uint32_t u32Data)
<> 144:ef7eb2e8f9f7 161 {
<> 144:ef7eb2e8f9f7 162 // Set data register
<> 144:ef7eb2e8f9f7 163 EMAC->MIIMDAT = u32Data ;
<> 144:ef7eb2e8f9f7 164 // Set PHY address, PHY register address, busy bit and write bit
<> 144:ef7eb2e8f9f7 165 EMAC->MIIMCTL = u32Reg | (u32Addr << 8) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk;
<> 144:ef7eb2e8f9f7 166 // Wait write complete by polling busy bit.
<> 144:ef7eb2e8f9f7 167 while(EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
<> 144:ef7eb2e8f9f7 168
<> 144:ef7eb2e8f9f7 169 }
<> 144:ef7eb2e8f9f7 170
<> 144:ef7eb2e8f9f7 171 /**
<> 144:ef7eb2e8f9f7 172 * @brief Read PHY register
<> 144:ef7eb2e8f9f7 173 * @param[in] u32Reg PHY register number
<> 144:ef7eb2e8f9f7 174 * @param[in] u32Addr PHY address, this address is board dependent
<> 144:ef7eb2e8f9f7 175 * @return Value read from PHY register
<> 144:ef7eb2e8f9f7 176 */
<> 144:ef7eb2e8f9f7 177 static uint32_t EMAC_MdioRead(uint32_t u32Reg, uint32_t u32Addr)
<> 144:ef7eb2e8f9f7 178 {
<> 144:ef7eb2e8f9f7 179 // Set PHY address, PHY register address, busy bit
<> 144:ef7eb2e8f9f7 180 EMAC->MIIMCTL = u32Reg | (u32Addr << EMAC_MIIMCTL_PHYADDR_Pos) | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk;
<> 144:ef7eb2e8f9f7 181 // Wait read complete by polling busy bit
<> 144:ef7eb2e8f9f7 182 while(EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk);
<> 144:ef7eb2e8f9f7 183 // Get return data
<> 144:ef7eb2e8f9f7 184 return EMAC->MIIMDAT;
<> 144:ef7eb2e8f9f7 185 }
<> 144:ef7eb2e8f9f7 186
<> 144:ef7eb2e8f9f7 187
<> 144:ef7eb2e8f9f7 188 /**
<> 144:ef7eb2e8f9f7 189 * @brief Initialize PHY chip, check for the auto-negotiation result.
<> 144:ef7eb2e8f9f7 190 * @param None
<> 144:ef7eb2e8f9f7 191 * @return None
<> 144:ef7eb2e8f9f7 192 */
<> 144:ef7eb2e8f9f7 193 static void EMAC_PhyInit(void)
<> 144:ef7eb2e8f9f7 194 {
<> 144:ef7eb2e8f9f7 195 uint32_t reg;
<> 144:ef7eb2e8f9f7 196
<> 144:ef7eb2e8f9f7 197 // Reset Phy Chip
<> 144:ef7eb2e8f9f7 198 EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, PHY_CNTL_RESET_PHY);
<> 144:ef7eb2e8f9f7 199
<> 144:ef7eb2e8f9f7 200 // Wait until reset complete
<> 144:ef7eb2e8f9f7 201 while (1) {
<> 144:ef7eb2e8f9f7 202 reg = EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) ;
<> 144:ef7eb2e8f9f7 203 if ((reg & PHY_CNTL_RESET_PHY)==0)
<> 144:ef7eb2e8f9f7 204 break;
<> 144:ef7eb2e8f9f7 205 }
<> 144:ef7eb2e8f9f7 206
<> 153:fa9ff456f731 207 if(~EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) && PHY_STATUS_LINK_VALID) { // Cable not connected
<> 144:ef7eb2e8f9f7 208 printf("Unplug\n..");
<> 144:ef7eb2e8f9f7 209 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
<> 144:ef7eb2e8f9f7 210 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
<> 144:ef7eb2e8f9f7 211 return;
<> 144:ef7eb2e8f9f7 212 }
<> 144:ef7eb2e8f9f7 213 // Configure auto negotiation capability
<> 144:ef7eb2e8f9f7 214 EMAC_MdioWrite(PHY_ANA_REG, EMAC_PHY_ADDR, PHY_ANA_DR100_TX_FULL |
<> 144:ef7eb2e8f9f7 215 PHY_ANA_DR100_TX_HALF |
<> 144:ef7eb2e8f9f7 216 PHY_ANA_DR10_TX_FULL |
<> 144:ef7eb2e8f9f7 217 PHY_ANA_DR10_TX_HALF |
<> 144:ef7eb2e8f9f7 218 PHY_ANA_IEEE_802_3_CSMA_CD);
<> 144:ef7eb2e8f9f7 219 // Restart auto negotiation
<> 144:ef7eb2e8f9f7 220 EMAC_MdioWrite(PHY_CNTL_REG, EMAC_PHY_ADDR, EMAC_MdioRead(PHY_CNTL_REG, EMAC_PHY_ADDR) | PHY_CNTL_RESTART_AN);
<> 144:ef7eb2e8f9f7 221
<> 144:ef7eb2e8f9f7 222 // Wait for auto-negotiation complete
<> 144:ef7eb2e8f9f7 223 while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_AN_COMPLETE));
<> 144:ef7eb2e8f9f7 224
<> 144:ef7eb2e8f9f7 225 // Check link valid again. Some PHYs needs to check result after link valid bit set
<> 144:ef7eb2e8f9f7 226 while(!(EMAC_MdioRead(PHY_STATUS_REG, EMAC_PHY_ADDR) & PHY_STATUS_LINK_VALID));
<> 144:ef7eb2e8f9f7 227
<> 144:ef7eb2e8f9f7 228 // Check link partner capability
<> 144:ef7eb2e8f9f7 229 reg = EMAC_MdioRead(PHY_ANLPA_REG, EMAC_PHY_ADDR) ;
<> 144:ef7eb2e8f9f7 230 if (reg & PHY_ANLPA_DR100_TX_FULL) {
<> 144:ef7eb2e8f9f7 231 printf("100F\n");
<> 144:ef7eb2e8f9f7 232 EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
<> 144:ef7eb2e8f9f7 233 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
<> 144:ef7eb2e8f9f7 234 } else if (reg & PHY_ANLPA_DR100_TX_HALF) {
<> 144:ef7eb2e8f9f7 235 printf("100H\n");
<> 144:ef7eb2e8f9f7 236 EMAC->CTL |= EMAC_CTL_OPMODE_Msk;
<> 144:ef7eb2e8f9f7 237 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
<> 144:ef7eb2e8f9f7 238 } else if (reg & PHY_ANLPA_DR10_TX_FULL) {
<> 144:ef7eb2e8f9f7 239 printf("10F\n");
<> 144:ef7eb2e8f9f7 240 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
<> 144:ef7eb2e8f9f7 241 EMAC->CTL |= EMAC_CTL_FUDUP_Msk;
<> 144:ef7eb2e8f9f7 242 } else {
<> 144:ef7eb2e8f9f7 243 printf("10H\n");
<> 144:ef7eb2e8f9f7 244 EMAC->CTL &= ~EMAC_CTL_OPMODE_Msk;
<> 144:ef7eb2e8f9f7 245 EMAC->CTL &= ~EMAC_CTL_FUDUP_Msk;
<> 144:ef7eb2e8f9f7 246 }
<> 144:ef7eb2e8f9f7 247 }
<> 144:ef7eb2e8f9f7 248
<> 144:ef7eb2e8f9f7 249 /**
<> 144:ef7eb2e8f9f7 250 * @brief Initial EMAC Tx descriptors and get Tx descriptor base address
<> 144:ef7eb2e8f9f7 251 * @param None
<> 144:ef7eb2e8f9f7 252 * @return None
<> 144:ef7eb2e8f9f7 253 */
<> 144:ef7eb2e8f9f7 254 static void EMAC_TxDescInit(void)
<> 144:ef7eb2e8f9f7 255 {
<> 144:ef7eb2e8f9f7 256 uint32_t i;
<> 144:ef7eb2e8f9f7 257
<> 144:ef7eb2e8f9f7 258 // Get Frame descriptor's base address.
<> 144:ef7eb2e8f9f7 259 EMAC->TXDSA = (uint32_t)&tx_desc[0];
<> 144:ef7eb2e8f9f7 260 u32NextTxDesc = u32CurrentTxDesc = (uint32_t)&tx_desc[0];
<> 144:ef7eb2e8f9f7 261
<> 144:ef7eb2e8f9f7 262 for(i = 0; i < EMAC_TX_DESC_SIZE; i++) {
<> 144:ef7eb2e8f9f7 263
<> 144:ef7eb2e8f9f7 264 if(s_u32EnableTs)
<> 144:ef7eb2e8f9f7 265 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN;
<> 144:ef7eb2e8f9f7 266 else
<> 144:ef7eb2e8f9f7 267 tx_desc[i].u32Status1 = EMAC_TXFD_PADEN | EMAC_TXFD_CRCAPP | EMAC_TXFD_INTEN | EMAC_TXFD_TTSEN;
<> 144:ef7eb2e8f9f7 268
<> 144:ef7eb2e8f9f7 269 tx_desc[i].u32Data = (uint32_t)((uint32_t)&tx_buf[i]);
<> 144:ef7eb2e8f9f7 270 tx_desc[i].u32Backup1 = tx_desc[i].u32Data;
<> 144:ef7eb2e8f9f7 271 tx_desc[i].u32Status2 = 0;
<> 144:ef7eb2e8f9f7 272 tx_desc[i].u32Next = (uint32_t)&tx_desc[(i + 1) % EMAC_TX_DESC_SIZE];
<> 144:ef7eb2e8f9f7 273 tx_desc[i].u32Backup2 = tx_desc[i].u32Next;
<> 144:ef7eb2e8f9f7 274
<> 144:ef7eb2e8f9f7 275 }
<> 144:ef7eb2e8f9f7 276
<> 144:ef7eb2e8f9f7 277 }
<> 144:ef7eb2e8f9f7 278
<> 144:ef7eb2e8f9f7 279
<> 144:ef7eb2e8f9f7 280 /**
<> 144:ef7eb2e8f9f7 281 * @brief Initial EMAC Rx descriptors and get Rx descriptor base address
<> 144:ef7eb2e8f9f7 282 * @param None
<> 144:ef7eb2e8f9f7 283 * @return None
<> 144:ef7eb2e8f9f7 284 */
<> 144:ef7eb2e8f9f7 285 static void EMAC_RxDescInit(void)
<> 144:ef7eb2e8f9f7 286 {
<> 144:ef7eb2e8f9f7 287
<> 144:ef7eb2e8f9f7 288 uint32_t i;
<> 144:ef7eb2e8f9f7 289
<> 144:ef7eb2e8f9f7 290 // Get Frame descriptor's base address.
<> 144:ef7eb2e8f9f7 291 EMAC->RXDSA = (uint32_t)&rx_desc[0];
<> 144:ef7eb2e8f9f7 292 u32CurrentRxDesc = (uint32_t)&rx_desc[0];
<> 144:ef7eb2e8f9f7 293
<> 144:ef7eb2e8f9f7 294 for(i=0; i < EMAC_RX_DESC_SIZE; i++) {
<> 144:ef7eb2e8f9f7 295 rx_desc[i].u32Status1 = EMAC_DESC_OWN_EMAC;
<> 144:ef7eb2e8f9f7 296 rx_desc[i].u32Data = (uint32_t)((uint32_t)&rx_buf[i]);
<> 144:ef7eb2e8f9f7 297 rx_desc[i].u32Backup1 = rx_desc[i].u32Data;
<> 144:ef7eb2e8f9f7 298 rx_desc[i].u32Status2 = 0;
<> 144:ef7eb2e8f9f7 299 rx_desc[i].u32Next = (uint32_t)&rx_desc[(i + 1) % EMAC_RX_DESC_SIZE];
<> 144:ef7eb2e8f9f7 300 rx_desc[i].u32Backup2 = rx_desc[i].u32Next;
<> 144:ef7eb2e8f9f7 301 }
<> 144:ef7eb2e8f9f7 302
<> 144:ef7eb2e8f9f7 303 }
<> 144:ef7eb2e8f9f7 304
<> 144:ef7eb2e8f9f7 305 /**
<> 144:ef7eb2e8f9f7 306 * @brief Convert subsecond value to nano second
<> 144:ef7eb2e8f9f7 307 * @param[in] subsec Subsecond value to be convert
<> 144:ef7eb2e8f9f7 308 * @return Nano second
<> 144:ef7eb2e8f9f7 309 */
<> 144:ef7eb2e8f9f7 310 static uint32_t EMAC_Subsec2Nsec(uint32_t subsec)
<> 144:ef7eb2e8f9f7 311 {
<> 144:ef7eb2e8f9f7 312 // 2^31 subsec == 10^9 ns
<> 144:ef7eb2e8f9f7 313 uint64_t i;
<> 144:ef7eb2e8f9f7 314 i = 1000000000ll * subsec;
<> 144:ef7eb2e8f9f7 315 i >>= 31;
<> 144:ef7eb2e8f9f7 316 return(i);
<> 144:ef7eb2e8f9f7 317 }
<> 144:ef7eb2e8f9f7 318
<> 144:ef7eb2e8f9f7 319 /**
<> 144:ef7eb2e8f9f7 320 * @brief Convert nano second to subsecond value
<> 144:ef7eb2e8f9f7 321 * @param[in] nsec Nano second to be convert
<> 144:ef7eb2e8f9f7 322 * @return Subsecond
<> 144:ef7eb2e8f9f7 323 */
<> 144:ef7eb2e8f9f7 324 static uint32_t EMAC_Nsec2Subsec(uint32_t nsec)
<> 144:ef7eb2e8f9f7 325 {
<> 144:ef7eb2e8f9f7 326 // 10^9 ns = 2^31 subsec
<> 144:ef7eb2e8f9f7 327 uint64_t i;
<> 144:ef7eb2e8f9f7 328 i = (1ll << 31) * nsec;
<> 144:ef7eb2e8f9f7 329 i /= 1000000000;
<> 144:ef7eb2e8f9f7 330 return(i);
<> 144:ef7eb2e8f9f7 331 }
<> 144:ef7eb2e8f9f7 332
<> 144:ef7eb2e8f9f7 333
<> 144:ef7eb2e8f9f7 334 /*@}*/ /* end of group NUC472_442_EMAC_EXPORTED_FUNCTIONS */
<> 144:ef7eb2e8f9f7 335
<> 144:ef7eb2e8f9f7 336
<> 144:ef7eb2e8f9f7 337
<> 144:ef7eb2e8f9f7 338 /// @endcond HIDDEN_SYMBOLS
<> 144:ef7eb2e8f9f7 339
<> 144:ef7eb2e8f9f7 340
<> 144:ef7eb2e8f9f7 341 /** @addtogroup NUC472_442_EMAC_EXPORTED_FUNCTIONS EMAC Exported Functions
<> 144:ef7eb2e8f9f7 342 @{
<> 144:ef7eb2e8f9f7 343 */
<> 144:ef7eb2e8f9f7 344
<> 144:ef7eb2e8f9f7 345
<> 144:ef7eb2e8f9f7 346 // Basic configuration functions
<> 144:ef7eb2e8f9f7 347 /**
<> 144:ef7eb2e8f9f7 348 * @brief Initialize EMAC interface, including descriptors, MAC address, and PHY.
<> 144:ef7eb2e8f9f7 349 * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
<> 144:ef7eb2e8f9f7 350 * @return None
<> 144:ef7eb2e8f9f7 351 * @note This API sets EMAC to work in RMII mode, but could configure to MII mode later with \ref EMAC_ENABLE_MII_INTF macro
<> 144:ef7eb2e8f9f7 352 * @note This API configures EMAC to receive all broadcast and multicast packets, but could configure to other settings with
<> 144:ef7eb2e8f9f7 353 * \ref EMAC_ENABLE_RECV_BCASTPKT, \ref EMAC_DISABLE_RECV_BCASTPKT, \ref EMAC_ENABLE_RECV_MCASTPKT, and \ref EMAC_DISABLE_RECV_MCASTPKT
<> 144:ef7eb2e8f9f7 354 * @note Receive(RX) and transmit(TX) are not enabled yet, application must call \ref EMAC_ENABLE_RX and \ref EMAC_ENABLE_TX to
<> 144:ef7eb2e8f9f7 355 * enable receive and transmit function.
<> 144:ef7eb2e8f9f7 356 */
<> 144:ef7eb2e8f9f7 357 void EMAC_Open(uint8_t *pu8MacAddr)
<> 144:ef7eb2e8f9f7 358 {
<> 144:ef7eb2e8f9f7 359 // Enable transmit and receive descriptor
<> 144:ef7eb2e8f9f7 360 EMAC_TxDescInit();
<> 144:ef7eb2e8f9f7 361 EMAC_RxDescInit();
<> 144:ef7eb2e8f9f7 362
<> 144:ef7eb2e8f9f7 363 // Set the CAM Control register and the MAC address value
<> 144:ef7eb2e8f9f7 364 EMAC_SetMacAddr(pu8MacAddr);
<> 144:ef7eb2e8f9f7 365
<> 144:ef7eb2e8f9f7 366 // Configure the MAC interrupt enable register.
<> 144:ef7eb2e8f9f7 367 EMAC->INTEN = EMAC_INTEN_RXIEN_Msk |
<> 144:ef7eb2e8f9f7 368 EMAC_INTEN_TXIEN_Msk |
<> 144:ef7eb2e8f9f7 369 EMAC_INTEN_RXGDIEN_Msk |
<> 144:ef7eb2e8f9f7 370 EMAC_INTEN_TXCPIEN_Msk |
<> 144:ef7eb2e8f9f7 371 EMAC_INTEN_RXBEIEN_Msk |
<> 144:ef7eb2e8f9f7 372 EMAC_INTEN_TXBEIEN_Msk |
<> 144:ef7eb2e8f9f7 373 EMAC_INTEN_RDUIEN_Msk |
<> 144:ef7eb2e8f9f7 374 EMAC_INTEN_TSALMIEN_Msk |
<> 144:ef7eb2e8f9f7 375 EMAC_INTEN_WOLIEN_Msk;
<> 144:ef7eb2e8f9f7 376
<> 144:ef7eb2e8f9f7 377 // Configure the MAC control register.
<> 144:ef7eb2e8f9f7 378 EMAC->CTL = EMAC_CTL_STRIPCRC_Msk |
<> 144:ef7eb2e8f9f7 379 EMAC_CTL_RMIIEN_Msk |
<> 144:ef7eb2e8f9f7 380 EMAC_CTL_RMIIRXCTL_Msk;
<> 144:ef7eb2e8f9f7 381
<> 144:ef7eb2e8f9f7 382 //Accept packets for us and all broadcast and multicast packets
<> 144:ef7eb2e8f9f7 383 EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk |
<> 144:ef7eb2e8f9f7 384 EMAC_CAMCTL_AMP_Msk |
<> 144:ef7eb2e8f9f7 385 EMAC_CAMCTL_ABP_Msk;
<> 144:ef7eb2e8f9f7 386
<> 144:ef7eb2e8f9f7 387 EMAC_PhyInit();
<> 144:ef7eb2e8f9f7 388 }
<> 144:ef7eb2e8f9f7 389
<> 144:ef7eb2e8f9f7 390 /**
<> 144:ef7eb2e8f9f7 391 * @brief This function stop all receive and transmit activity and disable MAC interface
<> 144:ef7eb2e8f9f7 392 * @param None
<> 144:ef7eb2e8f9f7 393 * @return None
<> 144:ef7eb2e8f9f7 394 */
<> 144:ef7eb2e8f9f7 395
<> 144:ef7eb2e8f9f7 396 void EMAC_Close(void)
<> 144:ef7eb2e8f9f7 397 {
<> 144:ef7eb2e8f9f7 398 EMAC->CTL |= EMAC_CTL_RST_Msk;
<> 144:ef7eb2e8f9f7 399 }
<> 144:ef7eb2e8f9f7 400
<> 144:ef7eb2e8f9f7 401 /**
<> 144:ef7eb2e8f9f7 402 * @brief Set the device MAC address
<> 144:ef7eb2e8f9f7 403 * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
<> 144:ef7eb2e8f9f7 404 * @return None
<> 144:ef7eb2e8f9f7 405 */
<> 144:ef7eb2e8f9f7 406 void EMAC_SetMacAddr(uint8_t *pu8MacAddr)
<> 144:ef7eb2e8f9f7 407 {
<> 144:ef7eb2e8f9f7 408 EMAC_EnableCamEntry(0, pu8MacAddr);
<> 144:ef7eb2e8f9f7 409
<> 144:ef7eb2e8f9f7 410 }
<> 144:ef7eb2e8f9f7 411
<> 144:ef7eb2e8f9f7 412 /**
<> 144:ef7eb2e8f9f7 413 * @brief Fill a CAM entry for MAC address comparison.
<> 144:ef7eb2e8f9f7 414 * @param[in] u32Entry MAC entry to fill. Entry 0 is used to store device MAC address, do not overwrite the setting in it.
<> 144:ef7eb2e8f9f7 415 * @param[in] pu8MacAddr Pointer to uint8_t array holds MAC address
<> 144:ef7eb2e8f9f7 416 * @return None
<> 144:ef7eb2e8f9f7 417 */
<> 144:ef7eb2e8f9f7 418 void EMAC_EnableCamEntry(uint32_t u32Entry, uint8_t *pu8MacAddr)
<> 144:ef7eb2e8f9f7 419 {
<> 144:ef7eb2e8f9f7 420 uint32_t u32Lsw, u32Msw;
<> 144:ef7eb2e8f9f7 421
<> 144:ef7eb2e8f9f7 422 u32Lsw = (pu8MacAddr[4] << 24) |
<> 144:ef7eb2e8f9f7 423 (pu8MacAddr[5] << 16);
<> 144:ef7eb2e8f9f7 424 u32Msw = (pu8MacAddr[0] << 24)|
<> 144:ef7eb2e8f9f7 425 (pu8MacAddr[1] << 16)|
<> 144:ef7eb2e8f9f7 426 (pu8MacAddr[2] << 8)|
<> 144:ef7eb2e8f9f7 427 pu8MacAddr[3];
<> 144:ef7eb2e8f9f7 428
<> 144:ef7eb2e8f9f7 429 *(uint32_t volatile *)(&EMAC->CAM0M + u32Entry * 4) = u32Msw;
<> 144:ef7eb2e8f9f7 430 *(uint32_t volatile *)(&EMAC->CAM0L + u32Entry * 4) = u32Lsw;
<> 144:ef7eb2e8f9f7 431
<> 144:ef7eb2e8f9f7 432 EMAC->CAMEN |= (1 << u32Entry);
<> 144:ef7eb2e8f9f7 433 }
<> 144:ef7eb2e8f9f7 434
<> 144:ef7eb2e8f9f7 435 /**
<> 144:ef7eb2e8f9f7 436 * @brief Disable a specified CAM entry
<> 144:ef7eb2e8f9f7 437 * @param[in] u32Entry CAM entry to be disabled
<> 144:ef7eb2e8f9f7 438 * @return None
<> 144:ef7eb2e8f9f7 439 */
<> 144:ef7eb2e8f9f7 440 void EMAC_DisableCamEntry(uint32_t u32Entry)
<> 144:ef7eb2e8f9f7 441 {
<> 144:ef7eb2e8f9f7 442 EMAC->CAMEN &= ~(1 << u32Entry);
<> 144:ef7eb2e8f9f7 443 }
<> 144:ef7eb2e8f9f7 444
<> 144:ef7eb2e8f9f7 445 // Receive functions
<> 144:ef7eb2e8f9f7 446 /**
<> 144:ef7eb2e8f9f7 447 * @brief Receive an Ethernet packet
<> 144:ef7eb2e8f9f7 448 * @param[in] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed)
<> 144:ef7eb2e8f9f7 449 * @param[in] pu32Size Received packet size (without 4 byte CRC).
<> 144:ef7eb2e8f9f7 450 * @return Packet receive success or not
<> 144:ef7eb2e8f9f7 451 * @retval 0 No packet available for receive
<> 144:ef7eb2e8f9f7 452 * @retval 1 A packet is received
<> 144:ef7eb2e8f9f7 453 * @note Return 0 doesn't guarantee the packet will be sent and received successfully.
<> 144:ef7eb2e8f9f7 454 */
<> 144:ef7eb2e8f9f7 455 uint32_t EMAC_RecvPkt(uint8_t *pu8Data, uint32_t *pu32Size)
<> 144:ef7eb2e8f9f7 456 {
<> 144:ef7eb2e8f9f7 457 EMAC_DESCRIPTOR_T *desc;
<> 144:ef7eb2e8f9f7 458 uint32_t status, reg;
<> 144:ef7eb2e8f9f7 459 uint32_t u32Count = 0;
<> 144:ef7eb2e8f9f7 460
<> 144:ef7eb2e8f9f7 461 // Clear Rx interrupt flags
<> 144:ef7eb2e8f9f7 462 reg = EMAC->INTSTS;
<> 144:ef7eb2e8f9f7 463 EMAC->INTSTS = reg & 0xFFFF; // Clear all RX related interrupt status
<> 144:ef7eb2e8f9f7 464
<> 144:ef7eb2e8f9f7 465 if (reg & EMAC_INTSTS_RXBEIF_Msk) {
<> 144:ef7eb2e8f9f7 466 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
<> 144:ef7eb2e8f9f7 467 printf("RX bus error\n");
<> 144:ef7eb2e8f9f7 468 } else {
<> 144:ef7eb2e8f9f7 469
<> 144:ef7eb2e8f9f7 470 // Get Rx Frame Descriptor
<> 144:ef7eb2e8f9f7 471 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
<> 144:ef7eb2e8f9f7 472
<> 144:ef7eb2e8f9f7 473 // If we reach last recv Rx descriptor, leave the loop
<> 144:ef7eb2e8f9f7 474 if(EMAC->CRXDSA == (uint32_t)desc)
<> 144:ef7eb2e8f9f7 475 return(0);
<> 144:ef7eb2e8f9f7 476 if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { // ownership=CPU
<> 144:ef7eb2e8f9f7 477
<> 144:ef7eb2e8f9f7 478 status = desc->u32Status1 >> 16;
<> 144:ef7eb2e8f9f7 479
<> 144:ef7eb2e8f9f7 480 // If Rx frame is good, process received frame
<> 144:ef7eb2e8f9f7 481 if(status & EMAC_RXFD_RXGD) {
<> 144:ef7eb2e8f9f7 482 // lower 16 bit in descriptor status1 stores the Rx packet length
<> 144:ef7eb2e8f9f7 483 *pu32Size = desc->u32Status1 & 0xffff;
<> 144:ef7eb2e8f9f7 484 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
<> 144:ef7eb2e8f9f7 485 u32Count = 1;
<> 144:ef7eb2e8f9f7 486 } else {
<> 144:ef7eb2e8f9f7 487 // Save Error status if necessary
<> 153:fa9ff456f731 488 if (status & EMAC_RXFD_RP) {;}
<> 153:fa9ff456f731 489 if (status & EMAC_RXFD_ALIE) {;}
<> 153:fa9ff456f731 490 if (status & EMAC_RXFD_PTLE) {;}
<> 153:fa9ff456f731 491 if (status & EMAC_RXFD_CRCE) {;}
<> 144:ef7eb2e8f9f7 492 }
<> 144:ef7eb2e8f9f7 493 }
<> 144:ef7eb2e8f9f7 494 }
<> 144:ef7eb2e8f9f7 495 return(u32Count);
<> 144:ef7eb2e8f9f7 496 }
<> 144:ef7eb2e8f9f7 497
<> 144:ef7eb2e8f9f7 498 /**
<> 144:ef7eb2e8f9f7 499 * @brief Receive an Ethernet packet and the time stamp while it's received
<> 144:ef7eb2e8f9f7 500 * @param[out] pu8Data Pointer to a buffer to store received packet (4 byte CRC removed)
<> 144:ef7eb2e8f9f7 501 * @param[out] pu32Size Received packet size (without 4 byte CRC).
<> 144:ef7eb2e8f9f7 502 * @param[out] pu32Sec Second value while packet sent
<> 144:ef7eb2e8f9f7 503 * @param[out] pu32Nsec Nano second value while packet sent
<> 144:ef7eb2e8f9f7 504 * @return Packet receive success or not
<> 144:ef7eb2e8f9f7 505 * @retval 0 No packet available for receive
<> 144:ef7eb2e8f9f7 506 * @retval 1 A packet is received
<> 144:ef7eb2e8f9f7 507 * @note Return 0 doesn't guarantee the packet will be sent and received successfully.
<> 144:ef7eb2e8f9f7 508 * @note Largest Ethernet packet is 1514 bytes after stripped CRC, application must give
<> 144:ef7eb2e8f9f7 509 * a buffer large enough to store such packet
<> 144:ef7eb2e8f9f7 510 */
<> 144:ef7eb2e8f9f7 511 uint32_t EMAC_RecvPktTS(uint8_t *pu8Data, uint32_t *pu32Size, uint32_t *pu32Sec, uint32_t *pu32Nsec)
<> 144:ef7eb2e8f9f7 512 {
<> 144:ef7eb2e8f9f7 513 EMAC_DESCRIPTOR_T *desc;
<> 144:ef7eb2e8f9f7 514 uint32_t status, reg;
<> 144:ef7eb2e8f9f7 515 uint32_t u32Count = 0;
<> 144:ef7eb2e8f9f7 516
<> 144:ef7eb2e8f9f7 517 // Clear Rx interrupt flags
<> 144:ef7eb2e8f9f7 518 reg = EMAC->INTSTS;
<> 144:ef7eb2e8f9f7 519 EMAC->INTSTS = reg & 0xFFFF; // Clear all Rx related interrupt status
<> 144:ef7eb2e8f9f7 520
<> 144:ef7eb2e8f9f7 521 if (reg & EMAC_INTSTS_RXBEIF_Msk) {
<> 144:ef7eb2e8f9f7 522 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
<> 144:ef7eb2e8f9f7 523 printf("RX bus error\n");
<> 144:ef7eb2e8f9f7 524 } else {
<> 144:ef7eb2e8f9f7 525
<> 144:ef7eb2e8f9f7 526 // Get Rx Frame Descriptor
<> 144:ef7eb2e8f9f7 527 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
<> 144:ef7eb2e8f9f7 528
<> 144:ef7eb2e8f9f7 529 // If we reach last recv Rx descriptor, leave the loop
<> 144:ef7eb2e8f9f7 530 if(EMAC->CRXDSA == (uint32_t)desc)
<> 144:ef7eb2e8f9f7 531 return(0);
<> 144:ef7eb2e8f9f7 532 if ((desc->u32Status1 | EMAC_DESC_OWN_EMAC) != EMAC_DESC_OWN_EMAC) { // ownership=CPU
<> 144:ef7eb2e8f9f7 533
<> 144:ef7eb2e8f9f7 534 status = desc->u32Status1 >> 16;
<> 144:ef7eb2e8f9f7 535
<> 144:ef7eb2e8f9f7 536 // If Rx frame is good, process received frame
<> 144:ef7eb2e8f9f7 537 if(status & EMAC_RXFD_RXGD) {
<> 144:ef7eb2e8f9f7 538 // lower 16 bit in descriptor status1 stores the Rx packet length
<> 144:ef7eb2e8f9f7 539 *pu32Size = desc->u32Status1 & 0xffff;
<> 144:ef7eb2e8f9f7 540 memcpy(pu8Data, (uint8_t *)desc->u32Backup1, *pu32Size);
<> 144:ef7eb2e8f9f7 541
<> 144:ef7eb2e8f9f7 542 *pu32Sec = desc->u32Next; // second stores in descriptor's NEXT field
<> 144:ef7eb2e8f9f7 543 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); // Sub nano second store in DATA field
<> 144:ef7eb2e8f9f7 544
<> 144:ef7eb2e8f9f7 545 u32Count = 1;
<> 144:ef7eb2e8f9f7 546 } else {
<> 144:ef7eb2e8f9f7 547 // Save Error status if necessary
<> 153:fa9ff456f731 548 if (status & EMAC_RXFD_RP) {;}
<> 153:fa9ff456f731 549 if (status & EMAC_RXFD_ALIE) {;}
<> 153:fa9ff456f731 550 if (status & EMAC_RXFD_PTLE) {;}
<> 153:fa9ff456f731 551 if (status & EMAC_RXFD_CRCE) {;}
<> 144:ef7eb2e8f9f7 552 }
<> 144:ef7eb2e8f9f7 553 }
<> 144:ef7eb2e8f9f7 554 }
<> 144:ef7eb2e8f9f7 555 return(u32Count);
<> 144:ef7eb2e8f9f7 556 }
<> 144:ef7eb2e8f9f7 557
<> 144:ef7eb2e8f9f7 558 /**
<> 144:ef7eb2e8f9f7 559 * @brief Clean up process after a packet is received
<> 144:ef7eb2e8f9f7 560 * @param None
<> 144:ef7eb2e8f9f7 561 * @return None
<> 144:ef7eb2e8f9f7 562 * @details EMAC Rx interrupt service routine \b must call this API to release the resource use by receive process
<> 144:ef7eb2e8f9f7 563 * @note Application can only call this function once every time \ref EMAC_RecvPkt or \ref EMAC_RecvPktTS returns 1
<> 144:ef7eb2e8f9f7 564 */
<> 144:ef7eb2e8f9f7 565 void EMAC_RecvPktDone(void)
<> 144:ef7eb2e8f9f7 566 {
<> 144:ef7eb2e8f9f7 567 EMAC_DESCRIPTOR_T *desc;
<> 144:ef7eb2e8f9f7 568 // Get Rx Frame Descriptor
<> 144:ef7eb2e8f9f7 569 desc = (EMAC_DESCRIPTOR_T *)u32CurrentRxDesc;
<> 144:ef7eb2e8f9f7 570
<> 144:ef7eb2e8f9f7 571 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
<> 144:ef7eb2e8f9f7 572 desc->u32Data = desc->u32Backup1;
<> 144:ef7eb2e8f9f7 573 desc->u32Next = desc->u32Backup2;
<> 144:ef7eb2e8f9f7 574
<> 144:ef7eb2e8f9f7 575 // Change ownership to DMA for next use
<> 144:ef7eb2e8f9f7 576 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
<> 144:ef7eb2e8f9f7 577
<> 144:ef7eb2e8f9f7 578 // Get Next Frame Descriptor pointer to process
<> 144:ef7eb2e8f9f7 579 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
<> 144:ef7eb2e8f9f7 580
<> 144:ef7eb2e8f9f7 581 // Save last processed Rx descriptor
<> 144:ef7eb2e8f9f7 582 u32CurrentRxDesc = (uint32_t)desc;
<> 144:ef7eb2e8f9f7 583
<> 144:ef7eb2e8f9f7 584 EMAC_TRIGGER_RX();
<> 144:ef7eb2e8f9f7 585 }
<> 144:ef7eb2e8f9f7 586
<> 144:ef7eb2e8f9f7 587 // Transmit functions
<> 144:ef7eb2e8f9f7 588
<> 144:ef7eb2e8f9f7 589 /**
<> 144:ef7eb2e8f9f7 590 * @brief Send an Ethernet packet
<> 144:ef7eb2e8f9f7 591 * @param[in] pu8Data Pointer to a buffer holds the packet to transmit
<> 144:ef7eb2e8f9f7 592 * @param[in] u32Size Packet size (without 4 byte CRC).
<> 144:ef7eb2e8f9f7 593 * @return Packet transmit success or not
<> 144:ef7eb2e8f9f7 594 * @retval 0 Transmit failed due to descriptor unavailable.
<> 144:ef7eb2e8f9f7 595 * @retval 1 Packet is copied to descriptor and triggered to transmit.
<> 144:ef7eb2e8f9f7 596 * @note Return 1 doesn't guarantee the packet will be sent and received successfully.
<> 144:ef7eb2e8f9f7 597 */
<> 144:ef7eb2e8f9f7 598 uint32_t EMAC_SendPkt(uint8_t *pu8Data, uint32_t u32Size)
<> 144:ef7eb2e8f9f7 599 {
<> 144:ef7eb2e8f9f7 600 EMAC_DESCRIPTOR_T *desc;
<> 144:ef7eb2e8f9f7 601 uint32_t status;
<> 144:ef7eb2e8f9f7 602
<> 144:ef7eb2e8f9f7 603 // Get Tx frame descriptor & data pointer
<> 144:ef7eb2e8f9f7 604 desc = (EMAC_DESCRIPTOR_T *)u32NextTxDesc;
<> 144:ef7eb2e8f9f7 605
<> 144:ef7eb2e8f9f7 606 status = desc->u32Status1;
<> 144:ef7eb2e8f9f7 607
<> 144:ef7eb2e8f9f7 608 // Check descriptor ownership
<> 144:ef7eb2e8f9f7 609 if((status & EMAC_DESC_OWN_EMAC))
<> 144:ef7eb2e8f9f7 610 return(0);
<> 144:ef7eb2e8f9f7 611
<> 144:ef7eb2e8f9f7 612 memcpy((uint8_t *)desc->u32Data, pu8Data, u32Size);
<> 144:ef7eb2e8f9f7 613
<> 144:ef7eb2e8f9f7 614 // Set Tx descriptor transmit byte count
<> 144:ef7eb2e8f9f7 615 desc->u32Status2 = u32Size;
<> 144:ef7eb2e8f9f7 616
<> 144:ef7eb2e8f9f7 617 // Change descriptor ownership to EMAC
<> 144:ef7eb2e8f9f7 618 desc->u32Status1 |= EMAC_DESC_OWN_EMAC;
<> 144:ef7eb2e8f9f7 619
<> 144:ef7eb2e8f9f7 620 // Get next Tx descriptor
<> 144:ef7eb2e8f9f7 621 u32NextTxDesc = (uint32_t)(desc->u32Next);
<> 144:ef7eb2e8f9f7 622
<> 144:ef7eb2e8f9f7 623 // Trigger EMAC to send the packet
<> 144:ef7eb2e8f9f7 624 EMAC_TRIGGER_TX();
<> 144:ef7eb2e8f9f7 625
<> 144:ef7eb2e8f9f7 626 return(1);
<> 144:ef7eb2e8f9f7 627 }
<> 144:ef7eb2e8f9f7 628
<> 144:ef7eb2e8f9f7 629
<> 144:ef7eb2e8f9f7 630 /**
<> 144:ef7eb2e8f9f7 631 * @brief Clean up process after packet(s) are sent
<> 144:ef7eb2e8f9f7 632 * @param None
<> 144:ef7eb2e8f9f7 633 * @return Number of packet sent between two function calls
<> 144:ef7eb2e8f9f7 634 * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDoneTS to
<> 144:ef7eb2e8f9f7 635 * release the resource use by transmit process
<> 144:ef7eb2e8f9f7 636 */
<> 144:ef7eb2e8f9f7 637 uint32_t EMAC_SendPktDone(void)
<> 144:ef7eb2e8f9f7 638 {
<> 144:ef7eb2e8f9f7 639 EMAC_DESCRIPTOR_T *desc;
<> 144:ef7eb2e8f9f7 640 uint32_t status, reg;
<> 144:ef7eb2e8f9f7 641 uint32_t last_tx_desc;
<> 144:ef7eb2e8f9f7 642 uint32_t u32Count = 0;
<> 144:ef7eb2e8f9f7 643
<> 144:ef7eb2e8f9f7 644 reg = EMAC->INTSTS;
<> 144:ef7eb2e8f9f7 645 // Clear Tx interrupt flags
<> 144:ef7eb2e8f9f7 646 EMAC->INTSTS = reg & (0xFFFF0000 & ~EMAC_INTSTS_TSALMIF_Msk);
<> 144:ef7eb2e8f9f7 647
<> 144:ef7eb2e8f9f7 648
<> 144:ef7eb2e8f9f7 649 if (reg & EMAC_INTSTS_TXBEIF_Msk) {
<> 144:ef7eb2e8f9f7 650 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
<> 144:ef7eb2e8f9f7 651 printf("TX bus error\n");
<> 144:ef7eb2e8f9f7 652 } else {
<> 144:ef7eb2e8f9f7 653 // Process the descriptor(s).
<> 144:ef7eb2e8f9f7 654 last_tx_desc = EMAC->CTXDSA ;
<> 144:ef7eb2e8f9f7 655 // Get our first descriptor to process
<> 144:ef7eb2e8f9f7 656 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
<> 144:ef7eb2e8f9f7 657 do {
<> 144:ef7eb2e8f9f7 658 // Descriptor ownership is still EMAC, so this packet haven't been send.
<> 144:ef7eb2e8f9f7 659 if(desc->u32Status1 & EMAC_DESC_OWN_EMAC)
<> 144:ef7eb2e8f9f7 660 break;
<> 144:ef7eb2e8f9f7 661 // Get Tx status stored in descriptor
<> 144:ef7eb2e8f9f7 662 status = desc->u32Status2 >> 16;
<> 144:ef7eb2e8f9f7 663 if (status & EMAC_TXFD_TXCP) {
<> 144:ef7eb2e8f9f7 664 u32Count++;
<> 144:ef7eb2e8f9f7 665 } else {
<> 144:ef7eb2e8f9f7 666 // Do nothing here on error.
<> 153:fa9ff456f731 667 if (status & EMAC_TXFD_TXABT) {;}
<> 153:fa9ff456f731 668 if (status & EMAC_TXFD_DEF) {;}
<> 153:fa9ff456f731 669 if (status & EMAC_TXFD_PAU) {;}
<> 153:fa9ff456f731 670 if (status & EMAC_TXFD_EXDEF) {;}
<> 153:fa9ff456f731 671 if (status & EMAC_TXFD_NCS) {;}
<> 153:fa9ff456f731 672 if (status & EMAC_TXFD_SQE) {;}
<> 153:fa9ff456f731 673 if (status & EMAC_TXFD_LC) {;}
<> 153:fa9ff456f731 674 if (status & EMAC_TXFD_TXHA) {;}
<> 144:ef7eb2e8f9f7 675 }
<> 144:ef7eb2e8f9f7 676
<> 144:ef7eb2e8f9f7 677 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
<> 144:ef7eb2e8f9f7 678 desc->u32Data = desc->u32Backup1;
<> 144:ef7eb2e8f9f7 679 desc->u32Next = desc->u32Backup2;
<> 144:ef7eb2e8f9f7 680 // go to next descriptor in link
<> 144:ef7eb2e8f9f7 681 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
<> 144:ef7eb2e8f9f7 682 } while (last_tx_desc != (uint32_t)desc); // If we reach last sent Tx descriptor, leave the loop
<> 144:ef7eb2e8f9f7 683 // Save last processed Tx descriptor
<> 144:ef7eb2e8f9f7 684 u32CurrentTxDesc = (uint32_t)desc;
<> 144:ef7eb2e8f9f7 685 }
<> 144:ef7eb2e8f9f7 686 return(u32Count);
<> 144:ef7eb2e8f9f7 687 }
<> 144:ef7eb2e8f9f7 688
<> 144:ef7eb2e8f9f7 689 /**
<> 144:ef7eb2e8f9f7 690 * @brief Clean up process after a packet is sent, and get the time stamp while packet is sent
<> 144:ef7eb2e8f9f7 691 * @param[in] pu32Sec Second value while packet sent
<> 144:ef7eb2e8f9f7 692 * @param[in] pu32Nsec Nano second value while packet sent
<> 144:ef7eb2e8f9f7 693 * @return If a packet sent successfully
<> 144:ef7eb2e8f9f7 694 * @retval 0 No packet sent successfully, and the value in *pu32Sec and *pu32Nsec are meaningless
<> 144:ef7eb2e8f9f7 695 * @retval 1 A packet sent successfully, and the value in *pu32Sec and *pu32Nsec is the time stamp while packet sent
<> 144:ef7eb2e8f9f7 696 * @details EMAC Tx interrupt service routine \b must call this API or \ref EMAC_SendPktDone to
<> 144:ef7eb2e8f9f7 697 * release the resource use by transmit process
<> 144:ef7eb2e8f9f7 698 */
<> 144:ef7eb2e8f9f7 699 uint32_t EMAC_SendPktDoneTS(uint32_t *pu32Sec, uint32_t *pu32Nsec)
<> 144:ef7eb2e8f9f7 700 {
<> 144:ef7eb2e8f9f7 701
<> 144:ef7eb2e8f9f7 702 EMAC_DESCRIPTOR_T *desc;
<> 144:ef7eb2e8f9f7 703 uint32_t status, reg;
<> 144:ef7eb2e8f9f7 704 uint32_t u32Count = 0;
<> 144:ef7eb2e8f9f7 705
<> 144:ef7eb2e8f9f7 706 reg = EMAC->INTSTS;
<> 144:ef7eb2e8f9f7 707 // Clear Tx interrupt flags
<> 144:ef7eb2e8f9f7 708 EMAC->INTSTS = reg & (0xFFFF0000 & ~EMAC_INTSTS_TSALMIF_Msk);
<> 144:ef7eb2e8f9f7 709
<> 144:ef7eb2e8f9f7 710
<> 144:ef7eb2e8f9f7 711 if (reg & EMAC_INTSTS_TXBEIF_Msk) {
<> 144:ef7eb2e8f9f7 712 // Bus error occurred, this is usually a bad sign about software bug and will occur again...
<> 144:ef7eb2e8f9f7 713 printf("TX bus error\n");
<> 144:ef7eb2e8f9f7 714 } else {
<> 144:ef7eb2e8f9f7 715 // Process the descriptor.
<> 144:ef7eb2e8f9f7 716 // Get our first descriptor to process
<> 144:ef7eb2e8f9f7 717 desc = (EMAC_DESCRIPTOR_T *) u32CurrentTxDesc;
<> 144:ef7eb2e8f9f7 718
<> 144:ef7eb2e8f9f7 719 // Descriptor ownership is still EMAC, so this packet haven't been send.
<> 144:ef7eb2e8f9f7 720 if(desc->u32Status1 & EMAC_DESC_OWN_EMAC)
<> 144:ef7eb2e8f9f7 721 return(0);
<> 144:ef7eb2e8f9f7 722 // Get Tx status stored in descriptor
<> 144:ef7eb2e8f9f7 723 status = desc->u32Status2 >> 16;
<> 144:ef7eb2e8f9f7 724 if (status & EMAC_TXFD_TXCP) {
<> 144:ef7eb2e8f9f7 725 u32Count = 1;
<> 144:ef7eb2e8f9f7 726 *pu32Sec = desc->u32Next; // second stores in descriptor's NEXT field
<> 144:ef7eb2e8f9f7 727 *pu32Nsec = EMAC_Subsec2Nsec(desc->u32Data); // Sub nano second store in DATA field
<> 144:ef7eb2e8f9f7 728 } else {
<> 144:ef7eb2e8f9f7 729 // Do nothing here on error.
<> 153:fa9ff456f731 730 if (status & EMAC_TXFD_TXABT) {;}
<> 153:fa9ff456f731 731 if (status & EMAC_TXFD_DEF) {;}
<> 153:fa9ff456f731 732 if (status & EMAC_TXFD_PAU) {;}
<> 153:fa9ff456f731 733 if (status & EMAC_TXFD_EXDEF) {;}
<> 153:fa9ff456f731 734 if (status & EMAC_TXFD_NCS) {;}
<> 153:fa9ff456f731 735 if (status & EMAC_TXFD_SQE) {;}
<> 153:fa9ff456f731 736 if (status & EMAC_TXFD_LC) {;}
<> 153:fa9ff456f731 737 if (status & EMAC_TXFD_TXHA) {;}
<> 144:ef7eb2e8f9f7 738 }
<> 144:ef7eb2e8f9f7 739
<> 144:ef7eb2e8f9f7 740 // restore descriptor link list and data pointer they will be overwrite if time stamp enabled
<> 144:ef7eb2e8f9f7 741 desc->u32Data = desc->u32Backup1;
<> 144:ef7eb2e8f9f7 742 desc->u32Next = desc->u32Backup2;
<> 144:ef7eb2e8f9f7 743 // go to next descriptor in link
<> 144:ef7eb2e8f9f7 744 desc = (EMAC_DESCRIPTOR_T *)desc->u32Next;
<> 144:ef7eb2e8f9f7 745
<> 144:ef7eb2e8f9f7 746 // Save last processed Tx descriptor
<> 144:ef7eb2e8f9f7 747 u32CurrentTxDesc = (uint32_t)desc;
<> 144:ef7eb2e8f9f7 748 }
<> 144:ef7eb2e8f9f7 749
<> 144:ef7eb2e8f9f7 750 return(u32Count);
<> 144:ef7eb2e8f9f7 751 }
<> 144:ef7eb2e8f9f7 752
<> 144:ef7eb2e8f9f7 753 // IEEE 1588 functions
<> 144:ef7eb2e8f9f7 754 /**
<> 144:ef7eb2e8f9f7 755 * @brief Enable IEEE1588 time stamp function and set current time
<> 144:ef7eb2e8f9f7 756 * @param[in] u32Sec Second value
<> 144:ef7eb2e8f9f7 757 * @param[in] u32Nsec Nano second value
<> 144:ef7eb2e8f9f7 758 * @return None
<> 144:ef7eb2e8f9f7 759 */
<> 144:ef7eb2e8f9f7 760 void EMAC_EnableTS(uint32_t u32Sec, uint32_t u32Nsec)
<> 144:ef7eb2e8f9f7 761 {
<> 144:ef7eb2e8f9f7 762 double f;
<> 144:ef7eb2e8f9f7 763 uint32_t reg;
<> 144:ef7eb2e8f9f7 764 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
<> 144:ef7eb2e8f9f7 765 EMAC->UPDSEC = u32Sec; // Assume current time is 0 sec + 0 nano sec
<> 144:ef7eb2e8f9f7 766 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
<> 144:ef7eb2e8f9f7 767
<> 144:ef7eb2e8f9f7 768 // PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns
<> 144:ef7eb2e8f9f7 769 // Assume we want to set each tick to 100ns.
<> 144:ef7eb2e8f9f7 770 // Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7
<> 144:ef7eb2e8f9f7 771 // Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz
<> 144:ef7eb2e8f9f7 772 // From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600
<> 144:ef7eb2e8f9f7 773 // So:
<> 144:ef7eb2e8f9f7 774 // EMAC->TSIR = 0xD7;
<> 144:ef7eb2e8f9f7 775 // EMAC->TSAR = 0x1E70C600;
<> 144:ef7eb2e8f9f7 776 f = (100.0 * 2147483648.0) / (1000000000.0) + 0.5;
<> 144:ef7eb2e8f9f7 777 EMAC->TSINC = (reg = (uint32_t)f);
<> 144:ef7eb2e8f9f7 778 f = (double)9223372036854775808.0 / ((double)(CLK_GetHCLKFreq()) * (double)reg);
<> 144:ef7eb2e8f9f7 779 EMAC->TSADDEND = (uint32_t)f;
<> 144:ef7eb2e8f9f7 780 EMAC->TSCTL |= (EMAC_TSCTL_TSUPDATE_Msk | EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk); // Fine update
<> 144:ef7eb2e8f9f7 781 }
<> 144:ef7eb2e8f9f7 782
<> 144:ef7eb2e8f9f7 783 /**
<> 144:ef7eb2e8f9f7 784 * @brief Disable IEEE1588 time stamp function
<> 144:ef7eb2e8f9f7 785 * @param None
<> 144:ef7eb2e8f9f7 786 * @return None
<> 144:ef7eb2e8f9f7 787 */
<> 144:ef7eb2e8f9f7 788 void EMAC_DisableTS(void)
<> 144:ef7eb2e8f9f7 789 {
<> 144:ef7eb2e8f9f7 790 EMAC->TSCTL = 0;
<> 144:ef7eb2e8f9f7 791 }
<> 144:ef7eb2e8f9f7 792
<> 144:ef7eb2e8f9f7 793 /**
<> 144:ef7eb2e8f9f7 794 * @brief Get current time stamp
<> 144:ef7eb2e8f9f7 795 * @param[out] pu32Sec Current second value
<> 144:ef7eb2e8f9f7 796 * @param[out] pu32Nsec Current nano second value
<> 144:ef7eb2e8f9f7 797 * @return None
<> 144:ef7eb2e8f9f7 798 */
<> 144:ef7eb2e8f9f7 799 void EMAC_GetTime(uint32_t *pu32Sec, uint32_t *pu32Nsec)
<> 144:ef7eb2e8f9f7 800 {
<> 144:ef7eb2e8f9f7 801 // Must read TSLSR firstly. Hardware will preserve TSMSR value at the time TSLSR read.
<> 144:ef7eb2e8f9f7 802 *pu32Nsec = EMAC_Subsec2Nsec(EMAC->TSSUBSEC);
<> 144:ef7eb2e8f9f7 803 *pu32Sec = EMAC->TSSEC;
<> 144:ef7eb2e8f9f7 804 }
<> 144:ef7eb2e8f9f7 805
<> 144:ef7eb2e8f9f7 806 /**
<> 144:ef7eb2e8f9f7 807 * @brief Set current time stamp
<> 144:ef7eb2e8f9f7 808 * @param[in] u32Sec Second value
<> 144:ef7eb2e8f9f7 809 * @param[in] u32Nsec Nano second value
<> 144:ef7eb2e8f9f7 810 * @return None
<> 144:ef7eb2e8f9f7 811 */
<> 144:ef7eb2e8f9f7 812 void EMAC_SetTime(uint32_t u32Sec, uint32_t u32Nsec)
<> 144:ef7eb2e8f9f7 813 {
<> 144:ef7eb2e8f9f7 814 // Disable time stamp counter before update time value (clear EMAC_TSCTL_TSIEN_Msk)
<> 144:ef7eb2e8f9f7 815 EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;
<> 144:ef7eb2e8f9f7 816 EMAC->UPDSEC = u32Sec;
<> 144:ef7eb2e8f9f7 817 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
<> 144:ef7eb2e8f9f7 818 EMAC->TSCTL |= (EMAC_TSCTL_TSIEN_Msk | EMAC_TSCTL_TSMODE_Msk);
<> 144:ef7eb2e8f9f7 819
<> 144:ef7eb2e8f9f7 820 }
<> 144:ef7eb2e8f9f7 821
<> 144:ef7eb2e8f9f7 822 /**
<> 144:ef7eb2e8f9f7 823 * @brief Enable alarm function and set alarm time
<> 144:ef7eb2e8f9f7 824 * @param[in] u32Sec Second value to trigger alarm
<> 144:ef7eb2e8f9f7 825 * @param[in] u32Nsec Nano second value to trigger alarm
<> 144:ef7eb2e8f9f7 826 * @return None
<> 144:ef7eb2e8f9f7 827 */
<> 144:ef7eb2e8f9f7 828 void EMAC_EnableAlarm(uint32_t u32Sec, uint32_t u32Nsec)
<> 144:ef7eb2e8f9f7 829 {
<> 144:ef7eb2e8f9f7 830
<> 144:ef7eb2e8f9f7 831 EMAC->ALMSEC = u32Sec;
<> 144:ef7eb2e8f9f7 832 EMAC->ALMSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
<> 144:ef7eb2e8f9f7 833 EMAC->TSCTL |= EMAC_TSCTL_TSALMEN_Msk;
<> 144:ef7eb2e8f9f7 834
<> 144:ef7eb2e8f9f7 835 }
<> 144:ef7eb2e8f9f7 836
<> 144:ef7eb2e8f9f7 837 /**
<> 144:ef7eb2e8f9f7 838 * @brief Disable alarm function
<> 144:ef7eb2e8f9f7 839 * @param None
<> 144:ef7eb2e8f9f7 840 * @return None
<> 144:ef7eb2e8f9f7 841 */
<> 144:ef7eb2e8f9f7 842 void EMAC_DisableAlarm(void)
<> 144:ef7eb2e8f9f7 843 {
<> 144:ef7eb2e8f9f7 844
<> 144:ef7eb2e8f9f7 845 EMAC->TSCTL &= ~EMAC_TSCTL_TSALMEN_Msk;
<> 144:ef7eb2e8f9f7 846
<> 144:ef7eb2e8f9f7 847 }
<> 144:ef7eb2e8f9f7 848
<> 144:ef7eb2e8f9f7 849 /**
<> 144:ef7eb2e8f9f7 850 * @brief Add a offset to current time
<> 144:ef7eb2e8f9f7 851 * @param[in] u32Neg Offset is negative value (u32Neg == 1) or positive value (u32Neg == 0).
<> 144:ef7eb2e8f9f7 852 * @param[in] u32Sec Second value to add to current time
<> 144:ef7eb2e8f9f7 853 * @param[in] u32Nsec Nano second value to add to current time
<> 144:ef7eb2e8f9f7 854 * @return None
<> 144:ef7eb2e8f9f7 855 */
<> 144:ef7eb2e8f9f7 856 void EMAC_UpdateTime(uint32_t u32Neg, uint32_t u32Sec, uint32_t u32Nsec)
<> 144:ef7eb2e8f9f7 857 {
<> 144:ef7eb2e8f9f7 858 EMAC->UPDSEC = u32Sec;
<> 144:ef7eb2e8f9f7 859 EMAC->UPDSUBSEC = EMAC_Nsec2Subsec(u32Nsec);
<> 144:ef7eb2e8f9f7 860 if(u32Neg)
<> 144:ef7eb2e8f9f7 861 EMAC->UPDSUBSEC |= BIT31; // Set bit 31 indicates this is a negative value
<> 144:ef7eb2e8f9f7 862
<> 144:ef7eb2e8f9f7 863 EMAC->TSCTL |= EMAC_TSCTL_TSUPDATE_Msk;
<> 144:ef7eb2e8f9f7 864
<> 144:ef7eb2e8f9f7 865 }
<> 144:ef7eb2e8f9f7 866
<> 144:ef7eb2e8f9f7 867
<> 144:ef7eb2e8f9f7 868 /*@}*/ /* end of group NUC472_442_EMAC_EXPORTED_FUNCTIONS */
<> 144:ef7eb2e8f9f7 869
<> 144:ef7eb2e8f9f7 870 /*@}*/ /* end of group NUC472_442_EMAC_Driver */
<> 144:ef7eb2e8f9f7 871
<> 144:ef7eb2e8f9f7 872 /*@}*/ /* end of group NUC472_442_Device_Driver */
<> 144:ef7eb2e8f9f7 873
<> 144:ef7eb2e8f9f7 874 /*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/