//***************************************************************************** // // emac.c - Driver for the Integrated Ethernet Controller // // Copyright (c) 2013-2017 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //***************************************************************************** //***************************************************************************** // //! \addtogroup emac_api //! @{ // //***************************************************************************** #include #include "types.h" #include #include #include "inc/hw_emac.h" #include "debug.h" #include "emac.h" #include "sysctl.h" #include "interrupt.h" #include "sw_crc.h" //***************************************************************************** // // Combined defines used in parameter validity checks. // //***************************************************************************** //***************************************************************************** // // Combined valid configuration flags. // //***************************************************************************** #define VALID_CONFIG_FLAGS (EMAC_CONFIG_USE_MACADDR1 | \ EMAC_CONFIG_SA_INSERT | \ EMAC_CONFIG_SA_REPLACE | \ EMAC_CONFIG_2K_PACKETS | \ EMAC_CONFIG_STRIP_CRC | \ EMAC_CONFIG_JABBER_DISABLE | \ EMAC_CONFIG_JUMBO_ENABLE | \ EMAC_CONFIG_IF_GAP_MASK | \ EMAC_CONFIG_CS_DISABLE | \ EMAC_CONFIG_100MBPS | \ EMAC_CONFIG_RX_OWN_DISABLE | \ EMAC_CONFIG_LOOPBACK | \ EMAC_CONFIG_FULL_DUPLEX | \ EMAC_CONFIG_CHECKSUM_OFFLOAD | \ EMAC_CONFIG_RETRY_DISABLE | \ EMAC_CONFIG_AUTO_CRC_STRIPPING | \ EMAC_CONFIG_BO_MASK | \ EMAC_CONFIG_DEFERRAL_CHK_ENABLE | \ EMAC_CONFIG_PREAMBLE_MASK) //***************************************************************************** // // Combined valid frame filter flags. // //***************************************************************************** #define VALID_FRMFILTER_FLAGS (EMAC_FRMFILTER_RX_ALL | \ EMAC_FRMFILTER_VLAN | \ EMAC_FRMFILTER_HASH_AND_PERFECT | \ EMAC_FRMFILTER_SADDR | \ EMAC_FRMFILTER_INV_SADDR | \ EMAC_FRMFILTER_PASS_NO_PAUSE | \ EMAC_FRMFILTER_PASS_ALL_CTRL | \ EMAC_FRMFILTER_PASS_ADDR_CTRL | \ EMAC_FRMFILTER_BROADCAST | \ EMAC_FRMFILTER_PASS_MULTICAST | \ EMAC_FRMFILTER_INV_DADDR | \ EMAC_FRMFILTER_HASH_MULTICAST | \ EMAC_FRMFILTER_HASH_UNICAST | \ EMAC_FRMFILTER_PROMISCUOUS) //***************************************************************************** // // Combined valid maskable interrupts. // //***************************************************************************** #define EMAC_MASKABLE_INTS (EMAC_INT_EARLY_RECEIVE | \ EMAC_INT_BUS_ERROR | \ EMAC_INT_EARLY_TRANSMIT | \ EMAC_INT_RX_WATCHDOG | \ EMAC_INT_RX_STOPPED | \ EMAC_INT_RX_NO_BUFFER | \ EMAC_INT_RECEIVE | \ EMAC_INT_TX_UNDERFLOW | \ EMAC_INT_RX_OVERFLOW | \ EMAC_INT_TX_JABBER | \ EMAC_INT_TX_NO_BUFFER | \ EMAC_INT_TX_STOPPED | \ EMAC_INT_TRANSMIT | \ EMAC_INT_NORMAL_INT | \ EMAC_INT_ABNORMAL_INT | \ EMAC_INT_PHY) //***************************************************************************** // // Combined valid normal interrupts. // //***************************************************************************** #define EMAC_NORMAL_INTS (EMAC_INT_TRANSMIT | \ EMAC_INT_RECEIVE | \ EMAC_INT_EARLY_RECEIVE | \ EMAC_INT_TX_NO_BUFFER) //***************************************************************************** // // Combined valid abnormal interrupts. // //***************************************************************************** #define EMAC_ABNORMAL_INTS (EMAC_INT_TX_STOPPED | \ EMAC_INT_TX_JABBER | \ EMAC_INT_RX_OVERFLOW | \ EMAC_INT_TX_UNDERFLOW | \ EMAC_INT_RX_NO_BUFFER | \ EMAC_INT_RX_STOPPED | \ EMAC_INT_RX_WATCHDOG | \ EMAC_INT_EARLY_TRANSMIT | \ EMAC_INT_BUS_ERROR) //***************************************************************************** // // Interrupt sources reported via the DMARIS register but which are not // masked (or enabled) via the DMAIM register. // //***************************************************************************** #define EMAC_NON_MASKED_INTS (EMAC_DMARIS_LPI | \ EMAC_DMARIS_TT | \ EMAC_DMARIS_PMT | \ EMAC_DMARIS_MMC) //***************************************************************************** // // The number of MAC addresses the module can store for filtering purposes. // //***************************************************************************** #define NUM_MAC_ADDR 4 //***************************************************************************** // // Macros aiding access to the MAC address registers. // //***************************************************************************** #define MAC_ADDR_OFFSET (EMAC_O_ADDR1L - EMAC_O_ADDR0L) #define EMAC_O_ADDRL(n) (EMAC_O_ADDR0L + (MAC_ADDR_OFFSET * (n))) #define EMAC_O_ADDRH(n) (EMAC_O_ADDR0H + (MAC_ADDR_OFFSET * (n))) //***************************************************************************** // // A structure used to help in choosing the correct clock divisor for the MII // based on the current system clock rate. // //***************************************************************************** static const struct { uint32_t ui32SysClockMax; uint32_t ui32Divisor; } g_pi16MIIClockDiv[] = { { 64000000, EMAC_MIIADDR_CR_35_60 }, { 104000000, EMAC_MIIADDR_CR_60_100 }, { 150000000, EMAC_MIIADDR_CR_100_150 } }; //***************************************************************************** // // The number of clock divisors in the above table. // //***************************************************************************** #define NUM_CLOCK_DIVISORS (sizeof(g_pi16MIIClockDiv) / \ sizeof(g_pi16MIIClockDiv[0])) //***************************************************************************** // // The define for accessing PHY registers in the MMD address space. // //***************************************************************************** #define DEV_ADDR(x) ((x & 0xF000) >> 12) #define REG_ADDR(x) ((x & 0x0FFF)) //***************************************************************************** // //! Initializes the Ethernet MAC and sets bus-related DMA parameters. //! //! \param ui32Base is the base address of the Ethernet controller. //! \param ui32SysClk is the current system clock frequency in Hertz. //! \param ui32BusConfig defines the bus operating mode for the Ethernet MAC //! DMA controller. //! \param ui32RxBurst is the maximum receive burst size in words. //! \param ui32TxBurst is the maximum transmit burst size in words. //! \param ui32DescSkipSize is the number of 32-bit words to skip between //! two unchained DMA descriptors. Values in the range 0 to 31 are valid. //! //! This function sets bus-related parameters for the Ethernet MAC DMA //! engines. It must be called after EMACPHYConfigSet() and called again //! after any subsequent call to EMACPHYConfigSet(). //! //! The \e ui32BusConfig parameter is the logical OR of various fields. The //! first sets the DMA channel priority weight: //! //! - \b EMAC_BCONFIG_DMA_PRIO_WEIGHT_1 //! - \b EMAC_BCONFIG_DMA_PRIO_WEIGHT_2 //! - \b EMAC_BCONFIG_DMA_PRIO_WEIGHT_3 //! - \b EMAC_BCONFIG_DMA_PRIO_WEIGHT_4 //! //! The second field sets the receive and transmit priorities used when //! arbitrating between the Rx and Tx DMA. The priorities are Rx:Tx unless //! \b EMAC_BCONFIG_TX_PRIORITY is also specified, in which case they become //! Tx:Rx. The priority provided here is ignored if //! \b EMAC_BCONFIG_PRIORITY_FIXED is specified. //! //! - \b EMAC_BCONFIG_PRIORITY_1_1 //! - \b EMAC_BCONFIG_PRIORITY_2_1 //! - \b EMAC_BCONFIG_PRIORITY_3_1 //! - \b EMAC_BCONFIG_PRIORITY_4_1 //! //! The following additional flags may also be defined: //! //! - \b EMAC_BCONFIG_TX_PRIORITY indicates that the transmit DMA should be //! higher priority in all arbitration for the system-side bus. If this is not //! defined, the receive DMA has higher priority. //! - \b EMAC_BCONFIG_ADDR_ALIGNED works in tandem with //! \b EMAC_BCONFIG_FIXED_BURST to control address alignment of AHB bursts. //! When both flags are specified, all bursts are aligned to the start address //! least significant bits. If \b EMAC_BCONFIG_FIXED_BURST is not specified, //! the first burst is unaligned but subsequent bursts are aligned to the //! address. //! - \b EMAC_BCONFIG_ALT_DESCRIPTORS indicates that the DMA engine should //! use the alternate descriptor format as defined in type //! \b tEMACDMADescriptor. If absent, the basic descriptor type is used. //! Alternate descriptors are required if using IEEE 1588-2008 advanced //! timestamping, VLAN or TCP/UDP/ICMP CRC insertion features. Note that, //! for clarity, emac.h does not contain type definitions for the basic //! descriptor type. Please see the technical reference manual/datasheet //! for information on basic descriptor structures. //! - \b EMAC_BCONFIG_PRIORITY_FIXED indicates that a fixed priority scheme //! should be employed when arbitrating between the transmit and receive DMA //! for system-side bus access. In this case, the receive channel always has //! priority unless \b EMAC_BCONFIG_TX_PRIORITY is set, in which case the //! transmit channel has priority. If \b EMAC_BCONFIG_PRIORITY_FIXED is not //! specified, a weighted round-robin arbitration scheme is used with the //! weighting defined using \b EMAC_BCONFIG_PRIORITY_1_1, //! \b EMAC_BCONFIG_PRIORITY_2_1, \b EMAC_BCONFIG_PRIORITY_3_1 or //! \b EMAC_BCONFIG_PRIORITY_4_1, and \b EMAC_BCONFIG_TX_PRIORITY. //! - \b EMAC_BCONFIG_FIXED_BURST indicates that fixed burst transfers should //! be used. //! - \b EMAC_BCONFIG_MIXED_BURST indicates that the DMA engine should use //! mixed burst types depending on the length of data to be transferred //! across the system bus. //! //! The \e ui32RxBurst and \e ui32TxBurst parameters indicate the maximum //! number of words that the relevant DMA should transfer in a single //! transaction. Valid values are 1, 2, 4, 8, 16 and 32. Any other value //! results in undefined behavior. //! //! The \e ui32DescSkipSize parameter is used when the descriptor lists are //! using ring mode (where descriptors are contiguous in memory with the last //! descriptor marked with the \b END_OF_RING flag) rather than chained mode //! (where each descriptor includes a field that points to the next descriptor //! in the list). In ring mode, the hardware uses the \e ui32DescSkipSize to //! skip past any application-defined fields after the end of the hardware- //! defined descriptor fields. The parameter value indicates the number of //! 32-bit words to skip after the last field of the hardware-defined //! descriptor to get to the first field of the next descriptor. When using //! arrays of either the \b tEMACDMADescriptor or \b tEMACAltDMADescriptor //! types defined for this driver, \e ui32DescSkipSize must be set to 1 to skip //! the \e pvNext pointer added to the end of each of these structures. //! Applications may modify these structure definitions to include their own //! application-specific data and modify \e ui32DescSkipSize appropriately if //! desired. //! //! \return None. // //***************************************************************************** void EMACInit(uint32_t ui32Base, uint32_t ui32SysClk, uint32_t ui32BusConfig, uint32_t ui32RxBurst, uint32_t ui32TxBurst, uint32_t ui32DescSkipSize) { uint32_t ui32Val, ui32Div; // // Parameter sanity checks. // ASSERT(ui32DescSkipSize < 32); ASSERT(ui32TxBurst < (32 * 8)); ASSERT(ui32RxBurst < (32 * 8)); // // Make sure that the DMA software reset is clear before continuing. // while (HWREG(EMAC0_BASE + EMAC_O_DMABUSMOD) & EMAC_DMABUSMOD_SWR) { } // // Set common flags. Note that this driver assumes we are always using // 8 word descriptors so we need to OR in EMAC_DMABUSMOD_ATDS here. // ui32Val = (ui32BusConfig | (ui32DescSkipSize << EMAC_DMABUSMOD_DSL_S) | EMAC_DMABUSMOD_ATDS); // // Do we need to use the 8X burst length multiplier? // if ((ui32TxBurst > 32) || (ui32RxBurst > 32)) { // // Divide both burst lengths by 8 and set the 8X burst length // multiplier. // ui32Val |= EMAC_DMABUSMOD_8XPBL; ui32TxBurst >>= 3; ui32RxBurst >>= 3; // // Sanity check - neither burst length should have become zero. If // they did, this indicates that the values passed are invalid. // ASSERT(ui32RxBurst); ASSERT(ui32TxBurst); } // // Are the receive and transmit burst lengths the same? // if (ui32RxBurst == ui32TxBurst) { // // Yes - set up to use a single burst length. // ui32Val |= (ui32TxBurst << EMAC_DMABUSMOD_PBL_S); } else { // // No - we need to use separate burst lengths for each. // ui32Val |= (EMAC_DMABUSMOD_USP | (ui32TxBurst << EMAC_DMABUSMOD_PBL_S) | (ui32RxBurst << EMAC_DMABUSMOD_RPBL_S)); } // // Finally, write the bus mode register. // HWREG(ui32Base + EMAC_O_DMABUSMOD) = ui32Val; // // Default the MII CSR clock divider based on the fastest system clock. // ui32Div = g_pi16MIIClockDiv[NUM_CLOCK_DIVISORS - 1].ui32Divisor; // // Find the MII CSR clock divider to use based on the current system clock. // for (ui32Val = 0; ui32Val < NUM_CLOCK_DIVISORS; ui32Val++) { if (ui32SysClk <= g_pi16MIIClockDiv[ui32Val].ui32SysClockMax) { ui32Div = g_pi16MIIClockDiv[ui32Val].ui32Divisor; break; } } // // Set the MII CSR clock speed. // HWREG(ui32Base + EMAC_O_MIIADDR) = ((HWREG(ui32Base + EMAC_O_MIIADDR) & ~EMAC_MIIADDR_CR_M) | ui32Div); // // Disable all the MMC interrupts as these are enabled by default at reset. // HWREG(ui32Base + EMAC_O_MMCRXIM) = 0xFFFFFFFF; HWREG(ui32Base + EMAC_O_MMCTXIM) = 0xFFFFFFFF; } //***************************************************************************** // //! Resets the Ethernet MAC. //! //! \param ui32Base is the base address of the Ethernet controller. //! //! This function performs a reset of the Ethernet MAC by resetting all logic //! and returning all registers to their default values. The function returns //! only after the hardware indicates that the reset has completed. //! //! \note To ensure that the reset completes, the selected PHY clock must be //! enabled when this function is called. If the PHY clock is absent, this //! function does not return. //! //! \return None. // //***************************************************************************** void EMACReset(uint32_t ui32Base) { // // Reset the Ethernet MAC. // HWREG(ui32Base + EMAC_O_DMABUSMOD) |= EMAC_DMABUSMOD_SWR; // // Wait for the reset to complete. // while (HWREG(ui32Base + EMAC_O_DMABUSMOD) & EMAC_DMABUSMOD_SWR) { } } //***************************************************************************** // //! Selects the Ethernet PHY in use. //! //! \param ui32Base is the base address of the Ethernet controller. //! \param ui32Config selects the PHY in use and, when using the internal //! PHY, allows various various PHY parameters to be configured. //! //! This function must be called prior to EMACInit() and EMACConfigSet() to //! select the Ethernet PHY to be used. If the internal PHY is selected, the //! function also allows configuration of various PHY parameters. Note that //! the Ethernet MAC is reset during this function call because parameters used //! by this function are latched by the hardware only on a MAC reset. The call //! sequence to select and configure the PHY, therefore, must be as follows: //! //! \verbatim //! // Enable and reset the MAC. //! SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0); //! SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0); //! if() //! { //! // Enable and reset the internal PHY. //! SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0); //! SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0); //! } //! //! // Ensure the MAC is completed its reset. //! while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0)) //! { //! } //! //! // Set the PHY type and configuration options. //! EMACPHYConfigSet(EMAC0_BASE, ); //! //! // Initialize and configure the MAC. //! EMACInit(EMAC0_BASE, , , //! , , ); //! EMACConfigSet(EMAC0_BASE, ); //! \endverbatim //! //! The \e ui32Config parameter must specify one of the following values: //! //! - \b EMAC_PHY_TYPE_INTERNAL selects the internal Ethernet PHY. //! - \b EMAC_PHY_TYPE_EXTERNAL_MII selects an external PHY connected via the //! MII interface. //! - \b EMAC_PHY_TYPE_EXTERNAL_RMII selects an external PHY connected via the //! RMII interface. //! //! If \b EMAC_PHY_TYPE_INTERNAL is selected, the following flags may be ORed //! into \e ui32Config to control various PHY features and modes. These flags //! are ignored if an external PHY is selected. //! //! - \b EMAC_PHY_INT_NIB_TXERR_DET_DIS disables odd nibble transmit error //! detection (sets the default value of PHY register MR10, bit 1). //! - \b EMAC_PHY_INT_RX_ER_DURING_IDLE enables receive error detection during //! idle (sets the default value of PHY register MR10, bit 2). //! - \b EMAC_PHY_INT_ISOLATE_MII_LLOSS ties the MII outputs low if no link is //! established in 100B-T and full duplex modes (sets the default value of PHY //! register MR10, bit 3). //! - \b EMAC_PHY_INT_LINK_LOSS_RECOVERY enables link loss recovery (sets the //! default value of PHY register MR9, bit 7). //! - \b EMAC_PHY_INT_TDRRUN enables execution of the TDR procedure after a link //! down event (sets the default value of PHY register MR9, bit 8). //! - \b EMAC_PHY_INT_LD_ON_RX_ERR_COUNT enables link down if the receiver //! error count reaches 32 within a 10-us interval (sets the default value of //! PHY register MR11 bit 3). //! - \b EMAC_PHY_INT_LD_ON_MTL3_ERR_COUNT enables link down if the MTL3 error //! count reaches 20 in a 10 us-interval (sets the default value of PHY register //! MR11 bit 2). //! - \b EMAC_PHY_INT_LD_ON_LOW_SNR enables link down if the low SNR threshold //! is crossed 20 times in a 10 us-interval (sets the default value of PHY //! register MR11 bit 1). //! - \b EMAC_PHY_INT_LD_ON_SIGNAL_ENERGY enables link down if energy detector //! indicates Energy Loss (sets the default value of PHY register MR11 bit 0). //! - \b EMAC_PHY_INT_POLARITY_SWAP inverts the polarity on both TPTD and TPRD //! pairs (sets the default value of PHY register MR11 bit 5). //! - \b EMAC_PHY_INT_MDI_SWAP swaps the MDI pairs putting receive on the TPTD //! pair and transmit on TPRD (sets the default value of PHY register MR11 bit //! 6). //! - \b EMAC_PHY_INT_ROBUST_MDIX enables robust auto MDI-X resolution (sets the //! default value of PHY register MR9 bit 5). //! - \b EMAC_PHY_INT_FAST_MDIX enables fast auto-MDI/MDIX resolution (sets the //! default value of PHY register MR9 bit 6). //! - \b EMAC_PHY_INT_MDIX_EN enables auto-MDI/MDIX crossover (sets the //! default value of PHY register MR9 bit 14). //! - \b EMAC_PHY_INT_FAST_RXDV_DETECT enables fast RXDV detection (set the //! default value of PHY register MR9 bit 1). //! - \b EMAC_PHY_INT_FAST_L_UP_DETECT enables fast link-up time during parallel //! detection (sets the default value of PHY register MR10 bit 6) //! - \b EMAC_PHY_INT_EXT_FULL_DUPLEX forces full-duplex while working with a //! link partner in forced 100B-TX (sets the default value of PHY register //! MR10 bit 5). //! - \b EMAC_PHY_INT_FAST_AN_80_50_35 enables fast auto-negotiation using //! break link, link fail inhibit and wait timers set to 80, 50 and 35 //! respectively (sets the default value of PHY register MR9 bits [4:2] to //! 3b100). //! - \b EMAC_PHY_INT_FAST_AN_120_75_50 enables fast auto-negotiation using //! break link, link fail inhibit and wait timers set to 120, 75 and 50 //! respectively (sets the default value of PHY register MR9 bits [4:2] to //! 3b101). //! - \b EMAC_PHY_INT_FAST_AN_140_150_100 enables fast auto-negotiation using //! break link, link fail inhibit and wait timers set to 140, 150 and 100 //! respectively (sets the default value of PHY register MR9 bits [4:2] to //! 3b110). //! - \b EMAC_PHY_FORCE_10B_T_HALF_DUPLEX disables auto-negotiation and forces //! operation in 10Base-T, half duplex mode (sets the default value of PHY //! register MR9 bits [13:11] to 3b000). //! - \b EMAC_PHY_FORCE_10B_T_FULL_DUPLEX disables auto-negotiation and forces //! operation in 10Base-T, full duplex mode (sets the default value of PHY //! register MR9 bits [13:11] to 3b001). //! - \b EMAC_PHY_FORCE_100B_T_HALF_DUPLEX disables auto-negotiation and forces //! operation in 100Base-T, half duplex mode (sets the default value of PHY //! register MR9 bits [13:11] to 3b010). //! - \b EMAC_PHY_FORCE_100B_T_FULL_DUPLEX disables auto-negotiation and forces //! operation in 100Base-T, full duplex mode (sets the default value of PHY //! register MR9 bits [13:11] to 3b011). //! - \b EMAC_PHY_AN_10B_T_HALF_DUPLEX enables auto-negotiation and advertises //! 10Base-T, half duplex mode (sets the default value of PHY register MR9 bits //! [13:11] to 3b100). //! - \b EMAC_PHY_AN_10B_T_FULL_DUPLEX enables auto-negotiation and advertises //! 10Base-T half or full duplex modes (sets the default value of PHY register //! MR9 bits [13:11] to 3b101). //! - \b EMAC_PHY_AN_100B_T_HALF_DUPLEX enables auto-negotiation and advertises //! 10Base-T half or full duplex, and 100Base-T half duplex modes (sets the //! default value of PHY register MR9 bits [13:11] to 3b110). //! - \b EMAC_PHY_AN_100B_T_FULL_DUPLEX enables auto-negotiation and advertises //! 10Base-T half or full duplex, and 100Base-T half or full duplex modes (sets //! the default value of PHY register MR9 bits [13:11] to 3b111). //! - \b EMAC_PHY_INT_HOLD prevents the PHY from transmitting energy on the //! line. //! //! As a side effect of this function, the Ethernet MAC is reset so any //! previous MAC configuration is lost. //! //! \return None. // //***************************************************************************** void EMACPHYConfigSet(uint32_t ui32Base, uint32_t ui32Config) { // // Write the Ethernet PHY configuration to the peripheral configuration // register. // HWREG(ui32Base + EMAC_O_PC) = ui32Config; // // If using the internal PHY, reset it to ensure that new configuration is // latched there. // if ((ui32Config & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_INTERNAL) { SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0)) { // // Wait for the PHY reset to complete. // } // // Delay a bit longer to ensure that the PHY reset has completed. // SysCtlDelay(10000); } // // If using an external RMII PHY, we must set 2 bits in the Ethernet MAC // Clock Configuration Register. // if ((ui32Config & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_EXTERNAL_RMII) { // // Select and enable the external clock from the RMII PHY. // HWREG(EMAC0_BASE + EMAC_O_CC) |= EMAC_CC_CLKEN; } else { // // Disable the external clock. // HWREG(EMAC0_BASE + EMAC_O_CC) &= ~EMAC_CC_CLKEN; } // // Reset the MAC regardless of whether the PHY connection changed or not. // EMACReset(EMAC0_BASE); SysCtlDelay(1000); } //***************************************************************************** // //! Configures basic Ethernet MAC operation parameters. //! //! \param ui32Base is the base address of the Ethernet controller. //! \param ui32Config provides various flags and values configuring the MAC. //! \param ui32ModeFlags provides configuration relating to the transmit and //! receive DMA engines. //! \param ui32RxMaxFrameSize sets the maximum receive frame size above which //! an error is reported. //! //! This function is called to configure basic operating parameters for the //! MAC and its DMA engines. //! //! The \e ui32Config parameter is the logical OR of various fields and //! flags. The first field determines which MAC address is used during //! insertion or replacement for all transmitted frames. Valid options are //! //! - \b EMAC_CONFIG_USE_MACADDR1 and //! - \b EMAC_CONFIG_USE_MACADDR0 //! //! The interframe gap between transmitted frames is controlled using one of //! the following values: //! //! - \b EMAC_CONFIG_IF_GAP_96BITS //! - \b EMAC_CONFIG_IF_GAP_88BITS //! - \b EMAC_CONFIG_IF_GAP_80BITS //! - \b EMAC_CONFIG_IF_GAP_72BITS //! - \b EMAC_CONFIG_IF_GAP_64BITS //! - \b EMAC_CONFIG_IF_GAP_56BITS //! - \b EMAC_CONFIG_IF_GAP_48BITS //! - \b EMAC_CONFIG_IF_GAP_40BITS //! //! The number of bytes of preamble added to the beginning of every transmitted //! frame is selected using one of the following values: //! //! - \b EMAC_CONFIG_7BYTE_PREAMBLE //! - \b EMAC_CONFIG_5BYTE_PREAMBLE //! - \b EMAC_CONFIG_3BYTE_PREAMBLE //! //! The back-off limit determines the range of the random time that the MAC //! delays after a collision and before attempting to retransmit a frame. One //! of the following values must be used to select this limit. In each case, //! the retransmission delay in terms of 512 bit time slots, is the lower of //! (2 ** N) and a random number between 0 and the selected backoff-limit. //! //! - \b EMAC_CONFIG_BO_LIMIT_1024 //! - \b EMAC_CONFIG_BO_LIMIT_256 //! - \b EMAC_CONFIG_BO_LIMIT_16 //! - \b EMAC_CONFIG_BO_LIMIT_2 //! //! Control over insertion or replacement of the source address in all //! transmitted frames is provided by using one of the following fields: //! //! - \b EMAC_CONFIG_SA_INSERT causes the MAC address (0 or 1 depending //! on whether \b EMAC_CONFIG_USE_MACADDR0 or \b EMAC_CONFIG_USE_MACADDR1 //! was specified) to be inserted into all transmitted frames. //! - \b EMAC_CONFIG_SA_REPLACE causes the MAC address to be replaced with //! the selected address in all transmitted frames. //! - \b EMAC_CONFIG_SA_FROM_DESCRIPTOR causes control of source address //! insertion or deletion to be controlled by fields in the DMA transmit //! descriptor, allowing control on a frame-by-frame basis. //! //! Whether the interface attempts to operate in full- or half-duplex mode is //! controlled by one of the following flags: //! //! - \b EMAC_CONFIG_FULL_DUPLEX //! - \b EMAC_CONFIG_HALF_DUPLEX //! //! The following additional flags may also be specified: //! //! - \b EMAC_CONFIG_2K_PACKETS enables IEEE802.3as support for 2K packets. //! When specified, the MAC considers all frames up to 2000 bytes in length as //! normal packets. When \b EMAC_CONFIG_JUMBO_ENABLE is not specified, all //! frames larger than 2000 bytes are treated as Giant frames. This flag is //! ignored if \b EMAC_CONFIG_JUMBO_ENABLE is specified. //! - \b EMAC_CONFIG_STRIP_CRC causes the 4-byte CRC of all Ethernet type //! frames to be stripped and dropped before the frame is forwarded to the //! application. //! - \b EMAC_CONFIG_JABBER_DISABLE disables the jabber timer on the //! transmitter and enables frames of up to 16384 bytes to be transmitted. If //! this flag is absent, the MAC does not allow more than 2048 (or 10240 if //! \b EMAC_CONFIG_JUMBO_ENABLE is specified) bytes to be sent in any one //! frame. //! - \b EMAC_CONFIG_JUMBO_ENABLE enables Jumbo Frames, allowing frames of //! up to 9018 (or 9022 if using VLAN tagging) to be handled without reporting //! giant frame errors. //! - \b EMAC_CONFIG_100MBPS forces the MAC to communicate with the PHY using //! 100Mbps signaling. If this option is not specified, the MAC uses 10Mbps //! signaling. This speed setting is important when using an external RMII //! PHY where the selected rate must match the PHY's setting which may have //! been made as a result of auto-negotiation. When using the internal PHY //! or an external MII PHY, the signaling rate is controlled by the PHY- //! provided transmit and receive clocks. //! - \b EMAC_CONFIG_CS_DISABLE disables Carrier Sense during transmission //! when operating in half-duplex mode. //! - \b EMAC_CONFIG_RX_OWN_DISABLE disables reception of transmitted frames //! when operating in half-duplex mode. //! - \b EMAC_CONFIG_LOOPBACK enables internal loopback. //! - \b EMAC_CONFIG_CHECKSUM_OFFLOAD enables IPv4 header checksum checking //! and IPv4 or IPv6 TCP, UPD or ICMP payload checksum checking. The results //! of the checksum calculations are reported via status fields in the DMA //! receive descriptors. //! - \b EMAC_CONFIG_RETRY_DISABLE disables retransmission in cases where //! half-duplex mode is in use and a collision occurs. This condition causes //! the current frame to be ignored and a frame abort to be reported in the //! transmit frame status. //! - \b EMAC_CONFIG_AUTO_CRC_STRIPPING strips the last 4 bytes (frame check //! sequence) from all Ether type frames before forwarding the frames to the //! application. //! - \b EMAC_CONFIG_DEFERRAL_CHK_ENABLE enables transmit deferral checking //! in half-duplex mode. When enabled, the transmitter reports an error if it //! is unable to transmit a frame for more than 24288 bit times (or 155680 //! bit times in Jumbo frame mode) due to an active carrier sense signal on //! the MII. //! //! The \e ui32ModeFlags parameter sets operating parameters related to the //! internal MAC FIFOs. It comprises a logical OR of the following fields. //! The first selects the transmit FIFO threshold. Transmission of a frame //! begins when this amount of data or a full frame exists in the transmit //! FIFO. This field is ignored if \b EMAC_MODE_TX_STORE_FORWARD is //! included. One of the following must be specified: //! //! - \b EMAC_MODE_TX_THRESHOLD_16_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_24_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_32_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_40_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_64_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_128_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_192_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_256_BYTES //! //! The second field controls the receive FIFO threshold. DMA transfers of //! received data begin either when the receive FIFO contains a full frame //! or this number of bytes. This field is ignored if //! \b EMAC_MODE_RX_STORE_FORWARD is included. One of the following must be //! specified: //! //! - \b EMAC_MODE_RX_THRESHOLD_64_BYTES //! - \b EMAC_MODE_RX_THRESHOLD_32_BYTES //! - \b EMAC_MODE_RX_THRESHOLD_96_BYTES //! - \b EMAC_MODE_RX_THRESHOLD_128_BYTES //! //! The following additional flags may be specified: //! //! - \b EMAC_MODE_KEEP_BAD_CRC causes frames with TCP/IP checksum errors //! to be forwarded to the application if those frames do not have any errors //! (including FCS errors) in the Ethernet framing. In these cases, the frames //! have errors only in the payload. If this flag is not specified, all frames //! with any detected error are discarded unless \b EMAC_MODE_RX_ERROR_FRAMES //! is also specified. //! - \b EMAC_MODE_RX_STORE_FORWARD causes the receive DMA to read frames //! from the FIFO only after the complete frame has been written to it. If //! this mode is enabled, the receive threshold is ignored. //! - \b EMAC_MODE_RX_FLUSH_DISABLE disables the flushing of received frames //! in cases where receive descriptors or buffers are unavailable. //! - \b EMAC_MODE_TX_STORE_FORWARD causes the transmitter to start //! transmitting a frame only after the whole frame has been written to the //! transmit FIFO. If this mode is enabled, the transmit threshold is ignored. //! - \b EMAC_MODE_RX_ERROR_FRAMES causes all frames other than runt error //! frames to be forwarded to the receive DMA regardless of any errors detected //! in the frames. //! - \b EMAC_MODE_RX_UNDERSIZED_FRAMES causes undersized frames (frames //! shorter than 64 bytes but with no errors) to the application. If this //! option is not selected, all undersized frames are dropped by the receiver //! unless it has already started transferring them to the receive FIFO due to //! the receive threshold setting. //! - \b EMAC_MODE_OPERATE_2ND_FRAME enables the transmit DMA to operate on a //! second frame while waiting for the previous frame to be transmitted and //! associated status and timestamps to be reported. If absent, the transmit //! DMA works on a single frame at any one time, waiting for that frame to be //! transmitted and its status to be received before moving on to the next //! frame. //! //! The \e ui32RxMaxFrameSize parameter may be used to override the default //! setting for the maximum number of bytes that can be received in a frame //! before that frame is flagged as being in error. If the parameter is set //! to 0, the default hardware settings are applied. If non-zero, any frame //! received which is longer than the \e ui32RxMaxFrameSize, regardless of //! whether the MAC is configured for normal or Jumbo frame operation, is //! flagged as an error. //! //! \return None. // //***************************************************************************** void EMACConfigSet(uint32_t ui32Base, uint32_t ui32Config, uint32_t ui32ModeFlags, uint32_t ui32RxMaxFrameSize) { // // Parameter sanity check. Note that we allow TX_ENABLED and RX_ENABLED // here because we'll mask them off before writing the value and this // makes back-to-back EMACConfigGet/EMACConfigSet calls work without the // caller needing to explicitly remove these bits from the parameter. // ASSERT((ui32Config & ~(VALID_CONFIG_FLAGS | EMAC_CONFIG_TX_ENABLED | EMAC_CONFIG_RX_ENABLED)) == 0); ASSERT(!ui32RxMaxFrameSize || ((ui32RxMaxFrameSize < 0x4000) && (ui32RxMaxFrameSize > 1522))); // // Set the configuration flags as specified. Note that we unconditionally // OR in the EMAC_CFG_PS bit here since this implementation supports only // MII and RMII interfaces to the PHYs. // HWREG(ui32Base + EMAC_O_CFG) = ((HWREG(ui32Base + EMAC_O_CFG) & ~VALID_CONFIG_FLAGS) | ui32Config | EMAC_CFG_PS); // // Set the maximum receive frame size. If 0 is passed, this implies // that the default maximum frame size should be used so just turn off // the override. // if (ui32RxMaxFrameSize) { HWREG(ui32Base + EMAC_O_WDOGTO) = ui32RxMaxFrameSize | EMAC_WDOGTO_PWE; } else { HWREG(ui32Base + EMAC_O_WDOGTO) &= ~EMAC_WDOGTO_PWE; } // // Set the operating mode register. // HWREG(ui32Base + EMAC_O_DMAOPMODE) = ui32ModeFlags; } //***************************************************************************** // //! Returns the Ethernet MAC's current basic configuration parameters. //! //! \param ui32Base is the base address of the Ethernet controller. //! \param pui32Config points to storage that is written with Ethernet MAC //! configuration. //! \param pui32Mode points to storage that is written with Ethernet MAC mode //! information. //! \param pui32RxMaxFrameSize points to storage that is written with the //! maximum receive frame size. //! //! This function is called to query the basic operating parameters for the //! MAC and its DMA engines. //! //! The \e pui32Config parameter is written with the logical OR of various //! fields and flags. The first field describes which MAC address is used //! during insertion or replacement for all transmitted frames. Valid options //! are //! //! - \b EMAC_CONFIG_USE_MACADDR1 //! - \b EMAC_CONFIG_USE_MACADDR0 //! //! The interframe gap between transmitted frames is given using one of the //! following values: //! //! - \b EMAC_CONFIG_IF_GAP_96BITS //! - \b EMAC_CONFIG_IF_GAP_88BITS //! - \b EMAC_CONFIG_IF_GAP_80BITS //! - \b EMAC_CONFIG_IF_GAP_72BITS //! - \b EMAC_CONFIG_IF_GAP_64BITS //! - \b EMAC_CONFIG_IF_GAP_56BITS //! - \b EMAC_CONFIG_IF_GAP_48BITS //! - \b EMAC_CONFIG_IF_GAP_40BITS //! //! The number of bytes of preamble added to the beginning of every transmitted //! frame is described using one of the following values: //! //! - \b EMAC_CONFIG_7BYTE_PREAMBLE //! - \b EMAC_CONFIG_5BYTE_PREAMBLE //! - \b EMAC_CONFIG_3BYTE_PREAMBLE //! //! The back-off limit determines the range of the random time that the MAC //! delays after a collision and before attempting to retransmit a frame. One //! of the following values provides the currently selected limit. In each //! case the retransmission delay in terms of 512 bit time slots, is the //! lower of (2 ** N) and a random number between 0 and the reported //! backoff-limit. //! //! - \b EMAC_CONFIG_BO_LIMIT_1024 //! - \b EMAC_CONFIG_BO_LIMIT_256 //! - \b EMAC_CONFIG_BO_LIMIT_16 //! - \b EMAC_CONFIG_BO_LIMIT_2 //! //! Handling of insertion or replacement of the source address in all //! transmitted frames is described by one of the following fields: //! //! - \b EMAC_CONFIG_SA_INSERT causes the MAC address (0 or 1 depending //! on whether \b EMAC_CONFIG_USE_MACADDR0 or \b EMAC_CONFIG_USE_MACADDR1 //! was specified) to be inserted into all transmitted frames. //! - \b EMAC_CONFIG_SA_REPLACE causes the MAC address to be replaced with //! the selected address in all transmitted frames. //! - \b EMAC_CONFIG_SA_FROM_DESCRIPTOR causes control of source address //! insertion or deletion to be controlled by fields in the DMA transmit //! descriptor, allowing control on a frame-by-frame basis. //! //! Whether the interface attempts to operate in full- or half-duplex mode is //! reported by one of the following flags: //! //! - \b EMAC_CONFIG_FULL_DUPLEX //! - \b EMAC_CONFIG_HALF_DUPLEX //! //! The following additional flags may also be included: //! //! - \b EMAC_CONFIG_2K_PACKETS indicates that IEEE802.3as support for 2K //! packets is enabled. When present, the MAC considers all frames up to 2000 //! bytes in length as normal packets. When \b EMAC_CONFIG_JUMBO_ENABLE is //! not reported, all frames larger than 2000 bytes are treated as Giant //! frames. The value of this flag should be ignored if //! \b EMAC_CONFIG_JUMBO_ENABLE is also reported. //! - \b EMAC_CONFIG_STRIP_CRC indicates that the 4-byte CRC of all Ethernet //! type frames is being stripped and dropped before the frame is forwarded to //! the application. //! - \b EMAC_CONFIG_JABBER_DISABLE indicates that the the jabber timer on the //! transmitter is disabled, allowing frames of up to 16384 bytes to be //! transmitted. If this flag is absent, the MAC does not allow more than 2048 //! (or 10240 if \b EMAC_CONFIG_JUMBO_ENABLE is reported) bytes to be sent in //! any one frame. //! - \b EMAC_CONFIG_JUMBO_ENABLE indicates that Jumbo Frames of up to 9018 //! (or 9022 if using VLAN tagging) are enabled. //! - \b EMAC_CONFIG_CS_DISABLE indicates that Carrier Sense is disabled //! during transmission when operating in half-duplex mode. //! - \b EMAC_CONFIG_100MBPS indicates that the MAC is using 100Mbps //! signaling to communicate with the PHY. //! - \b EMAC_CONFIG_RX_OWN_DISABLE indicates that reception of transmitted //! frames is disabled when operating in half-duplex mode. //! - \b EMAC_CONFIG_LOOPBACK indicates that internal loopback is enabled. //! - \b EMAC_CONFIG_CHECKSUM_OFFLOAD indicates that IPv4 header checksum //! checking and IPv4 or IPv6 TCP, UPD or ICMP payload checksum checking is //! enabled. The results of the checksum calculations are reported via status //! fields in the DMA receive descriptors. //! - \b EMAC_CONFIG_RETRY_DISABLE indicates that retransmission is disabled //! in cases where half-duplex mode is in use and a collision occurs. This //! condition causes the current frame to be ignored and a frame abort to be //! reported in the transmit frame status. //! - \b EMAC_CONFIG_AUTO_CRC_STRIPPING indicates that the last 4 bytes //! (frame check sequence) from all Ether type frames are being stripped before //! frames are forwarded to the application. //! - \b EMAC_CONFIG_DEFERRAL_CHK_ENABLE indicates that transmit deferral //! checking is disabled in half-duplex mode. When enabled, the transmitter //! reports an error if it is unable to transmit a frame for more than 24288 //! bit times (or 155680 bit times in Jumbo frame mode) due to an active //! carrier sense signal on the MII. //! - \b EMAC_CONFIG_TX_ENABLED indicates that the MAC transmitter is //! currently enabled. //! - \b EMAC_CONFIG_RX_ENABLED indicates that the MAC receiver is //! currently enabled. //! //! The \e pui32ModeFlags parameter is written with operating parameters //! related to the internal MAC FIFOs. It comprises a logical OR of the //! following fields. The first field reports the transmit FIFO threshold. //! Transmission of a frame begins when this amount of data or a full frame //! exists in the transmit FIFO. This field should be ignored if //! \b EMAC_MODE_TX_STORE_FORWARD is also reported. One of the following //! values is reported: //! //! - \b EMAC_MODE_TX_THRESHOLD_16_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_24_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_32_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_40_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_64_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_128_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_192_BYTES //! - \b EMAC_MODE_TX_THRESHOLD_256_BYTES //! //! The second field reports the receive FIFO threshold. DMA transfers of //! received data begin either when the receive FIFO contains a full frame //! or this number of bytes. This field should be ignored if //! \b EMAC_MODE_RX_STORE_FORWARD is included. One of the following values //! is reported: //! //! - \b EMAC_MODE_RX_THRESHOLD_64_BYTES //! - \b EMAC_MODE_RX_THRESHOLD_32_BYTES //! - \b EMAC_MODE_RX_THRESHOLD_96_BYTES //! - \b EMAC_MODE_RX_THRESHOLD_128_BYTES //! //! The following additional flags may be included: //! //! - \b EMAC_MODE_KEEP_BAD_CRC indicates that frames with TCP/IP checksum //! errors are being forwarded to the application if those frames do not have //! any errors (including FCS errors) in the Ethernet framing. In these cases, //! the frames have errors only in the payload. If this flag is not reported, //! all frames with any detected error are discarded unless //! \b EMAC_MODE_RX_ERROR_FRAMES is also reported. //! - \b EMAC_MODE_RX_STORE_FORWARD indicates that the receive DMA is //! configured to read frames from the FIFO only after the complete frame has //! been written to it. If this mode is enabled, the receive threshold is //! ignored. //! - \b EMAC_MODE_RX_FLUSH_DISABLE indicates that the flushing of received //! frames is disabled in cases where receive descriptors or buffers are //! unavailable. //! - \b EMAC_MODE_TX_STORE_FORWARD indicates that the transmitter is //! configured to transmit a frame only after the whole frame has been written //! to the transmit FIFO. If this mode is enabled, the transmit threshold is //! ignored. //! - \b EMAC_MODE_RX_ERROR_FRAMES indicates that all frames other than runt //! error frames are being forwarded to the receive DMA regardless of any //! errors detected in the frames. //! - \b EMAC_MODE_RX_UNDERSIZED_FRAMES indicates that undersized frames //! (frames shorter than 64 bytes but with no errors) are being forwarded to //! the application. If this option is not reported, all undersized frames are //! dropped by the receiver unless it has already started transferring them to //! the receive FIFO due to the receive threshold setting. //! - \b EMAC_MODE_OPERATE_2ND_FRAME indicates that the transmit DMA is //! configured to operate on a second frame while waiting for the previous //! frame to be transmitted and associated status and timestamps to be reported. //! If absent, the transmit DMA works on a single frame at any one time, //! waiting for that frame to be transmitted and its status to be received //! before moving on to the next frame. //! - \b EMAC_MODE_TX_DMA_ENABLED indicates that the transmit DMA engine is //! currently enabled. //! - \b EMAC_MODE_RX_DMA_ENABLED indicates that the receive DMA engine is //! currently enabled. //! //! The \e pui32RxMaxFrameSize is written with the currently configured maximum //! receive packet size. Packets larger than this are flagged as being in //! error. //! //! \return None. // //***************************************************************************** void EMACConfigGet(uint32_t ui32Base, uint32_t *pui32Config, uint32_t *pui32Mode, uint32_t *pui32RxMaxFrameSize) { uint32_t ui32Value; // // Parameter sanity check. // ASSERT(pui32Mode); ASSERT(pui32Config); ASSERT(pui32RxMaxFrameSize); // // Return the mode information from the operation mode register. // *pui32Mode = HWREG(ui32Base + EMAC_O_DMAOPMODE); // // Return the current configuration flags from the EMAC_O_CFG register. // *pui32Config = (HWREG(ui32Base + EMAC_O_CFG) & (VALID_CONFIG_FLAGS | EMAC_CONFIG_TX_ENABLED | EMAC_CONFIG_RX_ENABLED)); // // Get the receive packet size watchdog value. // ui32Value = HWREG(ui32Base + EMAC_O_WDOGTO); if (ui32Value & EMAC_WDOGTO_PWE) { // // The watchdog is enables so the maximum packet length can be read // from the watchdog timeout register. // *pui32RxMaxFrameSize = ui32Value & EMAC_WDOGTO_WTO_M; } else { // // The maximum packet size override found in the watchdog timer // register is not enabled so the maximum packet size is determined // by whether or not jumbo frame mode is enabled. // if (HWREG(ui32Base + EMAC_O_CFG) & EMAC_CFG_JFEN) { // // Jumbo frames are enabled so the watchdog kicks in at 10240 // bytes. // *pui32RxMaxFrameSize = 10240; } else { // // Jumbo frames are not enabled so the watchdog kicks in at // 2048 bytes. // *pui32RxMaxFrameSize = 2048; } } } //***************************************************************************** // //! Sets the MAC address of the Ethernet controller. //! //! \param ui32Base is the base address of the Ethernet controller. //! \param ui32Index is the zero-based index of the MAC address to set. //! \param pui8MACAddr is the pointer to the array of MAC-48 address octets. //! //! This function programs the IEEE-defined MAC-48 address specified in //! \e pui8MACAddr into the Ethernet controller. This address is used by the //! Ethernet controller for hardware-level filtering of incoming Ethernet //! packets (when promiscuous mode is not enabled). Index 0 is used to hold //! the local node's MAC address which is inserted into all transmitted //! packets. //! //! The controller may support several Ethernet MAC address slots, each of which //! may be programmed independently and used to filter incoming packets. The //! number of MAC addresses that the hardware supports may be queried using a //! call to EMACNumAddrGet(). The value of the \e ui32Index parameter must //! lie in the range from 0 to (number of MAC addresses - 1) inclusive. //! //! The MAC-48 address is defined as 6 octets, illustrated by the following //! example address. The numbers are shown in hexadecimal format. //! //! AC-DE-48-00-00-80 //! //! In this representation, the first three octets (AC-DE-48) are the //! Organizationally Unique Identifier (OUI). This is a number assigned by //! the IEEE to an organization that requests a block of MAC addresses. The //! last three octets (00-00-80) are a 24-bit number managed by the OUI owner //! to uniquely identify a piece of hardware within that organization that is //! to be connected to the Ethernet. //! //! In this representation, the octets are transmitted from left to right, //! with the ``AC'' octet being transmitted first and the ``80'' octet being //! transmitted last. Within an octet, the bits are transmitted LSB to MSB. //! For this address, the first bit to be transmitted would be ``0'', the LSB //! of ``AC'', and the last bit to be transmitted would be ``1'', the MSB of //! ``80''. //! //! The address passed to this function in the \e pui8MACAddr array is //! ordered with the first byte to be transmitted in the first array entry. //! For example, the address given above could be represented using the //! following array: //! //! uint8_t g_pui8MACAddr[] = { 0xAC, 0xDE, 0x48, 0x00, 0x00, 0x80 }; //! //! If the MAC address set by this function is currently enabled, it remains //! enabled following this call. Similarly, any filter configured for //! the MAC address remains unaffected by a change in the address. //! //! \return None. // //***************************************************************************** void EMACAddrSet(uint32_t ui32Base, uint32_t ui32Index, const uint8_t *pui8MACAddr) { // // Parameter sanity check. // ASSERT(ui32Index < NUM_MAC_ADDR); ASSERT(pui8MACAddr); // // Set the high 2 bytes of the MAC address. Note that we must set the // registers in this order since the address is latched internally // on the write to EMAC_O_ADDRL. // HWREG(ui32Base + EMAC_O_ADDRH(ui32Index)) = ((HWREG(ui32Base + EMAC_O_ADDRH(ui32Index)) & 0xFFFF0000) | pui8MACAddr[4] | (pui8MACAddr[5] << 8)); // // Set the first 4 bytes of the MAC address // HWREG(ui32Base + EMAC_O_ADDRL(ui32Index)) = (pui8MACAddr[0] | (pui8MACAddr[1] << 8) | (pui8MACAddr[2] << 16) | (pui8MACAddr[3] << 24)); } //***************************************************************************** // //! Gets one of the MAC addresses stored in the Ethernet controller. //! //! \param ui32Base is the base address of the controller. //! \param ui32Index is the zero-based index of the MAC address to return. //! \param pui8MACAddr is the pointer to the location in which to store the //! array of MAC-48 address octets. //! //! This function reads the currently programmed MAC address into the //! \e pui8MACAddr buffer. The \e ui32Index parameter defines which of the //! hardware's MAC addresses to return. The number of MAC addresses supported //! by the controller may be queried using a call to EMACNumAddrGet(). //! Index 0 refers to the MAC address of the local node. Other indices are //! used to define MAC addresses when filtering incoming packets. //! //! The address is written to the pui8MACAddr array ordered with the first byte //! to be transmitted in the first array entry. For example, if the address //! is written in its usual form with the Organizationally Unique Identifier //! (OUI) shown first as: //! //! AC-DE-48-00-00-80 //! //! the data is returned with 0xAC in the first byte of the array, 0xDE in //! the second, 0x48 in the third and so on. //! //! \return None. // //***************************************************************************** void EMACAddrGet(uint32_t ui32Base, uint32_t ui32Index, uint8_t *pui8MACAddr) { uint32_t ui32Val; // // Parameter sanity check. // ASSERT(ui32Index < NUM_MAC_ADDR); ASSERT(pui8MACAddr); // // Get the first 4 bytes of the MAC address. // ui32Val = HWREG(ui32Base + EMAC_O_ADDRL(ui32Index)); pui8MACAddr[0] = ui32Val & 0xFF; pui8MACAddr[1] = (ui32Val >> 8) & 0xFF; pui8MACAddr[2] = (ui32Val >> 16) & 0xFF; pui8MACAddr[3] = (ui32Val >> 24) & 0xFF; // // Get the last 2 bytes of the MAC address. // ui32Val = HWREG(ui32Base + EMAC_O_ADDRH(ui32Index)); pui8MACAddr[4] = ui32Val & 0xFF; pui8MACAddr[5] = (ui32Val >> 8) & 0xFF; } //***************************************************************************** // //! Returns the number of MAC addresses supported by the Ethernet controller. //! //! \param ui32Base is the base address of the Ethernet controller. //! //! This function may be used to determine the number of MAC addresses that the //! given controller supports. MAC address slots may be used when performing //! perfect (rather than hash table) filtering of packets. //! //! \return Returns the number of supported MAC addresses. // //***************************************************************************** uint32_t EMACNumAddrGet(uint32_t ui32Base) { // // The only Ethernet controller on MSP432E4 supports 4 MAC addresses. // return (NUM_MAC_ADDR); } //***************************************************************************** // //! Sets filtering parameters associated with one of the configured MAC //! addresses. //! //! \param ui32Base is the base address of the controller. //! \param ui32Index is the index of the MAC address slot for which the filter //! is to be set. //! \param ui32Config sets the filter parameters for the given MAC address. //! //! This function sets filtering parameters associated with one of the MAC //! address slots that the controller supports. This configuration is used //! when perfect filtering (rather than hash table filtering) is selected. //! //! Valid values for \e ui32Index are from 1 to (number of MAC address //! slots - 1). The number of supported MAC address slots may be found by //! calling EMACNumAddrGet(). MAC index 0 is the local MAC address and does //! not have filtering parameters associated with it. //! //! The \e ui32Config parameter determines how the given MAC address is used //! when filtering incoming Ethernet frames. It is comprised of a logical OR //! of the fields: //! //! - \b EMAC_FILTER_ADDR_ENABLE indicates that this MAC address is enabled //! and should be used when performing perfect filtering. If this flag is //! absent, the MAC address at the given index is disabled and is not used //! in filtering. //! - \b EMAC_FILTER_SOURCE_ADDR indicates that the MAC address at the given //! index is compared to the source address of incoming frames while //! performing perfect filtering. If absent, the MAC address is compared //! against the destination address. //! - \b EMAC_FILTER_MASK_BYTE_6 indicates that the MAC should ignore the //! sixth byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_5 indicates that the MAC should ignore the //! fifth byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_4 indicates that the MAC should ignore the //! fourth byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_3 indicates that the MAC should ignore the //! third byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_2 indicates that the MAC should ignore the //! second byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_1 indicates that the MAC should ignore the //! first byte of the source or destination address when filtering. //! //! \return None. // //***************************************************************************** void EMACAddrFilterSet(uint32_t ui32Base, uint32_t ui32Index, uint32_t ui32Config) { uint32_t ui32Val; // // Parameter sanity check. // ASSERT(ui32Index < NUM_MAC_ADDR); ASSERT((ui32Config & ~(EMAC_FILTER_BYTE_MASK_M | EMAC_FILTER_ADDR_ENABLE | EMAC_FILTER_SOURCE_ADDR)) == 0); ASSERT(ui32Index); // // Set the filter configuration for a particular MAC address. // HWREG(ui32Base + EMAC_O_ADDRH(ui32Index)) = (HWREG(ui32Base + EMAC_O_ADDRH(ui32Index)) & 0xFFFF) | ui32Config; // // Read and rewrite the low half of the MAC address register to ensure // that the upper half's data is latched. // ui32Val = HWREG(ui32Base + EMAC_O_ADDRL(ui32Index)); HWREG(ui32Base + EMAC_O_ADDRL(ui32Index)) = ui32Val; } //***************************************************************************** // //! Gets filtering parameters associated with one of the configured MAC //! addresses. //! //! \param ui32Base is the base address of the controller. //! \param ui32Index is the index of the MAC address slot for which the filter //! is to be queried. //! //! This function returns filtering parameters associated with one of the MAC //! address slots that the controller supports. This configuration is used //! when perfect filtering (rather than hash table filtering) is selected. //! //! Valid values for \e ui32Index are from 1 to (number of MAC address //! slots - 1). The number of supported MAC address slots may be found by //! calling EMACNumAddrGet(). MAC index 0 is the local MAC address and does //! not have filtering parameters associated with it. //! //! \return Returns the filter configuration as the logical OR of the //! following labels: //! //! - \b EMAC_FILTER_ADDR_ENABLE indicates that this MAC address is enabled //! and is used when performing perfect filtering. If this flag is absent, //! the MAC address at the given index is disabled and is not used in //! filtering. //! - \b EMAC_FILTER_SOURCE_ADDR indicates that the MAC address at the given //! index is compared to the source address of incoming frames while performing //! perfect filtering. If absent, the MAC address is compared against the //! destination address. //! - \b EMAC_FILTER_MASK_BYTE_6 indicates that the MAC ignores the //! sixth byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_5 indicates that the MAC ignores the //! fifth byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_4 indicates that the MAC ignores the //! fourth byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_3 indicates that the MAC ignores the //! third byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_2 indicates that the MAC ignores the //! second byte of the source or destination address when filtering. //! - \b EMAC_FILTER_MASK_BYTE_1 indicates that the MAC ignores the //! first byte of the source or destination address when filtering. // //***************************************************************************** uint32_t EMACAddrFilterGet(uint32_t ui32Base, uint32_t ui32Index) { // // Parameter sanity check. // ASSERT(ui32Index < NUM_MAC_ADDR); ASSERT(ui32Index); // // Read and return the filter settings for the requested MAC address slot. // return (HWREG(ui32Base + EMAC_O_ADDRH(ui32Index)) & (EMAC_FILTER_BYTE_MASK_M | EMAC_FILTER_ADDR_ENABLE | EMAC_FILTER_SOURCE_ADDR)); } //***************************************************************************** // //! Sets options related to Ethernet frame filtering. //! //! \param ui32Base is the base address of the controller. //! \param ui32FilterOpts is a logical OR of flags defining the required MAC //! address filtering options. //! //! This function allows various filtering options to be defined and allows //! an application to control which frames are received based on various //! criteria related to the frame source and destination MAC addresses or VLAN //! tagging. //! //! The \e ui32FilterOpts parameter is a logical OR of any of the following //! flags: //! //! - \b EMAC_FRMFILTER_RX_ALL configures the MAC to pass all received frames //! regardless of whether or not they pass any address filter that is //! configured. The receive status word in the relevant DMA descriptor is //! updated to indicate whether the configured filter passed or failed for //! the frame. //! - \b EMAC_FRMFILTER_VLAN configures the MAC to drop any frames that do //! not pass the VLAN tag comparison. //! - \b EMAC_FRMFILTER_HASH_AND_PERFECT configures the MAC to filter frames //! based on both any perfect filters set and the hash filter if enabled using //! \b EMAC_FRMFILTER_HASH_UNICAST or \b EMAC_FRMFILTER_HASH_MULTICAST. In //! this case, only if both filters fail is the packet rejected. If this //! option is absent, only one of the filter types is used, as controlled by //! \b EMAC_FRMFILTER_HASH_UNICAST and \b EMAC_FRMFILTER_HASH_MULTICAST //! for unicast and multicast frames respectively. //! - \b EMAC_FRMFILTER_SADDR configures the MAC to drop received frames //! when the source address field in the frame does not match the values //! programmed into the enabled SA registers. //! - \b EMAC_FRMFILTER_INV_SADDR enables inverse source address filtering. //! When this option is specified, frames for which the SA does not match the //! SA registers are marked as passing the source address filter. //! - \b EMAC_FRMFILTER_BROADCAST configures the MAC to discard all incoming //! broadcast frames. //! - \b EMAC_FRMFILTER_PASS_MULTICAST configures the MAC to pass all //! incoming frames with multicast destinations addresses. //! - \b EMAC_FRMFILTER_INV_DADDR inverts the sense of the destination //! address filtering for both unicast and multicast frames. //! - \b EMAC_FRMFILTER_HASH_MULTICAST enables destination address filtering //! of received multicast frames using the hash table. If absent, perfect //! destination address filtering is used. If used in conjunction with \b //! EMAC_FRMFILTER_HASH_AND_PERFECT, this flag indicates that the hash filter //! should be used for incoming multicast packets along with the perfect //! filter. //! - \b EMAC_FRMFILTER_HASH_UNICAST enables destination address filtering //! of received unicast frames using the hash table. If absent, perfect //! destination address filtering is used. If used in conjunction with \b //! EMAC_FRMFILTER_HASH_AND_PERFECT, this flag indicates that the hash filter //! should be used for incoming unicast packets along with the perfect filter. //! - \b EMAC_FRMFILTER_PROMISCUOUS configures the MAC to operate in //! promiscuous mode where all received frames are passed to the application //! and the SA and DA filter status bits of the descriptor receive status word //! are always cleared. //! //! Control frame filtering may be configured by ORing one of the following //! values into \e ui32FilterOpts: //! //! - \b EMAC_FRMFILTER_PASS_NO_CTRL prevents any control frame from reaching //! the application. //! - \b EMAC_FRMFILTER_PASS_NO_PAUSE passes all control frames other than //! PAUSE even if they fail the configured address filter. //! - \b EMAC_FRMFILTER_PASS_ALL_CTRL passes all control frames, including //! PAUSE even if they fail the configured address filter. //! - \b EMAC_FRMFILTER_PASS_ADDR_CTRL passes all control frames only if they //! pass the configured address filter. //! //! \return None. // //***************************************************************************** void EMACFrameFilterSet(uint32_t ui32Base, uint32_t ui32FilterOpts) { ASSERT((ui32FilterOpts & ~VALID_FRMFILTER_FLAGS) == 0); // // Set the Ethernet MAC frame filter according to the flags passed. // HWREG(ui32Base + EMAC_O_FRAMEFLTR) = ((HWREG(ui32Base + EMAC_O_FRAMEFLTR) & ~VALID_FRMFILTER_FLAGS) | ui32FilterOpts); } //***************************************************************************** // //! Returns the current Ethernet frame filtering settings. //! //! \param ui32Base is the base address of the controller. //! //! This function may be called to retrieve the frame filtering configuration //! set using a prior call to EMACFrameFilterSet(). //! //! \return Returns a value comprising the logical OR of various flags //! indicating the frame filtering options in use. Possible flags are: //! //! - \b EMAC_FRMFILTER_RX_ALL indicates that the MAC to is configured to //! pass all received frames regardless of whether or not they pass any //! address filter that is configured. The receive status word in the //! relevant DMA descriptor is updated to indicate whether the configured //! filter passed or failed for the frame. //! - \b EMAC_FRMFILTER_VLAN indicates that the MAC is configured to drop any //! frames which do not pass the VLAN tag comparison. //! - \b EMAC_FRMFILTER_HASH_AND_PERFECT indicates that the MAC is configured //! to pass frames if they match either the hash filter or the perfect filter. //! If this flag is absent, frames passing based on the result of a single //! filter, the perfect filter if \b EMAC_FRMFILTER_HASH_MULTICAST or //! \b EMAC_FRMFILTER_HASH_UNICAST are clear or the hash filter otherwise. //! - \b EMAC_FRMFILTER_SADDR indicates that the MAC is configured to drop //! received frames when the source address field in the frame does not match //! the values programmed into the enabled SA registers. //! - \b EMAC_FRMFILTER_INV_SADDR enables inverse source address filtering. //! When this option is specified, frames for which the SA does not match the //! SA registers are marked as passing the source address filter. //! - \b EMAC_FRMFILTER_BROADCAST indicates that the MAC is configured to //! discard all incoming broadcast frames. //! - \b EMAC_FRMFILTER_PASS_MULTICAST indicates that the MAC is configured //! to pass all incoming frames with multicast destinations addresses. //! - \b EMAC_FRMFILTER_INV_DADDR indicates that the sense of the destination //! address filtering for both unicast and multicast frames is inverted. //! - \b EMAC_FRMFILTER_HASH_MULTICAST indicates that destination address //! filtering of received multicast frames is enabled using the hash table. If //! absent, perfect destination address filtering is used. If used in //! conjunction with \b EMAC_FRMFILTER_HASH_AND_PERFECT, this flag indicates //! that the hash filter should be used for incoming multicast packets along //! with the perfect filter. //! - \b EMAC_FRMFILTER_HASH_UNICAST indicates that destination address //! filtering of received unicast frames is enabled using the hash table. If //! absent, perfect destination address filtering is used. If used in //! conjunction with \b EMAC_FRMFILTER_HASH_AND_PERFECT, this flag indicates //! that the hash filter should be used for incoming unicast packets along with //! the perfect filter. //! - \b EMAC_FRMFILTER_PROMISCUOUS indicates that the MAC is configured to //! operate in promiscuous mode where all received frames are passed to the //! application and the SA and DA filter status bits of the descriptor receive //! status word are always cleared. //! //! Control frame filtering configuration is indicated by one of the following //! values which may be extracted from the returned value using the mask //! \b EMAC_FRMFILTER_PASS_MASK: //! //! - \b EMAC_FRMFILTER_PASS_NO_CTRL prevents any control frame from reaching //! the application. //! - \b EMAC_FRMFILTER_PASS_NO_PAUSE passes all control frames other than //! PAUSE even if they fail the configured address filter. //! - \b EMAC_FRMFILTER_PASS_ALL_CTRL passes all control frames, including //! PAUSE even if they fail the configured address filter. //! - \b EMAC_FRMFILTER_PASS_ADDR_CTRL passes all control frames only if they //! pass the configured address filter. // //***************************************************************************** uint32_t EMACFrameFilterGet(uint32_t ui32Base) { // // Return the current MAC frame filter setting. // return (HWREG(ui32Base + EMAC_O_FRAMEFLTR) & VALID_FRMFILTER_FLAGS); } //***************************************************************************** // //! Sets the MAC address hash filter table. //! //! \param ui32Base is the base address of the controller. //! \param ui32HashHi is the upper 32 bits of the current 64-bit hash filter //! table to set. //! \param ui32HashLo is the lower 32 bits of the current 64-bit hash filter //! table to set. //! //! This function may be used to set the current 64-bit hash filter table //! used by the MAC to filter incoming packets when hash filtering is enabled. //! Hash filtering is enabled by passing \b EMAC_FRMFILTER_HASH_UNICAST //! and/or \b EMAC_FRMFILTER_HASH_MULTICAST in the \e ui32FilterOpts parameter //! to EMACFrameFilterSet(). The current hash filter may be retrieved //! by calling EMACHashFilterGet(). //! //! Hash table filtering allows many different MAC addresses to be filtered //! simultaneously at the cost of some false-positive results (in the form of //! packets passing the filter when their MAC address was not one of those //! required). A CRC of the packet source or destination MAC address is //! calculated and the bottom 6 bits are used as a bit index into the 64-bit //! hash filter table. If the bit in the hash table is set, the filter is //! considered to have passed. If the bit is clear, the filter fails and the //! packet is rejected (assuming normal rather than inverse filtering is //! configured). //! //! \return None. // //***************************************************************************** void EMACHashFilterSet(uint32_t ui32Base, uint32_t ui32HashHi, uint32_t ui32HashLo) { // Set the hash table with the values provided. HWREG(ui32Base + EMAC_O_HASHTBLL) = ui32HashLo; HWREG(ui32Base + EMAC_O_HASHTBLH) = ui32HashHi; } //***************************************************************************** // //! Returns the current MAC address hash filter table. //! //! \param ui32Base is the base address of the controller. //! \param pui32HashHi points to storage to be written with the upper 32 bits //! of the current 64-bit hash filter table. //! \param pui32HashLo points to storage to be written with the lower 32 bits //! of the current 64-bit hash filter table. //! //! This function may be used to retrieve the current 64-bit hash filter table //! from the MAC prior to making changes and setting the new hash filter via a //! call to EMACHashFilterSet(). //! //! Hash table filtering allows many different MAC addresses to be filtered //! simultaneously at the cost of some false-positive results in the form of //! packets passing the filter when their MAC address was not one of those //! required. A CRC of the packet source or destination MAC address is //! calculated and the bottom 6 bits are used as a bit index into the 64-bit //! hash filter table. If the bit in the hash table is set, the filter is //! considered to have passed. If the bit is clear, the filter fails and the //! packet is rejected (assuming normal rather than inverse filtering is //! configured). //! //! \return None. // //***************************************************************************** void EMACHashFilterGet(uint32_t ui32Base, uint32_t *pui32HashHi, uint32_t *pui32HashLo) { ASSERT(pui32HashHi); ASSERT(pui32HashLo); // // Get the current hash table values. // *pui32HashLo = HWREG(ui32Base + EMAC_O_HASHTBLL); *pui32HashHi = HWREG(ui32Base + EMAC_O_HASHTBLH); } //***************************************************************************** // //! Returns the bit number to set in the MAC hash filter corresponding to a //! given MAC address. //! //! \param pui8MACAddr points to a buffer containing the 6-byte MAC address //! for which the hash filter bit is to be determined. //! //! This function may be used to determine which bit in the MAC address hash //! filter to set to describe a given 6-byte MAC address. The returned value is //! a 6-bit number where bit 5 indicates which of the two hash table words is //! affected and the bottom 5 bits indicate the bit number to set within that //! word. For example, if 0x22 (100010b) is returned, this indicates that bit //! 2 of word 1 (\e ui32HashHi as passed to EMACHashFilterSet()) must be set //! to describe the passed MAC address. //! //! \return Returns the bit number to set in the MAC hash table to describe the //! passed MAC address. // //***************************************************************************** uint32_t EMACHashFilterBitCalculate(uint8_t *pui8MACAddr) { uint32_t ui32CRC, ui32Mask, ui32Loop; // // Parameter sanity check. // ASSERT(pui8MACAddr); // // Calculate the CRC for the MAC address. // ui32CRC = Crc32(0xFFFFFFFF, pui8MACAddr, 6); ui32CRC ^= 0xFFFFFFFF; // // Determine the hash bit to use from the calculated CRC. This is the // top 6 bits of the reversed CRC (or the bottom 6 bits of the calculated // CRC with the bit order of those 6 bits reversed). // ui32Mask = 0; // // Reverse the order of the bottom 6 bits of the calculated CRC. // for (ui32Loop = 0; ui32Loop < 6; ui32Loop++) { ui32Mask <<= 1; ui32Mask |= (ui32CRC & 1); ui32CRC >>= 1; } // // Return the final hash table bit index. // return (ui32Mask); } //***************************************************************************** // //! Sets the receive interrupt watchdog timer period. //! //! \param ui32Base is the base address of the Ethernet controller. //! \param ui8Timeout is the desired timeout expressed as a number of 256 //! system clock periods. //! //! This function configures the receive interrupt watchdog timer. //! The \e uiTimeout parameter specifies the number of 256 system clock periods //! that elapse before the timer expires. In cases where the DMA has //! transferred a frame using a descriptor that has //! \b DES1_RX_CTRL_DISABLE_INT set, the watchdog causes a receive //! interrupt to be generated when it times out. The watchdog timer is reset //! whenever a packet is transferred to memory using a DMA descriptor that //! does not disable the receive interrupt. //! //! To disable the receive interrupt watchdog function, set \e ui8Timeout to 0. //! //! \return None. // //***************************************************************************** void EMACRxWatchdogTimerSet(uint32_t ui32Base, uint8_t ui8Timeout) { // // Set the receive interrupt watchdog timeout period. // HWREG(ui32Base + EMAC_O_RXINTWDT) = (uint32_t)ui8Timeout; } //***************************************************************************** // //! Returns the current Ethernet MAC status. //! //! \param ui32Base is the base address of the Ethernet controller. //! //! This function returns information on the current status of all the main //! modules in the MAC transmit and receive data paths. //! //! \return Returns the current MAC status as a logical OR of any of the //! following flags: //! //! - \b EMAC_STATUS_TX_NOT_EMPTY //! - \b EMAC_STATUS_TX_WRITING_FIFO //! - \b EMAC_STATUS_TX_PAUSED //! - \b EMAC_STATUS_MAC_NOT_IDLE //! - \b EMAC_STATUS_RWC_ACTIVE //! - \b EMAC_STATUS_RPE_ACTIVE //! //! The transmit frame controller status can be extracted from the returned //! value by ANDing with \b EMAC_STATUS_TFC_STATE_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_TFC_STATE_IDLE //! - \b EMAC_STATUS_TFC_STATE_WAITING //! - \b EMAC_STATUS_TFC_STATE_PAUSING //! - \b EMAC_STATUS_TFC_STATE_WRITING //! //! The transmit FIFO read controller status can be extracted from the returned //! value by ANDing with \b EMAC_STATUS_TRC_STATE_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_TRC_STATE_IDLE //! - \b EMAC_STATUS_TRC_STATE_READING //! - \b EMAC_STATUS_TRC_STATE_WAITING //! - \b EMAC_STATUS_TRC_STATE_STATUS //! //! The current receive FIFO levels can be extracted from the returned value //! by ANDing with \b EMAC_STATUS_RX_FIFO_LEVEL_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_RX_FIFO_EMPTY indicating that the FIFO is empty. //! - \b EMAC_STATUS_RX_FIFO_BELOW indicating that the FIFO fill level is //! below the flow-control deactivate threshold. //! - \b EMAC_STATUS_RX_FIFO_ABOVE indicating that the FIFO fill level is //! above the flow-control activate threshold. //! - \b EMAC_STATUS_RX_FIFO_FULL indicating that the FIFO is full. //! //! The current receive FIFO state can be extracted from the returned value //! by ANDing with \b EMAC_STATUS_RX_FIFO_STATE_MASK and is one of the //! following: //! //! - \b EMAC_STATUS_RX_FIFO_IDLE //! - \b EMAC_STATUS_RX_FIFO_READING //! - \b EMAC_STATUS_RX_FIFO_STATUS //! - \b EMAC_STATUS_RX_FIFO_FLUSHING // //***************************************************************************** uint32_t EMACStatusGet(uint32_t ui32Base) { // // Read and return the MAC status register content. // return (HWREG(ui32Base + EMAC_O_STATUS)); } //***************************************************************************** // //! Orders the MAC DMA controller to attempt to acquire the next transmit //! descriptor. //! //! \param ui32Base is the base address of the Ethernet controller. //! //! This function must be called to restart the transmitter if it has been //! suspended due to the current transmit DMA descriptor being owned by the //! host. Once the application writes new values to the descriptor and marks //! it as being owned by the MAC DMA, this function causes the hardware to //! attempt to acquire the descriptor and start transmission of the new //! data. //! //! \return None. // //***************************************************************************** void EMACTxDMAPollDemand(uint32_t ui32Base) { // // Any write to the MACTXPOLLD register causes the transmit DMA to attempt // to resume. // HWREG(ui32Base + EMAC_O_TXPOLLD) = 0; } //***************************************************************************** // //! Orders the MAC DMA controller to attempt to acquire the next receive //! descriptor. //! //! \param ui32Base is the base address of the Ethernet controller. //! //! This function must be called to restart the receiver if it has been //! suspended due to the current receive DMA descriptor being owned by the //! host. Once the application reads any data from the descriptor and marks //! it as being owned by the MAC DMA, this function causes the hardware to //! attempt to acquire the descriptor before writing the next received packet //! into its buffer(s). //! //! \return None. // //***************************************************************************** void EMACRxDMAPollDemand(uint32_t ui32Base) { // // Any write to the MACRXPOLLD register causes the receive DMA to attempt // to resume. // HWREG(ui32Base + EMAC_O_RXPOLLD) = 0; } //***************************************************************************** // //! Sets the DMA receive descriptor list pointer. //! //! \param ui32Base is the base address of the controller. //! \param pDescriptor points to the first DMA descriptor in the list to //! be passed to the receive DMA engine. //! //! This function sets the Ethernet MAC's receive DMA descriptor list pointer. //! The \e pDescriptor pointer must point to one or more descriptor //! structures. //! //! When multiple descriptors are provided, they can be either chained or //! unchained. Chained descriptors are indicated by setting the //! \b DES0_TX_CTRL_CHAINED or \b DES1_RX_CTRL_CHAINED bit in the relevant //! word of the transmit or receive descriptor. If this bit is clear, //! unchained descriptors are assumed. //! //! Chained descriptors use a link pointer in each descriptor to //! point to the next descriptor in the chain. //! //! Unchained descriptors are assumed to be contiguous in memory with a //! consistent offset between the start of one descriptor and the next. //! If unchained descriptors are used, the \e pvLink field in the descriptor //! becomes available to store a second buffer pointer, allowing each //! descriptor to point to two buffers rather than one. In this case, //! the \e ui32DescSkipSize parameter to EMACInit() must previously have //! been set to the number of words between the end of one descriptor and //! the start of the next. This value must be 0 in cases where a packed array //! of \b tEMACDMADescriptor structures is used. If the application wishes to //! add new state fields to the end of the descriptor structure, the skip size //! should be set to accommodate the newly sized structure. //! //! Applications are responsible for initializing all descriptor fields //! appropriately before passing the descriptor list to the hardware. //! //! \return None. // //***************************************************************************** void EMACRxDMADescriptorListSet(uint32_t ui32Base, tEMACDMADescriptor *pDescriptor) { // // Parameter sanity check. // ASSERT(pDescriptor); ASSERT(((uint32_t)pDescriptor & 3) == 0); // // Write the supplied address to the MACRXDLADDR register. // HWREG(ui32Base + EMAC_O_RXDLADDR) = (uint32_t)pDescriptor; } //***************************************************************************** // //! Returns a pointer to the start of the DMA receive descriptor list. //! //! \param ui32Base is the base address of the controller. //! //! This function returns a pointer to the head of the Ethernet MAC's receive //! DMA descriptor list. This value corresponds to the pointer originally set //! using a call to EMACRxDMADescriptorListSet(). //! //! \return Returns a pointer to the start of the DMA receive descriptor list. // //***************************************************************************** tEMACDMADescriptor * EMACRxDMADescriptorListGet(uint32_t ui32Base) { // // Return the current receive DMA descriptor list pointer. // return ((tEMACDMADescriptor *)HWREG(ui32Base + EMAC_O_RXDLADDR)); } //***************************************************************************** // //! Returns the current DMA receive descriptor pointer. //! //! \param ui32Base is the base address of the controller. //! //! This function returns a pointer to the current Ethernet receive descriptor //! read by the DMA. //! //! \return Returns a pointer to the start of the current receive DMA //! descriptor. // //***************************************************************************** tEMACDMADescriptor * EMACRxDMACurrentDescriptorGet(uint32_t ui32Base) { // // Return the address of the current receive descriptor written by the DMA. // return ((tEMACDMADescriptor *)HWREG(ui32Base + EMAC_O_HOSRXDESC)); } //***************************************************************************** // //! Returns the current DMA receive buffer pointer. //! //! \param ui32Base is the base address of the controller. //! //! This function may be called to determine which buffer the receive DMA //! engine is currently writing to. //! //! \return Returns the receive buffer address currently being written by //! the DMA engine. // //***************************************************************************** uint8_t * EMACRxDMACurrentBufferGet(uint32_t ui32Base) { // // Return the receive buffer address currently being written by the DMA. // return ((uint8_t *)HWREG(ui32Base + EMAC_O_HOSRXBA)); } //***************************************************************************** // //! Sets the DMA transmit descriptor list pointer. //! //! \param ui32Base is the base address of the controller. //! \param pDescriptor points to the first DMA descriptor in the list to //! be passed to the transmit DMA engine. //! //! This function sets the Ethernet MAC's transmit DMA descriptor list pointer. //! The \e pDescriptor pointer must point to one or more descriptor //! structures. //! //! When multiple descriptors are provided, they can be either chained or //! unchained. Chained descriptors are indicated by setting the //! \b DES0_TX_CTRL_CHAINED or \b DES1_RX_CTRL_CHAINED bit in the relevant //! word of the transmit or receive descriptor. If this bit is clear, //! unchained descriptors are assumed. //! //! Chained descriptors use a link pointer in each descriptor to //! point to the next descriptor in the chain. //! //! Unchained descriptors are assumed to be contiguous in memory with a //! consistent offset between the start of one descriptor and the next. //! If unchained descriptors are used, the \e pvLink field in the descriptor //! becomes available to store a second buffer pointer, allowing each //! descriptor to point to two buffers rather than one. In this case, //! the \e ui32DescSkipSize parameter to EMACInit() must previously have //! been set to the number of words between the end of one descriptor and //! the start of the next. This value must be 0 in cases where a packed array //! of \b tEMACDMADescriptor structures is used. If the application wishes to //! add new state fields to the end of the descriptor structure, the skip size //! should be set to accommodate the newly sized structure. //! //! Applications are responsible for initializing all descriptor fields //! appropriately before passing the descriptor list to the hardware. //! //! \return None. // //***************************************************************************** void EMACTxDMADescriptorListSet(uint32_t ui32Base, tEMACDMADescriptor *pDescriptor) { // // Parameter sanity check. // ASSERT(pDescriptor); ASSERT(((uint32_t)pDescriptor & 3) == 0); // // Write the supplied address to the MACTXDLADDR register. // HWREG(ui32Base + EMAC_O_TXDLADDR) = (uint32_t)pDescriptor; } //***************************************************************************** // //! Returns a pointer to the start of the DMA transmit descriptor list. //! //! \param ui32Base is the base address of the controller. //! //! This function returns a pointer to the head of the Ethernet MAC's transmit //! DMA descriptor list. This value corresponds to the pointer originally set //! using a call to EMACTxDMADescriptorListSet(). //! //! \return Returns a pointer to the start of the DMA transmit descriptor list. // //***************************************************************************** tEMACDMADescriptor * EMACTxDMADescriptorListGet(uint32_t ui32Base) { // // Return the current transmit DMA descriptor list pointer. // return ((tEMACDMADescriptor *)HWREG(ui32Base + EMAC_O_TXDLADDR)); } //***************************************************************************** // //! Returns the current DMA transmit descriptor pointer. //! //! \param ui32Base is the base address of the controller. //! //! This function returns a pointer to the current Ethernet transmit descriptor //! read by the DMA. //! //! \return Returns a pointer to the start of the current transmit DMA //! descriptor. // //***************************************************************************** tEMACDMADescriptor * EMACTxDMACurrentDescriptorGet(uint32_t ui32Base) { // // Return the address of the current transmit descriptor read by the DMA. // return ((tEMACDMADescriptor *)HWREG(ui32Base + EMAC_O_HOSTXDESC)); } //***************************************************************************** // //! Returns the current DMA transmit buffer pointer. //! //! \param ui32Base is the base address of the controller. //! //! This function may be called to determine which buffer the transmit DMA //! engine is currently reading from. //! //! \return Returns the transmit buffer address currently being read by the //! DMA engine. // //***************************************************************************** uint8_t * EMACTxDMACurrentBufferGet(uint32_t ui32Base) { // // Return the transmit buffer address currently being read by the DMA. // return ((uint8_t *)HWREG(ui32Base + EMAC_O_HOSTXBA)); } //***************************************************************************** // //! Returns the current states of the Ethernet MAC transmit and receive DMA //! engines. //! //! \param ui32Base is the base address of the controller. //! //! This function may be used to query the current states of the transmit and //! receive DMA engines. The return value contains two fields, one providing //! the transmit state and the other the receive state. Macros //! \b EMAC_TX_DMA_STATE() and \b EMAC_RX_DMA_STATE() may be used to //! extract these fields from the returned value. Alternatively, masks //! \b EMAC_DMA_TXSTAT_MASK and \b EMAC_DMA_RXSTAT_MASK may be used //! directly to mask out the individual states from the returned value. //! //! \return Returns the states of the transmit and receive DMA engines. These //! states are ORed together into a single word containing one of: //! //! - \b EMAC_DMA_TXSTAT_STOPPED indicating that the transmit engine is //! stopped. //! - \b EMAC_DMA_TXSTAT_RUN_FETCH_DESC indicating that the transmit engine //! is fetching the next descriptor. //! - \b EMAC_DMA_TXSTAT_RUN_WAIT_STATUS indicating that the transmit engine //! is waiting for status from the MAC. //! - \b EMAC_DMA_TXSTAT_RUN_READING indicating that the transmit engine is //! currently transferring data from memory to the MAC transmit FIFO. //! - \b EMAC_DMA_TXSTAT_RUN_CLOSE_DESC indicating that the transmit engine //! is closing the descriptor after transmission of the buffer data. //! - \b EMAC_DMA_TXSTAT_TS_WRITE indicating that the transmit engine is //! currently writing timestamp information to the descriptor. //! - \b EMAC_DMA_TXSTAT_SUSPENDED indicating that the transmit engine is //! suspended due to the next descriptor being unavailable (owned by the host) //! or a transmit buffer underflow. //! //! and one of: //! //! - \b EMAC_DMA_RXSTAT_STOPPED indicating that the receive engine is //! stopped. //! - \b EMAC_DMA_RXSTAT_RUN_FETCH_DESC indicating that the receive engine //! is fetching the next descriptor. //! - \b EMAC_DMA_RXSTAT_RUN_WAIT_PACKET indicating that the receive engine //! is waiting for the next packet. //! - \b EMAC_DMA_RXSTAT_SUSPENDED indicating that the receive engine is //! suspended due to the next descriptor being unavailable. //! - \b EMAC_DMA_RXSTAT_RUN_CLOSE_DESC indicating that the receive engine //! is closing the descriptor after receiving a buffer of data. //! - \b EMAC_DMA_RXSTAT_TS_WRITE indicating that the transmit engine is //! currently writing timestamp information to the descriptor. //! - \b EMAC_DMA_RXSTAT_RUN_RECEIVING indicating that the receive engine is //! currently transferring data from the MAC receive FIFO to memory. //! //! Additionally, a DMA bus error may be signaled using \b EMAC_DMA_ERROR. //! If this flag is present, the source of the error is identified using one //! of the following values which may be extracted from the return value using //! \b EMAC_DMA_ERR_MASK: //! //! - \b EMAC_DMA_ERR_RX_DATA_WRITE indicates that an error occurred when //! writing received data to memory. //! - \b EMAC_DMA_ERR_TX_DATA_READ indicates that an error occurred when //! reading data from memory for transmission. //! - \b EMAC_DMA_ERR_RX_DESC_WRITE indicates that an error occurred when //! writing to the receive descriptor. //! - \b EMAC_DMA_ERR_TX_DESC_WRITE indicates that an error occurred when //! writing to the transmit descriptor. //! - \b EMAC_DMA_ERR_RX_DESC_READ indicates that an error occurred when //! reading the receive descriptor. //! - \b EMAC_DMA_ERR_TX_DESC_READ indicates that an error occurred when //! reading the transmit descriptor. // //***************************************************************************** uint32_t EMACDMAStateGet(uint32_t ui32Base) { // // Return the status of the DMA channels. // return (HWREG(ui32Base + EMAC_O_DMARIS) & (EMAC_DMARIS_FBI | EMAC_DMARIS_AE_M | EMAC_DMARIS_RS_M | EMAC_DMARIS_TS_M)); } //***************************************************************************** // //! Flushes the Ethernet controller transmit FIFO. //! //! \param ui32Base is the base address of the controller. //! //! This function flushes any data currently held in the Ethernet transmit //! FIFO. Data that has already been passed to the MAC for transmission is //! transmitted, possibly resulting in a transmit underflow or runt frame //! transmission. //! //! \return None. // //***************************************************************************** void EMACTxFlush(uint32_t ui32Base) { // // Check to make sure that the FIFO is not already empty. // if (HWREG(ui32Base + EMAC_O_STATUS) & EMAC_STATUS_TXFE) { // // Flush the transmit FIFO since it is not currently empty. // HWREG(ui32Base + EMAC_O_DMAOPMODE) |= EMAC_DMAOPMODE_FTF; // // Wait for the flush to complete. // while (HWREG(ui32Base + EMAC_O_DMAOPMODE) & EMAC_DMAOPMODE_FTF) { } } } //***************************************************************************** // //! Enables the Ethernet controller transmitter. //! //! \param ui32Base is the base address of the controller. //! //! When starting operations on the Ethernet interface, this function should //! be called to enable the transmitter after all configuration has been //! completed. //! //! \return None. // //***************************************************************************** void EMACTxEnable(uint32_t ui32Base) { // // Enable the MAC transmit path in the opmode register. // HWREG(ui32Base + EMAC_O_DMAOPMODE) |= EMAC_DMAOPMODE_ST; // // Enable transmission in the MAC configuration register. // HWREG(ui32Base + EMAC_O_CFG) |= EMAC_CFG_TE; } //***************************************************************************** // //! Disables the Ethernet controller transmitter. //! //! \param ui32Base is the base address of the controller. //! //! When terminating operations on the Ethernet interface, this function should //! be called. This function disables the transmitter. //! //! \return None. // //***************************************************************************** void EMACTxDisable(uint32_t ui32Base) { // // Disable transmission in the MAC configuration register. // HWREG(ui32Base + EMAC_O_CFG) &= ~EMAC_CFG_TE; // // Disable the MAC transmit path in the opmode register. // HWREG(ui32Base + EMAC_O_DMAOPMODE) &= ~EMAC_DMAOPMODE_ST; } //***************************************************************************** // //! Enables the Ethernet controller receiver. //! //! \param ui32Base is the base address of the controller. //! //! When starting operations on the Ethernet interface, this function should //! be called to enable the receiver after all configuration has been //! completed. //! //! \return None. // //***************************************************************************** void EMACRxEnable(uint32_t ui32Base) { // // Enable the MAC receive path. // HWREG(ui32Base + EMAC_O_DMAOPMODE) |= EMAC_DMAOPMODE_SR; // // Enable receive in the MAC configuration register. // HWREG(ui32Base + EMAC_O_CFG) |= EMAC_CFG_RE; } //***************************************************************************** // //! Disables the Ethernet controller receiver. //! //! \param ui32Base is the base address of the controller. //! //! When terminating operations on the Ethernet interface, this function should //! be called. This function disables the receiver. //! //! \return None. // //***************************************************************************** void EMACRxDisable(uint32_t ui32Base) { // // Disable reception in the MAC configuration register. // HWREG(ui32Base + EMAC_O_CFG) &= ~EMAC_CFG_RE; // // Disable the MAC receive path. // HWREG(ui32Base + EMAC_O_DMAOPMODE) &= ~EMAC_DMAOPMODE_SR; } //***************************************************************************** // //! Registers an interrupt handler for an Ethernet interrupt. //! //! \param ui32Base is the base address of the controller. //! \param pfnHandler is a pointer to the function to be called when the //! enabled Ethernet interrupts occur. //! //! This function sets the handler to be called when the Ethernet interrupt //! occurs. This function enables the global interrupt in the interrupt //! controller; specific Ethernet interrupts must be enabled via //! EMACIntEnable(). It is the interrupt handler's responsibility to clear //! the interrupt source. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void EMACIntRegister(uint32_t ui32Base, void (*pfnHandler)(void)) { // // Check the arguments. // ASSERT(pfnHandler != 0); // // Register the interrupt handler. // IntRegister(INT_EMAC0, pfnHandler); // // Enable the Ethernet interrupt. // IntEnable(INT_EMAC0); } //***************************************************************************** // //! Unregisters an interrupt handler for an Ethernet interrupt. //! //! \param ui32Base is the base address of the controller. //! //! This function unregisters the interrupt handler. This function disables //! the global interrupt in the interrupt controller so that the interrupt //! handler is no longer called. //! //! \sa IntRegister() for important information about registering interrupt //! handlers. //! //! \return None. // //***************************************************************************** void EMACIntUnregister(uint32_t ui32Base) { // // Disable the interrupt. // IntDisable(INT_EMAC0); // // Unregister the interrupt handler. // IntUnregister(INT_EMAC0); } //***************************************************************************** // //! Enables individual Ethernet MAC interrupt sources. //! //! \param ui32Base is the base address of the Ethernet MAC. //! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled. //! //! This function enables the indicated Ethernet MAC interrupt sources. Only //! the sources that are enabled can be reflected to the processor interrupt; //! disabled sources have no effect on the processor. //! //! The \e ui32IntFlags parameter is the logical OR of any of the following: //! //! - \b EMAC_INT_PHY indicates that the PHY has signaled a change of state. //! Software must read and write the appropriate PHY registers to enable and //! disable particular notifications. //! - \b EMAC_INT_EARLY_RECEIVE indicates that the DMA engine has filled the //! first data buffer of a packet. //! - \b EMAC_INT_BUS_ERROR indicates that a fatal bus error has occurred and //! that the DMA engine has been disabled. //! - \b EMAC_INT_EARLY_TRANSMIT indicates that a frame to be transmitted has //! been fully written from memory into the MAC transmit FIFO. //! - \b EMAC_INT_RX_WATCHDOG indicates that a frame with length greater than //! 2048 bytes (of 10240 bytes in Jumbo Frame mode) was received. //! - \b EMAC_INT_RX_STOPPED indicates that the receive process has entered //! the stopped state. //! - \b EMAC_INT_RX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's receive descriptor list and the DMA cannot, therefore, acquire //! a buffer. The receive process is suspended and can be resumed by changing //! the descriptor ownership and calling EMACRxDMAPollDemand(). //! - \b EMAC_INT_RECEIVE indicates that reception of a frame has completed //! and all requested status has been written to the appropriate DMA receive //! descriptor. //! - \b EMAC_INT_TX_UNDERFLOW indicates that the transmitter experienced an //! underflow during transmission. The transmit process is suspended. //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. //! This condition occurs when the frame size exceeds 2048 bytes (or 10240 //! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, //! acquire a buffer. Transmission is suspended and can be resumed by changing //! the descriptor ownership and calling EMACTxDMAPollDemand(). //! - \b EMAC_INT_TX_STOPPED indicates that the transmit process has stopped. //! - \b EMAC_INT_TRANSMIT indicates that transmission of a frame has //! completed and that all requested status has been updated in the descriptor. //! //! Summary interrupt bits \b EMAC_INT_NORMAL_INT and //! \b EMAC_INT_ABNORMAL_INT are enabled automatically by the driver if any //! of their constituent sources are enabled. Applications do not need to //! explicitly enable these bits. //! //! \note Timestamp-related interrupts from the IEEE 1588 module must be //! enabled independently by using a call to EMACTimestampTargetIntEnable(). //! //! \return None. // //***************************************************************************** void EMACIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Parameter sanity check. // ASSERT((ui32IntFlags & ~EMAC_MASKABLE_INTS) == 0); // // Enable the normal interrupt if any of its individual sources are // enabled. // if (ui32IntFlags & EMAC_NORMAL_INTS) { ui32IntFlags |= EMAC_INT_NORMAL_INT; } // // Similarly, enable the abnormal interrupt if any of its individual // sources are enabled. // if (ui32IntFlags & EMAC_ABNORMAL_INTS) { ui32IntFlags |= EMAC_INT_ABNORMAL_INT; } // // Set the MAC DMA interrupt mask appropriately if any of the sources // we've been asked to enable are found in that register. // if (ui32IntFlags & ~EMAC_INT_PHY) { HWREG(ui32Base + EMAC_O_DMAIM) |= ui32IntFlags & ~EMAC_INT_PHY; } // // Enable the PHY interrupt if we've been asked to do this. // if (ui32IntFlags & EMAC_INT_PHY) { HWREG(ui32Base + EMAC_O_EPHYIM) |= EMAC_EPHYIM_INT; } } //***************************************************************************** // //! Disables individual Ethernet MAC interrupt sources. //! //! \param ui32Base is the base address of the Ethernet MAC. //! \param ui32IntFlags is the bit mask of the interrupt sources to be disabled. //! //! This function disables the indicated Ethernet MAC interrupt sources. //! //! The \e ui32IntFlags parameter is the logical OR of any of the following: //! //! - \b EMAC_INT_PHY indicates that the PHY has signaled a change of state. //! Software must read and write the appropriate PHY registers to enable and //! disable particular notifications. //! - \b EMAC_INT_EARLY_RECEIVE indicates that the DMA engine has filled the //! first data buffer of a packet. //! - \b EMAC_INT_BUS_ERROR indicates that a fatal bus error has occurred and //! that the DMA engine has been disabled. //! - \b EMAC_INT_EARLY_TRANSMIT indicates that a frame to be transmitted has //! been fully written from memory into the MAC transmit FIFO. //! - \b EMAC_INT_RX_WATCHDOG indicates that a frame with length greater than //! 2048 bytes (of 10240 bytes in Jumbo Frame mode) was received. //! - \b EMAC_INT_RX_STOPPED indicates that the receive process has entered //! the stopped state. //! - \b EMAC_INT_RX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's receive descriptor list and the DMA cannot, therefore, acquire //! a buffer. The receive process is suspended and can be resumed by changing //! the descriptor ownership and calling EMACRxDMAPollDemand(). //! - \b EMAC_INT_RECEIVE indicates that reception of a frame has completed //! and all requested status has been written to the appropriate DMA receive //! descriptor. //! - \b EMAC_INT_TX_UNDERFLOW indicates that the transmitter experienced an //! underflow during transmission. The transmit process is suspended. //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. //! This condition occurs when the frame size exceeds 2048 bytes (or 10240 //! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, //! acquire a buffer. Transmission is suspended and can be resumed by changing //! the descriptor ownership and calling EMACTxDMAPollDemand(). //! - \b EMAC_INT_TX_STOPPED indicates that the transmit process has stopped. //! - \b EMAC_INT_TRANSMIT indicates that transmission of a frame has //! completed and that all requested status has been updated in the descriptor. //! - \b EMAC_INT_TIMESTAMP indicates that an interrupt from the timestamp //! module has occurred. This precise source of the interrupt can be //! determined by calling EMACTimestampIntStatus(), which also clears this //! bit. //! //! Summary interrupt bits \b EMAC_INT_NORMAL_INT and //! \b EMAC_INT_ABNORMAL_INT are disabled automatically by the driver if none //! of their constituent sources are enabled. Applications do not need to //! explicitly disable these bits. //! //! \note Timestamp-related interrupts from the IEEE 1588 module must be //! disabled independently by using a call to EMACTimestampTargetIntDisable(). //! //! \return None. // //***************************************************************************** void EMACIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags) { uint32_t ui32Mask; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT((ui32IntFlags & ~EMAC_MASKABLE_INTS) == 0); // // Get the current interrupt mask. // ui32Mask = HWREG(ui32Base + EMAC_O_DMAIM); // // Clear the requested bits. // ui32Mask &= ~(ui32IntFlags & ~EMAC_INT_PHY); // // If none of the normal interrupt sources are enabled, disable the // normal interrupt. // if (!(ui32Mask & EMAC_NORMAL_INTS)) { ui32Mask &= ~EMAC_INT_NORMAL_INT; } // // Similarly, if none of the abnormal interrupt sources are enabled, // disable the abnormal interrupt. // if (!(ui32Mask & EMAC_ABNORMAL_INTS)) { ui32Mask &= ~EMAC_INT_ABNORMAL_INT; } // // Write the new mask back to the hardware. // HWREG(ui32Base + EMAC_O_DMAIM) = ui32Mask; // // Disable the PHY interrupt if we've been asked to do this. // if (ui32IntFlags & EMAC_INT_PHY) { HWREG(ui32Base + EMAC_O_EPHYIM) &= ~EMAC_EPHYIM_INT; } } //***************************************************************************** // //! Gets the current Ethernet MAC interrupt status. //! //! \param ui32Base is the base address of the Ethernet MAC. //! \param bMasked is \b true to return the masked interrupt status or \b false //! to return the unmasked status. //! //! This function returns the interrupt status for the Ethernet MAC. Either //! the raw interrupt status or the status of interrupts that are allowed //! to reflect to the processor can be returned. //! //! \return Returns the current interrupt status as the logical OR of any of //! the following: //! //! - \b EMAC_INT_PHY indicates that the PHY interrupt has occurred. //! Software must read the relevant PHY interrupt status register to determine //! the cause. //! - \b EMAC_INT_EARLY_RECEIVE indicates that the DMA engine has filled the //! first data buffer of a packet. //! - \b EMAC_INT_BUS_ERROR indicates that a fatal bus error has occurred and //! that the DMA engine has been disabled. The cause of the error can be //! determined by calling EMACDMAStateGet(). //! - \b EMAC_INT_EARLY_TRANSMIT indicates that a frame to be transmitted has //! been fully written from memory into the MAC transmit FIFO. //! - \b EMAC_INT_RX_WATCHDOG indicates that a frame with length greater than //! 2048 bytes (of 10240 bytes in Jumbo Frame mode) was received. //! - \b EMAC_INT_RX_STOPPED indicates that the receive process has entered //! the stopped state. //! - \b EMAC_INT_RX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's receive descriptor list and the DMA cannot, therefore, acquire //! a buffer. The receive process is suspended and can be resumed by changing //! the descriptor ownership and calling EMACRxDMAPollDemand(). //! - \b EMAC_INT_RECEIVE indicates that reception of a frame has completed //! and all requested status has been written to the appropriate DMA receive //! descriptor. //! - \b EMAC_INT_TX_UNDERFLOW indicates that the transmitter experienced an //! underflow during transmission. The transmit process is suspended. //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. //! This condition occurs when the frame size exceeds 2048 bytes (or 10240 //! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, //! acquire a buffer. Transmission is suspended and can be resumed by changing //! the descriptor ownership and calling EMACTxDMAPollDemand(). //! - \b EMAC_INT_TX_STOPPED indicates that the transmit process has stopped. //! - \b EMAC_INT_TRANSMIT indicates that transmission of a frame has //! completed and that all requested status has been updated in the descriptor. //! - \b EMAC_INT_NORMAL_INT is a summary interrupt comprising the logical //! OR of the masked state of \b EMAC_INT_TRANSMIT, \b EMAC_INT_RECEIVE, //! \b EMAC_INT_TX_NO_BUFFER and \b EMAC_INT_EARLY_RECEIVE. //! - \b EMAC_INT_ABNORMAL_INT is a summary interrupt comprising the logical //! OR of the masked state of \b EMAC_INT_TX_STOPPED, \b EMAC_INT_TX_JABBER, //! \b EMAC_INT_RX_OVERFLOW, \b EMAC_INT_TX_UNDERFLOW, //! \b EMAC_INT_RX_NO_BUFFER, \b EMAC_INT_RX_STOPPED, //! \b EMAC_INT_RX_WATCHDOG, \b EMAC_INT_EARLY_TRANSMIT and //! \b EMAC_INT_BUS_ERROR. // //***************************************************************************** uint32_t EMACIntStatus(uint32_t ui32Base, bool bMasked) { uint32_t ui32Val, ui32PHYStat; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Get the unmasked interrupt status and clear any unwanted status fields. // ui32Val = HWREG(ui32Base + EMAC_O_DMARIS); ui32Val &= ~(EMAC_DMARIS_AE_M | EMAC_DMARIS_TS_M | EMAC_DMARIS_RS_M); // // This peripheral doesn't have a masked interrupt status register // so perform the masking manually. Note that only the bottom 16 bits // of the register can be masked so make sure we take this into account. // if (bMasked) { ui32Val &= (EMAC_NON_MASKED_INTS | HWREG(ui32Base + EMAC_O_DMAIM)); } // // Read the PHY interrupt status. // if (bMasked) { ui32PHYStat = HWREG(ui32Base + EMAC_O_EPHYMISC); } else { ui32PHYStat = HWREG(ui32Base + EMAC_O_EPHYRIS); } // // If the PHY interrupt is reported, add the appropriate flag to the // return value. // if (ui32PHYStat & EMAC_EPHYMISC_INT) { ui32Val |= EMAC_INT_PHY; } return (ui32Val); } //***************************************************************************** // //! Clears individual Ethernet MAC interrupt sources. //! //! \param ui32Base is the base address of the Ethernet MAC. //! \param ui32IntFlags is the bit mask of the interrupt sources to be cleared. //! //! This function disables the indicated Ethernet MAC interrupt sources. //! //! The \e ui32IntFlags parameter is the logical OR of any of the following: //! //! - \b EMAC_INT_PHY indicates that the PHY has signaled a change of state. //! Software must read and write the appropriate PHY registers to enable, //! disable and clear particular notifications. //! - \b EMAC_INT_EARLY_RECEIVE indicates that the DMA engine has filled the //! first data buffer of a packet. //! - \b EMAC_INT_BUS_ERROR indicates that a fatal bus error has occurred and //! that the DMA engine has been disabled. //! - \b EMAC_INT_EARLY_TRANSMIT indicates that a frame to be transmitted has //! been fully written from memory into the MAC transmit FIFO. //! - \b EMAC_INT_RX_WATCHDOG indicates that a frame with length greater than //! 2048 bytes (of 10240 bytes in Jumbo Frame mode) was received. //! - \b EMAC_INT_RX_STOPPED indicates that the receive process has entered //! the stopped state. //! - \b EMAC_INT_RX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's receive descriptor list and the DMA cannot, therefore, acquire //! a buffer. The receive process is suspended and can be resumed by changing //! the descriptor ownership and calling EMACRxDMAPollDemand(). //! - \b EMAC_INT_RECEIVE indicates that reception of a frame has completed //! and all requested status has been written to the appropriate DMA receive //! descriptor. //! - \b EMAC_INT_TX_UNDERFLOW indicates that the transmitter experienced an //! underflow during transmission. The transmit process is suspended. //! - \b EMAC_INT_RX_OVERFLOW indicates that an overflow was experienced //! during reception. //! - \b EMAC_INT_TX_JABBER indicates that the transmit jabber timer expired. //! This condition occurs when the frame size exceeds 2048 bytes (or 10240 //! bytes in Jumbo Frame mode) and causes the transmit process to abort and //! enter the Stopped state. //! - \b EMAC_INT_TX_NO_BUFFER indicates that the host owns the next buffer //! in the DMA's transmit descriptor list and that the DMA cannot, therefore, //! acquire a buffer. Transmission is suspended and can be resumed by changing //! the descriptor ownership and calling EMACTxDMAPollDemand(). //! - \b EMAC_INT_TX_STOPPED indicates that the transmit process has stopped. //! - \b EMAC_INT_TRANSMIT indicates that transmission of a frame has //! completed and that all requested status has been updated in the descriptor. //! //! Summary interrupt bits \b EMAC_INT_NORMAL_INT and //! \b EMAC_INT_ABNORMAL_INT are cleared automatically by the driver if any //! of their constituent sources are cleared. Applications do not need to //! explicitly clear these bits. //! //! \return None. // //***************************************************************************** void EMACIntClear(uint32_t ui32Base, uint32_t ui32IntFlags) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Mask in the normal interrupt if one of the sources it relates to is // specified. // if (ui32IntFlags & EMAC_NORMAL_INTS) { ui32IntFlags |= EMAC_INT_NORMAL_INT; } // // Similarly, mask in the abnormal interrupt if one of the sources it // relates to is specified. // if (ui32IntFlags & EMAC_ABNORMAL_INTS) { ui32IntFlags |= EMAC_INT_ABNORMAL_INT; } // // Clear the maskable interrupt sources. We write exactly the value passed // (with the summary sources added if necessary) but remember that only // the bottom 17 bits of the register are actually clearable. Only do // this if some bits are actually set that refer to the DMA interrupt // sources. // if (ui32IntFlags & ~EMAC_INT_PHY) { HWREG(ui32Base + EMAC_O_DMARIS) = (ui32IntFlags & ~EMAC_INT_PHY); } // // Clear the PHY interrupt if we've been asked to do this. // if (ui32IntFlags & EMAC_INT_PHY) { HWREG(ui32Base + EMAC_O_EPHYMISC) |= EMAC_EPHYMISC_INT; } } //***************************************************************************** // //! Writes to the PHY register. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to access. //! \param ui8RegAddr is the address of the PHY register to be accessed. //! \param ui16Data is the data to be written to the PHY register. //! //! This function writes the \e ui16Data value to the PHY register specified by //! \e ui8RegAddr. //! //! \return None. // //***************************************************************************** void EMACPHYWrite(uint32_t ui32Base, uint8_t ui8PhyAddr, uint8_t ui8RegAddr, uint16_t ui16Data) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Parameter sanity check. // ASSERT(ui8PhyAddr < 32); // // Make sure the MII is idle. // while (HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB) { } // // Write the value provided. // HWREG(ui32Base + EMAC_O_MIIDATA) = ui16Data; // // Tell the MAC to write the given PHY register. // HWREG(ui32Base + EMAC_O_MIIADDR) = ((HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_CR_M) | (ui8RegAddr << EMAC_MIIADDR_MII_S) | (ui8PhyAddr << EMAC_MIIADDR_PLA_S) | EMAC_MIIADDR_MIIW | EMAC_MIIADDR_MIIB); // // Wait for the write to complete. // while (HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB) { } } //***************************************************************************** // //! Reads from a PHY register. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to access. //! \param ui8RegAddr is the address of the PHY register to be accessed. //! //! This function returns the contents of the PHY register specified by //! \e ui8RegAddr. //! //! \return Returns the 16-bit value read from the PHY. // //***************************************************************************** uint16_t EMACPHYRead(uint32_t ui32Base, uint8_t ui8PhyAddr, uint8_t ui8RegAddr) { // // Parameter sanity check. // ASSERT(ui8PhyAddr < 32); ASSERT(ui32Base == EMAC0_BASE); // // Make sure the MII is idle. // while (HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB) { } // // Tell the MAC to read the given PHY register. // HWREG(ui32Base + EMAC_O_MIIADDR) = ((HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_CR_M) | (ui8RegAddr << EMAC_MIIADDR_MII_S) | (ui8PhyAddr << EMAC_MIIADDR_PLA_S) | EMAC_MIIADDR_MIIB); // // Wait for the read to complete. // while (HWREG(ui32Base + EMAC_O_MIIADDR) & EMAC_MIIADDR_MIIB) { } // // Return the result. // return (HWREG(ui32Base + EMAC_O_MIIDATA) & EMAC_MIIDATA_DATA_M); } //***************************************************************************** // //! Reads from an extended PHY register. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to access. //! \param ui16RegAddr is the address of the PHY extended register to be //! accessed. //! //! When using the internal PHY or when connected to an external PHY //! supporting extended registers, this function returns the contents of the //! extended PHY register specified by \e ui16RegAddr. //! //! \return Returns the 16-bit value read from the PHY. // //***************************************************************************** uint16_t EMACPHYExtendedRead(uint32_t ui32Base, uint8_t ui8PhyAddr, uint16_t ui16RegAddr) { // // Parameter sanity check. // ASSERT(ui8PhyAddr < 32); ASSERT(ui32Base == EMAC0_BASE); // // Set the address of the register we're about to read. // EMACPHYWrite(EMAC0_BASE, ui8PhyAddr, EPHY_REGCTL, 0x001F); EMACPHYWrite(EMAC0_BASE, ui8PhyAddr, EPHY_ADDAR, ui16RegAddr); // // Read the extended register value. // EMACPHYWrite(EMAC0_BASE, ui8PhyAddr, EPHY_REGCTL, 0x401F); return (EMACPHYRead(EMAC0_BASE, ui8PhyAddr, EPHY_ADDAR)); } //***************************************************************************** // //! Writes a value to an extended PHY register. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to access. //! \param ui16RegAddr is the address of the PHY extended register to be //! accessed. //! \param ui16Value is the value to write to the register. //! //! When using the internal PHY or when connected to an external PHY //! supporting extended registers, this function allows a value to be written //! to the extended PHY register specified by \e ui16RegAddr. //! //! \return None. // //***************************************************************************** void EMACPHYExtendedWrite(uint32_t ui32Base, uint8_t ui8PhyAddr, uint16_t ui16RegAddr, uint16_t ui16Value) { // // Parameter sanity check. // ASSERT(ui8PhyAddr < 32); ASSERT(ui32Base == EMAC0_BASE); // // Set the address of the register we're about to write. // EMACPHYWrite(EMAC0_BASE, ui8PhyAddr, EPHY_REGCTL, 0x001F); EMACPHYWrite(EMAC0_BASE, ui8PhyAddr, EPHY_ADDAR, ui16RegAddr); // // Write the extended register. // EMACPHYWrite(EMAC0_BASE, ui8PhyAddr, EPHY_REGCTL, 0x401F); EMACPHYWrite(EMAC0_BASE, ui8PhyAddr, EPHY_ADDAR, ui16Value); } //***************************************************************************** // //! Powers off the Ethernet PHY. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to power down. //! //! This function powers off the Ethernet PHY, reducing the current //! consumption of the device. While in the powered-off state, the Ethernet //! controller is unable to connect to Ethernet. //! //! \return None. // //***************************************************************************** void EMACPHYPowerOff(uint32_t ui32Base, uint8_t ui8PhyAddr) { // // Set the PWRDN bit and clear the ANEN bit in the PHY, putting it into // its low power mode. // EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_BMCR, (EMACPHYRead(ui32Base, ui8PhyAddr, EPHY_BMCR) & ~EPHY_BMCR_ANEN) | EPHY_BMCR_PWRDWN); } //***************************************************************************** // //! Powers on the Ethernet PHY. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to power up. //! //! This function powers on the Ethernet PHY, enabling it return to normal //! operation. By default, the PHY is powered on, so this function is only //! called if EMACPHYPowerOff() has previously been called. //! //! \return None. // //***************************************************************************** void EMACPHYPowerOn(uint32_t ui32Base, uint8_t ui8PhyAddr) { // // Clear the PWRDN bit and set the ANEGEN bit in the PHY, putting it into // normal operating mode. // EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_BMCR, (EMACPHYRead(ui32Base, ui8PhyAddr, EPHY_BMCR) & ~EPHY_BMCR_PWRDWN) | EPHY_BMCR_ANEN); } //***************************************************************************** // //! Configures the Ethernet MAC's IEEE 1588 timestamping options. //! //! \param ui32Base is the base address of the controller. //! \param ui32Config contains flags selecting particular configuration //! options. //! \param ui32SubSecondInc is the number that the IEEE 1588 subsecond clock //! should increment on each tick. //! //! This function is used to configure the operation of the Ethernet MAC's //! internal timestamping clock. This clock is used to timestamp incoming //! and outgoing packets and as an accurate system time reference when //! IEEE 1588 Precision Time Protocol is in use. //! //! The \e ui32Config parameter contains a collection of flags selecting the //! desired options. Valid flags are: //! //! One of the following to determine whether IEEE 1588 version 1 or version 2 //! packet format is to be processed: //! //! - \b EMAC_TS_PTP_VERSION_2 //! - \b EMAC_TS_PTP_VERSION_1 //! //! One of the following to determine how the IEEE 1588 clock's subsecond //! value should be interpreted and handled: //! //! - \b EMAC_TS_DIGITAL_ROLLOVER causes the clock's subsecond value to roll //! over at 0x3BA9C9FF (999999999 decimal). In this mode, it can be considered //! as a nanosecond counter with each digit representing 1 ns. //! - \b EMAC_TS_BINARY_ROLLOVER causes the clock's subsecond value to roll //! over at 0x7FFFFFFF. In this mode, the subsecond value counts 0.465 ns //! periods. //! //! One of the following to enable or disable MAC address filtering. When //! enabled, PTP frames are filtered unless the destination MAC address matches //! any of the currently programmed MAC addresses. //! //! - \b EMAC_TS_MAC_FILTER_ENABLE //! - \b EMAC_TS_MAC_FILTER_DISABLE //! //! One of the following to determine how the clock is updated: //! - \b EMAC_TS_UPDATE_COARSE causes the IEEE 1588 clock to advance by //! the value supplied in the \e ui32SubSecondInc parameter on each main //! oscillator clock cycle. //! - \b EMAC_TS_UPDATE_FINE selects the fine update method which causes the //! IEEE 1588 clock to advance by the the value supplied in the //! \e ui32SubSecondInc parameter each time a carry is generated from the //! addend accumulator register. //! //! One of the following to determine which IEEE 1588 messages are timestamped: //! //! - \b EMAC_TS_SYNC_FOLLOW_DREQ_DRESP timestamps SYNC, Follow_Up, Delay_Req //! and Delay_Resp messages. //! - \b EMAC_TS_SYNC_ONLY timestamps only SYNC messages. //! - \b EMAC_TS_DELAYREQ_ONLY timestamps only Delay_Req messages. //! - \b EMAC_TS_ALL timestamps all IEEE 1588 messages. //! - \b EMAC_TS_SYNC_PDREQ_PDRESP timestamps only SYNC, Pdelay_Req and //! Pdelay_Resp messages. //! - \b EMAC_TS_DREQ_PDREQ_PDRESP timestamps only Delay_Req, Pdelay_Req and //! Pdelay_Resp messages. //! - \b EMAC_TS_SYNC_DELAYREQ timestamps only Delay_Req messages. //! - \b EMAC_TS_PDREQ_PDRESP timestamps only Pdelay_Req and Pdelay_Resp //! messages. //! //! Optional, additional flags are: //! //! - \b EMAC_TS_PROCESS_IPV4_UDP processes PTP packets encapsulated in UDP //! over IPv4 packets. If absent, the MAC ignores these frames. //! - \b EMAC_TS_PROCESS_IPV6_UDP processes PTP packets encapsulated in UDP //! over IPv6 packets. If absent, the MAC ignores these frames. //! - \b EMAC_TS_PROCESS_ETHERNET processes PTP packets encapsulated directly //! in Ethernet frames. If absent, the MAC ignores these frames. //! - \b EMAC_TS_ALL_RX_FRAMES enables timestamping for all frames received //! by the MAC, regardless of type. //! //! The \e ui32SubSecondInc controls the rate at which the timestamp clock's //! subsecond count increments. Its meaning depends on which of \b //! EMAC_TS_DIGITAL_ROLLOVER or \b EMAC_TS_BINARY_ROLLOVER and //! \b EMAC_TS_UPDATE_FINE or \b EMAC_TS_UPDATE_COARSE were included //! in \e ui32Config. //! //! The timestamp second counter is incremented each time the subsecond counter //! rolls over. In digital rollover mode, the subsecond counter acts as a //! simple 31-bit counter, rolling over to 0 after reaching 0x7FFFFFFF. In //! this case, each lsb of the subsecond counter represents 0.465 ns (assuming //! the definition of 1 second resolution for the seconds counter). When //! binary rollover mode is selected, the subsecond counter acts as a //! nanosecond counter and rolls over to 0 after reaching 999,999,999 making //! each lsb represent 1 nanosecond. //! //! In coarse update mode, the timestamp subsecond counter is incremented by //! \e ui32SubSecondInc on each main oscillator clock tick. Setting //! \e ui32SubSecondInc to the main oscillator clock period in either 1 ns or //! 0.465 ns units ensures that the time stamp, read as seconds and //! subseconds, increments at the same rate as the main oscillator clock. For //! example, if the main oscillator is 25 MHz, \e ui32SubSecondInc is set to 40 //! if digital rollover mode is selected or (40 / 0.465) = 86 in binary //! rollover mode. //! //! In fine update mode, the subsecond increment value must be set according //! to the desired accuracy of the recovered IEEE 1588 clock which must be //! lower than the system clock rate. Fine update mode is typically used when //! synchronizing the local clock to the IEEE 1588 master clock. The subsecond //! counter is incremented by \e ui32SubSecondInc counts each time a 32-bit //! accumulator register generates a carry. The accumulator register is //! incremented by the addend value on each main oscillator tick and this //! addend value is modified to allow fine control over the rate of change of //! the timestamp counter. The addend value is calculated using the ratio of //! the main oscillator clock rate and the desired IEEE 1588 clock rate and the //! \e ui32SubSecondInc value is set to correspond to the desired IEEE 1588 //! clock rate. As an example, using digital rollover mode and a 25-MHz //! main oscillator clock with a desired IEEE 1588 clock accuracy of 12.5 MHz, //! we would set \e ui32SubSecondInc to the 12.5-MHz clock period of 80 ns and //! set the initial addend value to 0x80000000 to generate a carry on every //! second system clock. //! //! \sa EMACTimestampAddendSet() //! //! \return None. // //***************************************************************************** void EMACTimestampConfigSet(uint32_t ui32Base, uint32_t ui32Config, uint32_t ui32SubSecondInc) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Ensure that the PTP module clock is enabled. // HWREG(ui32Base + EMAC_O_CC) |= EMAC_CC_PTPCEN; // // Write the subsecond increment value. // HWREG(ui32Base + EMAC_O_SUBSECINC) = ((ui32SubSecondInc << EMAC_SUBSECINC_SSINC_S) & EMAC_SUBSECINC_SSINC_M); // // Set the timestamp configuration. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) = ui32Config; } //***************************************************************************** // //! Returns the current IEEE 1588 timestamping configuration. //! //! \param ui32Base is the base address of the controller. //! \param pui32SubSecondInc points to storage that is written with the //! current subsecond increment value for the IEEE 1588 clock. //! //! This function may be used to retreive the current MAC timestamping //! configuration. //! //! \sa EMACTimestampConfigSet() //! //! \return Returns the current timestamping configuration as a logical OR of //! the following flags: //! //! - \b EMAC_TS_PTP_VERSION_2 indicates that the MAC is processing PTP //! version 2 messages. If this flag is absent, PTP version 1 messages are //! expected. //! - \b EMAC_TS_DIGITAL_ROLLOVER causes the clock's subsecond value to roll //! over at 0x3BA9C9FF (999999999 decimal). In this mode, it can be considered //! as a nanosecond counter with each digit representing 1 ns. If this flag is //! absent, the subsecond value rolls over at 0x7FFFFFFF, effectively counting //! increments of 0.465 ns. //! - \b EMAC_TS_MAC_FILTER_ENABLE indicates that incoming PTP messages //! are filtered using any of the configured MAC addresses. Messages with a //! destination address programmed into the MAC address filter are passed, //! others are discarded. If this flag is absent, the MAC address is ignored. //! - \b EMAC_TS_UPDATE_FINE implements the fine update method that causes the //! IEEE 1588 clock to advance by the the value returned in the //! \e *pui32SubSecondInc parameter each time a carry is generated from the //! addend accumulator register. If this flag is absent, the coarse update //! method is in use and the clock is advanced by the \e *pui32SubSecondInc //! value on each system clock tick. //! - \b EMAC_TS_SYNC_ONLY indicates that timestamps are only generated for //! SYNC messages. //! - \b EMAC_TS_DELAYREQ_ONLY indicates that timestamps are only generated //! for Delay_Req messages. //! - \b EMAC_TS_ALL indicates that timestamps are generated for all //! IEEE 1588 messages. //! - \b EMAC_TS_SYNC_PDREQ_PDRESP timestamps only SYNC, Pdelay_Req and //! Pdelay_Resp messages. //! - \b EMAC_TS_DREQ_PDREQ_PDRESP indicates that timestamps are only //! generated for Delay_Req, Pdelay_Req and Pdelay_Resp messages. //! - \b EMAC_TS_SYNC_DELAYREQ indicates that timestamps are only generated //! for Delay_Req messages. //! - \b EMAC_TS_PDREQ_PDRESP indicates that timestamps are only generated //! for Pdelay_Req and Pdelay_Resp messages. //! - \b EMAC_TS_PROCESS_IPV4_UDP indicates that PTP packets encapsulated in //! UDP over IPv4 packets are being processed. If absent, the MAC ignores //! these frames. //! - \b EMAC_TS_PROCESS_IPV6_UDP indicates that PTP packets encapsulated in //! UDP over IPv6 packets are being processed. If absent, the MAC ignores //! these frames. //! - \b EMAC_TS_PROCESS_ETHERNET indicates that PTP packets encapsulated //! directly in Ethernet frames are being processd. If absent, the MAC ignores //! these frames. //! - \b EMAC_TS_ALL_RX_FRAMES indicates that timestamping is enabled for all //! frames received by the MAC, regardless of type. //! //! If \b EMAC_TS_ALL_RX_FRAMES and none of the options specifying subsets //! of PTP packets to timestamp are set, the MAC is configured to timestamp //! SYNC, Follow_Up, Delay_Req and Delay_Resp messages only. // //***************************************************************************** uint32_t EMACTimestampConfigGet(uint32_t ui32Base, uint32_t *pui32SubSecondInc) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(pui32SubSecondInc); // // Read the current subsecond increment value. // *pui32SubSecondInc = (HWREG(ui32Base + EMAC_O_SUBSECINC) & EMAC_SUBSECINC_SSINC_M) >> EMAC_SUBSECINC_SSINC_S; // // Return the current timestamp configuration. // return (HWREG(ui32Base + EMAC_O_TIMSTCTRL)); } //***************************************************************************** // //! Enables packet timestamping and starts the system clock running. //! //! \param ui32Base is the base address of the controller. //! //! This function is used to enable the system clock used to timestamp //! Ethernet frames and to enable that timestamping. //! //! \return None. // //***************************************************************************** void EMACTimestampEnable(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Enable IEEE 1588 timestamping. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) |= EMAC_TIMSTCTRL_TSEN; // // If necessary, initialize the timestamping system. This bit self-clears // once the system time is loaded. Only do this if initialization is not // currently ongoing. // if (!(HWREG(ui32Base + EMAC_O_TIMSTCTRL) & EMAC_TIMSTCTRL_TSINIT)) { HWREG(ui32Base + EMAC_O_TIMSTCTRL) |= EMAC_TIMSTCTRL_TSINIT; } } //***************************************************************************** // //! Disables packet timestamping and stops the system clock. //! //! \param ui32Base is the base address of the controller. //! //! This function is used to stop the system clock used to timestamp //! Ethernet frames and to disable timestamping. //! //! \return None. // //***************************************************************************** void EMACTimestampDisable(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Disable IEEE 1588 timestamping. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) &= ~EMAC_TIMSTCTRL_TSEN; } //***************************************************************************** // //! Sets the current system time. //! //! \param ui32Base is the base address of the controller. //! \param ui32Seconds is the seconds value of the new system clock setting. //! \param ui32SubSeconds is the subseconds value of the new system clock //! setting. //! //! This function may be used to set the current system time. The system //! clock is set to the value passed in the \e ui32Seconds and //! \e ui32SubSeconds parameters. //! //! The meaning of \e ui32SubSeconds depends on the current system time //! configuration. If EMACTimestampConfigSet() was previously called with //! the \e EMAC_TS_DIGITAL_ROLLOVER configuration option, each bit in the //! \e ui32SubSeconds value represents 1 ns. If \e EMAC_TS_BINARY_ROLLOVER was //! specified instead, a \e ui32SubSeconds bit represents 0.46 ns. //! //! \return None. // //***************************************************************************** void EMACTimestampSysTimeSet(uint32_t ui32Base, uint32_t ui32Seconds, uint32_t ui32SubSeconds) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Write the new time to the system time update registers. // HWREG(ui32Base + EMAC_O_TIMSECU) = ui32Seconds; HWREG(ui32Base + EMAC_O_TIMNANOU) = ui32SubSeconds; // // Wait for any previous update to complete. // while (HWREG(ui32Base + EMAC_O_TIMSTCTRL) & EMAC_TIMSTCTRL_TSINIT) { // // Spin for a while. // } // // Force the system clock to reset. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) |= EMAC_TIMSTCTRL_TSINIT; } //***************************************************************************** // //! Gets the current system time. //! //! \param ui32Base is the base address of the controller. //! \param pui32Seconds points to storage for the current seconds value. //! \param pui32SubSeconds points to storage for the current subseconds value. //! //! This function may be used to get the current system time. //! //! The meaning of \e ui32SubSeconds depends on the current system time //! configuration. If EMACTimestampConfigSet() was previously called with //! the \e EMAC_TS_DIGITAL_ROLLOVER configuration option, each bit in the //! \e ui32SubSeconds value represents 1 ns. If \e EMAC_TS_BINARY_ROLLOVER was //! specified instead, a \e ui32SubSeconds bit represents 0.46 ns. //! //! \return None. // //***************************************************************************** void EMACTimestampSysTimeGet(uint32_t ui32Base, uint32_t *pui32Seconds, uint32_t *pui32SubSeconds) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(pui32Seconds); ASSERT(pui32SubSeconds); // // Read the two-part system time from the seconds and nanoseconds // registers. We do this in a way that should guard against us reading // the registers across a nanosecond wrap. // do { *pui32Seconds = HWREG(ui32Base + EMAC_O_TIMSEC); *pui32SubSeconds = HWREG(ui32Base + EMAC_O_TIMNANO); } while (*pui32Seconds != HWREG(ui32Base + EMAC_O_TIMNANO)); } //***************************************************************************** // //! Adjusts the current system time upwards or downwards by a given amount. //! //! \param ui32Base is the base address of the controller. //! \param ui32Seconds is the seconds value of the time update to apply. //! \param ui32SubSeconds is the subseconds value of the time update to apply. //! \param bInc defines the direction of the update. //! //! This function may be used to adjust the current system time either upwards //! or downwards by a given amount. The size of the adjustment is given by //! the \e ui32Seconds and \e ui32SubSeconds parameter and the direction //! by the \e bInc parameter. When \e bInc is \e true, the system time is //! advanced by the interval given. When it is \e false, the time is retarded //! by the interval. //! //! The meaning of \e ui32SubSeconds depends on the current system time //! configuration. If EMACTimestampConfigSet() was previously called with //! the \e EMAC_TS_DIGITAL_ROLLOVER configuration option, each bit in the //! subsecond value represents 1 ns. If \e EMAC_TS_BINARY_ROLLOVER was //! specified instead, a subsecond bit represents 0.46 ns. //! //! \return None. // //***************************************************************************** void EMACTimestampSysTimeUpdate(uint32_t ui32Base, uint32_t ui32Seconds, uint32_t ui32SubSeconds, bool bInc) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Write the new time to the system time update registers. // HWREG(ui32Base + EMAC_O_TIMSECU) = ui32Seconds; HWREG(ui32Base + EMAC_O_TIMNANOU) = ui32SubSeconds | (bInc ? 0 : EMAC_TIMNANOU_ADDSUB); // // Wait for any previous update to complete. // while (HWREG(ui32Base + EMAC_O_TIMSTCTRL) & EMAC_TIMSTCTRL_TSUPDT) { // // Spin for a while. // } // // Force the system clock to update by the value provided. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) |= EMAC_TIMSTCTRL_TSUPDT; } //***************************************************************************** // //! Adjusts the system time update rate when using the fine correction method. //! //! \param ui32Base is the base address of the controller. //! \param ui32Increment is the number to add to the accumulator register on //! each tick of the 25-MHz main oscillator. //! //! This function is used to control the rate of update of the system time //! when in fine update mode. Fine correction mode is selected if //! \e EMAC_TS_UPDATE_FINE is supplied in the \e ui32Config parameter passed //! to a previous call to EMACTimestampConfigSet(). Fine update mode is //! typically used when synchronizing the local clock to the IEEE 1588 master //! clock. The subsecond counter is incremented by the number passed to //! EMACTimestampConfigSet() in the \e ui32SubSecondInc parameter each time a //! 32-bit accumulator register generates a carry. The accumulator register is //! incremented by the "addend" value on each main oscillator tick, and this //! addend value is modified to allow fine control over the rate of change of //! the timestamp counter. The addend value is calculated using the ratio of //! the main oscillator clock rate and the desired IEEE 1588 clock rate and the //! \e ui32SubSecondInc value is set to correspond to the desired IEEE 1588 //! clock rate. //! //! As an example, using digital rollover mode and a 25-MHz main oscillator //! clock with a desired IEEE 1588 clock accuracy of 12.5 MHz, and having made //! a previous call to EMACTimestampConfigSet() with \e ui32SubSecondInc set to //! the 12.5-MHz clock period of 80 ns, the initial \e ui32Increment value //! would be set to 0x80000000 to generate a carry on every second main //! oscillator tick. Because the system time updates each time the accumulator //! overflows, small changes in the \e ui32Increment value can be used to very //! finely control the system time rate. //! //! \return None. //! //! \sa EMACTimestampConfigSet() // //***************************************************************************** void EMACTimestampAddendSet(uint32_t ui32Base, uint32_t ui32Increment) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); HWREG(ui32Base + EMAC_O_TIMADD) = ui32Increment; // // Wait for any previous update to complete. // while (HWREG(ui32Base + EMAC_O_TIMSTCTRL) & EMAC_TIMSTCTRL_ADDREGUP) { // // Spin for a while. // } // // Force the system clock to update by the value provided. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) |= EMAC_TIMSTCTRL_ADDREGUP; } //***************************************************************************** // //! Sets the target system time at which the next Ethernet timer interrupt is //! generated. //! //! \param ui32Base is the base address of the controller. //! \param ui32Seconds is the second value of the desired target time. //! \param ui32SubSeconds is the subseconds value of the desired target time. //! //! This function may be used to schedule an interrupt at some future time. //! The time reference for the function is the IEEE 1588 time as returned by //! EMACTimestampSysTimeGet(). To generate an interrupt when the system //! time exceeds a given value, call this function to set the desired time, //! then EMACTimestampTargetIntEnable() to enable the interrupt. When the //! system time increments past the target time, an Ethernet interrupt with //! status \b EMAC_INT_TIMESTAMP is generated. //! //! The accuracy of the interrupt timing depends on the Ethernet timer //! update frequency and the subsecond increment value currently in use. The //! interrupt is generated on the first timer increment that causes the //! system time to be greater than or equal to the target time set. //! //! \return None. // //***************************************************************************** void EMACTimestampTargetSet(uint32_t ui32Base, uint32_t ui32Seconds, uint32_t ui32SubSeconds) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Wait for any previous write to complete. // while (HWREG(ui32Base + EMAC_O_TARGNANO) & EMAC_TARGNANO_TRGTBUSY) { } // // Write the new target time. // HWREG(ui32Base + EMAC_O_TARGSEC) = ui32Seconds; HWREG(ui32Base + EMAC_O_TARGNANO) = ui32SubSeconds; } //***************************************************************************** // //! Enables the Ethernet system time interrupt. //! //! \param ui32Base is the base address of the controller. //! //! This function may be used after EMACTimestampTargetSet() to schedule an //! interrupt at some future time. The time reference for the function is //! the IEEE 1588 time as returned by EMACTimestampSysTimeGet(). To generate //! an interrupt when the system time exceeds a given value, call this function //! to set the desired time, then EMACTimestampTargetIntEnable() to enable the //! interrupt. When the system time increments past the target time, an //! Ethernet interrupt with status \b EMAC_INT_TIMESTAMP is generated. //! //! \return None. // //***************************************************************************** void EMACTimestampTargetIntEnable(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Set the bit to enable the timestamp target interrupt. This bit clears // automatically when the interrupt fires after which point, you must // set a new target time and re-enable the interrupts. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) |= EMAC_TIMSTCTRL_INTTRIG; } //***************************************************************************** // //! Disables the Ethernet system time interrupt. //! //! \param ui32Base is the base address of the controller. //! //! This function may be used to disable any pending Ethernet system time //! interrupt previously scheduled using calls to EMACTimestampTargetSet() //! and EMACTimestampTargetIntEnable(). //! //! \return None. // //***************************************************************************** void EMACTimestampTargetIntDisable(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Clear the bit to disable the timestamp target interrupt. This bit // clears automatically when the interrupt fires, so it only must be // disabled if you want to cancel a previously-set interrupt. // HWREG(ui32Base + EMAC_O_TIMSTCTRL) &= ~EMAC_TIMSTCTRL_INTTRIG; } //***************************************************************************** // //! Reads the status of the Ethernet system time interrupt. //! //! \param ui32Base is the base address of the controller. //! //! When an Ethernet interrupt occurs and \b EMAC_INT_TIMESTAMP is reported //! bu EMACIntStatus(), this function must be called to read and clear the //! timer interrupt status. //! //! \return The return value is the logical OR of the values //! \b EMAC_TS_INT_TS_SEC_OVERFLOW and \b EMAC_TS_INT_TARGET_REACHED. //! //! - \b EMAC_TS_INT_TS_SEC_OVERFLOW indicates that the second counter in the //! hardware timer has rolled over. //! - \b EMAC_TS_INT_TARGET_REACHED indicates that the system time incremented //! past the value set in an earlier call to EMACTimestampTargetSet(). When //! this occurs, a new target time may be set and the interrupt re-enabled //! using calls to EMACTimestampTargetSet() and //! EMACTimestampTargetIntEnable(). // //***************************************************************************** uint32_t EMACTimestampIntStatus(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Return the current interrupt status from the timestamp module. // return (HWREG(ui32Base + EMAC_O_TIMSTAT)); } //***************************************************************************** // //! Configures the Ethernet MAC PPS output in simple mode. //! //! \param ui32Base is the base address of the controller. //! \param ui32FreqConfig determines the frequency of the output generated on //! the PPS pin. //! //! This function configures the Ethernet MAC PPS (Pulse Per Second) engine to //! operate in its simple mode which allows the generation of a few, fixed //! frequencies and pulse widths on the PPS pin. If more complex pulse //! train generation is required, the MAC also provides a command-based //! PPS control mode that can be selected by calling //! EMACTimestampPPSCommandModeSet(). //! //! The \e ui32FreqConfig parameter may take one of the following values: //! //! - \b EMAC_PPS_SINGLE_PULSE generates a single high pulse on the PPS //! output once per second. The pulse width is the same as the system clock //! period. //! - \b EMAC_PPS_1HZ generates a 1Hz signal on the PPS output. This option //! is not available if the system time subsecond counter is currently //! configured to operate in binary rollover mode. //! - \b EMAC_PPS_2HZ, \b EMAC_PPS_4HZ, \b EMAC_PPS_8HZ, //! \b EMAC_PPS_16HZ, \b EMAC_PPS_32HZ, \b EMAC_PPS_64HZ, //! \b EMAC_PPS_128HZ, \b EMAC_PPS_256HZ, \b EMAC_PPS_512HZ, //! \b EMAC_PPS_1024HZ, \b EMAC_PPS_2048HZ, \b EMAC_PPS_4096HZ, //! \b EMAC_PPS_8192HZ, \b EMAC_PPS_16384HZ generate the requested //! frequency on the PPS output in both binary and digital rollover modes. //! - \b EMAC_PPS_32768HZ generates a 32KHz signal on the PPS output. This //! option is not available if the system time subsecond counter is currently //! configured to operate in digital rollover mode. //! //! Except when \b EMAC_PPS_SINGLE_PULSE is specified, the signal generated //! on PPS has a duty cycle of 50% when binary rollover mode is used for the //! system time subsecond count. In digital mode, the output frequency //! averages the value requested and is resynchronized each second. For //! example, if \b EMAC_PPS_4HZ is selected in digital rollover mode, the //! output generates three clocks with 50 percent duty cycle and 268 ms //! period followed by a fourth clock of 195 ms period, 134 ms low and 61 ms high. //! //! \return None. // //***************************************************************************** void EMACTimestampPPSSimpleModeSet(uint32_t ui32Base, uint32_t ui32FreqConfig) { bool bDigital; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Are we currently running the clock in digital or binary rollover mode? // bDigital = (HWREG(ui32Base + EMAC_O_TIMSTCTRL) & EMAC_TS_DIGITAL_ROLLOVER) ? true : false; // // Weed out some unsupported frequencies. The hardware can't produce a // 1Hz output when we are in binary rollover mode and can't produce a // 32KHz output when we are digital rollover mode. // ASSERT(bDigital || (ui32FreqConfig != EMAC_PPS_1HZ)); ASSERT(!bDigital || (ui32FreqConfig != EMAC_PPS_32768HZ)); // // Adjust the supplied frequency if we are currently in binary update mode // where the control value generates an output that is twice as fast as // in digital mode. // if ((ui32FreqConfig != EMAC_PPS_SINGLE_PULSE) && !bDigital) { ui32FreqConfig--; } // // Write the frequency control value to the PPS control register, clearing // the PPSEN0 bit to ensure that the PPS engine is in simple mode and not // waiting for a command. We also clear the TRGMODS0 field to revert to // the default operation of the target time registers. // HWREG(ui32Base + EMAC_O_PPSCTRL) = ui32FreqConfig; } //***************************************************************************** // //! Configures the Ethernet MAC PPS output in command mode. //! \param ui32Base is the base address of the controller. //! \param ui32Config determines how the system target time is used. //! //! The simple mode of operation offered by the PPS (Pulse Per Second) engine //! may be too restrictive for some applications. The second mode, however, //! allows complex pulse trains to be generated using commands that tell the //! engine to send individual pulses or start and stop trains if pulses. In //! this mode, the pulse width and period may be set arbitrarily based on //! ticks of the clock used to update the system time. Commands are triggered //! at specific times using the target time last set using a call to //! EMACTimestampTargetSet(). //! //! The \e ui32Config parameter may be used to control whether the target //! time is used to trigger commands only or can also generate an interrupt //! to the CPU. Valid values are: //! //! - \b EMAC_PPS_TARGET_INT configures the target time to only raise //! an interrupt and not to trigger any pending PPS command. //! - \b EMAC_PPS_TARGET_PPS configures the target time to trigger a pending //! PPS command but not raise an interrupt. //! - \b EMAC_PPS_TARGET_BOTH configures the target time to trigger any //! pending PPS command and also raise an interrupt. //! //! To use command mode, an application must call this function to enable the //! mode, then call: //! //! - EMACTimestampPPSPeriodSet() to set the desired pulse width and period //! then //! - EMACTimestampTargetSet() to set the time at which the next command is //! executed, and finally //! - EMACTimestampPPSCommand() to send a command to cause the pulse or //! pulse train to be started at the required time. //! //! \return None. // //***************************************************************************** void EMACTimestampPPSCommandModeSet(uint32_t ui32Base, uint32_t ui32Config) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(!(ui32Config & (EMAC_PPS_TARGET_INT | EMAC_PPS_TARGET_PPS | EMAC_PPS_TARGET_BOTH))); // // Wait for any previous command write to complete. // while (HWREG(ui32Base + EMAC_O_PPSCTRL) & EMAC_PPSCTRL_PPSCTRL_M) { // // Wait a bit. // } // // Write the configuration value to the PPS control register, setting the // PPSEN0 bit to ensure that the PPS engine is in command mode and // clearing the command in the PPSCTRL field. // HWREG(ui32Base + EMAC_O_PPSCTRL) = (EMAC_PPSCTRL_PPSEN0 | ui32Config); } //***************************************************************************** // //! Sends a command to control the PPS output from the Ethernet MAC. //! //! \param ui32Base is the base address of the controller. //! \param ui8Cmd identifies the command to be sent. //! //! This function may be used to send a command to the MAC PPS (Pulse Per //! Second) controller when it is operating in command mode. Command mode //! is selected by calling EMACTimestampPPSCommandModeSet(). Valid //! commands are as follow: //! //! - \b EMAC_PPS_COMMAND_NONE indicates no command. //! - \b EMAC_PPS_COMMAND_START_SINGLE indicates that a single high pulse //! should be generated when the system time reaches the current target time. //! - \b EMAC_PPS_COMMAND_START_TRAIN indicates that a train of pulses //! should be started when the system time reaches the current target time. //! - \b EMAC_PPS_COMMAND_CANCEL_START cancels any pending start command if //! the system time has not yet reached the programmed target time. //! - \b EMAC_PPS_COMMAND_STOP_AT_TIME indicates that the current pulse //! train should be stopped when the system time reaches the current target //! time. //! - \b EMAC_PPS_COMMAND_STOP_NOW indicates that the current pulse train //! should be stopped immediately. //! - \b EMAC_PPS_COMMAND_CANCEL_STOP cancels any pending stop command if //! the system time has not yet reached the programmed target time. //! //! In all cases, the width of the pulses generated is governed by the //! \e ui32Width parameter passed to EMACTimestampPPSPeriodSet(). If a //! command starts a train of pulses, the period of the pulses is governed //! by the \e ui32Period parameter passed to the same function. //! Target times associated with PPS commands are set by calling //! EMACTimestampTargetSet(). //! //! \return None. // //***************************************************************************** void EMACTimestampPPSCommand(uint32_t ui32Base, uint8_t ui8Cmd) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Wait for any previous command write to complete. // while (HWREG(ui32Base + EMAC_O_PPSCTRL) & EMAC_PPSCTRL_PPSCTRL_M) { // // Wait a bit. // } // // Write the command to the PPS control register. // HWREG(ui32Base + EMAC_O_PPSCTRL) = (EMAC_PPSCTRL_PPSEN0 | ui8Cmd); } //***************************************************************************** // //! Sets the period and width of the pulses on the Ethernet MAC PPS output. //! //! \param ui32Base is the base address of the controller. //! \param ui32Period is the period of the PPS output expressed in terms of //! system time update ticks. //! \param ui32Width is the width of the high portion of the PPS output //! expressed in terms of system time update ticks. //! //! This function may be used to control the period and duty cycle of the //! signal output on the Ethernet MAC PPS pin when the PPS generator is //! operating in command mode and a command to send one or more pulses has been //! executed. Command mode is selected by calling //! EMACTimestampPPSCommandModeSet(). //! //! In simple mode, the PPS output signal frequency is controlled by the //! \e ui32FreqConfig parameter passed to EMACTimestampPPSSimpleModeSet(). //! //! The \e ui32Period and \e ui32Width parameters are expressed in terms of //! system time update ticks. When the system time is operating in coarse //! update mode, each tick is equivalent to the system clock. In fine update //! mode, a tick occurs every time the 32-bit system time accumulator overflows //! and this, in turn, is determined by the value passed to the function //! EMACTimestampAddendSet(). Regardless of the tick source, each tick //! increments the actual system time, queried using EMACTimestampSysTimeGet() //! by the subsecond increment value passed in the \e ui32SubSecondInc to //! EMACTimestampConfigSet(). //! //! \return None. // //***************************************************************************** void EMACTimestampPPSPeriodSet(uint32_t ui32Base, uint32_t ui32Period, uint32_t ui32Width) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Write the desired PPS period and pulse width. // HWREG(ui32Base + EMAC_O_PPS0INTVL) = ui32Period; HWREG(ui32Base + EMAC_O_PPS0WIDTH) = ui32Width; } //***************************************************************************** // //! Sets options related to reception of VLAN-tagged frames. //! //! \param ui32Base is the base address of the controller. //! \param ui16Tag is the IEEE 802.1Q VLAN tag expected for incoming frames. //! \param ui32Config determines how the receiver handles VLAN-tagged frames. //! //! This function configures the receiver's handling of IEEE 802.1Q VLAN //! tagged frames. Incoming tagged frames are filtered using either a perfect //! filter or a hash filter. When hash filtering is disabled, VLAN frames //! tagged with the value of \e ui16Tag pass the filter and all others are //! rejected. The tag comparison may involve all 16 bits or only the 12-bit //! VLAN ID portion of the tag. //! //! The \e ui32Config parameter is a logical OR of the following values: //! //! - \b EMAC_VLAN_RX_HASH_ENABLE enables hash filtering for VLAN tags. If //! this flag is absent, perfect filtering using the tag supplied in \e ui16Tag //! is performed. The hash filter may be set using EMACVLANHashFilterSet(), //! and EMACVLANHashFilterBitCalculate() may be used to determine which bits //! to set in the filter for given VLAN tags. //! - \b EMAC_VLAN_RX_SVLAN_ENABLE causes the receiver to recognize S-VLAN //! (Type = 0x88A8) frames as valid VLAN-tagged frames. If absent, only //! frames with type 0x8100 are considered valid VLAN frames. //! - \b EMAC_VLAN_RX_INVERSE_MATCH causes the receiver to pass all VLAN //! frames for which the tags do not match the supplied \e ui16Tag value. If //! this flag is absent, only tagged frames matching \e ui16Tag are passed. //! - \b EMAC_VLAN_RX_12BIT_TAG causes the receiver to compare only the //! bottom 12 bits of \e ui16Tag when performing either perfect or hash //! filtering of VLAN frames. If this flag is absent, all 16 bits of the frame //! tag are examined when filtering. If this flag is set and \e ui16Tag has //! all bottom 12 bits clear, the receiver passes all frames with types //! 0x8100 or 0x88A8 regardless of the tag values they contain. //! //! \note To ensure that VLAN frames that fail the tag filter are dropped //! by the MAC, EMACFrameFilterSet() must be called with the \b //! EMAC_FRMFILTER_VLAN flag set in the \e ui32FilterOpts parameter. If //! this flag is not set, failing VLAN packets are received by the //! application, but bit 10 of RDES0 (\b EMAC_FRMFILTER_VLAN) is clear //! indicating that the packet did not match the current VLAG tag filter. //! //! \sa EMACVLANRxConfigGet() //! //! \return None // //***************************************************************************** void EMACVLANRxConfigSet(uint32_t ui32Base, uint16_t ui16Tag, uint32_t ui32Config) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Write the VLAN tag register. // HWREG(ui32Base + EMAC_O_VLANTG) = ui32Config | (((uint32_t)ui16Tag) << EMAC_VLANTG_VL_S); } //***************************************************************************** // //! Returns the currently-set options related to reception of VLAN-tagged //! frames. //! //! \param ui32Base is the base address of the controller. //! \param pui16Tag points to storage which is written with the currently //! configured VLAN tag used for perfect filtering. //! //! This function returns information on how the receiver is currently //! handling IEEE 802.1Q VLAN-tagged frames. //! //! \sa EMACVLANRxConfigSet() //! //! \return Returns flags defining how VLAN-tagged frames are handled. The //! value is a logical OR of the following flags: //! //! - \b EMAC_VLAN_RX_HASH_ENABLE indicates that hash filtering is enabled //! for VLAN tags. If this flag is absent, perfect filtering using the tag //! returned in \e *pui16Tag is performed. //! - \b EMAC_VLAN_RX_SVLAN_ENABLE indicates that the receiver recognizes //! S-VLAN (Type = 0x88A8) frames as valid VLAN-tagged frames. If absent, only //! frames with type 0x8100 are considered valid VLAN frames. //! - \b EMAC_VLAN_RX_INVERSE_MATCH indicates that the receiver passes all //! VLAN frames for which the tags do not match the \e *pui16Tag value. If //! this flag is absent, only tagged frames matching \e *pui16Tag are passed. //! - \b EMAC_VLAN_RX_12BIT_TAG indicates that the receiver is comparing only //! the bottom 12 bits of \e *pui16Tag when performing either perfect or hash //! filtering of VLAN frames. If this flag is absent, all 16 bits of the frame //! tag are examined when filtering. If this flag is set and \e *pui16Tag has //! all bottom 12 bits clear, the receiver passes all frames with types //! 0x8100 or 0x88A8 regardless of the tag values they contain. // //***************************************************************************** uint32_t EMACVLANRxConfigGet(uint32_t ui32Base, uint16_t *pui16Tag) { uint32_t ui32Value; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(pui16Tag); // // Read the VLAN tag register. // ui32Value = HWREG(ui32Base + EMAC_O_VLANTG); // // Extract the VLAN tag from the register. // *pui16Tag = (ui32Value & EMAC_VLANTG_VL_M) >> EMAC_VLANTG_VL_S; // // Return the configuration flags. // return (ui32Value & ~EMAC_VLANTG_VL_M); } //***************************************************************************** // //! Sets options related to transmission of VLAN-tagged frames. //! //! \param ui32Base is the base address of the controller. //! \param ui16Tag is the VLAN tag to be used when inserting or replacing tags //! in transmitted frames. //! \param ui32Config determines the VLAN-related processing performed by //! the transmitter. //! //! This function is used to configure transmitter options relating to //! IEEE 802.1Q VLAN tagging. The transmitter may be set to insert tagging //! into untagged frames or replace existing tags with new values. //! //! The \e ui16Tag parameter contains the VLAN tag to be used in outgoing //! tagged frames. The \e ui32Config parameter is a logical OR of the //! following labels: //! //! - \b EMAC_VLAN_TX_SVLAN uses the S-VLAN type (0x88A8) when inserting or //! replacing tags in transmitted frames. If this label is absent, C-VLAN //! type (0x8100) is used. //! - \b EMAC_VLAN_TX_USE_VLC informs the transmitter that the VLAN tag //! handling should be defined by the VLAN control (VLC) value provided in //! this function call. If this tag is absent, VLAN handling is controlled //! by fields in the transmit descriptor. //! //! If \b EMAC_VLAN_TX_USE_VLC is set, one of the following four labels //! must also be included to define the transmit VLAN tag handling: //! //! - \b EMAC_VLAN_TX_VLC_NONE instructs the transmitter to perform no VLAN //! tag insertion, deletion or replacement. //! - \b EMAC_VLAN_TX_VLC_DELETE instructs the transmitter to remove VLAN //! tags from all transmitted frames that contain them. As a result, bytes //! 13, 14, 15 and 16 are removed from all frames with types 0x8100 or 0x88A8. //! - \b EMAC_VLAN_TX_VLC_INSERT instructs the transmitter to insert a VLAN //! type and tag into all outgoing frames regardless of whether or not they //! already contain a VLAN tag. //! - \b EMAC_VLAN_TX_VLC_REPLACE instructs the transmitter to replace the //! VLAN tag in all frames of type 0x8100 or 0x88A8 with the value provided to //! this function in the \e ui16Tag parameter. //! //! \return None // //***************************************************************************** void EMACVLANTxConfigSet(uint32_t ui32Base, uint16_t ui16Tag, uint32_t ui32Config) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Write the VLAN Tag Inclusion or Replacement register. // HWREG(ui32Base + EMAC_O_VLNINCREP) = ui32Config | ((uint32_t)ui16Tag << EMAC_VLNINCREP_VLT_S); } //***************************************************************************** // //! Returns currently-selected options related to transmission of VLAN-tagged //! frames. //! //! \param ui32Base is the base address of the controller. //! \param pui16Tag points to storage that is written with the VLAN tag //! currently being used for insertion or replacement. //! //! This function returns information on the current settings related to VLAN //! tagging of transmitted frames. //! //! \sa EMACVLANTxConfigSet() //! //! \return Returns flags describing the current VLAN configuration relating //! to frame transmission. The return value is a logical OR of the following //! values: //! //! - \b EMAC_VLAN_TX_SVLAN indicates that the S-VLAN type (0x88A8) is //! being used when inserting or replacing tags in transmitted frames. If //! this label is absent, C-VLAN type (0x8100) is being used. //! - \b EMAC_VLAN_TX_USE_VLC indicates that the transmitter is processing //! VLAN frames according to the VLAN control (VLC) value returned here. If //! this tag is absent, VLAN handling is controlled by fields in the transmit //! descriptor. //! //! If \b EMAC_VLAN_TX_USE_VLC is returned, one of the following four labels //! is also included to define the transmit VLAN tag handling. Note that this //! value may be extracted from the return value using the mask \b //! EMAC_VLAN_TX_VLC_MASK. //! //! - \b EMAC_VLAN_TX_VLC_NONE indicates that the transmitter is not //! performing VLAN tag insertion, deletion or replacement. //! - \b EMAC_VLAN_TX_VLC_DELETE indicates that the transmitter is removing //! VLAN tags from all transmitted frames which contain them. //! - \b EMAC_VLAN_TX_VLC_INSERT indicates that the transmitter is inserting //! a VLAN type and tag into all outgoing frames regardless of whether or not //! they already contain a VLAN tag. //! - \b EMAC_VLAN_TX_VLC_REPLACE indicates that the transmitter is replacing //! the VLAN tag in all transmitted frames of type 0x8100 or 0x88A8 with the //! value returned in \e *pui16Tag. // //***************************************************************************** uint32_t EMACVLANTxConfigGet(uint32_t ui32Base, uint16_t *pui16Tag) { uint32_t ui32Value; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(pui16Tag); // // Read the VLAN Tag Inclusion or Replacement register. // ui32Value = HWREG(ui32Base + EMAC_O_VLNINCREP); // // Extract the tag. // *pui16Tag = (uint16_t)((ui32Value & EMAC_VLNINCREP_VLT_M) >> EMAC_VLNINCREP_VLT_S); // // Return the configuration flags. // return (ui32Value & ~EMAC_VLNINCREP_VLT_M); } //***************************************************************************** // //! Returns the bit number to set in the VLAN hash filter corresponding to a //! given tag. //! //! \param ui16Tag is the VLAN tag for which the hash filter bit number is to //! be determined. //! //! This function may be used to determine which bit in the VLAN hash filter //! to set to describe a given 12- or 16-bit VLAN tag. The returned value is //! a 4-bit value indicating the bit number to set within the 16-bit VLAN //! hash filter. For example, if 0x02 is returned, this indicates that bit //! 2 of the hash filter must be set to pass the supplied VLAN tag. //! //! \return Returns the bit number to set in the VLAN hash filter to describe //! the passed tag. // //***************************************************************************** uint32_t EMACVLANHashFilterBitCalculate(uint16_t ui16Tag) { uint32_t ui32CRC, ui32Mask, ui32Loop; // // Calculate the CRC for the MAC address. // ui32CRC = Crc32(0xFFFFFFFF, (uint8_t *)&ui16Tag, 2); ui32CRC ^= 0xFFFFFFFF; // // Determine the hash bit to use from the calculated CRC. This is the // top 4 bits of the reversed CRC (or the bottom 4 bits of the calculated // CRC with the bit order of those 4 bits reversed). // ui32Mask = 0; // // Reverse the order of the bottom 4 bits of the calculated CRC. // for (ui32Loop = 0; ui32Loop < 4; ui32Loop++) { ui32Mask <<= 1; ui32Mask |= (ui32CRC & 1); ui32CRC >>= 1; } // // Return the final hash filter bit index. // return (ui32Mask); } //***************************************************************************** // //! Sets the hash filter used to control reception of VLAN-tagged frames. //! //! \param ui32Base is the base address of the controller. //! \param ui32Hash is the hash filter value to set. //! //! This function allows the VLAG tag hash filter to be set. By using hash //! filtering, several different VLAN tags can be filtered very easily at the //! cost of some false positive results that must be removed by software. //! //! The hash filter value passed in \e ui32Hash may be built up by calling //! EMACVLANHashFilterBitCalculate() for each VLAN tag that is to pass the //! filter and then set each of the bits for which the numbers are returned by //! that function. Care must be taken when clearing bits in the hash filter //! due to the fact that there is a many-to-one correspondence between VLAN //! tags and hash filter bits. //! //! \return None // //***************************************************************************** void EMACVLANHashFilterSet(uint32_t ui32Base, uint32_t ui32Hash) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Write the VLAN Hash Table register. // HWREG(ui32Base + EMAC_O_VLANHASH) = ui32Hash; } //***************************************************************************** // //! Returns the current value of the hash filter used to control reception of //! VLAN-tagged frames. //! //! \param ui32Base is the base address of the controller. //! //! This function allows the current VLAN tag hash filter value to be returned. //! Additional VLAN tags may be added to this filter by setting the appropriate //! bits, determined by calling EMACVLANHashFilterBitCalculate(), and then //! calling EMACVLANHashFilterSet() to set the new filter value. //! //! \return Returns the current value of the VLAN hash filter. // //***************************************************************************** uint32_t EMACVLANHashFilterGet(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Return the VLAN Hash Table register. // return (HWREG(ui32Base + EMAC_O_VLANHASH)); } //***************************************************************************** // //! Sets values defining up to four frames used to trigger a remote wake-up. //! //! \param ui32Base is the base address of the controller. //! \param pFilter points to the structure containing remote wake-up frame //! filter information. //! //! This function may be used to define up to four different frames that //! are considered by the Ethernet MAC to be remote wake-up signals. The //! data passed to the function describes a wake-up frame in terms of a CRC //! calculated on up to 31 payload bytes in the frame. The actual bytes used //! in the CRC calculation are defined by means of a bit mask where a ``1'' //! indicates that a byte in the frame should contribute to the CRC //! calculation and a ``0'' indicates that the byte should be skipped, as well //! as an offset from the start of the frame to the payload byte that represents //! the first byte in the 31-byte CRC-checked sequence. //! //! The \e pFilter parameter points to a structure containing the information //! necessary to set up the filters. This structure contains the following //! fields, each of which is replicated 4 times, once for each possible wake-up //! frame: //! //! - \b pui32ByteMask defines whether a given byte in the chosen 31-byte //! sequence within the frame should contribute to the CRC calculation or not. //! A 1 indicates that the byte should contribute to the calculation, a 0 //! causes the byte to be skipped. //! - \b pui8Command contains flags defining whether this filter is enabled //! and, if so, whether it refers to unicast or multicast packets. Valid //! values are one of \b EMAC_RWU_FILTER_MULTICAST or \b //! EMAC_RWU_FILTER_UNICAST ORed with one of \b EMAC_RWU_FILTER_ENABLE or //! \b EMAC_RWU_FILTER_DISABLE. //! - \b pui8Offset defines the zero-based index of the byte within the frame //! at which CRC checking defined by \b pui32ByteMask begins. //! Alternatively, this value can be thought of as the number of bytes in the //! frame that the MAC skips before accumulating the CRC based on the pattern //! in \b pui32ByteMask. //! - \b pui16CRC provides the value of the calculated CRC for a valid remote //! wake-up frame. If the incoming frame is processed according to the filter //! values provided and the final CRC calculation equals this value, the //! frame is considered to be a valid remote wake-up frame. //! //! Note that this filter uses CRC16 rather than CRC32 as used in frame //! checksums. The required CRC uses a direct algorithm with polynomial 0x8005, //! initial seed value 0xFFFF, no final XOR and reversed data order. CRCs //! for use in this function may be determined using the online calculator //! found at http://www.zorc.breitbandkatze.de/crc.html. //! //! \return None. // //***************************************************************************** void EMACRemoteWakeUpFrameFilterSet(uint32_t ui32Base, const tEMACWakeUpFrameFilter *pFilter) { uint32_t *pui32Data; uint32_t ui32Loop; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(pFilter); // // Make sure that the internal register counter for the frame filter // is reset. This bit automatically resets after 1 clock cycle. // HWREG(ui32Base + EMAC_O_PMTCTLSTAT) |= EMAC_PMTCTLSTAT_WUPFRRST; // // Get a word pointer to the supplied structure. // pui32Data = (uint32_t *)pFilter; // // Write the 8 words of the wake-up filter definition to the hardware. // for (ui32Loop = 0; ui32Loop < 8; ui32Loop++) { // // Write a word of the filter definition. // HWREG(ui32Base + EMAC_O_RWUFF) = pui32Data[ui32Loop]; } } //***************************************************************************** // //! Returns the current remote wake-up frame filter configuration. //! //! \param ui32Base is the base address of the controller. //! \param pFilter points to the structure that is written with the current //! remote wake-up frame filter information. //! //! This function may be used to read the current wake-up frame filter //! settings. The data returned by the function describes wake-up frames in //! terms of a CRC calculated on up to 31 payload bytes in the frame. The //! actual bytes used in the CRC calculation are defined by means of a bit mask //! where a ``1'' indicates that a byte in the frame should contribute to the //! CRC calculation and a ``0'' indicates that the byte should be skipped, and //! an offset from the start of the frame to the payload byte that represents //! the first byte in the 31-byte CRC-checked sequence. //! //! The \e pFilter parameter points to storage that is written with a //! structure containing the information defining the frame filters. This //! structure contains the following fields, each of which is replicated 4 //! times, once for each possible wake-up frame: //! //! - \b pui32ByteMask defines whether a given byte in the chosen 31-byte //! sequence within the frame should contribute to the CRC calculation or not. //! A 1 indicates that the byte should contribute to the calculation, a 0 //! causes the byte to be skipped. //! - \b pui8Command contains flags defining whether this filter is enabled //! and, if so, whether it refers to unicast or multicast packets. Valid //! values are one of \b EMAC_RWU_FILTER_MULTICAST or \b //! EMAC_RWU_FILTER_UNICAST ORed with one of \b EMAC_RWU_FILTER_ENABLE or //! \b EMAC_RWU_FILTER_DISABLE. //! - \b pui8Offset defines the zero-based index of the byte within the frame //! at which CRC checking defined by \b pui32ByteMask begins. //! Alternatively, this value can be thought of as the number of bytes in the //! frame that the MAC skips before accumulating the CRC based on the pattern //! in \b pui32ByteMask. //! - \b pui16CRC provides the value of the calculated CRC for a valid remote //! wake-up frame. If the incoming frame is processed according to the filter //! values provided and the final CRC calculation equals this value, the //! frame is considered to be a valid remote wake-up frame. //! //! Note that this filter uses CRC16 rather than CRC32 as used in frame //! checksums. //! //! \return None. // //***************************************************************************** void EMACRemoteWakeUpFrameFilterGet(uint32_t ui32Base, tEMACWakeUpFrameFilter *pFilter) { uint32_t *pui32Data; uint32_t ui32Loop; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(pFilter); // // Make sure that the internal register counter for the frame filter // is reset. This bit automatically resets after 1 clock cycle. // HWREG(ui32Base + EMAC_O_PMTCTLSTAT) |= EMAC_PMTCTLSTAT_WUPFRRST; // // Get a word pointer to the supplied structure. // pui32Data = (uint32_t *)pFilter; // // Read the 8 words of the wake-up filter definition from the hardware. // for (ui32Loop = 0; ui32Loop < 8; ui32Loop++) { // // Read a word of the filter definition. // pui32Data[ui32Loop] = HWREG(ui32Base + EMAC_O_RWUFF); } } //***************************************************************************** // //! Sets the Ethernet MAC remote wake-up configuration. //! //! \param ui32Base is the base address of the controller. //! \param ui32Flags defines which types of frame should trigger a remote //! wake-up and allows the MAC to be put into power-down mode. //! //! This function allows the MAC's remote wake-up features to be configured, //! determining which types of frame should trigger a wake-up event and //! allowing an application to place the MAC in power-down mode. In this //! mode, the MAC ignores all received frames until one matching a //! configured remote wake-up frame is received, at which point the MAC //! automatically exits power-down mode and continues to receive frames. //! //! The \e ui32Flags parameter is a logical OR of the following flags: //! //! - \b EMAC_PMT_GLOBAL_UNICAST_ENABLE instructs the MAC to wake up when any //! unicast frame matching the MAC destination address filter is received. //! - \b EMAC_PMT_WAKEUP_PACKET_ENABLE instructs the MAC to wake up when any //! received frame matches the remote wake-up filter configured via a call //! to EMACRemoteWakeUpFrameFilterSet(). //! - \b EMAC_PMT_MAGIC_PACKET_ENABLE instructs the MAC to wake up when a //! standard Wake-on-LAN "magic packet" is received. The magic packet contains //! 6 bytes of 0xFF followed immediately by 16 repetitions of the destination //! MAC address. //! - \b EMAC_PMT_POWER_DOWN instructs the MAC to enter power-down mode and //! wait for an incoming frame matching the remote wake-up frames as described //! by other flags and via the remote wake-up filter. This flag should only //! set set if at least one other flag is specified to configure a wake-up //! frame type. //! //! When the MAC is in power-down mode, software may exit the mode by calling //! this function with the \b EMAC_PMT_POWER_DOWN flag absent from \e ui32Flags. //! If a configured wake-up frame is received while in power-down mode, the //! \b EMAC_INT_POWER_MGMNT interrupt is signaled and may be cleared by reading //! the status using EMACPowerManagementStatusGet(). //! //! \note While it is possible to gate the clock to the MAC while it is in //! power-down mode, doing so prevents the reading of the registers required //! to determine the interrupt status and also prevents power-down mode from //! exiting via another call to this function. //! //! \return None. // //***************************************************************************** void EMACPowerManagementControlSet(uint32_t ui32Base, uint32_t ui32Flags) { uint32_t ui32Value; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ASSERT(~(ui32Flags & ~(EMAC_PMT_GLOBAL_UNICAST_ENABLE | EMAC_PMT_WAKEUP_PACKET_ENABLE | EMAC_PMT_MAGIC_PACKET_ENABLE | EMAC_PMT_POWER_DOWN))); // // Read the control/status register, clear all the bits we can set, mask // in the new values then rewrite the new register value. // ui32Value = HWREG(ui32Base + EMAC_O_PMTCTLSTAT); ui32Value &= ~(EMAC_PMTCTLSTAT_GLBLUCAST | EMAC_PMTCTLSTAT_WUPFREN | EMAC_PMTCTLSTAT_MGKPKTEN | EMAC_PMTCTLSTAT_PWRDWN); ui32Value |= ui32Flags; HWREG(ui32Base + EMAC_O_PMTCTLSTAT) = ui32Value; } //***************************************************************************** // //! Queries the current Ethernet MAC remote wake-up configuration. //! //! \param ui32Base is the base address of the controller. //! //! This function allows the MAC's remote wake-up settings to be queried. //! These settings determine which types of frame should trigger a remote //! wake-up event //! //! \return Returns a logical OR of the following flags: //! //! - \b EMAC_PMT_GLOBAL_UNICAST_ENABLE indicates that the MAC wakes up when //! any unicast frame matching the MAC destination address filter is received. //! - \b EMAC_PMT_WAKEUP_PACKET_ENABLE indicates that the MAC wakes up when any //! received frame matches the remote wake-up filter configured via a call //! to EMACRemoteWakeUpFrameFilterSet(). //! - \b EMAC_PMT_MAGIC_PACKET_ENABLE indicates that the MAC wakes up when a //! standard Wake-on-LAN "magic packet" is received. The magic packet contains //! 6 bytes of 0xFF followed immediately by 16 repetitions of the destination //! MAC address. //! - \b EMAC_PMT_POWER_DOWN indicates that the MAC is currently in power-down //! mode and is waiting for an incoming frame matching the remote wake-up //! frames as described by other returned flags and via the remote wake-up //! filter. // //***************************************************************************** uint32_t EMACPowerManagementControlGet(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Read the control/status register and mask off the control bits to return // them to the caller. // return (HWREG(ui32Base + EMAC_O_PMTCTLSTAT) & (EMAC_PMTCTLSTAT_GLBLUCAST | EMAC_PMTCTLSTAT_WUPFREN | EMAC_PMTCTLSTAT_MGKPKTEN | EMAC_PMTCTLSTAT_PWRDWN)); } //***************************************************************************** // //! Queries the current Ethernet MAC remote wake-up status. //! //! \param ui32Base is the base address of the controller. //! //! This function returns information on the remote wake-up state of the //! Ethernet MAC. If the MAC has been woken up since the last call, the //! returned value indicates the type of received frame that caused the MAC //! to exit power-down state. //! //! \return Returns a logical OR of the following flags: //! //! - \b EMAC_PMT_POWER_DOWN indicates that the MAC is currently in power-down //! mode. //! - \b EMAC_PMT_WAKEUP_PACKET_RECEIVED indicates that the MAC exited //! power-down mode due to a remote wake-up frame being received. This //! function call clears this flag. //! - \b EMAC_PMT_MAGIC_PACKET_RECEIVED indicates that the MAC exited //! power-down mode due to a wake-on-LAN magic packet being received. This //! function call clears this flag. // //***************************************************************************** uint32_t EMACPowerManagementStatusGet(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Read the control/status register and mask off the status bits to return // them to the caller. // return (HWREG(ui32Base + EMAC_O_PMTCTLSTAT) & (EMAC_PMTCTLSTAT_WUPRX | EMAC_PMTCTLSTAT_MGKPRX | EMAC_PMTCTLSTAT_PWRDWN)); } //***************************************************************************** // //! Enables the wake-on-LAN feature of the MAC controller. //! //! \param ui32Base is the base address of the controller. //! //! This function is used to enable the wake-on-LAN feature of the MAC //! controller. It is done by first checking if the transmit path is idle and //! disabling the trasnmitter and the transmit DMA controller. Then it checks //! if any data from the network is being actively received and if not then it //! disables the receive DMA controller. //! //! \return None. // //***************************************************************************** void EMACWoLEnter(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Check if the Transmit interrupt bit is clear. // while (HWREG(ui32Base + EMAC_O_DMARIS) == EMAC_DMARIS_TI) { } // // Disable transmission in the MAC configuration register. // HWREG(ui32Base + EMAC_O_CFG) &= ~EMAC_CFG_TE; // // Disable the MAC transmit path in the opmode register. // HWREG(ui32Base + EMAC_O_DMAOPMODE) &= ~EMAC_DMAOPMODE_ST; // // Check if the Receive FIFO is empty. // while ((HWREG(ui32Base + EMAC_O_STATUS) & EMAC_STATUS_RX_FIFO_LEVEL_MASK) == EMAC_STATUS_RX_FIFO_EMPTY) { } // // Disable the MAC receive path. // HWREG(ui32Base + EMAC_O_DMAOPMODE) &= ~EMAC_DMAOPMODE_SR; } //***************************************************************************** // //! Configures the LPI timers and control register. //! //! \param ui32Base is the base address of the controller. //! \param bLPIConfig is state of LPI trasnmit automate bit. //! \param ui16LPILSTimer is the value of LS timer in milli-seconds. //! \param ui16LPITWTimer is the value of TW timer in micro-seconds. //! //! This function is used to configure the LPI timer and control registers when //! the link is established as EEE mode or when the link is lost. When the link //! is established as EEE, then \e ui16LPILSTimer is programmed as the link //! status timer value and \e ui16LPITWTimer is programmed as the transmit wait //! timer value. The parameter \e bLPIConfig is used to decide if the transmit //! path must be automated or should be under user control. //! //! \return None. // //***************************************************************************** void EMACLPIConfig(uint32_t ui32Base, bool bLPIConfig, uint16_t ui16LPILSTimer, uint16_t ui16LPITWTimer) { uint32_t ui32TimerValue; // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); ui32TimerValue = ((ui16LPILSTimer << EMAC_LPITIMERCTL_LST_S) & EMAC_LPITIMERCTL_LST_M); ui32TimerValue |= ui16LPITWTimer & EMAC_LPITIMERCTL_TWT_M; // // Update the LPI Timer. // HWREG(ui32Base + EMAC_O_LPITIMERCTL) = ui32TimerValue; // // Configure the LPI Control registers. // if (bLPIConfig) { HWREG(ui32Base + EMAC_O_LPICTLSTAT) |= EMAC_LPICTLSTAT_LPITXA; } else { HWREG(ui32Base + EMAC_O_LPICTLSTAT) = 0x0; } } //***************************************************************************** // //! Enables the transmit path for LPI mode entry. //! //! \param ui32Base is the base address of the controller. //! //! This function is used to enable the transmit path in LPI mode when there //! is no more data to be transmitted by the MAC controller. //! //! \return None. // //***************************************************************************** void EMACLPIEnter(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); HWREG(ui32Base + EMAC_O_LPICTLSTAT) |= EMAC_LPICTLSTAT_LPIEN; } //***************************************************************************** // //! Returns the status of the LPI link. //! //! \param ui32Base is the base address of the controller. //! //! This function may be used to read the status of the transmit and receive //! path when the link is configured in LPI mode. //! //! \return Returns the lower 16 bits of the LPI Control and Status register. // //***************************************************************************** uint16_t EMACLPIStatus(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Configure the LPI Control registers. // return (HWREG(ui32Base + EMAC_O_LPICTLSTAT) & 0xFFFF); } //***************************************************************************** // //! Sets the link status of the external PHY. //! //! \param ui32Base is the base address of the controller. //! //! This function is used to set the link status of the external PHY when the //! link is established in EEE mode. //! //! \return None. // //***************************************************************************** void EMACLPILinkSet(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Configure the LPI Control registers. // HWREG(ui32Base + EMAC_O_LPICTLSTAT) |= EMAC_LPICTLSTAT_PLS; } //***************************************************************************** // //! Clears the link status of the external PHY. //! //! \param ui32Base is the base address of the controller. //! //! This function is used to clear the link status of the external PHY when the //! link is lost due to a disconnect or EEE mode link is not established. //! //! \return None. // //***************************************************************************** void EMACLPILinkClear(uint32_t ui32Base) { // // Parameter sanity check. // ASSERT(ui32Base == EMAC0_BASE); // // Configure the LPI Control registers. // HWREG(ui32Base + EMAC_O_LPICTLSTAT) &= ~(EMAC_LPICTLSTAT_PLS); } //***************************************************************************** // //! Writes a value to an extended PHY register in MMD address space. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to access. //! \param ui16RegAddr is the address of the PHY extended register to be //! accessed. //! \param ui16Value is the value to write to the register. //! //! When uhen connected to an external PHY supporting extended registers in MMD //! address space, this function allows a value to be written to the MMD //! register specified by \e ui16RegAddr. //! //! \return None. // //***************************************************************************** void EMACPHYMMDWrite(uint32_t ui32Base, uint8_t ui8PhyAddr, uint16_t ui16RegAddr, uint16_t ui16Data) { // // Parameter sanity check. // ASSERT(ui8PhyAddr < 32); // // Set the address of the register we're about to write. // EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, DEV_ADDR(ui16RegAddr)); EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_ADDAR, REG_ADDR(ui16RegAddr)); // // Write the extended register value. // EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, (0x4000 | DEV_ADDR(ui16RegAddr))); EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, ui16Data); } //***************************************************************************** // //! Reads from an extended PHY register in MMD address space. //! //! \param ui32Base is the base address of the controller. //! \param ui8PhyAddr is the physical address of the PHY to access. //! \param ui16RegAddr is the address of the PHY extended register to be //! accessed. //! //! When connected to an external PHY supporting extended registers, this //! this function returns the contents of the MMD register specified by //! \e ui16RegAddr. //! //! \return Returns the 16-bit value read from the PHY. // //***************************************************************************** uint16_t EMACPHYMMDRead(uint32_t ui32Base, uint8_t ui8PhyAddr, uint16_t ui16RegAddr) { // // Parameter sanity check. // ASSERT(ui8PhyAddr < 32); // // Set the address of the register we're about to read. // EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, DEV_ADDR(ui16RegAddr)); EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_ADDAR, REG_ADDR(ui16RegAddr)); // // Read the extended register value. // EMACPHYWrite(ui32Base, ui8PhyAddr, EPHY_REGCTL, (0x4000 | DEV_ADDR(ui16RegAddr))); return (EMACPHYRead(ui32Base, ui8PhyAddr, EPHY_ADDAR)); } //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************