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.
Fork of mbed-src by
ethernet_api.c
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include <string.h> 00017 00018 #include "ethernet_api.h" 00019 #include "cmsis.h" 00020 #include "mbed_interface.h" 00021 #include "toolchain.h" 00022 #include "error.h" 00023 00024 #define NEW_LOGIC 0 00025 #define NEW_ETH_BUFFER 0 00026 00027 #if NEW_ETH_BUFFER 00028 00029 #define NUM_RX_FRAG 4 // Number of Rx Fragments (== packets) 00030 #define NUM_TX_FRAG 3 // Number of Tx Fragments (== packets) 00031 00032 #define ETH_MAX_FLEN 1536 // Maximum Ethernet Frame Size 00033 #define ETH_FRAG_SIZE ETH_MAX_FLEN // Packet Fragment size (same as packet length) 00034 00035 #else 00036 00037 // Memfree calculation: 00038 // (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) + 00039 // (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556 00040 /* EMAC Memory Buffer configuration for 16K Ethernet RAM. */ 00041 #define NUM_RX_FRAG 4 /* Num.of RX Fragments 4*1536= 6.0kB */ 00042 #define NUM_TX_FRAG 3 /* Num.of TX Fragments 3*1536= 4.6kB */ 00043 //#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */ 00044 00045 //#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */ 00046 #define ETH_FRAG_SIZE 0x300 /* Packet Fragment size 1536/2 Bytes */ 00047 #define ETH_MAX_FLEN 0x300 /* Max. Ethernet Frame Size */ 00048 00049 const int ethernet_MTU_SIZE = 0x300; 00050 00051 #endif 00052 00053 #define ETHERNET_ADDR_SIZE 6 00054 00055 PACKED struct RX_DESC_TypeDef { /* RX Descriptor struct */ 00056 unsigned int Packet; 00057 unsigned int Ctrl; 00058 }; 00059 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef; 00060 00061 PACKED struct RX_STAT_TypeDef { /* RX Status struct */ 00062 unsigned int Info; 00063 unsigned int HashCRC; 00064 }; 00065 typedef struct RX_STAT_TypeDef RX_STAT_TypeDef; 00066 00067 PACKED struct TX_DESC_TypeDef { /* TX Descriptor struct */ 00068 unsigned int Packet; 00069 unsigned int Ctrl; 00070 }; 00071 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef; 00072 00073 PACKED struct TX_STAT_TypeDef { /* TX Status struct */ 00074 unsigned int Info; 00075 }; 00076 typedef struct TX_STAT_TypeDef TX_STAT_TypeDef; 00077 00078 /* MAC Configuration Register 1 */ 00079 #define MAC1_REC_EN 0x00000001 /* Receive Enable */ 00080 #define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */ 00081 #define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */ 00082 #define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */ 00083 #define MAC1_LOOPB 0x00000010 /* Loop Back Mode */ 00084 #define MAC1_RES_TX 0x00000100 /* Reset TX Logic */ 00085 #define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */ 00086 #define MAC1_RES_RX 0x00000400 /* Reset RX Logic */ 00087 #define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */ 00088 #define MAC1_SIM_RES 0x00004000 /* Simulation Reset */ 00089 #define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */ 00090 00091 /* MAC Configuration Register 2 */ 00092 #define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */ 00093 #define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */ 00094 #define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */ 00095 #define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */ 00096 #define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */ 00097 #define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */ 00098 #define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */ 00099 #define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */ 00100 #define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */ 00101 #define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */ 00102 #define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */ 00103 #define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */ 00104 #define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */ 00105 00106 /* Back-to-Back Inter-Packet-Gap Register */ 00107 #define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */ 00108 #define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */ 00109 00110 /* Non Back-to-Back Inter-Packet-Gap Register */ 00111 #define IPGR_DEF 0x00000012 /* Recommended value */ 00112 00113 /* Collision Window/Retry Register */ 00114 #define CLRT_DEF 0x0000370F /* Default value */ 00115 00116 /* PHY Support Register */ 00117 #define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */ 00118 //#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */ 00119 #define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */ 00120 00121 /* Test Register */ 00122 #define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */ 00123 #define TEST_TST_PAUSE 0x00000002 /* Test Pause */ 00124 #define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */ 00125 00126 /* MII Management Configuration Register */ 00127 #define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */ 00128 #define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */ 00129 #define MCFG_CLK_SEL 0x0000003C /* Clock Select Mask */ 00130 #define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */ 00131 00132 /* MII Management Command Register */ 00133 #define MCMD_READ 0x00000001 /* MII Read */ 00134 #define MCMD_SCAN 0x00000002 /* MII Scan continuously */ 00135 00136 #define MII_WR_TOUT 0x00050000 /* MII Write timeout count */ 00137 #define MII_RD_TOUT 0x00050000 /* MII Read timeout count */ 00138 00139 /* MII Management Address Register */ 00140 #define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */ 00141 #define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */ 00142 00143 /* MII Management Indicators Register */ 00144 #define MIND_BUSY 0x00000001 /* MII is Busy */ 00145 #define MIND_SCAN 0x00000002 /* MII Scanning in Progress */ 00146 #define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */ 00147 #define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */ 00148 00149 /* Command Register */ 00150 #define CR_RX_EN 0x00000001 /* Enable Receive */ 00151 #define CR_TX_EN 0x00000002 /* Enable Transmit */ 00152 #define CR_REG_RES 0x00000008 /* Reset Host Registers */ 00153 #define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */ 00154 #define CR_RX_RES 0x00000020 /* Reset Receive Datapath */ 00155 #define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */ 00156 #define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */ 00157 #define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */ 00158 #define CR_RMII 0x00000200 /* Reduced MII Interface */ 00159 #define CR_FULL_DUP 0x00000400 /* Full Duplex */ 00160 00161 /* Status Register */ 00162 #define SR_RX_EN 0x00000001 /* Enable Receive */ 00163 #define SR_TX_EN 0x00000002 /* Enable Transmit */ 00164 00165 /* Transmit Status Vector 0 Register */ 00166 #define TSV0_CRC_ERR 0x00000001 /* CRC error */ 00167 #define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */ 00168 #define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */ 00169 #define TSV0_DONE 0x00000008 /* Tramsmission Completed */ 00170 #define TSV0_MCAST 0x00000010 /* Multicast Destination */ 00171 #define TSV0_BCAST 0x00000020 /* Broadcast Destination */ 00172 #define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */ 00173 #define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */ 00174 #define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */ 00175 #define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */ 00176 #define TSV0_GIANT 0x00000400 /* Giant Frame */ 00177 #define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */ 00178 #define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */ 00179 #define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */ 00180 #define TSV0_PAUSE 0x20000000 /* Pause Frame */ 00181 #define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */ 00182 #define TSV0_VLAN 0x80000000 /* VLAN Frame */ 00183 00184 /* Transmit Status Vector 1 Register */ 00185 #define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */ 00186 #define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */ 00187 00188 /* Receive Status Vector Register */ 00189 #define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */ 00190 #define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */ 00191 #define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */ 00192 #define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */ 00193 #define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */ 00194 #define RSV_CRC_ERR 0x00100000 /* CRC Error */ 00195 #define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */ 00196 #define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */ 00197 #define RSV_REC_OK 0x00800000 /* Frame Received OK */ 00198 #define RSV_MCAST 0x01000000 /* Multicast Frame */ 00199 #define RSV_BCAST 0x02000000 /* Broadcast Frame */ 00200 #define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */ 00201 #define RSV_CTRL_FRAME 0x08000000 /* Control Frame */ 00202 #define RSV_PAUSE 0x10000000 /* Pause Frame */ 00203 #define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */ 00204 #define RSV_VLAN 0x40000000 /* VLAN Frame */ 00205 00206 /* Flow Control Counter Register */ 00207 #define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */ 00208 #define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */ 00209 00210 /* Flow Control Status Register */ 00211 #define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */ 00212 00213 /* Receive Filter Control Register */ 00214 #define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */ 00215 #define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */ 00216 #define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */ 00217 #define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */ 00218 #define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/ 00219 #define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */ 00220 #define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */ 00221 #define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */ 00222 00223 /* Receive Filter WoL Status/Clear Registers */ 00224 #define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */ 00225 #define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */ 00226 #define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */ 00227 #define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */ 00228 #define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */ 00229 #define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */ 00230 #define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */ 00231 #define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */ 00232 00233 /* Interrupt Status/Enable/Clear/Set Registers */ 00234 #define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */ 00235 #define INT_RX_ERR 0x00000002 /* Receive Error */ 00236 #define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */ 00237 #define INT_RX_DONE 0x00000008 /* Receive Done */ 00238 #define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */ 00239 #define INT_TX_ERR 0x00000020 /* Transmit Error */ 00240 #define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */ 00241 #define INT_TX_DONE 0x00000080 /* Transmit Done */ 00242 #define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */ 00243 #define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */ 00244 00245 /* Power Down Register */ 00246 #define PD_POWER_DOWN 0x80000000 /* Power Down MAC */ 00247 00248 /* RX Descriptor Control Word */ 00249 #define RCTRL_SIZE 0x000007FF /* Buffer size mask */ 00250 #define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */ 00251 00252 /* RX Status Hash CRC Word */ 00253 #define RHASH_SA 0x000001FF /* Hash CRC for Source Address */ 00254 #define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */ 00255 00256 /* RX Status Information Word */ 00257 #define RINFO_SIZE 0x000007FF /* Data size in bytes */ 00258 #define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */ 00259 #define RINFO_VLAN 0x00080000 /* VLAN Frame */ 00260 #define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */ 00261 #define RINFO_MCAST 0x00200000 /* Multicast Frame */ 00262 #define RINFO_BCAST 0x00400000 /* Broadcast Frame */ 00263 #define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */ 00264 #define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */ 00265 #define RINFO_LEN_ERR 0x02000000 /* Length Error */ 00266 #define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */ 00267 #define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */ 00268 #define RINFO_OVERRUN 0x10000000 /* Receive overrun */ 00269 #define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */ 00270 #define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */ 00271 #define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */ 00272 00273 //#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN) 00274 #define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_SYM_ERR | \ 00275 RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN) 00276 00277 00278 /* TX Descriptor Control Word */ 00279 #define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */ 00280 #define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */ 00281 #define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */ 00282 #define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */ 00283 #define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */ 00284 #define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */ 00285 #define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */ 00286 00287 /* TX Status Information Word */ 00288 #define TINFO_COL_CNT 0x01E00000 /* Collision Count */ 00289 #define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */ 00290 #define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */ 00291 #define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */ 00292 #define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */ 00293 #define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */ 00294 #define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */ 00295 #define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */ 00296 00297 /* ENET Device Revision ID */ 00298 #define OLD_EMAC_MODULE_ID 0x39022000 /* Rev. ID for first rev '-' */ 00299 00300 /* DP83848C PHY Registers */ 00301 #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */ 00302 #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */ 00303 #define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */ 00304 #define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */ 00305 #define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */ 00306 #define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */ 00307 #define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */ 00308 #define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */ 00309 00310 /* PHY Extended Registers */ 00311 #define PHY_REG_STS 0x10 /* Status Register */ 00312 #define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */ 00313 #define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */ 00314 #define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */ 00315 #define PHY_REG_RECR 0x15 /* Receive Error Counter */ 00316 #define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */ 00317 #define PHY_REG_RBR 0x17 /* RMII and Bypass Register */ 00318 #define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */ 00319 #define PHY_REG_PHYCR 0x19 /* PHY Control Register */ 00320 #define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */ 00321 #define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */ 00322 #define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */ 00323 00324 #define PHY_REG_SCSR 0x1F /* PHY Special Control/Status Register */ 00325 00326 #define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */ 00327 #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */ 00328 #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */ 00329 #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */ 00330 #define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */ 00331 00332 #define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */ 00333 #define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */ 00334 00335 #define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */ 00336 00337 #define PHY_STS_LINK 0x0001 /* PHY Status Link Mask */ 00338 #define PHY_STS_SPEED 0x0002 /* PHY Status Speed Mask */ 00339 #define PHY_STS_DUPLEX 0x0004 /* PHY Status Duplex Mask */ 00340 00341 #define PHY_BMCR_RESET 0x8000 /* PHY Reset */ 00342 00343 #define PHY_BMSR_LINK 0x0004 /* PHY BMSR Link valid */ 00344 00345 #define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */ 00346 #define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */ 00347 00348 00349 static int phy_read(unsigned int PhyReg); 00350 static int phy_write(unsigned int PhyReg, unsigned short Data); 00351 00352 static void txdscr_init(void); 00353 static void rxdscr_init(void); 00354 00355 #if defined (__ICCARM__) 00356 # define AHBSRAM1 00357 #elif defined(TOOLCHAIN_GCC_CR) 00358 # define AHBSRAM1 __attribute__((section(".data.$RamPeriph32"))) 00359 #else 00360 # define AHBSRAM1 __attribute__((section("AHBSRAM1"),aligned)) 00361 #endif 00362 00363 AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE]; 00364 AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE]; 00365 AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG]; 00366 AHBSRAM1 volatile RX_STAT_TypeDef rxstat[NUM_RX_FRAG]; 00367 AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG]; 00368 AHBSRAM1 volatile TX_STAT_TypeDef txstat[NUM_TX_FRAG]; 00369 00370 00371 #if NEW_LOGIC 00372 static int rx_consume_offset = -1; 00373 static int tx_produce_offset = -1; 00374 #else 00375 static int send_doff = 0; 00376 static int send_idx = -1; 00377 static int send_size = 0; 00378 00379 static int receive_soff = 0; 00380 static int receive_idx = -1; 00381 #endif 00382 00383 static uint32_t phy_id = 0; 00384 00385 static inline int rinc(int idx, int mod) { 00386 ++idx; 00387 idx %= mod; 00388 return idx; 00389 } 00390 00391 //extern unsigned int SystemFrequency; 00392 static inline unsigned int clockselect() { 00393 if(SystemCoreClock < 10000000) { 00394 return 1; 00395 } else if(SystemCoreClock < 15000000) { 00396 return 2; 00397 } else if(SystemCoreClock < 20000000) { 00398 return 3; 00399 } else if(SystemCoreClock < 25000000) { 00400 return 4; 00401 } else if(SystemCoreClock < 35000000) { 00402 return 5; 00403 } else if(SystemCoreClock < 50000000) { 00404 return 6; 00405 } else if(SystemCoreClock < 70000000) { 00406 return 7; 00407 } else if(SystemCoreClock < 80000000) { 00408 return 8; 00409 } else if(SystemCoreClock < 90000000) { 00410 return 9; 00411 } else if(SystemCoreClock < 100000000) { 00412 return 10; 00413 } else if(SystemCoreClock < 120000000) { 00414 return 11; 00415 } else if(SystemCoreClock < 130000000) { 00416 return 12; 00417 } else if(SystemCoreClock < 140000000) { 00418 return 13; 00419 } else if(SystemCoreClock < 150000000) { 00420 return 15; 00421 } else if(SystemCoreClock < 160000000) { 00422 return 16; 00423 } else { 00424 return 0; 00425 } 00426 } 00427 00428 #ifndef min 00429 #define min(x, y) (((x)<(y))?(x):(y)) 00430 #endif 00431 00432 /*---------------------------------------------------------------------------- 00433 Ethernet Device initialize 00434 *----------------------------------------------------------------------------*/ 00435 int ethernet_init() { 00436 int regv, tout; 00437 char mac[ETHERNET_ADDR_SIZE]; 00438 unsigned int clock = clockselect(); 00439 00440 LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */ 00441 00442 LPC_PINCON->PINSEL2 = 0x50150105; /* Enable P1 Ethernet Pins. */ 00443 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005; 00444 00445 /* Reset all EMAC internal modules. */ 00446 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | 00447 MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; 00448 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; 00449 00450 for(tout = 100; tout; tout--) __NOP(); /* A short delay after reset. */ 00451 00452 LPC_EMAC->MAC1 = MAC1_PASS_ALL; /* Initialize MAC control registers. */ 00453 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; 00454 LPC_EMAC->MAXF = ETH_MAX_FLEN; 00455 LPC_EMAC->CLRT = CLRT_DEF; 00456 LPC_EMAC->IPGR = IPGR_DEF; 00457 00458 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; /* Enable Reduced MII interface. */ 00459 00460 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */ 00461 LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */ 00462 00463 for(tout = 100; tout; tout--) __NOP(); /* A short delay */ 00464 00465 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; 00466 LPC_EMAC->MCMD = 0; 00467 00468 LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */ 00469 00470 for (tout = 100; tout; tout--) __NOP(); /* A short delay */ 00471 00472 LPC_EMAC->SUPP = 0; 00473 00474 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */ 00475 for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */ 00476 regv = phy_read(PHY_REG_BMCR); 00477 if(regv < 0 || tout == 0) { 00478 return -1; /* Error */ 00479 } 00480 if(!(regv & PHY_BMCR_RESET)) { 00481 break; /* Reset complete. */ 00482 } 00483 } 00484 00485 phy_id = (phy_read(PHY_REG_IDR1) << 16); 00486 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0); 00487 00488 if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) { 00489 error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id); 00490 } 00491 00492 ethernet_set_link(-1, 0); 00493 00494 /* Set the Ethernet MAC Address registers */ 00495 ethernet_address(mac); 00496 LPC_EMAC->SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4]; 00497 LPC_EMAC->SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2]; 00498 LPC_EMAC->SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0]; 00499 00500 txdscr_init(); /* initialize DMA TX Descriptor */ 00501 rxdscr_init(); /* initialize DMA RX Descriptor */ 00502 00503 LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; 00504 /* Receive Broadcast, Perfect Match Packets */ 00505 00506 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */ 00507 LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */ 00508 00509 00510 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */ 00511 LPC_EMAC->MAC1 |= MAC1_REC_EN; 00512 00513 #if NEW_LOGIC 00514 rx_consume_offset = -1; 00515 tx_produce_offset = -1; 00516 #else 00517 send_doff = 0; 00518 send_idx = -1; 00519 send_size = 0; 00520 00521 receive_soff = 0; 00522 receive_idx = -1; 00523 #endif 00524 00525 return 0; 00526 } 00527 00528 /*---------------------------------------------------------------------------- 00529 Ethernet Device Uninitialize 00530 *----------------------------------------------------------------------------*/ 00531 void ethernet_free() { 00532 LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE); 00533 LPC_EMAC->IntClear = 0xFFFF; 00534 00535 LPC_SC->PCONP &= ~0x40000000; /* Power down the EMAC controller. */ 00536 00537 LPC_PINCON->PINSEL2 &= ~0x50150105; /* Disable P1 ethernet pins. */ 00538 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000000; 00539 } 00540 00541 // if(TxProduceIndex == TxConsumeIndex) buffer array is empty 00542 // if(TxProduceIndex == TxConsumeIndex - 1) buffer is full, should not fill 00543 // TxProduceIndex - The buffer that will/is being fileld by driver, s/w increment 00544 // TxConsumeIndex - The buffer that will/is beign sent by hardware 00545 00546 int ethernet_write(const char *data, int slen) { 00547 00548 #if NEW_LOGIC 00549 00550 if(tx_produce_offset < 0) { // mark as active if not already 00551 tx_produce_offset = 0; 00552 } 00553 00554 int index = LPC_EMAC->TxProduceIndex; 00555 00556 int remaining = ETH_MAX_FLEN - tx_produce_offset - 4; // bytes written plus checksum 00557 int requested = slen; 00558 int ncopy = min(remaining, requested); 00559 00560 void *pdst = (void *)(txdesc[index].Packet + tx_produce_offset); 00561 void *psrc = (void *)(data); 00562 00563 if(ncopy > 0 ){ 00564 if(data != NULL) { 00565 memcpy(pdst, psrc, ncopy); 00566 } else { 00567 memset(pdst, 0, ncopy); 00568 } 00569 } 00570 00571 tx_produce_offset += ncopy; 00572 00573 return ncopy; 00574 00575 #else 00576 void *pdst, *psrc; 00577 const int dlen = ETH_FRAG_SIZE; 00578 int copy = 0; 00579 int soff = 0; 00580 00581 if(send_idx == -1) { 00582 send_idx = LPC_EMAC->TxProduceIndex; 00583 } 00584 00585 if(slen + send_doff > ethernet_MTU_SIZE) { 00586 return -1; 00587 } 00588 00589 do { 00590 copy = min(slen - soff, dlen - send_doff); 00591 pdst = (void *)(txdesc[send_idx].Packet + send_doff); 00592 psrc = (void *)(data + soff); 00593 if(send_doff + copy > ETH_FRAG_SIZE) { 00594 txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT); 00595 send_idx = rinc(send_idx, NUM_TX_FRAG); 00596 send_doff = 0; 00597 } 00598 00599 if(data != NULL) { 00600 memcpy(pdst, psrc, copy); 00601 } else { 00602 memset(pdst, 0, copy); 00603 } 00604 00605 soff += copy; 00606 send_doff += copy; 00607 send_size += copy; 00608 } while(soff != slen); 00609 00610 return soff; 00611 #endif 00612 } 00613 00614 int ethernet_send() { 00615 00616 #if NEW_LOGIC 00617 if(tx_produce_offset < 0) { // no buffer active 00618 return -1; 00619 } 00620 00621 // ensure there is a link 00622 if(!ethernet_link()) { 00623 return -2; 00624 } 00625 00626 // we have been writing in to a buffer, so finalise it 00627 int size = tx_produce_offset; 00628 int index = LPC_EMAC->TxProduceIndex; 00629 txdesc[index].Ctrl = (tx_produce_offset-1) | (TCTRL_INT | TCTRL_LAST); 00630 00631 // Increment ProduceIndex to allow it to be sent 00632 // We can only do this if the next slot is free 00633 int next = rinc(index, NUM_TX_FRAG); 00634 while(next == LPC_EMAC->TxConsumeIndex) { 00635 for(int i=0; i<1000; i++) { __NOP(); } 00636 } 00637 00638 LPC_EMAC->TxProduceIndex = next; 00639 tx_produce_offset = -1; 00640 return size; 00641 00642 #else 00643 int s = send_size; 00644 txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT | TCTRL_LAST); 00645 send_idx = rinc(send_idx, NUM_TX_FRAG); 00646 LPC_EMAC->TxProduceIndex = send_idx; 00647 send_doff = 0; 00648 send_idx = -1; 00649 send_size = 0; 00650 return s; 00651 #endif 00652 } 00653 00654 // RxConsmeIndex - The index of buffer the driver will/is reading from. Driver should inc once read 00655 // RxProduceIndex - The index of buffer that will/is being filled by MAC. H/w will inc once rxd 00656 // 00657 // if(RxConsumeIndex == RxProduceIndex) buffer array is empty 00658 // if(RxConsumeIndex == RxProduceIndex + 1) buffer array is full 00659 00660 // Recevies an arrived ethernet packet. 00661 // Receiving an ethernet packet will drop the last received ethernet packet 00662 // and make a new ethernet packet ready to read. 00663 // Returns size of packet, else 0 if nothing to receive 00664 00665 // We read from RxConsumeIndex from position rx_consume_offset 00666 // if rx_consume_offset < 0, then we have not recieved the RxConsumeIndex packet for reading 00667 // rx_consume_offset = -1 // no frame 00668 // rx_consume_offset = 0 // start of frame 00669 // Assumption: A fragment should alway be a whole frame 00670 00671 int ethernet_receive() { 00672 #if NEW_LOGIC 00673 00674 // if we are currently reading a valid RxConsume buffer, increment to the next one 00675 if(rx_consume_offset >= 0) { 00676 LPC_EMAC->RxConsumeIndex = rinc(LPC_EMAC->RxConsumeIndex, NUM_RX_FRAG); 00677 } 00678 00679 // if the buffer is empty, mark it as no valid buffer 00680 if(LPC_EMAC->RxConsumeIndex == LPC_EMAC->RxProduceIndex) { 00681 rx_consume_offset = -1; 00682 return 0; 00683 } 00684 00685 uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info; 00686 rx_consume_offset = 0; 00687 00688 // check if it is not marked as last or for errors 00689 if(!(info & RINFO_LAST_FLAG) || (info & RINFO_ERR_MASK)) { 00690 return -1; 00691 } 00692 00693 int size = (info & RINFO_SIZE) + 1; 00694 return size - 4; // don't include checksum bytes 00695 00696 #else 00697 if(receive_idx == -1) { 00698 receive_idx = LPC_EMAC->RxConsumeIndex; 00699 } else { 00700 while(!(rxstat[receive_idx].Info & RINFO_LAST_FLAG) && (receive_idx != LPC_EMAC->RxProduceIndex)) { 00701 receive_idx = rinc(receive_idx, NUM_RX_FRAG); 00702 } 00703 unsigned int info = rxstat[receive_idx].Info; 00704 int slen = (info & RINFO_SIZE) + 1; 00705 00706 if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) { 00707 /* Invalid frame, ignore it and free buffer. */ 00708 receive_idx = rinc(receive_idx, NUM_RX_FRAG); 00709 } 00710 receive_idx = rinc(receive_idx, NUM_RX_FRAG); 00711 receive_soff = 0; 00712 00713 LPC_EMAC->RxConsumeIndex = receive_idx; 00714 } 00715 00716 if(receive_idx == LPC_EMAC->RxProduceIndex) { 00717 receive_idx = -1; 00718 return 0; 00719 } 00720 00721 return (rxstat[receive_idx].Info & RINFO_SIZE) - 3; 00722 #endif 00723 } 00724 00725 // Read from an recevied ethernet packet. 00726 // After receive returnd a number bigger than 0 it is 00727 // possible to read bytes from this packet. 00728 // Read will write up to size bytes into data. 00729 // It is possible to use read multible times. 00730 // Each time read will start reading after the last read byte before. 00731 00732 int ethernet_read(char *data, int dlen) { 00733 #if NEW_LOGIC 00734 // Check we have a valid buffer to read 00735 if(rx_consume_offset < 0) { 00736 return 0; 00737 } 00738 00739 // Assume 1 fragment block 00740 uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info; 00741 int size = (info & RINFO_SIZE) + 1 - 4; // exclude checksum 00742 00743 int remaining = size - rx_consume_offset; 00744 int requested = dlen; 00745 int ncopy = min(remaining, requested); 00746 00747 void *psrc = (void *)(rxdesc[LPC_EMAC->RxConsumeIndex].Packet + rx_consume_offset); 00748 void *pdst = (void *)(data); 00749 00750 if(data != NULL && ncopy > 0) { 00751 memcpy(pdst, psrc, ncopy); 00752 } 00753 00754 rx_consume_offset += ncopy; 00755 00756 return ncopy; 00757 #else 00758 int slen; 00759 int copy = 0; 00760 unsigned int more; 00761 unsigned int info; 00762 void *pdst, *psrc; 00763 int doff = 0; 00764 00765 if(receive_idx == LPC_EMAC->RxProduceIndex || receive_idx == -1) { 00766 return 0; 00767 } 00768 00769 do { 00770 info = rxstat[receive_idx].Info; 00771 more = !(info & RINFO_LAST_FLAG); 00772 slen = (info & RINFO_SIZE) + 1; 00773 00774 if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) { 00775 /* Invalid frame, ignore it and free buffer. */ 00776 receive_idx = rinc(receive_idx, NUM_RX_FRAG); 00777 } else { 00778 00779 copy = min(slen - receive_soff, dlen - doff); 00780 psrc = (void *)(rxdesc[receive_idx].Packet + receive_soff); 00781 pdst = (void *)(data + doff); 00782 00783 if(data != NULL) { 00784 /* check if Buffer available */ 00785 memcpy(pdst, psrc, copy); 00786 } 00787 00788 receive_soff += copy; 00789 doff += copy; 00790 00791 if((more && (receive_soff == slen))) { 00792 receive_idx = rinc(receive_idx, NUM_RX_FRAG); 00793 receive_soff = 0; 00794 } 00795 } 00796 } while(more && !(doff == dlen) && !receive_soff); 00797 00798 return doff; 00799 #endif 00800 } 00801 00802 int ethernet_link(void) { 00803 if (phy_id == DP83848C_ID) { 00804 return (phy_read(PHY_REG_STS) & PHY_STS_LINK); 00805 } 00806 else { // LAN8720_ID 00807 return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK); 00808 } 00809 } 00810 00811 static int phy_write(unsigned int PhyReg, unsigned short Data) { 00812 unsigned int timeOut; 00813 00814 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg; 00815 LPC_EMAC->MWTD = Data; 00816 00817 for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */ 00818 if((LPC_EMAC->MIND & MIND_BUSY) == 0) { 00819 return 0; 00820 } 00821 } 00822 00823 return -1; 00824 } 00825 00826 static int phy_read(unsigned int PhyReg) { 00827 unsigned int timeOut; 00828 00829 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg; 00830 LPC_EMAC->MCMD = MCMD_READ; 00831 00832 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */ 00833 if((LPC_EMAC->MIND & MIND_BUSY) == 0) { 00834 LPC_EMAC->MCMD = 0; 00835 return LPC_EMAC->MRDD; /* Return a 16-bit value. */ 00836 } 00837 } 00838 00839 return -1; 00840 } 00841 00842 00843 static void txdscr_init() { 00844 int i; 00845 00846 for(i = 0; i < NUM_TX_FRAG; i++) { 00847 txdesc[i].Packet = (uint32_t)&txbuf[i]; 00848 txdesc[i].Ctrl = 0; 00849 txstat[i].Info = 0; 00850 } 00851 00852 LPC_EMAC->TxDescriptor = (uint32_t)txdesc; /* Set EMAC Transmit Descriptor Registers. */ 00853 LPC_EMAC->TxStatus = (uint32_t)txstat; 00854 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1; 00855 00856 LPC_EMAC->TxProduceIndex = 0; /* Tx Descriptors Point to 0 */ 00857 } 00858 00859 static void rxdscr_init() { 00860 int i; 00861 00862 for(i = 0; i < NUM_RX_FRAG; i++) { 00863 rxdesc[i].Packet = (uint32_t)&rxbuf[i]; 00864 rxdesc[i].Ctrl = RCTRL_INT | (ETH_FRAG_SIZE-1); 00865 rxstat[i].Info = 0; 00866 rxstat[i].HashCRC = 0; 00867 } 00868 00869 LPC_EMAC->RxDescriptor = (uint32_t)rxdesc; /* Set EMAC Receive Descriptor Registers. */ 00870 LPC_EMAC->RxStatus = (uint32_t)rxstat; 00871 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1; 00872 00873 LPC_EMAC->RxConsumeIndex = 0; /* Rx Descriptors Point to 0 */ 00874 } 00875 00876 void ethernet_address(char *mac) { 00877 mbed_mac_address(mac); 00878 } 00879 00880 void ethernet_set_link(int speed, int duplex) { 00881 unsigned short phy_data; 00882 int tout; 00883 00884 if((speed < 0) || (speed > 1)) { 00885 phy_data = PHY_AUTO_NEG; 00886 } else { 00887 phy_data = (((unsigned short) speed << 13) | 00888 ((unsigned short) duplex << 8)); 00889 } 00890 00891 phy_write(PHY_REG_BMCR, phy_data); 00892 00893 for(tout = 100; tout; tout--) { __NOP(); } /* A short delay */ 00894 00895 switch(phy_id) { 00896 case DP83848C_ID: 00897 phy_data = phy_read(PHY_REG_STS); 00898 00899 if(phy_data & PHY_STS_DUPLEX) { 00900 LPC_EMAC->MAC2 |= MAC2_FULL_DUP; 00901 LPC_EMAC->Command |= CR_FULL_DUP; 00902 LPC_EMAC->IPGT = IPGT_FULL_DUP; 00903 } else { 00904 LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP; 00905 LPC_EMAC->Command &= ~CR_FULL_DUP; 00906 LPC_EMAC->IPGT = IPGT_HALF_DUP; 00907 } 00908 00909 if(phy_data & PHY_STS_SPEED) { 00910 LPC_EMAC->SUPP &= ~SUPP_SPEED; 00911 } else { 00912 LPC_EMAC->SUPP |= SUPP_SPEED; 00913 } 00914 break; 00915 00916 case LAN8720_ID: 00917 phy_data = phy_read(PHY_REG_SCSR); 00918 00919 if (phy_data & PHY_SCSR_DUPLEX) { 00920 LPC_EMAC->MAC2 |= MAC2_FULL_DUP; 00921 LPC_EMAC->Command |= CR_FULL_DUP; 00922 LPC_EMAC->IPGT = IPGT_FULL_DUP; 00923 } else { 00924 LPC_EMAC->Command &= ~CR_FULL_DUP; 00925 LPC_EMAC->IPGT = IPGT_HALF_DUP; 00926 } 00927 00928 if(phy_data & PHY_SCSR_100MBIT) { 00929 LPC_EMAC->SUPP |= SUPP_SPEED; 00930 } else { 00931 LPC_EMAC->SUPP &= ~SUPP_SPEED; 00932 } 00933 break; 00934 } 00935 }
Generated on Tue Jul 12 2022 13:47:00 by
1.7.2
