Date: March 20, 2011 This library is created from "LPC17xx CMSIS-Compliant Standard Peripheral Firmware Driver Library (GNU, Keil, IAR) (Jan 28, 2011)", available from NXP's website, under "All microcontrollers support documents" [[http://ics.nxp.com/support/documents/microcontrollers/?type=software]] You will need to follow [[/projects/libraries/svn/mbed/trunk/LPC1768/LPC17xx.h]] while using this library Examples provided here [[/users/frank26080115/programs/LPC1700CMSIS_Examples/]] The beautiful thing is that NXP does not place copyright protection on any of the files in here Only a few modifications are made to make it compile with the mbed online compiler, I fixed some warnings as well. This is untested as of March 20, 2011 Forum post about this library: [[/forum/mbed/topic/2030/]]
lpc17xx_emac.c@0:84d7747641aa, 2011-03-20 (annotated)
- Committer:
- frank26080115
- Date:
- Sun Mar 20 18:45:15 2011 +0000
- Revision:
- 0:84d7747641aa
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
frank26080115 | 0:84d7747641aa | 1 | /** |
frank26080115 | 0:84d7747641aa | 2 | * @file lpc17xx_emac.c |
frank26080115 | 0:84d7747641aa | 3 | * @brief Contains all functions support for Ethernet MAC firmware library on LPC17xx |
frank26080115 | 0:84d7747641aa | 4 | * @version 2.0 |
frank26080115 | 0:84d7747641aa | 5 | * @date 21. May. 2010 |
frank26080115 | 0:84d7747641aa | 6 | * @author NXP MCU SW Application Team |
frank26080115 | 0:84d7747641aa | 7 | ************************************************************************** |
frank26080115 | 0:84d7747641aa | 8 | * Software that is described herein is for illustrative purposes only |
frank26080115 | 0:84d7747641aa | 9 | * which provides customers with programming information regarding the |
frank26080115 | 0:84d7747641aa | 10 | * products. This software is supplied "AS IS" without any warranties. |
frank26080115 | 0:84d7747641aa | 11 | * NXP Semiconductors assumes no responsibility or liability for the |
frank26080115 | 0:84d7747641aa | 12 | * use of the software, conveys no license or title under any patent, |
frank26080115 | 0:84d7747641aa | 13 | * copyright, or mask work right to the product. NXP Semiconductors |
frank26080115 | 0:84d7747641aa | 14 | * reserves the right to make changes in the software without |
frank26080115 | 0:84d7747641aa | 15 | * notification. NXP Semiconductors also make no representation or |
frank26080115 | 0:84d7747641aa | 16 | * warranty that such application will be suitable for the specified |
frank26080115 | 0:84d7747641aa | 17 | * use without further testing or modification. |
frank26080115 | 0:84d7747641aa | 18 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 19 | |
frank26080115 | 0:84d7747641aa | 20 | /* Peripheral group ----------------------------------------------------------- */ |
frank26080115 | 0:84d7747641aa | 21 | /** @addtogroup EMAC |
frank26080115 | 0:84d7747641aa | 22 | * @{ |
frank26080115 | 0:84d7747641aa | 23 | */ |
frank26080115 | 0:84d7747641aa | 24 | |
frank26080115 | 0:84d7747641aa | 25 | /* Includes ------------------------------------------------------------------- */ |
frank26080115 | 0:84d7747641aa | 26 | #include "lpc17xx_emac.h" |
frank26080115 | 0:84d7747641aa | 27 | #include "lpc17xx_clkpwr.h" |
frank26080115 | 0:84d7747641aa | 28 | |
frank26080115 | 0:84d7747641aa | 29 | /* If this source file built with example, the LPC17xx FW library configuration |
frank26080115 | 0:84d7747641aa | 30 | * file in each example directory ("lpc17xx_libcfg.h") must be included, |
frank26080115 | 0:84d7747641aa | 31 | * otherwise the default FW library configuration file must be included instead |
frank26080115 | 0:84d7747641aa | 32 | */ |
frank26080115 | 0:84d7747641aa | 33 | #ifdef __BUILD_WITH_EXAMPLE__ |
frank26080115 | 0:84d7747641aa | 34 | #include "lpc17xx_libcfg.h" |
frank26080115 | 0:84d7747641aa | 35 | #else |
frank26080115 | 0:84d7747641aa | 36 | #include "lpc17xx_libcfg_default.h" |
frank26080115 | 0:84d7747641aa | 37 | #endif /* __BUILD_WITH_EXAMPLE__ */ |
frank26080115 | 0:84d7747641aa | 38 | |
frank26080115 | 0:84d7747641aa | 39 | |
frank26080115 | 0:84d7747641aa | 40 | #ifdef _EMAC |
frank26080115 | 0:84d7747641aa | 41 | |
frank26080115 | 0:84d7747641aa | 42 | /* Private Variables ---------------------------------------------------------- */ |
frank26080115 | 0:84d7747641aa | 43 | /** @defgroup EMAC_Private_Variables EMAC Private Variables |
frank26080115 | 0:84d7747641aa | 44 | * @{ |
frank26080115 | 0:84d7747641aa | 45 | */ |
frank26080115 | 0:84d7747641aa | 46 | |
frank26080115 | 0:84d7747641aa | 47 | /* MII Mgmt Configuration register - Clock divider setting */ |
frank26080115 | 0:84d7747641aa | 48 | const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 }; |
frank26080115 | 0:84d7747641aa | 49 | |
frank26080115 | 0:84d7747641aa | 50 | /* EMAC local DMA Descriptors */ |
frank26080115 | 0:84d7747641aa | 51 | |
frank26080115 | 0:84d7747641aa | 52 | /** Rx Descriptor data array */ |
frank26080115 | 0:84d7747641aa | 53 | static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG]; |
frank26080115 | 0:84d7747641aa | 54 | |
frank26080115 | 0:84d7747641aa | 55 | /** Rx Status data array - Must be 8-Byte aligned */ |
frank26080115 | 0:84d7747641aa | 56 | #if defined ( __CC_ARM ) |
frank26080115 | 0:84d7747641aa | 57 | static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; |
frank26080115 | 0:84d7747641aa | 58 | #elif defined ( __ICCARM__ ) |
frank26080115 | 0:84d7747641aa | 59 | #pragma data_alignment=8 |
frank26080115 | 0:84d7747641aa | 60 | static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; |
frank26080115 | 0:84d7747641aa | 61 | #elif defined ( __GNUC__ ) |
frank26080115 | 0:84d7747641aa | 62 | static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; |
frank26080115 | 0:84d7747641aa | 63 | #endif |
frank26080115 | 0:84d7747641aa | 64 | |
frank26080115 | 0:84d7747641aa | 65 | /** Tx Descriptor data array */ |
frank26080115 | 0:84d7747641aa | 66 | static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG]; |
frank26080115 | 0:84d7747641aa | 67 | /** Tx Status data array */ |
frank26080115 | 0:84d7747641aa | 68 | static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG]; |
frank26080115 | 0:84d7747641aa | 69 | |
frank26080115 | 0:84d7747641aa | 70 | /* EMAC local DMA buffers */ |
frank26080115 | 0:84d7747641aa | 71 | /** Rx buffer data */ |
frank26080115 | 0:84d7747641aa | 72 | static uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2]; |
frank26080115 | 0:84d7747641aa | 73 | /** Tx buffer data */ |
frank26080115 | 0:84d7747641aa | 74 | static uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2]; |
frank26080115 | 0:84d7747641aa | 75 | |
frank26080115 | 0:84d7747641aa | 76 | /** |
frank26080115 | 0:84d7747641aa | 77 | * @} |
frank26080115 | 0:84d7747641aa | 78 | */ |
frank26080115 | 0:84d7747641aa | 79 | |
frank26080115 | 0:84d7747641aa | 80 | /* Private Functions ---------------------------------------------------------- */ |
frank26080115 | 0:84d7747641aa | 81 | static void rx_descr_init (void); |
frank26080115 | 0:84d7747641aa | 82 | static void tx_descr_init (void); |
frank26080115 | 0:84d7747641aa | 83 | static int32_t write_PHY (uint32_t PhyReg, uint16_t Value); |
frank26080115 | 0:84d7747641aa | 84 | static int32_t read_PHY (uint32_t PhyReg); |
frank26080115 | 0:84d7747641aa | 85 | |
frank26080115 | 0:84d7747641aa | 86 | static void setEmacAddr(uint8_t abStationAddr[]); |
frank26080115 | 0:84d7747641aa | 87 | static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len); |
frank26080115 | 0:84d7747641aa | 88 | |
frank26080115 | 0:84d7747641aa | 89 | |
frank26080115 | 0:84d7747641aa | 90 | /*--------------------------- rx_descr_init ---------------------------------*/ |
frank26080115 | 0:84d7747641aa | 91 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 92 | * @brief Initializes RX Descriptor |
frank26080115 | 0:84d7747641aa | 93 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 94 | * @return None |
frank26080115 | 0:84d7747641aa | 95 | ***********************************************************************/ |
frank26080115 | 0:84d7747641aa | 96 | static void rx_descr_init (void) |
frank26080115 | 0:84d7747641aa | 97 | { |
frank26080115 | 0:84d7747641aa | 98 | /* Initialize Receive Descriptor and Status array. */ |
frank26080115 | 0:84d7747641aa | 99 | uint32_t i; |
frank26080115 | 0:84d7747641aa | 100 | |
frank26080115 | 0:84d7747641aa | 101 | for (i = 0; i < EMAC_NUM_RX_FRAG; i++) { |
frank26080115 | 0:84d7747641aa | 102 | Rx_Desc[i].Packet = (uint32_t)&rx_buf[i]; |
frank26080115 | 0:84d7747641aa | 103 | Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1); |
frank26080115 | 0:84d7747641aa | 104 | Rx_Stat[i].Info = 0; |
frank26080115 | 0:84d7747641aa | 105 | Rx_Stat[i].HashCRC = 0; |
frank26080115 | 0:84d7747641aa | 106 | } |
frank26080115 | 0:84d7747641aa | 107 | |
frank26080115 | 0:84d7747641aa | 108 | /* Set EMAC Receive Descriptor Registers. */ |
frank26080115 | 0:84d7747641aa | 109 | LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0]; |
frank26080115 | 0:84d7747641aa | 110 | LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0]; |
frank26080115 | 0:84d7747641aa | 111 | LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1; |
frank26080115 | 0:84d7747641aa | 112 | |
frank26080115 | 0:84d7747641aa | 113 | /* Rx Descriptors Point to 0 */ |
frank26080115 | 0:84d7747641aa | 114 | LPC_EMAC->RxConsumeIndex = 0; |
frank26080115 | 0:84d7747641aa | 115 | } |
frank26080115 | 0:84d7747641aa | 116 | |
frank26080115 | 0:84d7747641aa | 117 | |
frank26080115 | 0:84d7747641aa | 118 | /*--------------------------- tx_descr_init ---- ----------------------------*/ |
frank26080115 | 0:84d7747641aa | 119 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 120 | * @brief Initializes TX Descriptor |
frank26080115 | 0:84d7747641aa | 121 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 122 | * @return None |
frank26080115 | 0:84d7747641aa | 123 | ***********************************************************************/ |
frank26080115 | 0:84d7747641aa | 124 | static void tx_descr_init (void) { |
frank26080115 | 0:84d7747641aa | 125 | /* Initialize Transmit Descriptor and Status array. */ |
frank26080115 | 0:84d7747641aa | 126 | uint32_t i; |
frank26080115 | 0:84d7747641aa | 127 | |
frank26080115 | 0:84d7747641aa | 128 | for (i = 0; i < EMAC_NUM_TX_FRAG; i++) { |
frank26080115 | 0:84d7747641aa | 129 | Tx_Desc[i].Packet = (uint32_t)&tx_buf[i]; |
frank26080115 | 0:84d7747641aa | 130 | Tx_Desc[i].Ctrl = 0; |
frank26080115 | 0:84d7747641aa | 131 | Tx_Stat[i].Info = 0; |
frank26080115 | 0:84d7747641aa | 132 | } |
frank26080115 | 0:84d7747641aa | 133 | |
frank26080115 | 0:84d7747641aa | 134 | /* Set EMAC Transmit Descriptor Registers. */ |
frank26080115 | 0:84d7747641aa | 135 | LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0]; |
frank26080115 | 0:84d7747641aa | 136 | LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0]; |
frank26080115 | 0:84d7747641aa | 137 | LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1; |
frank26080115 | 0:84d7747641aa | 138 | |
frank26080115 | 0:84d7747641aa | 139 | /* Tx Descriptors Point to 0 */ |
frank26080115 | 0:84d7747641aa | 140 | LPC_EMAC->TxProduceIndex = 0; |
frank26080115 | 0:84d7747641aa | 141 | } |
frank26080115 | 0:84d7747641aa | 142 | |
frank26080115 | 0:84d7747641aa | 143 | |
frank26080115 | 0:84d7747641aa | 144 | /*--------------------------- write_PHY -------------------------------------*/ |
frank26080115 | 0:84d7747641aa | 145 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 146 | * @brief Write value to PHY device |
frank26080115 | 0:84d7747641aa | 147 | * @param[in] PhyReg: PHY Register address |
frank26080115 | 0:84d7747641aa | 148 | * @param[in] Value: Value to write |
frank26080115 | 0:84d7747641aa | 149 | * @return 0 - if success |
frank26080115 | 0:84d7747641aa | 150 | * 1 - if fail |
frank26080115 | 0:84d7747641aa | 151 | ***********************************************************************/ |
frank26080115 | 0:84d7747641aa | 152 | static int32_t write_PHY (uint32_t PhyReg, uint16_t Value) |
frank26080115 | 0:84d7747641aa | 153 | { |
frank26080115 | 0:84d7747641aa | 154 | /* Write a data 'Value' to PHY register 'PhyReg'. */ |
frank26080115 | 0:84d7747641aa | 155 | uint32_t tout; |
frank26080115 | 0:84d7747641aa | 156 | |
frank26080115 | 0:84d7747641aa | 157 | LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; |
frank26080115 | 0:84d7747641aa | 158 | LPC_EMAC->MWTD = Value; |
frank26080115 | 0:84d7747641aa | 159 | |
frank26080115 | 0:84d7747641aa | 160 | /* Wait until operation completed */ |
frank26080115 | 0:84d7747641aa | 161 | tout = 0; |
frank26080115 | 0:84d7747641aa | 162 | for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) { |
frank26080115 | 0:84d7747641aa | 163 | if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { |
frank26080115 | 0:84d7747641aa | 164 | return (0); |
frank26080115 | 0:84d7747641aa | 165 | } |
frank26080115 | 0:84d7747641aa | 166 | } |
frank26080115 | 0:84d7747641aa | 167 | // Time out! |
frank26080115 | 0:84d7747641aa | 168 | return (-1); |
frank26080115 | 0:84d7747641aa | 169 | } |
frank26080115 | 0:84d7747641aa | 170 | |
frank26080115 | 0:84d7747641aa | 171 | |
frank26080115 | 0:84d7747641aa | 172 | /*--------------------------- read_PHY --------------------------------------*/ |
frank26080115 | 0:84d7747641aa | 173 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 174 | * @brief Read value from PHY device |
frank26080115 | 0:84d7747641aa | 175 | * @param[in] PhyReg: PHY Register address |
frank26080115 | 0:84d7747641aa | 176 | * @return 0 - if success |
frank26080115 | 0:84d7747641aa | 177 | * 1 - if fail |
frank26080115 | 0:84d7747641aa | 178 | ***********************************************************************/ |
frank26080115 | 0:84d7747641aa | 179 | static int32_t read_PHY (uint32_t PhyReg) |
frank26080115 | 0:84d7747641aa | 180 | { |
frank26080115 | 0:84d7747641aa | 181 | /* Read a PHY register 'PhyReg'. */ |
frank26080115 | 0:84d7747641aa | 182 | uint32_t tout; |
frank26080115 | 0:84d7747641aa | 183 | |
frank26080115 | 0:84d7747641aa | 184 | LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; |
frank26080115 | 0:84d7747641aa | 185 | LPC_EMAC->MCMD = EMAC_MCMD_READ; |
frank26080115 | 0:84d7747641aa | 186 | |
frank26080115 | 0:84d7747641aa | 187 | /* Wait until operation completed */ |
frank26080115 | 0:84d7747641aa | 188 | tout = 0; |
frank26080115 | 0:84d7747641aa | 189 | for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) { |
frank26080115 | 0:84d7747641aa | 190 | if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { |
frank26080115 | 0:84d7747641aa | 191 | LPC_EMAC->MCMD = 0; |
frank26080115 | 0:84d7747641aa | 192 | return (LPC_EMAC->MRDD); |
frank26080115 | 0:84d7747641aa | 193 | } |
frank26080115 | 0:84d7747641aa | 194 | } |
frank26080115 | 0:84d7747641aa | 195 | // Time out! |
frank26080115 | 0:84d7747641aa | 196 | return (-1); |
frank26080115 | 0:84d7747641aa | 197 | } |
frank26080115 | 0:84d7747641aa | 198 | |
frank26080115 | 0:84d7747641aa | 199 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 200 | * @brief Set Station MAC address for EMAC module |
frank26080115 | 0:84d7747641aa | 201 | * @param[in] abStationAddr Pointer to Station address that contains 6-bytes |
frank26080115 | 0:84d7747641aa | 202 | * of MAC address (should be in order from MAC Address 1 to MAC Address 6) |
frank26080115 | 0:84d7747641aa | 203 | * @return None |
frank26080115 | 0:84d7747641aa | 204 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 205 | static void setEmacAddr(uint8_t abStationAddr[]) |
frank26080115 | 0:84d7747641aa | 206 | { |
frank26080115 | 0:84d7747641aa | 207 | /* Set the Ethernet MAC Address registers */ |
frank26080115 | 0:84d7747641aa | 208 | LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4]; |
frank26080115 | 0:84d7747641aa | 209 | LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2]; |
frank26080115 | 0:84d7747641aa | 210 | LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0]; |
frank26080115 | 0:84d7747641aa | 211 | } |
frank26080115 | 0:84d7747641aa | 212 | |
frank26080115 | 0:84d7747641aa | 213 | |
frank26080115 | 0:84d7747641aa | 214 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 215 | * @brief Calculates CRC code for number of bytes in the frame |
frank26080115 | 0:84d7747641aa | 216 | * @param[in] frame_no_fcs Pointer to the first byte of the frame |
frank26080115 | 0:84d7747641aa | 217 | * @param[in] frame_len length of the frame without the FCS |
frank26080115 | 0:84d7747641aa | 218 | * @return the CRC as a 32 bit integer |
frank26080115 | 0:84d7747641aa | 219 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 220 | static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len) |
frank26080115 | 0:84d7747641aa | 221 | { |
frank26080115 | 0:84d7747641aa | 222 | int i; // iterator |
frank26080115 | 0:84d7747641aa | 223 | int j; // another iterator |
frank26080115 | 0:84d7747641aa | 224 | char byte; // current byte |
frank26080115 | 0:84d7747641aa | 225 | int crc; // CRC result |
frank26080115 | 0:84d7747641aa | 226 | int q0, q1, q2, q3; // temporary variables |
frank26080115 | 0:84d7747641aa | 227 | crc = 0xFFFFFFFF; |
frank26080115 | 0:84d7747641aa | 228 | for (i = 0; i < frame_len; i++) { |
frank26080115 | 0:84d7747641aa | 229 | byte = *frame_no_fcs++; |
frank26080115 | 0:84d7747641aa | 230 | for (j = 0; j < 2; j++) { |
frank26080115 | 0:84d7747641aa | 231 | if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) { |
frank26080115 | 0:84d7747641aa | 232 | q3 = 0x04C11DB7; |
frank26080115 | 0:84d7747641aa | 233 | } else { |
frank26080115 | 0:84d7747641aa | 234 | q3 = 0x00000000; |
frank26080115 | 0:84d7747641aa | 235 | } |
frank26080115 | 0:84d7747641aa | 236 | if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) { |
frank26080115 | 0:84d7747641aa | 237 | q2 = 0x09823B6E; |
frank26080115 | 0:84d7747641aa | 238 | } else { |
frank26080115 | 0:84d7747641aa | 239 | q2 = 0x00000000; |
frank26080115 | 0:84d7747641aa | 240 | } |
frank26080115 | 0:84d7747641aa | 241 | if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) { |
frank26080115 | 0:84d7747641aa | 242 | q1 = 0x130476DC; |
frank26080115 | 0:84d7747641aa | 243 | } else { |
frank26080115 | 0:84d7747641aa | 244 | q1 = 0x00000000; |
frank26080115 | 0:84d7747641aa | 245 | } |
frank26080115 | 0:84d7747641aa | 246 | if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) { |
frank26080115 | 0:84d7747641aa | 247 | q0 = 0x2608EDB8; |
frank26080115 | 0:84d7747641aa | 248 | } else { |
frank26080115 | 0:84d7747641aa | 249 | q0 = 0x00000000; |
frank26080115 | 0:84d7747641aa | 250 | } |
frank26080115 | 0:84d7747641aa | 251 | crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0; |
frank26080115 | 0:84d7747641aa | 252 | byte >>= 4; |
frank26080115 | 0:84d7747641aa | 253 | } |
frank26080115 | 0:84d7747641aa | 254 | } |
frank26080115 | 0:84d7747641aa | 255 | return crc; |
frank26080115 | 0:84d7747641aa | 256 | } |
frank26080115 | 0:84d7747641aa | 257 | /* End of Private Functions --------------------------------------------------- */ |
frank26080115 | 0:84d7747641aa | 258 | |
frank26080115 | 0:84d7747641aa | 259 | |
frank26080115 | 0:84d7747641aa | 260 | /* Public Functions ----------------------------------------------------------- */ |
frank26080115 | 0:84d7747641aa | 261 | /** @addtogroup EMAC_Public_Functions |
frank26080115 | 0:84d7747641aa | 262 | * @{ |
frank26080115 | 0:84d7747641aa | 263 | */ |
frank26080115 | 0:84d7747641aa | 264 | |
frank26080115 | 0:84d7747641aa | 265 | |
frank26080115 | 0:84d7747641aa | 266 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 267 | * @brief Initializes the EMAC peripheral according to the specified |
frank26080115 | 0:84d7747641aa | 268 | * parameters in the EMAC_ConfigStruct. |
frank26080115 | 0:84d7747641aa | 269 | * @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure |
frank26080115 | 0:84d7747641aa | 270 | * that contains the configuration information for the |
frank26080115 | 0:84d7747641aa | 271 | * specified EMAC peripheral. |
frank26080115 | 0:84d7747641aa | 272 | * @return None |
frank26080115 | 0:84d7747641aa | 273 | * |
frank26080115 | 0:84d7747641aa | 274 | * Note: This function will initialize EMAC module according to procedure below: |
frank26080115 | 0:84d7747641aa | 275 | * - Remove the soft reset condition from the MAC |
frank26080115 | 0:84d7747641aa | 276 | * - Configure the PHY via the MIIM interface of the MAC |
frank26080115 | 0:84d7747641aa | 277 | * - Select RMII mode |
frank26080115 | 0:84d7747641aa | 278 | * - Configure the transmit and receive DMA engines, including the descriptor arrays |
frank26080115 | 0:84d7747641aa | 279 | * - Configure the host registers (MAC1,MAC2 etc.) in the MAC |
frank26080115 | 0:84d7747641aa | 280 | * - Enable the receive and transmit data paths |
frank26080115 | 0:84d7747641aa | 281 | * In default state after initializing, only Rx Done and Tx Done interrupt are enabled, |
frank26080115 | 0:84d7747641aa | 282 | * all remain interrupts are disabled |
frank26080115 | 0:84d7747641aa | 283 | * (Ref. from LPC17xx UM) |
frank26080115 | 0:84d7747641aa | 284 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 285 | Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct) |
frank26080115 | 0:84d7747641aa | 286 | { |
frank26080115 | 0:84d7747641aa | 287 | /* Initialize the EMAC Ethernet controller. */ |
frank26080115 | 0:84d7747641aa | 288 | int32_t regv,tout, tmp; |
frank26080115 | 0:84d7747641aa | 289 | |
frank26080115 | 0:84d7747641aa | 290 | /* Set up clock and power for Ethernet module */ |
frank26080115 | 0:84d7747641aa | 291 | CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE); |
frank26080115 | 0:84d7747641aa | 292 | |
frank26080115 | 0:84d7747641aa | 293 | /* Reset all EMAC internal modules */ |
frank26080115 | 0:84d7747641aa | 294 | LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX | |
frank26080115 | 0:84d7747641aa | 295 | EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES; |
frank26080115 | 0:84d7747641aa | 296 | |
frank26080115 | 0:84d7747641aa | 297 | LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM; |
frank26080115 | 0:84d7747641aa | 298 | |
frank26080115 | 0:84d7747641aa | 299 | /* A short delay after reset. */ |
frank26080115 | 0:84d7747641aa | 300 | for (tout = 100; tout; tout--); |
frank26080115 | 0:84d7747641aa | 301 | |
frank26080115 | 0:84d7747641aa | 302 | /* Initialize MAC control registers. */ |
frank26080115 | 0:84d7747641aa | 303 | LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL; |
frank26080115 | 0:84d7747641aa | 304 | LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN; |
frank26080115 | 0:84d7747641aa | 305 | LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN; |
frank26080115 | 0:84d7747641aa | 306 | /* |
frank26080115 | 0:84d7747641aa | 307 | * Find the clock that close to desired target clock |
frank26080115 | 0:84d7747641aa | 308 | */ |
frank26080115 | 0:84d7747641aa | 309 | tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK; |
frank26080115 | 0:84d7747641aa | 310 | for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){ |
frank26080115 | 0:84d7747641aa | 311 | if (EMAC_clkdiv[tout] >= tmp) break; |
frank26080115 | 0:84d7747641aa | 312 | } |
frank26080115 | 0:84d7747641aa | 313 | tout++; |
frank26080115 | 0:84d7747641aa | 314 | // Write to MAC configuration register and reset |
frank26080115 | 0:84d7747641aa | 315 | LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII; |
frank26080115 | 0:84d7747641aa | 316 | // release reset |
frank26080115 | 0:84d7747641aa | 317 | LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII); |
frank26080115 | 0:84d7747641aa | 318 | LPC_EMAC->CLRT = EMAC_CLRT_DEF; |
frank26080115 | 0:84d7747641aa | 319 | LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF; |
frank26080115 | 0:84d7747641aa | 320 | |
frank26080115 | 0:84d7747641aa | 321 | /* Enable Reduced MII interface. */ |
frank26080115 | 0:84d7747641aa | 322 | LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM; |
frank26080115 | 0:84d7747641aa | 323 | |
frank26080115 | 0:84d7747641aa | 324 | /* Reset Reduced MII Logic. */ |
frank26080115 | 0:84d7747641aa | 325 | LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII; |
frank26080115 | 0:84d7747641aa | 326 | |
frank26080115 | 0:84d7747641aa | 327 | for (tout = 100; tout; tout--); |
frank26080115 | 0:84d7747641aa | 328 | LPC_EMAC->SUPP = 0; |
frank26080115 | 0:84d7747641aa | 329 | |
frank26080115 | 0:84d7747641aa | 330 | /* Put the DP83848C in reset mode */ |
frank26080115 | 0:84d7747641aa | 331 | write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET); |
frank26080115 | 0:84d7747641aa | 332 | |
frank26080115 | 0:84d7747641aa | 333 | /* Wait for hardware reset to end. */ |
frank26080115 | 0:84d7747641aa | 334 | for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { |
frank26080115 | 0:84d7747641aa | 335 | regv = read_PHY (EMAC_PHY_REG_BMCR); |
frank26080115 | 0:84d7747641aa | 336 | if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) { |
frank26080115 | 0:84d7747641aa | 337 | /* Reset complete, device not Power Down. */ |
frank26080115 | 0:84d7747641aa | 338 | break; |
frank26080115 | 0:84d7747641aa | 339 | } |
frank26080115 | 0:84d7747641aa | 340 | if (tout == 0){ |
frank26080115 | 0:84d7747641aa | 341 | // Time out, return ERROR |
frank26080115 | 0:84d7747641aa | 342 | return (ERROR); |
frank26080115 | 0:84d7747641aa | 343 | } |
frank26080115 | 0:84d7747641aa | 344 | } |
frank26080115 | 0:84d7747641aa | 345 | |
frank26080115 | 0:84d7747641aa | 346 | // Set PHY mode |
frank26080115 | 0:84d7747641aa | 347 | if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){ |
frank26080115 | 0:84d7747641aa | 348 | return (ERROR); |
frank26080115 | 0:84d7747641aa | 349 | } |
frank26080115 | 0:84d7747641aa | 350 | |
frank26080115 | 0:84d7747641aa | 351 | // Set EMAC address |
frank26080115 | 0:84d7747641aa | 352 | setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr); |
frank26080115 | 0:84d7747641aa | 353 | |
frank26080115 | 0:84d7747641aa | 354 | /* Initialize Tx and Rx DMA Descriptors */ |
frank26080115 | 0:84d7747641aa | 355 | rx_descr_init (); |
frank26080115 | 0:84d7747641aa | 356 | tx_descr_init (); |
frank26080115 | 0:84d7747641aa | 357 | |
frank26080115 | 0:84d7747641aa | 358 | // Set Receive Filter register: enable broadcast and multicast |
frank26080115 | 0:84d7747641aa | 359 | LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN; |
frank26080115 | 0:84d7747641aa | 360 | |
frank26080115 | 0:84d7747641aa | 361 | /* Enable Rx Done and Tx Done interrupt for EMAC */ |
frank26080115 | 0:84d7747641aa | 362 | LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE; |
frank26080115 | 0:84d7747641aa | 363 | |
frank26080115 | 0:84d7747641aa | 364 | /* Reset all interrupts */ |
frank26080115 | 0:84d7747641aa | 365 | LPC_EMAC->IntClear = 0xFFFF; |
frank26080115 | 0:84d7747641aa | 366 | |
frank26080115 | 0:84d7747641aa | 367 | /* Enable receive and transmit mode of MAC Ethernet core */ |
frank26080115 | 0:84d7747641aa | 368 | LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN); |
frank26080115 | 0:84d7747641aa | 369 | LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; |
frank26080115 | 0:84d7747641aa | 370 | |
frank26080115 | 0:84d7747641aa | 371 | return SUCCESS; |
frank26080115 | 0:84d7747641aa | 372 | } |
frank26080115 | 0:84d7747641aa | 373 | |
frank26080115 | 0:84d7747641aa | 374 | |
frank26080115 | 0:84d7747641aa | 375 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 376 | * @brief De-initializes the EMAC peripheral registers to their |
frank26080115 | 0:84d7747641aa | 377 | * default reset values. |
frank26080115 | 0:84d7747641aa | 378 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 379 | * @return None |
frank26080115 | 0:84d7747641aa | 380 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 381 | void EMAC_DeInit(void) |
frank26080115 | 0:84d7747641aa | 382 | { |
frank26080115 | 0:84d7747641aa | 383 | // Disable all interrupt |
frank26080115 | 0:84d7747641aa | 384 | LPC_EMAC->IntEnable = 0x00; |
frank26080115 | 0:84d7747641aa | 385 | // Clear all pending interrupt |
frank26080115 | 0:84d7747641aa | 386 | LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP); |
frank26080115 | 0:84d7747641aa | 387 | |
frank26080115 | 0:84d7747641aa | 388 | /* TurnOff clock and power for Ethernet module */ |
frank26080115 | 0:84d7747641aa | 389 | CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE); |
frank26080115 | 0:84d7747641aa | 390 | } |
frank26080115 | 0:84d7747641aa | 391 | |
frank26080115 | 0:84d7747641aa | 392 | |
frank26080115 | 0:84d7747641aa | 393 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 394 | * @brief Check specified PHY status in EMAC peripheral |
frank26080115 | 0:84d7747641aa | 395 | * @param[in] ulPHYState Specified PHY Status Type, should be: |
frank26080115 | 0:84d7747641aa | 396 | * - EMAC_PHY_STAT_LINK: Link Status |
frank26080115 | 0:84d7747641aa | 397 | * - EMAC_PHY_STAT_SPEED: Speed Status |
frank26080115 | 0:84d7747641aa | 398 | * - EMAC_PHY_STAT_DUP: Duplex Status |
frank26080115 | 0:84d7747641aa | 399 | * @return Status of specified PHY status (0 or 1). |
frank26080115 | 0:84d7747641aa | 400 | * (-1) if error. |
frank26080115 | 0:84d7747641aa | 401 | * |
frank26080115 | 0:84d7747641aa | 402 | * Note: |
frank26080115 | 0:84d7747641aa | 403 | * For EMAC_PHY_STAT_LINK, return value: |
frank26080115 | 0:84d7747641aa | 404 | * - 0: Link Down |
frank26080115 | 0:84d7747641aa | 405 | * - 1: Link Up |
frank26080115 | 0:84d7747641aa | 406 | * For EMAC_PHY_STAT_SPEED, return value: |
frank26080115 | 0:84d7747641aa | 407 | * - 0: 10Mbps |
frank26080115 | 0:84d7747641aa | 408 | * - 1: 100Mbps |
frank26080115 | 0:84d7747641aa | 409 | * For EMAC_PHY_STAT_DUP, return value: |
frank26080115 | 0:84d7747641aa | 410 | * - 0: Half-Duplex |
frank26080115 | 0:84d7747641aa | 411 | * - 1: Full-Duplex |
frank26080115 | 0:84d7747641aa | 412 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 413 | int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState) |
frank26080115 | 0:84d7747641aa | 414 | { |
frank26080115 | 0:84d7747641aa | 415 | int32_t regv, tmp; |
frank26080115 | 0:84d7747641aa | 416 | #ifdef MCB_LPC_1768 |
frank26080115 | 0:84d7747641aa | 417 | regv = read_PHY (EMAC_PHY_REG_STS); |
frank26080115 | 0:84d7747641aa | 418 | switch(ulPHYState){ |
frank26080115 | 0:84d7747641aa | 419 | case EMAC_PHY_STAT_LINK: |
frank26080115 | 0:84d7747641aa | 420 | tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0; |
frank26080115 | 0:84d7747641aa | 421 | break; |
frank26080115 | 0:84d7747641aa | 422 | case EMAC_PHY_STAT_SPEED: |
frank26080115 | 0:84d7747641aa | 423 | tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1; |
frank26080115 | 0:84d7747641aa | 424 | break; |
frank26080115 | 0:84d7747641aa | 425 | case EMAC_PHY_STAT_DUP: |
frank26080115 | 0:84d7747641aa | 426 | tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; |
frank26080115 | 0:84d7747641aa | 427 | break; |
frank26080115 | 0:84d7747641aa | 428 | #elif defined(IAR_LPC_1768) |
frank26080115 | 0:84d7747641aa | 429 | /* Use IAR_LPC_1768 board: |
frank26080115 | 0:84d7747641aa | 430 | * FSZ8721BL doesn't have Status Register |
frank26080115 | 0:84d7747641aa | 431 | * so we read Basic Mode Status Register (0x01h) instead |
frank26080115 | 0:84d7747641aa | 432 | */ |
frank26080115 | 0:84d7747641aa | 433 | regv = read_PHY (EMAC_PHY_REG_BMSR); |
frank26080115 | 0:84d7747641aa | 434 | switch(ulPHYState){ |
frank26080115 | 0:84d7747641aa | 435 | case EMAC_PHY_STAT_LINK: |
frank26080115 | 0:84d7747641aa | 436 | tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0; |
frank26080115 | 0:84d7747641aa | 437 | break; |
frank26080115 | 0:84d7747641aa | 438 | case EMAC_PHY_STAT_SPEED: |
frank26080115 | 0:84d7747641aa | 439 | tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0; |
frank26080115 | 0:84d7747641aa | 440 | break; |
frank26080115 | 0:84d7747641aa | 441 | case EMAC_PHY_STAT_DUP: |
frank26080115 | 0:84d7747641aa | 442 | tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; |
frank26080115 | 0:84d7747641aa | 443 | break; |
frank26080115 | 0:84d7747641aa | 444 | #endif |
frank26080115 | 0:84d7747641aa | 445 | default: |
frank26080115 | 0:84d7747641aa | 446 | tmp = -1; |
frank26080115 | 0:84d7747641aa | 447 | break; |
frank26080115 | 0:84d7747641aa | 448 | } |
frank26080115 | 0:84d7747641aa | 449 | return (tmp); |
frank26080115 | 0:84d7747641aa | 450 | } |
frank26080115 | 0:84d7747641aa | 451 | |
frank26080115 | 0:84d7747641aa | 452 | |
frank26080115 | 0:84d7747641aa | 453 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 454 | * @brief Set specified PHY mode in EMAC peripheral |
frank26080115 | 0:84d7747641aa | 455 | * @param[in] ulPHYMode Specified PHY mode, should be: |
frank26080115 | 0:84d7747641aa | 456 | * - EMAC_MODE_AUTO |
frank26080115 | 0:84d7747641aa | 457 | * - EMAC_MODE_10M_FULL |
frank26080115 | 0:84d7747641aa | 458 | * - EMAC_MODE_10M_HALF |
frank26080115 | 0:84d7747641aa | 459 | * - EMAC_MODE_100M_FULL |
frank26080115 | 0:84d7747641aa | 460 | * - EMAC_MODE_100M_HALF |
frank26080115 | 0:84d7747641aa | 461 | * @return Return (0) if no error, otherwise return (-1) |
frank26080115 | 0:84d7747641aa | 462 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 463 | int32_t EMAC_SetPHYMode(uint32_t ulPHYMode) |
frank26080115 | 0:84d7747641aa | 464 | { |
frank26080115 | 0:84d7747641aa | 465 | int32_t id1, id2, tout, regv; |
frank26080115 | 0:84d7747641aa | 466 | |
frank26080115 | 0:84d7747641aa | 467 | /* Check if this is a DP83848C PHY. */ |
frank26080115 | 0:84d7747641aa | 468 | id1 = read_PHY (EMAC_PHY_REG_IDR1); |
frank26080115 | 0:84d7747641aa | 469 | id2 = read_PHY (EMAC_PHY_REG_IDR2); |
frank26080115 | 0:84d7747641aa | 470 | |
frank26080115 | 0:84d7747641aa | 471 | #ifdef MCB_LPC_1768 |
frank26080115 | 0:84d7747641aa | 472 | if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) { |
frank26080115 | 0:84d7747641aa | 473 | switch(ulPHYMode){ |
frank26080115 | 0:84d7747641aa | 474 | case EMAC_MODE_AUTO: |
frank26080115 | 0:84d7747641aa | 475 | write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); |
frank26080115 | 0:84d7747641aa | 476 | #elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */ |
frank26080115 | 0:84d7747641aa | 477 | if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) { |
frank26080115 | 0:84d7747641aa | 478 | /* Configure the PHY device */ |
frank26080115 | 0:84d7747641aa | 479 | switch(ulPHYMode){ |
frank26080115 | 0:84d7747641aa | 480 | case EMAC_MODE_AUTO: |
frank26080115 | 0:84d7747641aa | 481 | /* Use auto-negotiation about the link speed. */ |
frank26080115 | 0:84d7747641aa | 482 | write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); |
frank26080115 | 0:84d7747641aa | 483 | // write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN); |
frank26080115 | 0:84d7747641aa | 484 | #endif |
frank26080115 | 0:84d7747641aa | 485 | /* Wait to complete Auto_Negotiation */ |
frank26080115 | 0:84d7747641aa | 486 | for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { |
frank26080115 | 0:84d7747641aa | 487 | regv = read_PHY (EMAC_PHY_REG_BMSR); |
frank26080115 | 0:84d7747641aa | 488 | if (regv & EMAC_PHY_BMSR_AUTO_DONE) { |
frank26080115 | 0:84d7747641aa | 489 | /* Auto-negotiation Complete. */ |
frank26080115 | 0:84d7747641aa | 490 | break; |
frank26080115 | 0:84d7747641aa | 491 | } |
frank26080115 | 0:84d7747641aa | 492 | if (tout == 0){ |
frank26080115 | 0:84d7747641aa | 493 | // Time out, return error |
frank26080115 | 0:84d7747641aa | 494 | return (-1); |
frank26080115 | 0:84d7747641aa | 495 | } |
frank26080115 | 0:84d7747641aa | 496 | } |
frank26080115 | 0:84d7747641aa | 497 | break; |
frank26080115 | 0:84d7747641aa | 498 | case EMAC_MODE_10M_FULL: |
frank26080115 | 0:84d7747641aa | 499 | /* Connect at 10MBit full-duplex */ |
frank26080115 | 0:84d7747641aa | 500 | write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M); |
frank26080115 | 0:84d7747641aa | 501 | break; |
frank26080115 | 0:84d7747641aa | 502 | case EMAC_MODE_10M_HALF: |
frank26080115 | 0:84d7747641aa | 503 | /* Connect at 10MBit half-duplex */ |
frank26080115 | 0:84d7747641aa | 504 | write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M); |
frank26080115 | 0:84d7747641aa | 505 | break; |
frank26080115 | 0:84d7747641aa | 506 | case EMAC_MODE_100M_FULL: |
frank26080115 | 0:84d7747641aa | 507 | /* Connect at 100MBit full-duplex */ |
frank26080115 | 0:84d7747641aa | 508 | write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M); |
frank26080115 | 0:84d7747641aa | 509 | break; |
frank26080115 | 0:84d7747641aa | 510 | case EMAC_MODE_100M_HALF: |
frank26080115 | 0:84d7747641aa | 511 | /* Connect at 100MBit half-duplex */ |
frank26080115 | 0:84d7747641aa | 512 | write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M); |
frank26080115 | 0:84d7747641aa | 513 | break; |
frank26080115 | 0:84d7747641aa | 514 | default: |
frank26080115 | 0:84d7747641aa | 515 | // un-supported |
frank26080115 | 0:84d7747641aa | 516 | return (-1); |
frank26080115 | 0:84d7747641aa | 517 | } |
frank26080115 | 0:84d7747641aa | 518 | } |
frank26080115 | 0:84d7747641aa | 519 | // It's not correct module ID |
frank26080115 | 0:84d7747641aa | 520 | else { |
frank26080115 | 0:84d7747641aa | 521 | return (-1); |
frank26080115 | 0:84d7747641aa | 522 | } |
frank26080115 | 0:84d7747641aa | 523 | |
frank26080115 | 0:84d7747641aa | 524 | // Update EMAC configuration with current PHY status |
frank26080115 | 0:84d7747641aa | 525 | if (EMAC_UpdatePHYStatus() < 0){ |
frank26080115 | 0:84d7747641aa | 526 | return (-1); |
frank26080115 | 0:84d7747641aa | 527 | } |
frank26080115 | 0:84d7747641aa | 528 | |
frank26080115 | 0:84d7747641aa | 529 | // Complete |
frank26080115 | 0:84d7747641aa | 530 | return (0); |
frank26080115 | 0:84d7747641aa | 531 | } |
frank26080115 | 0:84d7747641aa | 532 | |
frank26080115 | 0:84d7747641aa | 533 | |
frank26080115 | 0:84d7747641aa | 534 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 535 | * @brief Auto-Configures value for the EMAC configuration register to |
frank26080115 | 0:84d7747641aa | 536 | * match with current PHY mode |
frank26080115 | 0:84d7747641aa | 537 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 538 | * @return Return (0) if no error, otherwise return (-1) |
frank26080115 | 0:84d7747641aa | 539 | * |
frank26080115 | 0:84d7747641aa | 540 | * Note: The EMAC configuration will be auto-configured: |
frank26080115 | 0:84d7747641aa | 541 | * - Speed mode. |
frank26080115 | 0:84d7747641aa | 542 | * - Half/Full duplex mode |
frank26080115 | 0:84d7747641aa | 543 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 544 | int32_t EMAC_UpdatePHYStatus(void) |
frank26080115 | 0:84d7747641aa | 545 | { |
frank26080115 | 0:84d7747641aa | 546 | int32_t regv, tout; |
frank26080115 | 0:84d7747641aa | 547 | |
frank26080115 | 0:84d7747641aa | 548 | /* Check the link status. */ |
frank26080115 | 0:84d7747641aa | 549 | #ifdef MCB_LPC_1768 |
frank26080115 | 0:84d7747641aa | 550 | for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { |
frank26080115 | 0:84d7747641aa | 551 | regv = read_PHY (EMAC_PHY_REG_STS); |
frank26080115 | 0:84d7747641aa | 552 | if (regv & EMAC_PHY_SR_LINK) { |
frank26080115 | 0:84d7747641aa | 553 | /* Link is on. */ |
frank26080115 | 0:84d7747641aa | 554 | break; |
frank26080115 | 0:84d7747641aa | 555 | } |
frank26080115 | 0:84d7747641aa | 556 | if (tout == 0){ |
frank26080115 | 0:84d7747641aa | 557 | // time out |
frank26080115 | 0:84d7747641aa | 558 | return (-1); |
frank26080115 | 0:84d7747641aa | 559 | } |
frank26080115 | 0:84d7747641aa | 560 | } |
frank26080115 | 0:84d7747641aa | 561 | /* Configure Full/Half Duplex mode. */ |
frank26080115 | 0:84d7747641aa | 562 | if (regv & EMAC_PHY_SR_DUP) { |
frank26080115 | 0:84d7747641aa | 563 | /* Full duplex is enabled. */ |
frank26080115 | 0:84d7747641aa | 564 | LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; |
frank26080115 | 0:84d7747641aa | 565 | LPC_EMAC->Command |= EMAC_CR_FULL_DUP; |
frank26080115 | 0:84d7747641aa | 566 | LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; |
frank26080115 | 0:84d7747641aa | 567 | } else { |
frank26080115 | 0:84d7747641aa | 568 | /* Half duplex mode. */ |
frank26080115 | 0:84d7747641aa | 569 | LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; |
frank26080115 | 0:84d7747641aa | 570 | } |
frank26080115 | 0:84d7747641aa | 571 | if (regv & EMAC_PHY_SR_SPEED) { |
frank26080115 | 0:84d7747641aa | 572 | /* 10MBit mode. */ |
frank26080115 | 0:84d7747641aa | 573 | LPC_EMAC->SUPP = 0; |
frank26080115 | 0:84d7747641aa | 574 | } else { |
frank26080115 | 0:84d7747641aa | 575 | /* 100MBit mode. */ |
frank26080115 | 0:84d7747641aa | 576 | LPC_EMAC->SUPP = EMAC_SUPP_SPEED; |
frank26080115 | 0:84d7747641aa | 577 | } |
frank26080115 | 0:84d7747641aa | 578 | #elif defined(IAR_LPC_1768) |
frank26080115 | 0:84d7747641aa | 579 | for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { |
frank26080115 | 0:84d7747641aa | 580 | regv = read_PHY (EMAC_PHY_REG_BMSR); |
frank26080115 | 0:84d7747641aa | 581 | if (regv & EMAC_PHY_BMSR_LINK_STATUS) { |
frank26080115 | 0:84d7747641aa | 582 | /* Link is on. */ |
frank26080115 | 0:84d7747641aa | 583 | break; |
frank26080115 | 0:84d7747641aa | 584 | } |
frank26080115 | 0:84d7747641aa | 585 | if (tout == 0){ |
frank26080115 | 0:84d7747641aa | 586 | // time out |
frank26080115 | 0:84d7747641aa | 587 | return (-1); |
frank26080115 | 0:84d7747641aa | 588 | } |
frank26080115 | 0:84d7747641aa | 589 | } |
frank26080115 | 0:84d7747641aa | 590 | |
frank26080115 | 0:84d7747641aa | 591 | /* Configure Full/Half Duplex mode. */ |
frank26080115 | 0:84d7747641aa | 592 | if (regv & EMAC_PHY_SR_FULL_DUP) { |
frank26080115 | 0:84d7747641aa | 593 | /* Full duplex is enabled. */ |
frank26080115 | 0:84d7747641aa | 594 | LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; |
frank26080115 | 0:84d7747641aa | 595 | LPC_EMAC->Command |= EMAC_CR_FULL_DUP; |
frank26080115 | 0:84d7747641aa | 596 | LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; |
frank26080115 | 0:84d7747641aa | 597 | } else { |
frank26080115 | 0:84d7747641aa | 598 | /* Half duplex mode. */ |
frank26080115 | 0:84d7747641aa | 599 | LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; |
frank26080115 | 0:84d7747641aa | 600 | } |
frank26080115 | 0:84d7747641aa | 601 | |
frank26080115 | 0:84d7747641aa | 602 | /* Configure 100MBit/10MBit mode. */ |
frank26080115 | 0:84d7747641aa | 603 | if (!(regv & EMAC_PHY_SR_100_SPEED)) { |
frank26080115 | 0:84d7747641aa | 604 | /* 10MBit mode. */ |
frank26080115 | 0:84d7747641aa | 605 | LPC_EMAC->SUPP = 0; |
frank26080115 | 0:84d7747641aa | 606 | } else { |
frank26080115 | 0:84d7747641aa | 607 | /* 100MBit mode. */ |
frank26080115 | 0:84d7747641aa | 608 | LPC_EMAC->SUPP = EMAC_SUPP_SPEED; |
frank26080115 | 0:84d7747641aa | 609 | } |
frank26080115 | 0:84d7747641aa | 610 | #endif |
frank26080115 | 0:84d7747641aa | 611 | // Complete |
frank26080115 | 0:84d7747641aa | 612 | return (0); |
frank26080115 | 0:84d7747641aa | 613 | } |
frank26080115 | 0:84d7747641aa | 614 | |
frank26080115 | 0:84d7747641aa | 615 | |
frank26080115 | 0:84d7747641aa | 616 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 617 | * @brief Enable/Disable hash filter functionality for specified destination |
frank26080115 | 0:84d7747641aa | 618 | * MAC address in EMAC module |
frank26080115 | 0:84d7747641aa | 619 | * @param[in] dstMAC_addr Pointer to the first MAC destination address, should |
frank26080115 | 0:84d7747641aa | 620 | * be 6-bytes length, in order LSB to the MSB |
frank26080115 | 0:84d7747641aa | 621 | * @param[in] NewState New State of this command, should be: |
frank26080115 | 0:84d7747641aa | 622 | * - ENABLE. |
frank26080115 | 0:84d7747641aa | 623 | * - DISABLE. |
frank26080115 | 0:84d7747641aa | 624 | * @return None |
frank26080115 | 0:84d7747641aa | 625 | * |
frank26080115 | 0:84d7747641aa | 626 | * Note: |
frank26080115 | 0:84d7747641aa | 627 | * The standard Ethernet cyclic redundancy check (CRC) function is calculated from |
frank26080115 | 0:84d7747641aa | 628 | * the 6 byte destination address in the Ethernet frame (this CRC is calculated |
frank26080115 | 0:84d7747641aa | 629 | * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of |
frank26080115 | 0:84d7747641aa | 630 | * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access |
frank26080115 | 0:84d7747641aa | 631 | * the hash table: it is used as an index in the 64 bit HashFilter register that has been |
frank26080115 | 0:84d7747641aa | 632 | * programmed with accept values. If the selected accept value is 1, the frame is |
frank26080115 | 0:84d7747641aa | 633 | * accepted. |
frank26080115 | 0:84d7747641aa | 634 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 635 | void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState) |
frank26080115 | 0:84d7747641aa | 636 | { |
frank26080115 | 0:84d7747641aa | 637 | uint32_t *pReg; |
frank26080115 | 0:84d7747641aa | 638 | uint32_t tmp; |
frank26080115 | 0:84d7747641aa | 639 | int32_t crc; |
frank26080115 | 0:84d7747641aa | 640 | |
frank26080115 | 0:84d7747641aa | 641 | // Calculate the CRC from the destination MAC address |
frank26080115 | 0:84d7747641aa | 642 | crc = emac_CRCCalc(dstMAC_addr, 6); |
frank26080115 | 0:84d7747641aa | 643 | // Extract the value from CRC to get index value for hash filter table |
frank26080115 | 0:84d7747641aa | 644 | crc = (crc >> 23) & 0x3F; |
frank26080115 | 0:84d7747641aa | 645 | |
frank26080115 | 0:84d7747641aa | 646 | pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \ |
frank26080115 | 0:84d7747641aa | 647 | : ((uint32_t *)&LPC_EMAC->HashFilterL); |
frank26080115 | 0:84d7747641aa | 648 | tmp = (crc > 31) ? (crc - 32) : crc; |
frank26080115 | 0:84d7747641aa | 649 | if (NewState == ENABLE) { |
frank26080115 | 0:84d7747641aa | 650 | (*pReg) |= (1UL << tmp); |
frank26080115 | 0:84d7747641aa | 651 | } else { |
frank26080115 | 0:84d7747641aa | 652 | (*pReg) &= ~(1UL << tmp); |
frank26080115 | 0:84d7747641aa | 653 | } |
frank26080115 | 0:84d7747641aa | 654 | // Enable Rx Filter |
frank26080115 | 0:84d7747641aa | 655 | LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT; |
frank26080115 | 0:84d7747641aa | 656 | } |
frank26080115 | 0:84d7747641aa | 657 | |
frank26080115 | 0:84d7747641aa | 658 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 659 | * @brief Enable/Disable Filter mode for each specified type EMAC peripheral |
frank26080115 | 0:84d7747641aa | 660 | * @param[in] ulFilterMode Filter mode, should be: |
frank26080115 | 0:84d7747641aa | 661 | * - EMAC_RFC_UCAST_EN: all frames of unicast types |
frank26080115 | 0:84d7747641aa | 662 | * will be accepted |
frank26080115 | 0:84d7747641aa | 663 | * - EMAC_RFC_BCAST_EN: broadcast frame will be |
frank26080115 | 0:84d7747641aa | 664 | * accepted |
frank26080115 | 0:84d7747641aa | 665 | * - EMAC_RFC_MCAST_EN: all frames of multicast |
frank26080115 | 0:84d7747641aa | 666 | * types will be accepted |
frank26080115 | 0:84d7747641aa | 667 | * - EMAC_RFC_UCAST_HASH_EN: The imperfect hash |
frank26080115 | 0:84d7747641aa | 668 | * filter will be applied to unicast addresses |
frank26080115 | 0:84d7747641aa | 669 | * - EMAC_RFC_MCAST_HASH_EN: The imperfect hash |
frank26080115 | 0:84d7747641aa | 670 | * filter will be applied to multicast addresses |
frank26080115 | 0:84d7747641aa | 671 | * - EMAC_RFC_PERFECT_EN: the destination address |
frank26080115 | 0:84d7747641aa | 672 | * will be compared with the 6 byte station address |
frank26080115 | 0:84d7747641aa | 673 | * programmed in the station address by the filter |
frank26080115 | 0:84d7747641aa | 674 | * - EMAC_RFC_MAGP_WOL_EN: the result of the magic |
frank26080115 | 0:84d7747641aa | 675 | * packet filter will generate a WoL interrupt when |
frank26080115 | 0:84d7747641aa | 676 | * there is a match |
frank26080115 | 0:84d7747641aa | 677 | * - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address |
frank26080115 | 0:84d7747641aa | 678 | * matching filter and the imperfect hash filter will |
frank26080115 | 0:84d7747641aa | 679 | * generate a WoL interrupt when there is a match |
frank26080115 | 0:84d7747641aa | 680 | * @param[in] NewState New State of this command, should be: |
frank26080115 | 0:84d7747641aa | 681 | * - ENABLE |
frank26080115 | 0:84d7747641aa | 682 | * - DISABLE |
frank26080115 | 0:84d7747641aa | 683 | * @return None |
frank26080115 | 0:84d7747641aa | 684 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 685 | void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState) |
frank26080115 | 0:84d7747641aa | 686 | { |
frank26080115 | 0:84d7747641aa | 687 | if (NewState == ENABLE){ |
frank26080115 | 0:84d7747641aa | 688 | LPC_EMAC->RxFilterCtrl |= ulFilterMode; |
frank26080115 | 0:84d7747641aa | 689 | } else { |
frank26080115 | 0:84d7747641aa | 690 | LPC_EMAC->RxFilterCtrl &= ~ulFilterMode; |
frank26080115 | 0:84d7747641aa | 691 | } |
frank26080115 | 0:84d7747641aa | 692 | } |
frank26080115 | 0:84d7747641aa | 693 | |
frank26080115 | 0:84d7747641aa | 694 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 695 | * @brief Get status of Wake On LAN Filter for each specified |
frank26080115 | 0:84d7747641aa | 696 | * type in EMAC peripheral, clear this status if it is set |
frank26080115 | 0:84d7747641aa | 697 | * @param[in] ulWoLMode WoL Filter mode, should be: |
frank26080115 | 0:84d7747641aa | 698 | * - EMAC_WOL_UCAST: unicast frames caused WoL |
frank26080115 | 0:84d7747641aa | 699 | * - EMAC_WOL_UCAST: broadcast frame caused WoL |
frank26080115 | 0:84d7747641aa | 700 | * - EMAC_WOL_MCAST: multicast frame caused WoL |
frank26080115 | 0:84d7747641aa | 701 | * - EMAC_WOL_UCAST_HASH: unicast frame that passes the |
frank26080115 | 0:84d7747641aa | 702 | * imperfect hash filter caused WoL |
frank26080115 | 0:84d7747641aa | 703 | * - EMAC_WOL_MCAST_HASH: multicast frame that passes the |
frank26080115 | 0:84d7747641aa | 704 | * imperfect hash filter caused WoL |
frank26080115 | 0:84d7747641aa | 705 | * - EMAC_WOL_PERFECT:perfect address matching filter |
frank26080115 | 0:84d7747641aa | 706 | * caused WoL |
frank26080115 | 0:84d7747641aa | 707 | * - EMAC_WOL_RX_FILTER: the receive filter caused WoL |
frank26080115 | 0:84d7747641aa | 708 | * - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL |
frank26080115 | 0:84d7747641aa | 709 | * @return SET/RESET |
frank26080115 | 0:84d7747641aa | 710 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 711 | FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode) |
frank26080115 | 0:84d7747641aa | 712 | { |
frank26080115 | 0:84d7747641aa | 713 | if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) { |
frank26080115 | 0:84d7747641aa | 714 | LPC_EMAC->RxFilterWoLClear = ulWoLMode; |
frank26080115 | 0:84d7747641aa | 715 | return SET; |
frank26080115 | 0:84d7747641aa | 716 | } else { |
frank26080115 | 0:84d7747641aa | 717 | return RESET; |
frank26080115 | 0:84d7747641aa | 718 | } |
frank26080115 | 0:84d7747641aa | 719 | } |
frank26080115 | 0:84d7747641aa | 720 | |
frank26080115 | 0:84d7747641aa | 721 | |
frank26080115 | 0:84d7747641aa | 722 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 723 | * @brief Write data to Tx packet data buffer at current index due to |
frank26080115 | 0:84d7747641aa | 724 | * TxProduceIndex |
frank26080115 | 0:84d7747641aa | 725 | * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure |
frank26080115 | 0:84d7747641aa | 726 | * data that contain specified information about |
frank26080115 | 0:84d7747641aa | 727 | * Packet data buffer. |
frank26080115 | 0:84d7747641aa | 728 | * @return None |
frank26080115 | 0:84d7747641aa | 729 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 730 | void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) |
frank26080115 | 0:84d7747641aa | 731 | { |
frank26080115 | 0:84d7747641aa | 732 | uint32_t idx,len; |
frank26080115 | 0:84d7747641aa | 733 | uint32_t *sp,*dp; |
frank26080115 | 0:84d7747641aa | 734 | |
frank26080115 | 0:84d7747641aa | 735 | idx = LPC_EMAC->TxProduceIndex; |
frank26080115 | 0:84d7747641aa | 736 | sp = (uint32_t *)pDataStruct->pbDataBuf; |
frank26080115 | 0:84d7747641aa | 737 | dp = (uint32_t *)Tx_Desc[idx].Packet; |
frank26080115 | 0:84d7747641aa | 738 | /* Copy frame data to EMAC packet buffers. */ |
frank26080115 | 0:84d7747641aa | 739 | for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { |
frank26080115 | 0:84d7747641aa | 740 | *dp++ = *sp++; |
frank26080115 | 0:84d7747641aa | 741 | } |
frank26080115 | 0:84d7747641aa | 742 | Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST); |
frank26080115 | 0:84d7747641aa | 743 | } |
frank26080115 | 0:84d7747641aa | 744 | |
frank26080115 | 0:84d7747641aa | 745 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 746 | * @brief Read data from Rx packet data buffer at current index due |
frank26080115 | 0:84d7747641aa | 747 | * to RxConsumeIndex |
frank26080115 | 0:84d7747641aa | 748 | * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure |
frank26080115 | 0:84d7747641aa | 749 | * data that contain specified information about |
frank26080115 | 0:84d7747641aa | 750 | * Packet data buffer. |
frank26080115 | 0:84d7747641aa | 751 | * @return None |
frank26080115 | 0:84d7747641aa | 752 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 753 | void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) |
frank26080115 | 0:84d7747641aa | 754 | { |
frank26080115 | 0:84d7747641aa | 755 | uint32_t idx, len; |
frank26080115 | 0:84d7747641aa | 756 | uint32_t *dp, *sp; |
frank26080115 | 0:84d7747641aa | 757 | |
frank26080115 | 0:84d7747641aa | 758 | idx = LPC_EMAC->RxConsumeIndex; |
frank26080115 | 0:84d7747641aa | 759 | dp = (uint32_t *)pDataStruct->pbDataBuf; |
frank26080115 | 0:84d7747641aa | 760 | sp = (uint32_t *)Rx_Desc[idx].Packet; |
frank26080115 | 0:84d7747641aa | 761 | |
frank26080115 | 0:84d7747641aa | 762 | if (pDataStruct->pbDataBuf != NULL) { |
frank26080115 | 0:84d7747641aa | 763 | for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { |
frank26080115 | 0:84d7747641aa | 764 | *dp++ = *sp++; |
frank26080115 | 0:84d7747641aa | 765 | } |
frank26080115 | 0:84d7747641aa | 766 | } |
frank26080115 | 0:84d7747641aa | 767 | } |
frank26080115 | 0:84d7747641aa | 768 | |
frank26080115 | 0:84d7747641aa | 769 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 770 | * @brief Enable/Disable interrupt for each type in EMAC |
frank26080115 | 0:84d7747641aa | 771 | * @param[in] ulIntType Interrupt Type, should be: |
frank26080115 | 0:84d7747641aa | 772 | * - EMAC_INT_RX_OVERRUN: Receive Overrun |
frank26080115 | 0:84d7747641aa | 773 | * - EMAC_INT_RX_ERR: Receive Error |
frank26080115 | 0:84d7747641aa | 774 | * - EMAC_INT_RX_FIN: Receive Descriptor Finish |
frank26080115 | 0:84d7747641aa | 775 | * - EMAC_INT_RX_DONE: Receive Done |
frank26080115 | 0:84d7747641aa | 776 | * - EMAC_INT_TX_UNDERRUN: Transmit Under-run |
frank26080115 | 0:84d7747641aa | 777 | * - EMAC_INT_TX_ERR: Transmit Error |
frank26080115 | 0:84d7747641aa | 778 | * - EMAC_INT_TX_FIN: Transmit descriptor finish |
frank26080115 | 0:84d7747641aa | 779 | * - EMAC_INT_TX_DONE: Transmit Done |
frank26080115 | 0:84d7747641aa | 780 | * - EMAC_INT_SOFT_INT: Software interrupt |
frank26080115 | 0:84d7747641aa | 781 | * - EMAC_INT_WAKEUP: Wakeup interrupt |
frank26080115 | 0:84d7747641aa | 782 | * @param[in] NewState New State of this function, should be: |
frank26080115 | 0:84d7747641aa | 783 | * - ENABLE. |
frank26080115 | 0:84d7747641aa | 784 | * - DISABLE. |
frank26080115 | 0:84d7747641aa | 785 | * @return None |
frank26080115 | 0:84d7747641aa | 786 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 787 | void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState) |
frank26080115 | 0:84d7747641aa | 788 | { |
frank26080115 | 0:84d7747641aa | 789 | if (NewState == ENABLE) { |
frank26080115 | 0:84d7747641aa | 790 | LPC_EMAC->IntEnable |= ulIntType; |
frank26080115 | 0:84d7747641aa | 791 | } else { |
frank26080115 | 0:84d7747641aa | 792 | LPC_EMAC->IntEnable &= ~(ulIntType); |
frank26080115 | 0:84d7747641aa | 793 | } |
frank26080115 | 0:84d7747641aa | 794 | } |
frank26080115 | 0:84d7747641aa | 795 | |
frank26080115 | 0:84d7747641aa | 796 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 797 | * @brief Check whether if specified interrupt flag is set or not |
frank26080115 | 0:84d7747641aa | 798 | * for each interrupt type in EMAC and clear interrupt pending |
frank26080115 | 0:84d7747641aa | 799 | * if it is set. |
frank26080115 | 0:84d7747641aa | 800 | * @param[in] ulIntType Interrupt Type, should be: |
frank26080115 | 0:84d7747641aa | 801 | * - EMAC_INT_RX_OVERRUN: Receive Overrun |
frank26080115 | 0:84d7747641aa | 802 | * - EMAC_INT_RX_ERR: Receive Error |
frank26080115 | 0:84d7747641aa | 803 | * - EMAC_INT_RX_FIN: Receive Descriptor Finish |
frank26080115 | 0:84d7747641aa | 804 | * - EMAC_INT_RX_DONE: Receive Done |
frank26080115 | 0:84d7747641aa | 805 | * - EMAC_INT_TX_UNDERRUN: Transmit Under-run |
frank26080115 | 0:84d7747641aa | 806 | * - EMAC_INT_TX_ERR: Transmit Error |
frank26080115 | 0:84d7747641aa | 807 | * - EMAC_INT_TX_FIN: Transmit descriptor finish |
frank26080115 | 0:84d7747641aa | 808 | * - EMAC_INT_TX_DONE: Transmit Done |
frank26080115 | 0:84d7747641aa | 809 | * - EMAC_INT_SOFT_INT: Software interrupt |
frank26080115 | 0:84d7747641aa | 810 | * - EMAC_INT_WAKEUP: Wakeup interrupt |
frank26080115 | 0:84d7747641aa | 811 | * @return New state of specified interrupt (SET or RESET) |
frank26080115 | 0:84d7747641aa | 812 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 813 | IntStatus EMAC_IntGetStatus(uint32_t ulIntType) |
frank26080115 | 0:84d7747641aa | 814 | { |
frank26080115 | 0:84d7747641aa | 815 | if (LPC_EMAC->IntStatus & ulIntType) { |
frank26080115 | 0:84d7747641aa | 816 | LPC_EMAC->IntClear = ulIntType; |
frank26080115 | 0:84d7747641aa | 817 | return SET; |
frank26080115 | 0:84d7747641aa | 818 | } else { |
frank26080115 | 0:84d7747641aa | 819 | return RESET; |
frank26080115 | 0:84d7747641aa | 820 | } |
frank26080115 | 0:84d7747641aa | 821 | } |
frank26080115 | 0:84d7747641aa | 822 | |
frank26080115 | 0:84d7747641aa | 823 | |
frank26080115 | 0:84d7747641aa | 824 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 825 | * @brief Check whether if the current RxConsumeIndex is not equal to the |
frank26080115 | 0:84d7747641aa | 826 | * current RxProduceIndex. |
frank26080115 | 0:84d7747641aa | 827 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 828 | * @return TRUE if they're not equal, otherwise return FALSE |
frank26080115 | 0:84d7747641aa | 829 | * |
frank26080115 | 0:84d7747641aa | 830 | * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex, |
frank26080115 | 0:84d7747641aa | 831 | * it means there're available data has been received. They should be read |
frank26080115 | 0:84d7747641aa | 832 | * out and released the Receive Data Buffer by updating the RxConsumeIndex value. |
frank26080115 | 0:84d7747641aa | 833 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 834 | Bool EMAC_CheckReceiveIndex(void) |
frank26080115 | 0:84d7747641aa | 835 | { |
frank26080115 | 0:84d7747641aa | 836 | if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) { |
frank26080115 | 0:84d7747641aa | 837 | return TRUE; |
frank26080115 | 0:84d7747641aa | 838 | } else { |
frank26080115 | 0:84d7747641aa | 839 | return FALSE; |
frank26080115 | 0:84d7747641aa | 840 | } |
frank26080115 | 0:84d7747641aa | 841 | } |
frank26080115 | 0:84d7747641aa | 842 | |
frank26080115 | 0:84d7747641aa | 843 | |
frank26080115 | 0:84d7747641aa | 844 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 845 | * @brief Check whether if the current TxProduceIndex is not equal to the |
frank26080115 | 0:84d7747641aa | 846 | * current RxProduceIndex - 1. |
frank26080115 | 0:84d7747641aa | 847 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 848 | * @return TRUE if they're not equal, otherwise return FALSE |
frank26080115 | 0:84d7747641aa | 849 | * |
frank26080115 | 0:84d7747641aa | 850 | * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1, |
frank26080115 | 0:84d7747641aa | 851 | * it means the transmit buffer is available and data can be written to transmit |
frank26080115 | 0:84d7747641aa | 852 | * buffer to be sent. |
frank26080115 | 0:84d7747641aa | 853 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 854 | Bool EMAC_CheckTransmitIndex(void) |
frank26080115 | 0:84d7747641aa | 855 | { |
frank26080115 | 0:84d7747641aa | 856 | uint32_t tmp = LPC_EMAC->TxConsumeIndex -1; |
frank26080115 | 0:84d7747641aa | 857 | if (LPC_EMAC->TxProduceIndex == tmp) { |
frank26080115 | 0:84d7747641aa | 858 | return FALSE; |
frank26080115 | 0:84d7747641aa | 859 | } else { |
frank26080115 | 0:84d7747641aa | 860 | return TRUE; |
frank26080115 | 0:84d7747641aa | 861 | } |
frank26080115 | 0:84d7747641aa | 862 | } |
frank26080115 | 0:84d7747641aa | 863 | |
frank26080115 | 0:84d7747641aa | 864 | |
frank26080115 | 0:84d7747641aa | 865 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 866 | * @brief Get current status value of receive data (due to RxConsumeIndex) |
frank26080115 | 0:84d7747641aa | 867 | * @param[in] ulRxStatType Received Status type, should be one of following: |
frank26080115 | 0:84d7747641aa | 868 | * - EMAC_RINFO_CTRL_FRAME: Control Frame |
frank26080115 | 0:84d7747641aa | 869 | * - EMAC_RINFO_VLAN: VLAN Frame |
frank26080115 | 0:84d7747641aa | 870 | * - EMAC_RINFO_FAIL_FILT: RX Filter Failed |
frank26080115 | 0:84d7747641aa | 871 | * - EMAC_RINFO_MCAST: Multicast Frame |
frank26080115 | 0:84d7747641aa | 872 | * - EMAC_RINFO_BCAST: Broadcast Frame |
frank26080115 | 0:84d7747641aa | 873 | * - EMAC_RINFO_CRC_ERR: CRC Error in Frame |
frank26080115 | 0:84d7747641aa | 874 | * - EMAC_RINFO_SYM_ERR: Symbol Error from PHY |
frank26080115 | 0:84d7747641aa | 875 | * - EMAC_RINFO_LEN_ERR: Length Error |
frank26080115 | 0:84d7747641aa | 876 | * - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size) |
frank26080115 | 0:84d7747641aa | 877 | * - EMAC_RINFO_ALIGN_ERR: Alignment error |
frank26080115 | 0:84d7747641aa | 878 | * - EMAC_RINFO_OVERRUN: Receive overrun |
frank26080115 | 0:84d7747641aa | 879 | * - EMAC_RINFO_NO_DESCR: No new Descriptor available |
frank26080115 | 0:84d7747641aa | 880 | * - EMAC_RINFO_LAST_FLAG: last Fragment in Frame |
frank26080115 | 0:84d7747641aa | 881 | * - EMAC_RINFO_ERR: Error Occurred (OR of all error) |
frank26080115 | 0:84d7747641aa | 882 | * @return Current value of receive data (due to RxConsumeIndex) |
frank26080115 | 0:84d7747641aa | 883 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 884 | FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType) |
frank26080115 | 0:84d7747641aa | 885 | { |
frank26080115 | 0:84d7747641aa | 886 | uint32_t idx; |
frank26080115 | 0:84d7747641aa | 887 | idx = LPC_EMAC->RxConsumeIndex; |
frank26080115 | 0:84d7747641aa | 888 | return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET); |
frank26080115 | 0:84d7747641aa | 889 | } |
frank26080115 | 0:84d7747641aa | 890 | |
frank26080115 | 0:84d7747641aa | 891 | |
frank26080115 | 0:84d7747641aa | 892 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 893 | * @brief Get size of current Received data in received buffer (due to |
frank26080115 | 0:84d7747641aa | 894 | * RxConsumeIndex) |
frank26080115 | 0:84d7747641aa | 895 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 896 | * @return Size of received data |
frank26080115 | 0:84d7747641aa | 897 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 898 | uint32_t EMAC_GetReceiveDataSize(void) |
frank26080115 | 0:84d7747641aa | 899 | { |
frank26080115 | 0:84d7747641aa | 900 | uint32_t idx; |
frank26080115 | 0:84d7747641aa | 901 | idx =LPC_EMAC->RxConsumeIndex; |
frank26080115 | 0:84d7747641aa | 902 | return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE); |
frank26080115 | 0:84d7747641aa | 903 | } |
frank26080115 | 0:84d7747641aa | 904 | |
frank26080115 | 0:84d7747641aa | 905 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 906 | * @brief Increase the RxConsumeIndex (after reading the Receive buffer |
frank26080115 | 0:84d7747641aa | 907 | * to release the Receive buffer) and wrap-around the index if |
frank26080115 | 0:84d7747641aa | 908 | * it reaches the maximum Receive Number |
frank26080115 | 0:84d7747641aa | 909 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 910 | * @return None |
frank26080115 | 0:84d7747641aa | 911 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 912 | void EMAC_UpdateRxConsumeIndex(void) |
frank26080115 | 0:84d7747641aa | 913 | { |
frank26080115 | 0:84d7747641aa | 914 | // Get current Rx consume index |
frank26080115 | 0:84d7747641aa | 915 | uint32_t idx = LPC_EMAC->RxConsumeIndex; |
frank26080115 | 0:84d7747641aa | 916 | |
frank26080115 | 0:84d7747641aa | 917 | /* Release frame from EMAC buffer */ |
frank26080115 | 0:84d7747641aa | 918 | if (++idx == EMAC_NUM_RX_FRAG) idx = 0; |
frank26080115 | 0:84d7747641aa | 919 | LPC_EMAC->RxConsumeIndex = idx; |
frank26080115 | 0:84d7747641aa | 920 | } |
frank26080115 | 0:84d7747641aa | 921 | |
frank26080115 | 0:84d7747641aa | 922 | /*********************************************************************//** |
frank26080115 | 0:84d7747641aa | 923 | * @brief Increase the TxProduceIndex (after writting to the Transmit buffer |
frank26080115 | 0:84d7747641aa | 924 | * to enable the Transmit buffer) and wrap-around the index if |
frank26080115 | 0:84d7747641aa | 925 | * it reaches the maximum Transmit Number |
frank26080115 | 0:84d7747641aa | 926 | * @param[in] None |
frank26080115 | 0:84d7747641aa | 927 | * @return None |
frank26080115 | 0:84d7747641aa | 928 | **********************************************************************/ |
frank26080115 | 0:84d7747641aa | 929 | void EMAC_UpdateTxProduceIndex(void) |
frank26080115 | 0:84d7747641aa | 930 | { |
frank26080115 | 0:84d7747641aa | 931 | // Get current Tx produce index |
frank26080115 | 0:84d7747641aa | 932 | uint32_t idx = LPC_EMAC->TxProduceIndex; |
frank26080115 | 0:84d7747641aa | 933 | |
frank26080115 | 0:84d7747641aa | 934 | /* Start frame transmission */ |
frank26080115 | 0:84d7747641aa | 935 | if (++idx == EMAC_NUM_TX_FRAG) idx = 0; |
frank26080115 | 0:84d7747641aa | 936 | LPC_EMAC->TxProduceIndex = idx; |
frank26080115 | 0:84d7747641aa | 937 | } |
frank26080115 | 0:84d7747641aa | 938 | |
frank26080115 | 0:84d7747641aa | 939 | |
frank26080115 | 0:84d7747641aa | 940 | /** |
frank26080115 | 0:84d7747641aa | 941 | * @} |
frank26080115 | 0:84d7747641aa | 942 | */ |
frank26080115 | 0:84d7747641aa | 943 | |
frank26080115 | 0:84d7747641aa | 944 | #endif /* _EMAC */ |
frank26080115 | 0:84d7747641aa | 945 | |
frank26080115 | 0:84d7747641aa | 946 | /** |
frank26080115 | 0:84d7747641aa | 947 | * @} |
frank26080115 | 0:84d7747641aa | 948 | */ |
frank26080115 | 0:84d7747641aa | 949 | |
frank26080115 | 0:84d7747641aa | 950 | /* --------------------------------- End Of File ------------------------------ */ |