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