mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed Microcontroller Library
elessair 0:f269e3021894 2 * Copyright (c) 2006-2015 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 *
elessair 0:f269e3021894 16 * Contribution by Nitin Bhaskar(nitin.bhaskar.27.09@gmail.com)
elessair 0:f269e3021894 17 */
elessair 0:f269e3021894 18 #include "ethernet_api.h"
elessair 0:f269e3021894 19
elessair 0:f269e3021894 20 #include <string.h>
elessair 0:f269e3021894 21 #include "cmsis.h"
elessair 0:f269e3021894 22 #include "mbed_interface.h"
elessair 0:f269e3021894 23 #include "toolchain.h"
elessair 0:f269e3021894 24 #include "mbed_error.h"
elessair 0:f269e3021894 25 #include "pinmap.h"
elessair 0:f269e3021894 26
elessair 0:f269e3021894 27 #define NEW_LOGIC 0
elessair 0:f269e3021894 28 #define NEW_ETH_BUFFER 0
elessair 0:f269e3021894 29
elessair 0:f269e3021894 30 #if NEW_ETH_BUFFER
elessair 0:f269e3021894 31
elessair 0:f269e3021894 32 #define NUM_RX_FRAG 4 // Number of Rx Fragments (== packets)
elessair 0:f269e3021894 33 #define NUM_TX_FRAG 3 // Number of Tx Fragments (== packets)
elessair 0:f269e3021894 34
elessair 0:f269e3021894 35 #define ETH_MAX_FLEN 1536 // Maximum Ethernet Frame Size
elessair 0:f269e3021894 36 #define ETH_FRAG_SIZE ETH_MAX_FLEN // Packet Fragment size (same as packet length)
elessair 0:f269e3021894 37
elessair 0:f269e3021894 38 #else
elessair 0:f269e3021894 39
elessair 0:f269e3021894 40 // Memfree calculation:
elessair 0:f269e3021894 41 // (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) +
elessair 0:f269e3021894 42 // (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556
elessair 0:f269e3021894 43 /* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
elessair 0:f269e3021894 44 #define NUM_RX_FRAG 4 /* Num.of RX Fragments 4*1536= 6.0kB */
elessair 0:f269e3021894 45 #define NUM_TX_FRAG 3 /* Num.of TX Fragments 3*1536= 4.6kB */
elessair 0:f269e3021894 46 //#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */
elessair 0:f269e3021894 47
elessair 0:f269e3021894 48 //#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */
elessair 0:f269e3021894 49 #define ETH_FRAG_SIZE 0x300 /* Packet Fragment size 1536/2 Bytes */
elessair 0:f269e3021894 50 #define ETH_MAX_FLEN 0x300 /* Max. Ethernet Frame Size */
elessair 0:f269e3021894 51
elessair 0:f269e3021894 52 const int ethernet_MTU_SIZE = 0x300;
elessair 0:f269e3021894 53
elessair 0:f269e3021894 54 #endif
elessair 0:f269e3021894 55
elessair 0:f269e3021894 56 #define ETHERNET_ADDR_SIZE 6
elessair 0:f269e3021894 57
elessair 0:f269e3021894 58 /* Descriptors Fields bits */
elessair 0:f269e3021894 59 #define TRDES_OWN_BIT (1U<<31) /* Own bit in RDES0 & TDES0 */
elessair 0:f269e3021894 60 #define RX_END_RING (1<<15) /* Receive End of Ring bit in RDES1 */
elessair 0:f269e3021894 61 #define RX_NXTDESC_FLAG (1<<14) /* Second Address Chained bit in RDES1 */
elessair 0:f269e3021894 62 #define TX_LAST_SEGM (1<<29) /* Last Segment bit in TDES0 */
elessair 0:f269e3021894 63 #define TX_FIRST_SEGM (1<<28) /* First Segment bit in TDES0 */
elessair 0:f269e3021894 64 #define TX_END_RING (1<<21) /* Transmit End of Ring bit in TDES0 */
elessair 0:f269e3021894 65 #define TX_NXTDESC_FLAG (1<<20) /* Second Address Chained bit in TDES0 */
elessair 0:f269e3021894 66
elessair 0:f269e3021894 67 PACKED struct RX_DESC_TypeDef { /* RX Descriptor struct */
elessair 0:f269e3021894 68 unsigned int Status;
elessair 0:f269e3021894 69 unsigned int Ctrl;
elessair 0:f269e3021894 70 unsigned int BufAddr1;
elessair 0:f269e3021894 71 unsigned int NextDescAddr;
elessair 0:f269e3021894 72 };
elessair 0:f269e3021894 73 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
elessair 0:f269e3021894 74
elessair 0:f269e3021894 75 PACKED struct TX_DESC_TypeDef { /* TX Descriptor struct */
elessair 0:f269e3021894 76 unsigned int Status;
elessair 0:f269e3021894 77 unsigned int Ctrl;
elessair 0:f269e3021894 78 unsigned int BufAddr1;
elessair 0:f269e3021894 79 unsigned int NextDescAddr;
elessair 0:f269e3021894 80 };
elessair 0:f269e3021894 81 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
elessair 0:f269e3021894 82
elessair 0:f269e3021894 83 /* ETHMODE RMII SELECT */
elessair 0:f269e3021894 84 #define RMII_SELECT 0x04
elessair 0:f269e3021894 85 /* define to tell PHY about write operation */
elessair 0:f269e3021894 86 #define MII_WRITE (1 << 1)
elessair 0:f269e3021894 87 /* define to tell PHY about read operation */
elessair 0:f269e3021894 88 #define MII_READ (0 << 1)
elessair 0:f269e3021894 89 /* define to enable duplex mode */
elessair 0:f269e3021894 90 #define MAC_DUPLEX_MODE (1 << 11)
elessair 0:f269e3021894 91
elessair 0:f269e3021894 92 /* MAC_FRAME_FILTER register bit defines */
elessair 0:f269e3021894 93 #define MAC_FRAME_FILTER_PR (1 << 0) /* Promiscuous Mode */
elessair 0:f269e3021894 94 #define MAC_FRAME_FILTER_RA (1UL << 31) /* Receive all */
elessair 0:f269e3021894 95
elessair 0:f269e3021894 96 /* MAC_CONFIG register bit defines */
elessair 0:f269e3021894 97 #define MAC_CONFIG_RE (1 << 2) /* Receiver enable */
elessair 0:f269e3021894 98 #define MAC_CONFIG_TE (1 << 3) /* Transmitter Enable */
elessair 0:f269e3021894 99
elessair 0:f269e3021894 100 /* DMA_OP_MODE register bit defines */
elessair 0:f269e3021894 101 #define DMA_OP_MODE_SSR (1 << 1) /* Start/stop receive */
elessair 0:f269e3021894 102 #define DMA_OP_MODE_SST (1 << 13) /* Start/Stop Transmission Command */
elessair 0:f269e3021894 103
elessair 0:f269e3021894 104 /* DMA_INT_EN register bit defines */
elessair 0:f269e3021894 105 #define DMA_INT_EN_TIE (1 << 0) /* Transmit interrupt enable */
elessair 0:f269e3021894 106 #define DMA_INT_EN_TSE (1 << 1) /* Transmit stopped enable */
elessair 0:f269e3021894 107 #define DMA_INT_EN_TUE (1 << 2) /* Transmit buffer unavailable enable */
elessair 0:f269e3021894 108 #define DMA_INT_EN_TJE (1 << 3) /* Transmit jabber timeout enable */
elessair 0:f269e3021894 109 #define DMA_INT_EN_OVE (1 << 4) /* Overflow interrupt enable */
elessair 0:f269e3021894 110 #define DMA_INT_EN_UNE (1 << 5) /* Underflow interrupt enable */
elessair 0:f269e3021894 111 #define DMA_INT_EN_RIE (1 << 6) /* Receive interrupt enable */
elessair 0:f269e3021894 112 #define DMA_INT_EN_RUE (1 << 7) /* Receive buffer unavailable enable */
elessair 0:f269e3021894 113 #define DMA_INT_EN_RSE (1 << 8) /* Received stopped enable */
elessair 0:f269e3021894 114 #define DMA_INT_EN_RWE (1 << 9) /* Receive watchdog timeout enable */
elessair 0:f269e3021894 115 #define DMA_INT_EN_ETE (1 << 10) /* Early transmit interrupt enable */
elessair 0:f269e3021894 116 #define DMA_INT_EN_FBE (1 << 13) /* Fatal bus error enable */
elessair 0:f269e3021894 117 #define DMA_INT_EN_ERE (1 << 14) /* Early receive interrupt enable */
elessair 0:f269e3021894 118 #define DMA_INT_EN_AIE (1 << 15) /* Abnormal interrupt summary enable */
elessair 0:f269e3021894 119 #define DMA_INT_EN_NIE (1 << 16) /* Normal interrupt summary enable */
elessair 0:f269e3021894 120
elessair 0:f269e3021894 121
elessair 0:f269e3021894 122
elessair 0:f269e3021894 123 /* PHY Support Register */
elessair 0:f269e3021894 124 #define SUPP_SPEED 0x00004000 /* Reduced MII Logic Current Speed */
elessair 0:f269e3021894 125 //#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */
elessair 0:f269e3021894 126 #define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */
elessair 0:f269e3021894 127
elessair 0:f269e3021894 128 /* MII Management Command Register */
elessair 0:f269e3021894 129 #define MCMD_READ 0x00000001 /* MII Read */
elessair 0:f269e3021894 130 #define MCMD_SCAN 0x00000002 /* MII Scan continuously */
elessair 0:f269e3021894 131
elessair 0:f269e3021894 132 #define MII_WR_TOUT 0x00050000 /* MII Write timeout count */
elessair 0:f269e3021894 133 #define MII_RD_TOUT 0x00050000 /* MII Read timeout count */
elessair 0:f269e3021894 134
elessair 0:f269e3021894 135 /* MII Management Address Register */
elessair 0:f269e3021894 136 #define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */
elessair 0:f269e3021894 137 #define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */
elessair 0:f269e3021894 138
elessair 0:f269e3021894 139 /* MII Management Indicators Register */
elessair 0:f269e3021894 140 #define MIND_BUSY 0x00000001 /* MII is Busy */
elessair 0:f269e3021894 141 #define MIND_SCAN 0x00000002 /* MII Scanning in Progress */
elessair 0:f269e3021894 142 #define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */
elessair 0:f269e3021894 143 #define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */
elessair 0:f269e3021894 144
elessair 0:f269e3021894 145 /* DP83848C PHY Registers */
elessair 0:f269e3021894 146 #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
elessair 0:f269e3021894 147 #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
elessair 0:f269e3021894 148 #define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
elessair 0:f269e3021894 149 #define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
elessair 0:f269e3021894 150 #define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
elessair 0:f269e3021894 151 #define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
elessair 0:f269e3021894 152 #define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
elessair 0:f269e3021894 153 #define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
elessair 0:f269e3021894 154
elessair 0:f269e3021894 155 /* PHY Extended Registers */
elessair 0:f269e3021894 156 #define PHY_REG_STS 0x10 /* Status Register */
elessair 0:f269e3021894 157 #define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
elessair 0:f269e3021894 158 #define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
elessair 0:f269e3021894 159 #define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
elessair 0:f269e3021894 160 #define PHY_REG_RECR 0x15 /* Receive Error Counter */
elessair 0:f269e3021894 161 #define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
elessair 0:f269e3021894 162 #define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
elessair 0:f269e3021894 163 #define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
elessair 0:f269e3021894 164 #define PHY_REG_PHYCR 0x19 /* PHY Control Register */
elessair 0:f269e3021894 165 #define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
elessair 0:f269e3021894 166 #define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
elessair 0:f269e3021894 167 #define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
elessair 0:f269e3021894 168
elessair 0:f269e3021894 169 #define PHY_REG_SCSR 0x1F /* PHY Special Control/Status Register */
elessair 0:f269e3021894 170
elessair 0:f269e3021894 171 #define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
elessair 0:f269e3021894 172 #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
elessair 0:f269e3021894 173 #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
elessair 0:f269e3021894 174 #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
elessair 0:f269e3021894 175 #define PHY_AUTO_NEG 0x1000 /* Select Auto Negotiation */
elessair 0:f269e3021894 176
elessair 0:f269e3021894 177 #define DP83848C_DEF_ADR 0x01 /* Default PHY device address */
elessair 0:f269e3021894 178 #define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */
elessair 0:f269e3021894 179
elessair 0:f269e3021894 180 #define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */
elessair 0:f269e3021894 181
elessair 0:f269e3021894 182 #define PHY_STS_LINK 0x0001 /* PHY Status Link Mask */
elessair 0:f269e3021894 183 #define PHY_STS_SPEED 0x0002 /* PHY Status Speed Mask */
elessair 0:f269e3021894 184 #define PHY_STS_DUPLEX 0x0004 /* PHY Status Duplex Mask */
elessair 0:f269e3021894 185
elessair 0:f269e3021894 186 #define PHY_BMCR_RESET 0x8000 /* PHY Reset */
elessair 0:f269e3021894 187
elessair 0:f269e3021894 188 #define PHY_BMSR_LINK 0x0004 /* PHY BMSR Link valid */
elessair 0:f269e3021894 189
elessair 0:f269e3021894 190 #define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */
elessair 0:f269e3021894 191 #define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */
elessair 0:f269e3021894 192
elessair 0:f269e3021894 193 static int phy_read(unsigned int PhyReg);
elessair 0:f269e3021894 194 static int phy_write(unsigned int PhyReg, unsigned short Data);
elessair 0:f269e3021894 195
elessair 0:f269e3021894 196 static void txdscr_init(void);
elessair 0:f269e3021894 197 static void rxdscr_init(void);
elessair 0:f269e3021894 198
elessair 0:f269e3021894 199 #if defined (__ICCARM__)
elessair 0:f269e3021894 200 # define AHBSRAM1
elessair 0:f269e3021894 201 #elif defined(TOOLCHAIN_GCC_CR)
elessair 0:f269e3021894 202 # define AHBSRAM1 __attribute__((section(".data.$RamPeriph32")))
elessair 0:f269e3021894 203 #else
elessair 0:f269e3021894 204 # define AHBSRAM1 __attribute__((section("AHBSRAM1"),aligned))
elessair 0:f269e3021894 205 #endif
elessair 0:f269e3021894 206
elessair 0:f269e3021894 207 AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE];
elessair 0:f269e3021894 208 AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE];
elessair 0:f269e3021894 209 AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG];
elessair 0:f269e3021894 210 AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG];
elessair 0:f269e3021894 211
elessair 0:f269e3021894 212 #ifndef min
elessair 0:f269e3021894 213 #define min(x, y) (((x)<(y))?(x):(y))
elessair 0:f269e3021894 214 #endif
elessair 0:f269e3021894 215
elessair 0:f269e3021894 216 static uint32_t phy_id = 0;
elessair 0:f269e3021894 217 static uint32_t TxDescIndex = 0;
elessair 0:f269e3021894 218 static uint32_t RxDescIndex = 0;
elessair 0:f269e3021894 219 static uint32_t RxOffset = 0;
elessair 0:f269e3021894 220
elessair 0:f269e3021894 221 /*----------------------------------------------------------------------------
elessair 0:f269e3021894 222 Ethernet Device initialize
elessair 0:f269e3021894 223 *----------------------------------------------------------------------------*/
elessair 0:f269e3021894 224 int ethernet_init()
elessair 0:f269e3021894 225 {
elessair 0:f269e3021894 226 int regv, tout;
elessair 0:f269e3021894 227 char mac[ETHERNET_ADDR_SIZE];
elessair 0:f269e3021894 228
elessair 0:f269e3021894 229 pin_function(PC_0, (SCU_MODE_INACT | FUNC3)); /* Enable ENET RX CLK */
elessair 0:f269e3021894 230 pin_function(P1_19, (SCU_MODE_INACT | FUNC0)); /* Enable ENET TX CLK */
elessair 0:f269e3021894 231
elessair 0:f269e3021894 232 /* Ethernet pinmuxing */
elessair 0:f269e3021894 233 pin_function(P2_0, SCU_PINIO_FAST | FUNC7); /* ENET_MDC */
elessair 0:f269e3021894 234 pin_function(P1_17, SCU_PINIO_FAST | FUNC3); /* ENET_MDIO */
elessair 0:f269e3021894 235 pin_function(P1_18, SCU_PINIO_FAST | FUNC3); /* ENET_TXD0 */
elessair 0:f269e3021894 236 pin_function(P1_20, SCU_PINIO_FAST | FUNC3); /* ENET_TXD1 */
elessair 0:f269e3021894 237 pin_function(P1_19, SCU_PINIO_FAST | FUNC0); /* ENET_REF */
elessair 0:f269e3021894 238 pin_function(P0_1, SCU_PINIO_FAST | FUNC6); /* ENET_TX_EN */
elessair 0:f269e3021894 239 pin_function(P1_15, SCU_PINIO_FAST | FUNC3); /* ENET_RXD0 */
elessair 0:f269e3021894 240 pin_function(P0_0, SCU_PINIO_FAST | FUNC2); /* ENET_RXD1 */
elessair 0:f269e3021894 241 pin_function(P1_16, SCU_PINIO_FAST | FUNC3); /* ENET_CRS */
elessair 0:f269e3021894 242 pin_function(PC_9, SCU_PINIO_FAST | FUNC3); /* ENET_RX_ER */
elessair 0:f269e3021894 243 pin_function(P1_16, SCU_PINIO_FAST | FUNC7); /* ENET_RXDV */
elessair 0:f269e3021894 244
elessair 0:f269e3021894 245 LPC_CREG->CREG6 |= RMII_SELECT;
elessair 0:f269e3021894 246
elessair 0:f269e3021894 247 /* perform RGU soft reset */
elessair 0:f269e3021894 248 LPC_RGU->RESET_CTRL0 = 1 << 22;
elessair 0:f269e3021894 249 LPC_RGU->RESET_CTRL0 = 0;
elessair 0:f269e3021894 250
elessair 0:f269e3021894 251 /* Wait until reset is performed */
elessair 0:f269e3021894 252 while(1) {
elessair 0:f269e3021894 253 if (LPC_RGU->RESET_ACTIVE_STATUS0 & (1 << 22))
elessair 0:f269e3021894 254 break;
elessair 0:f269e3021894 255 }
elessair 0:f269e3021894 256
elessair 0:f269e3021894 257 /* Reset MAC DMA Controller */
elessair 0:f269e3021894 258 LPC_ETHERNET->DMA_BUS_MODE |= 0x01;
elessair 0:f269e3021894 259 while(LPC_ETHERNET->DMA_BUS_MODE & 0x01);
elessair 0:f269e3021894 260
elessair 0:f269e3021894 261 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */
elessair 0:f269e3021894 262
elessair 0:f269e3021894 263 for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */
elessair 0:f269e3021894 264 regv = phy_read(PHY_REG_BMCR);
elessair 0:f269e3021894 265 if(regv < 0 || tout == 0) {
elessair 0:f269e3021894 266 return -1; /* Error */
elessair 0:f269e3021894 267 }
elessair 0:f269e3021894 268 if(!(regv & PHY_BMCR_RESET)) {
elessair 0:f269e3021894 269 break; /* Reset complete. */
elessair 0:f269e3021894 270 }
elessair 0:f269e3021894 271 }
elessair 0:f269e3021894 272
elessair 0:f269e3021894 273 phy_id = (phy_read(PHY_REG_IDR1) << 16);
elessair 0:f269e3021894 274 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
elessair 0:f269e3021894 275
elessair 0:f269e3021894 276 if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) {
elessair 0:f269e3021894 277 error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
elessair 0:f269e3021894 278 }
elessair 0:f269e3021894 279
elessair 0:f269e3021894 280 ethernet_set_link(-1, 0);
elessair 0:f269e3021894 281
elessair 0:f269e3021894 282 /* Set the Ethernet MAC Address registers */
elessair 0:f269e3021894 283 ethernet_address(mac);
elessair 0:f269e3021894 284 LPC_ETHERNET->MAC_ADDR0_HIGH = (mac[5] << 8) | mac[4];
elessair 0:f269e3021894 285 LPC_ETHERNET->MAC_ADDR0_LOW = (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0];
elessair 0:f269e3021894 286
elessair 0:f269e3021894 287 txdscr_init(); /* initialize DMA TX Descriptor */
elessair 0:f269e3021894 288 rxdscr_init(); /* initialize DMA RX Descriptor */
elessair 0:f269e3021894 289
elessair 0:f269e3021894 290 /* Configure Filter */
elessair 0:f269e3021894 291 LPC_ETHERNET->MAC_FRAME_FILTER = MAC_FRAME_FILTER_PR | MAC_FRAME_FILTER_RA;
elessair 0:f269e3021894 292
elessair 0:f269e3021894 293 /* Enable Receiver and Transmitter */
elessair 0:f269e3021894 294 LPC_ETHERNET->MAC_CONFIG |= (MAC_CONFIG_RE | MAC_CONFIG_TE);
elessair 0:f269e3021894 295
elessair 0:f269e3021894 296 //LPC_ETHERNET->DMA_INT_EN = DMA_INT_EN_NIE | DMA_INT_EN_RIE | DMA_INT_EN_TJE; /* Enable EMAC interrupts. */
elessair 0:f269e3021894 297
elessair 0:f269e3021894 298 /* Start Transmission & Receive processes */
elessair 0:f269e3021894 299 LPC_ETHERNET->DMA_OP_MODE |= (DMA_OP_MODE_SST | DMA_OP_MODE_SSR);
elessair 0:f269e3021894 300
elessair 0:f269e3021894 301 return 0;
elessair 0:f269e3021894 302 }
elessair 0:f269e3021894 303
elessair 0:f269e3021894 304 /*----------------------------------------------------------------------------
elessair 0:f269e3021894 305 Ethernet Device Uninitialize
elessair 0:f269e3021894 306 *----------------------------------------------------------------------------*/
elessair 0:f269e3021894 307 void ethernet_free()
elessair 0:f269e3021894 308 {
elessair 0:f269e3021894 309 }
elessair 0:f269e3021894 310
elessair 0:f269e3021894 311 /*----------------------------------------------------------------------------
elessair 0:f269e3021894 312 Ethernet write
elessair 0:f269e3021894 313 *----------------------------------------------------------------------------*/
elessair 0:f269e3021894 314 int ethernet_write(const char *data, int slen)
elessair 0:f269e3021894 315 {
elessair 0:f269e3021894 316 if (slen > ETH_FRAG_SIZE)
elessair 0:f269e3021894 317 return -1;
elessair 0:f269e3021894 318
elessair 0:f269e3021894 319 txdesc[TxDescIndex].Ctrl = slen;
elessair 0:f269e3021894 320 memcpy((void *)txdesc[TxDescIndex].BufAddr1, data, slen);
elessair 0:f269e3021894 321 return slen;
elessair 0:f269e3021894 322 }
elessair 0:f269e3021894 323
elessair 0:f269e3021894 324 /*----------------------------------------------------------------------------
elessair 0:f269e3021894 325 Ethernet Send
elessair 0:f269e3021894 326 *----------------------------------------------------------------------------*/
elessair 0:f269e3021894 327 int ethernet_send()
elessair 0:f269e3021894 328 {
elessair 0:f269e3021894 329 int s = txdesc[TxDescIndex].Ctrl;
elessair 0:f269e3021894 330 txdesc[TxDescIndex].Status |= TRDES_OWN_BIT;
elessair 0:f269e3021894 331 LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1; // Wake Up the DMA if it's in Suspended Mode
elessair 0:f269e3021894 332 TxDescIndex++;
elessair 0:f269e3021894 333 if (TxDescIndex == NUM_TX_FRAG)
elessair 0:f269e3021894 334 TxDescIndex = 0;
elessair 0:f269e3021894 335
elessair 0:f269e3021894 336 return s;
elessair 0:f269e3021894 337 }
elessair 0:f269e3021894 338
elessair 0:f269e3021894 339 /*----------------------------------------------------------------------------
elessair 0:f269e3021894 340 Ethernet receive
elessair 0:f269e3021894 341 *----------------------------------------------------------------------------*/
elessair 0:f269e3021894 342 int ethernet_receive()
elessair 0:f269e3021894 343 {
elessair 0:f269e3021894 344 int i, slen = 0;
elessair 0:f269e3021894 345 for (i = RxDescIndex;; i++) {
elessair 0:f269e3021894 346 if (rxdesc[i].Status & TRDES_OWN_BIT)
elessair 0:f269e3021894 347 return (slen - RxOffset);
elessair 0:f269e3021894 348 else
elessair 0:f269e3021894 349 slen += (rxdesc[i].Status >> 16) & 0x03FFF;
elessair 0:f269e3021894 350 }
elessair 0:f269e3021894 351 return 0;
elessair 0:f269e3021894 352 }
elessair 0:f269e3021894 353
elessair 0:f269e3021894 354
elessair 0:f269e3021894 355 /*----------------------------------------------------------------------------
elessair 0:f269e3021894 356 Ethernet read
elessair 0:f269e3021894 357 *----------------------------------------------------------------------------*/
elessair 0:f269e3021894 358 int ethernet_read(char *data, int dlen)
elessair 0:f269e3021894 359 {
elessair 0:f269e3021894 360 int copylen;
elessair 0:f269e3021894 361 uint32_t *pSrc = (uint32_t *)rxdesc[RxDescIndex].BufAddr1;
elessair 0:f269e3021894 362 copylen = (rxdesc[RxDescIndex].Status >> 16) & 0x03FFF;
elessair 0:f269e3021894 363 if (rxdesc[RxDescIndex].Status & TRDES_OWN_BIT || (dlen + RxOffset) > copylen)
elessair 0:f269e3021894 364 return -1;
elessair 0:f269e3021894 365
elessair 0:f269e3021894 366 if ((dlen + RxOffset) == copylen) {
elessair 0:f269e3021894 367 memcpy(&pSrc[RxOffset], data, copylen);
elessair 0:f269e3021894 368 rxdesc[RxDescIndex].Status = TRDES_OWN_BIT;
elessair 0:f269e3021894 369 RxDescIndex++;
elessair 0:f269e3021894 370 RxOffset = 0;
elessair 0:f269e3021894 371 if (RxDescIndex == NUM_RX_FRAG)
elessair 0:f269e3021894 372 RxDescIndex = 0;
elessair 0:f269e3021894 373 } else if ((dlen + RxOffset) < copylen) {
elessair 0:f269e3021894 374 copylen = dlen;
elessair 0:f269e3021894 375 memcpy(&pSrc[RxOffset], data, copylen);
elessair 0:f269e3021894 376 RxOffset += dlen;
elessair 0:f269e3021894 377 }
elessair 0:f269e3021894 378 return copylen;
elessair 0:f269e3021894 379 }
elessair 0:f269e3021894 380
elessair 0:f269e3021894 381 int ethernet_link(void)
elessair 0:f269e3021894 382 {
elessair 0:f269e3021894 383
elessair 0:f269e3021894 384 if (phy_id == DP83848C_ID) {
elessair 0:f269e3021894 385 return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
elessair 0:f269e3021894 386 } else { // LAN8720_ID
elessair 0:f269e3021894 387 return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
elessair 0:f269e3021894 388 }
elessair 0:f269e3021894 389 }
elessair 0:f269e3021894 390
elessair 0:f269e3021894 391 static int phy_write(unsigned int PhyReg, unsigned short Data)
elessair 0:f269e3021894 392 {
elessair 0:f269e3021894 393 unsigned int timeOut;
elessair 0:f269e3021894 394
elessair 0:f269e3021894 395 while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY);
elessair 0:f269e3021894 396 LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_WRITE;
elessair 0:f269e3021894 397 LPC_ETHERNET->MAC_MII_DATA = Data;
elessair 0:f269e3021894 398 LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY; // Start PHY Write Cycle
elessair 0:f269e3021894 399
elessair 0:f269e3021894 400 /* Wait utill operation completed */
elessair 0:f269e3021894 401 for (timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) {
elessair 0:f269e3021894 402 if ((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) {
elessair 0:f269e3021894 403 break;
elessair 0:f269e3021894 404 }
elessair 0:f269e3021894 405 }
elessair 0:f269e3021894 406
elessair 0:f269e3021894 407 return -1;
elessair 0:f269e3021894 408 }
elessair 0:f269e3021894 409
elessair 0:f269e3021894 410 static int phy_read(unsigned int PhyReg)
elessair 0:f269e3021894 411 {
elessair 0:f269e3021894 412 unsigned int timeOut;
elessair 0:f269e3021894 413
elessair 0:f269e3021894 414 while(LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY);
elessair 0:f269e3021894 415 LPC_ETHERNET->MAC_MII_ADDR = (DP83848C_DEF_ADR<<11) | (PhyReg<<6) | MII_READ;
elessair 0:f269e3021894 416 LPC_ETHERNET->MAC_MII_ADDR |= MIND_BUSY;
elessair 0:f269e3021894 417
elessair 0:f269e3021894 418 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */
elessair 0:f269e3021894 419 if((LPC_ETHERNET->MAC_MII_ADDR & MIND_BUSY) == 0) {
elessair 0:f269e3021894 420 return LPC_ETHERNET->MAC_MII_DATA; /* Return a 16-bit value. */
elessair 0:f269e3021894 421 }
elessair 0:f269e3021894 422 }
elessair 0:f269e3021894 423
elessair 0:f269e3021894 424 return -1;
elessair 0:f269e3021894 425 }
elessair 0:f269e3021894 426
elessair 0:f269e3021894 427 static void txdscr_init()
elessair 0:f269e3021894 428 {
elessair 0:f269e3021894 429 int i;
elessair 0:f269e3021894 430
elessair 0:f269e3021894 431 for(i = 0; i < NUM_TX_FRAG; i++) {
elessair 0:f269e3021894 432 txdesc[i].Status = TX_LAST_SEGM | TX_FIRST_SEGM;;
elessair 0:f269e3021894 433 txdesc[i].Ctrl = 0;
elessair 0:f269e3021894 434 txdesc[i].BufAddr1 = (uint32_t)&txbuf[i];
elessair 0:f269e3021894 435 if (i == (NUM_RX_FRAG - 1)) {
elessair 0:f269e3021894 436 txdesc[i].Status |= TX_END_RING;
elessair 0:f269e3021894 437 }
elessair 0:f269e3021894 438 }
elessair 0:f269e3021894 439
elessair 0:f269e3021894 440 LPC_ETHERNET->DMA_TRANS_DES_ADDR = (uint32_t)txdesc; /* Set EMAC Transmit Descriptor Registers. */
elessair 0:f269e3021894 441 }
elessair 0:f269e3021894 442
elessair 0:f269e3021894 443
elessair 0:f269e3021894 444 static void rxdscr_init()
elessair 0:f269e3021894 445 {
elessair 0:f269e3021894 446 int i;
elessair 0:f269e3021894 447
elessair 0:f269e3021894 448 for(i = 0; i < NUM_RX_FRAG; i++) {
elessair 0:f269e3021894 449 rxdesc[i].Status = TRDES_OWN_BIT;
elessair 0:f269e3021894 450 rxdesc[i].Ctrl = ETH_FRAG_SIZE;
elessair 0:f269e3021894 451 rxdesc[i].BufAddr1 = (uint32_t)&rxbuf[i];
elessair 0:f269e3021894 452 if (i == (NUM_RX_FRAG - 1)) {
elessair 0:f269e3021894 453 rxdesc[i].Ctrl |= RX_END_RING;
elessair 0:f269e3021894 454 }
elessair 0:f269e3021894 455 }
elessair 0:f269e3021894 456
elessair 0:f269e3021894 457 LPC_ETHERNET->DMA_REC_DES_ADDR = (uint32_t)rxdesc; /* Set EMAC Receive Descriptor Registers. */
elessair 0:f269e3021894 458 }
elessair 0:f269e3021894 459
elessair 0:f269e3021894 460 void ethernet_address(char *mac)
elessair 0:f269e3021894 461 {
elessair 0:f269e3021894 462 mbed_mac_address(mac);
elessair 0:f269e3021894 463 }
elessair 0:f269e3021894 464
elessair 0:f269e3021894 465 void ethernet_set_link(int speed, int duplex)
elessair 0:f269e3021894 466 {
elessair 0:f269e3021894 467 volatile unsigned short phy_data;
elessair 0:f269e3021894 468 int tout;
elessair 0:f269e3021894 469
elessair 0:f269e3021894 470 if((speed < 0) || (speed > 1)) {
elessair 0:f269e3021894 471
elessair 0:f269e3021894 472 phy_data = PHY_AUTO_NEG;
elessair 0:f269e3021894 473
elessair 0:f269e3021894 474 } else {
elessair 0:f269e3021894 475
elessair 0:f269e3021894 476 phy_data = (((unsigned short) speed << 13) |
elessair 0:f269e3021894 477 ((unsigned short) duplex << 8));
elessair 0:f269e3021894 478 }
elessair 0:f269e3021894 479
elessair 0:f269e3021894 480 phy_write(PHY_REG_BMCR, phy_data);
elessair 0:f269e3021894 481
elessair 0:f269e3021894 482 for(tout = 100; tout; tout--) {
elessair 0:f269e3021894 483 __NOP(); /* A short delay */
elessair 0:f269e3021894 484 }
elessair 0:f269e3021894 485
elessair 0:f269e3021894 486 switch(phy_id) {
elessair 0:f269e3021894 487 case DP83848C_ID:
elessair 0:f269e3021894 488
elessair 0:f269e3021894 489 phy_data = phy_read(PHY_REG_STS);
elessair 0:f269e3021894 490
elessair 0:f269e3021894 491 if(phy_data & PHY_STS_DUPLEX) {
elessair 0:f269e3021894 492 /* Full duplex is enabled. */
elessair 0:f269e3021894 493 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE;
elessair 0:f269e3021894 494 } else {
elessair 0:f269e3021894 495 LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE;
elessair 0:f269e3021894 496 }
elessair 0:f269e3021894 497
elessair 0:f269e3021894 498 if(phy_data & PHY_STS_SPEED) {
elessair 0:f269e3021894 499 LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED;
elessair 0:f269e3021894 500 } else {
elessair 0:f269e3021894 501 LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED;
elessair 0:f269e3021894 502 }
elessair 0:f269e3021894 503 break;
elessair 0:f269e3021894 504
elessair 0:f269e3021894 505 case LAN8720_ID:
elessair 0:f269e3021894 506
elessair 0:f269e3021894 507 for(tout = 100; tout; tout--) {
elessair 0:f269e3021894 508 phy_data = phy_read(PHY_REG_BMSR);
elessair 0:f269e3021894 509 if (phy_data & PHY_STS_DUPLEX)
elessair 0:f269e3021894 510 break;
elessair 0:f269e3021894 511 }
elessair 0:f269e3021894 512
elessair 0:f269e3021894 513 if (phy_data & PHY_STS_DUPLEX) {
elessair 0:f269e3021894 514 /* Full duplex is enabled. */
elessair 0:f269e3021894 515 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPLEX_MODE;
elessair 0:f269e3021894 516 } else {
elessair 0:f269e3021894 517 LPC_ETHERNET->MAC_CONFIG &= ~MAC_DUPLEX_MODE;
elessair 0:f269e3021894 518 }
elessair 0:f269e3021894 519
elessair 0:f269e3021894 520 if(phy_data & PHY_STS_SPEED) {
elessair 0:f269e3021894 521 LPC_ETHERNET->MAC_CONFIG &= ~SUPP_SPEED;
elessair 0:f269e3021894 522 } else {
elessair 0:f269e3021894 523 LPC_ETHERNET->MAC_CONFIG |= SUPP_SPEED;
elessair 0:f269e3021894 524 }
elessair 0:f269e3021894 525 break;
elessair 0:f269e3021894 526 }
elessair 0:f269e3021894 527 }
elessair 0:f269e3021894 528