mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Tue Dec 16 08:15:08 2014 +0000
Revision:
440:8a0b45cd594f
Parent:
285:31249416b6f9
Synchronized with git revision 67fbbf0b635d0c0d93fbe433306c537c2ad206aa

Full URL: https://github.com/mbedmicro/mbed/commit/67fbbf0b635d0c0d93fbe433306c537c2ad206aa/

Targets: nrf51 - updating app_timer.c from Norid'c SDKv7.1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 15:4892fe388435 1 /* mbed Microcontroller Library
bogdanm 15:4892fe388435 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 15:4892fe388435 3 *
bogdanm 15:4892fe388435 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 15:4892fe388435 5 * you may not use this file except in compliance with the License.
bogdanm 15:4892fe388435 6 * You may obtain a copy of the License at
bogdanm 15:4892fe388435 7 *
bogdanm 15:4892fe388435 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 15:4892fe388435 9 *
bogdanm 15:4892fe388435 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 15:4892fe388435 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 15:4892fe388435 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 15:4892fe388435 13 * See the License for the specific language governing permissions and
bogdanm 15:4892fe388435 14 * limitations under the License.
bogdanm 15:4892fe388435 15 */
bogdanm 15:4892fe388435 16 #include <string.h>
bogdanm 15:4892fe388435 17
bogdanm 15:4892fe388435 18 #include "ethernet_api.h"
bogdanm 15:4892fe388435 19 #include "cmsis.h"
bogdanm 15:4892fe388435 20 #include "mbed_interface.h"
bogdanm 15:4892fe388435 21 #include "toolchain.h"
mbed_official 285:31249416b6f9 22 #include "mbed_error.h"
bogdanm 15:4892fe388435 23
bogdanm 15:4892fe388435 24 #define NEW_LOGIC 0
bogdanm 15:4892fe388435 25 #define NEW_ETH_BUFFER 0
bogdanm 15:4892fe388435 26
bogdanm 15:4892fe388435 27 #if NEW_ETH_BUFFER
bogdanm 15:4892fe388435 28
bogdanm 15:4892fe388435 29 #define NUM_RX_FRAG 4 // Number of Rx Fragments (== packets)
bogdanm 15:4892fe388435 30 #define NUM_TX_FRAG 3 // Number of Tx Fragments (== packets)
bogdanm 15:4892fe388435 31
bogdanm 15:4892fe388435 32 #define ETH_MAX_FLEN 1536 // Maximum Ethernet Frame Size
bogdanm 15:4892fe388435 33 #define ETH_FRAG_SIZE ETH_MAX_FLEN // Packet Fragment size (same as packet length)
bogdanm 15:4892fe388435 34
bogdanm 15:4892fe388435 35 #else
bogdanm 15:4892fe388435 36
bogdanm 15:4892fe388435 37 // Memfree calculation:
bogdanm 15:4892fe388435 38 // (16 * 1024) - ((2 * 4 * NUM_RX) + (2 * 4 * NUM_RX) + (0x300 * NUM_RX) +
bogdanm 15:4892fe388435 39 // (2 * 4 * NUM_TX) + (1 * 4 * NUM_TX) + (0x300 * NUM_TX)) = 8556
bogdanm 15:4892fe388435 40 /* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
bogdanm 15:4892fe388435 41 #define NUM_RX_FRAG 4 /* Num.of RX Fragments 4*1536= 6.0kB */
bogdanm 15:4892fe388435 42 #define NUM_TX_FRAG 3 /* Num.of TX Fragments 3*1536= 4.6kB */
bogdanm 15:4892fe388435 43 //#define ETH_FRAG_SIZE 1536 /* Packet Fragment size 1536 Bytes */
bogdanm 15:4892fe388435 44
bogdanm 15:4892fe388435 45 //#define ETH_MAX_FLEN 1536 /* Max. Ethernet Frame Size */
bogdanm 15:4892fe388435 46 #define ETH_FRAG_SIZE 0x300 /* Packet Fragment size 1536/2 Bytes */
bogdanm 15:4892fe388435 47 #define ETH_MAX_FLEN 0x300 /* Max. Ethernet Frame Size */
bogdanm 15:4892fe388435 48
bogdanm 15:4892fe388435 49 const int ethernet_MTU_SIZE = 0x300;
bogdanm 15:4892fe388435 50
bogdanm 15:4892fe388435 51 #endif
bogdanm 15:4892fe388435 52
bogdanm 15:4892fe388435 53 #define ETHERNET_ADDR_SIZE 6
bogdanm 15:4892fe388435 54
bogdanm 15:4892fe388435 55 PACKED struct RX_DESC_TypeDef { /* RX Descriptor struct */
bogdanm 15:4892fe388435 56 unsigned int Packet;
bogdanm 15:4892fe388435 57 unsigned int Ctrl;
bogdanm 15:4892fe388435 58 };
bogdanm 15:4892fe388435 59 typedef struct RX_DESC_TypeDef RX_DESC_TypeDef;
bogdanm 15:4892fe388435 60
bogdanm 15:4892fe388435 61 PACKED struct RX_STAT_TypeDef { /* RX Status struct */
bogdanm 15:4892fe388435 62 unsigned int Info;
bogdanm 15:4892fe388435 63 unsigned int HashCRC;
bogdanm 15:4892fe388435 64 };
bogdanm 15:4892fe388435 65 typedef struct RX_STAT_TypeDef RX_STAT_TypeDef;
bogdanm 15:4892fe388435 66
bogdanm 15:4892fe388435 67 PACKED struct TX_DESC_TypeDef { /* TX Descriptor struct */
bogdanm 15:4892fe388435 68 unsigned int Packet;
bogdanm 15:4892fe388435 69 unsigned int Ctrl;
bogdanm 15:4892fe388435 70 };
bogdanm 15:4892fe388435 71 typedef struct TX_DESC_TypeDef TX_DESC_TypeDef;
bogdanm 15:4892fe388435 72
bogdanm 15:4892fe388435 73 PACKED struct TX_STAT_TypeDef { /* TX Status struct */
bogdanm 15:4892fe388435 74 unsigned int Info;
bogdanm 15:4892fe388435 75 };
bogdanm 15:4892fe388435 76 typedef struct TX_STAT_TypeDef TX_STAT_TypeDef;
bogdanm 15:4892fe388435 77
bogdanm 15:4892fe388435 78 /* MAC Configuration Register 1 */
bogdanm 15:4892fe388435 79 #define MAC1_REC_EN 0x00000001 /* Receive Enable */
bogdanm 15:4892fe388435 80 #define MAC1_PASS_ALL 0x00000002 /* Pass All Receive Frames */
bogdanm 15:4892fe388435 81 #define MAC1_RX_FLOWC 0x00000004 /* RX Flow Control */
bogdanm 15:4892fe388435 82 #define MAC1_TX_FLOWC 0x00000008 /* TX Flow Control */
bogdanm 15:4892fe388435 83 #define MAC1_LOOPB 0x00000010 /* Loop Back Mode */
bogdanm 15:4892fe388435 84 #define MAC1_RES_TX 0x00000100 /* Reset TX Logic */
bogdanm 15:4892fe388435 85 #define MAC1_RES_MCS_TX 0x00000200 /* Reset MAC TX Control Sublayer */
bogdanm 15:4892fe388435 86 #define MAC1_RES_RX 0x00000400 /* Reset RX Logic */
bogdanm 15:4892fe388435 87 #define MAC1_RES_MCS_RX 0x00000800 /* Reset MAC RX Control Sublayer */
bogdanm 15:4892fe388435 88 #define MAC1_SIM_RES 0x00004000 /* Simulation Reset */
bogdanm 15:4892fe388435 89 #define MAC1_SOFT_RES 0x00008000 /* Soft Reset MAC */
bogdanm 15:4892fe388435 90
bogdanm 15:4892fe388435 91 /* MAC Configuration Register 2 */
bogdanm 15:4892fe388435 92 #define MAC2_FULL_DUP 0x00000001 /* Full Duplex Mode */
bogdanm 15:4892fe388435 93 #define MAC2_FRM_LEN_CHK 0x00000002 /* Frame Length Checking */
bogdanm 15:4892fe388435 94 #define MAC2_HUGE_FRM_EN 0x00000004 /* Huge Frame Enable */
bogdanm 15:4892fe388435 95 #define MAC2_DLY_CRC 0x00000008 /* Delayed CRC Mode */
bogdanm 15:4892fe388435 96 #define MAC2_CRC_EN 0x00000010 /* Append CRC to every Frame */
bogdanm 15:4892fe388435 97 #define MAC2_PAD_EN 0x00000020 /* Pad all Short Frames */
bogdanm 15:4892fe388435 98 #define MAC2_VLAN_PAD_EN 0x00000040 /* VLAN Pad Enable */
bogdanm 15:4892fe388435 99 #define MAC2_ADET_PAD_EN 0x00000080 /* Auto Detect Pad Enable */
bogdanm 15:4892fe388435 100 #define MAC2_PPREAM_ENF 0x00000100 /* Pure Preamble Enforcement */
bogdanm 15:4892fe388435 101 #define MAC2_LPREAM_ENF 0x00000200 /* Long Preamble Enforcement */
bogdanm 15:4892fe388435 102 #define MAC2_NO_BACKOFF 0x00001000 /* No Backoff Algorithm */
bogdanm 15:4892fe388435 103 #define MAC2_BACK_PRESSURE 0x00002000 /* Backoff Presurre / No Backoff */
bogdanm 15:4892fe388435 104 #define MAC2_EXCESS_DEF 0x00004000 /* Excess Defer */
bogdanm 15:4892fe388435 105
bogdanm 15:4892fe388435 106 /* Back-to-Back Inter-Packet-Gap Register */
bogdanm 15:4892fe388435 107 #define IPGT_FULL_DUP 0x00000015 /* Recommended value for Full Duplex */
bogdanm 15:4892fe388435 108 #define IPGT_HALF_DUP 0x00000012 /* Recommended value for Half Duplex */
bogdanm 15:4892fe388435 109
bogdanm 15:4892fe388435 110 /* Non Back-to-Back Inter-Packet-Gap Register */
bogdanm 15:4892fe388435 111 #define IPGR_DEF 0x00000012 /* Recommended value */
bogdanm 15:4892fe388435 112
bogdanm 15:4892fe388435 113 /* Collision Window/Retry Register */
bogdanm 15:4892fe388435 114 #define CLRT_DEF 0x0000370F /* Default value */
bogdanm 15:4892fe388435 115
bogdanm 15:4892fe388435 116 /* PHY Support Register */
bogdanm 15:4892fe388435 117 #define SUPP_SPEED 0x00000100 /* Reduced MII Logic Current Speed */
bogdanm 15:4892fe388435 118 //#define SUPP_RES_RMII 0x00000800 /* Reset Reduced MII Logic */
bogdanm 15:4892fe388435 119 #define SUPP_RES_RMII 0x00000000 /* Reset Reduced MII Logic */
bogdanm 15:4892fe388435 120
bogdanm 15:4892fe388435 121 /* Test Register */
bogdanm 15:4892fe388435 122 #define TEST_SHCUT_PQUANTA 0x00000001 /* Shortcut Pause Quanta */
bogdanm 15:4892fe388435 123 #define TEST_TST_PAUSE 0x00000002 /* Test Pause */
bogdanm 15:4892fe388435 124 #define TEST_TST_BACKP 0x00000004 /* Test Back Pressure */
bogdanm 15:4892fe388435 125
bogdanm 15:4892fe388435 126 /* MII Management Configuration Register */
bogdanm 15:4892fe388435 127 #define MCFG_SCAN_INC 0x00000001 /* Scan Increment PHY Address */
bogdanm 15:4892fe388435 128 #define MCFG_SUPP_PREAM 0x00000002 /* Suppress Preamble */
bogdanm 15:4892fe388435 129 #define MCFG_CLK_SEL 0x0000003C /* Clock Select Mask */
bogdanm 15:4892fe388435 130 #define MCFG_RES_MII 0x00008000 /* Reset MII Management Hardware */
bogdanm 15:4892fe388435 131
bogdanm 15:4892fe388435 132 /* MII Management Command Register */
bogdanm 15:4892fe388435 133 #define MCMD_READ 0x00000001 /* MII Read */
bogdanm 15:4892fe388435 134 #define MCMD_SCAN 0x00000002 /* MII Scan continuously */
bogdanm 15:4892fe388435 135
bogdanm 15:4892fe388435 136 #define MII_WR_TOUT 0x00050000 /* MII Write timeout count */
bogdanm 15:4892fe388435 137 #define MII_RD_TOUT 0x00050000 /* MII Read timeout count */
bogdanm 15:4892fe388435 138
bogdanm 15:4892fe388435 139 /* MII Management Address Register */
bogdanm 15:4892fe388435 140 #define MADR_REG_ADR 0x0000001F /* MII Register Address Mask */
bogdanm 15:4892fe388435 141 #define MADR_PHY_ADR 0x00001F00 /* PHY Address Mask */
bogdanm 15:4892fe388435 142
bogdanm 15:4892fe388435 143 /* MII Management Indicators Register */
bogdanm 15:4892fe388435 144 #define MIND_BUSY 0x00000001 /* MII is Busy */
bogdanm 15:4892fe388435 145 #define MIND_SCAN 0x00000002 /* MII Scanning in Progress */
bogdanm 15:4892fe388435 146 #define MIND_NOT_VAL 0x00000004 /* MII Read Data not valid */
bogdanm 15:4892fe388435 147 #define MIND_MII_LINK_FAIL 0x00000008 /* MII Link Failed */
bogdanm 15:4892fe388435 148
bogdanm 15:4892fe388435 149 /* Command Register */
bogdanm 15:4892fe388435 150 #define CR_RX_EN 0x00000001 /* Enable Receive */
bogdanm 15:4892fe388435 151 #define CR_TX_EN 0x00000002 /* Enable Transmit */
bogdanm 15:4892fe388435 152 #define CR_REG_RES 0x00000008 /* Reset Host Registers */
bogdanm 15:4892fe388435 153 #define CR_TX_RES 0x00000010 /* Reset Transmit Datapath */
bogdanm 15:4892fe388435 154 #define CR_RX_RES 0x00000020 /* Reset Receive Datapath */
bogdanm 15:4892fe388435 155 #define CR_PASS_RUNT_FRM 0x00000040 /* Pass Runt Frames */
bogdanm 15:4892fe388435 156 #define CR_PASS_RX_FILT 0x00000080 /* Pass RX Filter */
bogdanm 15:4892fe388435 157 #define CR_TX_FLOW_CTRL 0x00000100 /* TX Flow Control */
bogdanm 15:4892fe388435 158 #define CR_RMII 0x00000200 /* Reduced MII Interface */
bogdanm 15:4892fe388435 159 #define CR_FULL_DUP 0x00000400 /* Full Duplex */
bogdanm 15:4892fe388435 160
bogdanm 15:4892fe388435 161 /* Status Register */
bogdanm 15:4892fe388435 162 #define SR_RX_EN 0x00000001 /* Enable Receive */
bogdanm 15:4892fe388435 163 #define SR_TX_EN 0x00000002 /* Enable Transmit */
bogdanm 15:4892fe388435 164
bogdanm 15:4892fe388435 165 /* Transmit Status Vector 0 Register */
bogdanm 15:4892fe388435 166 #define TSV0_CRC_ERR 0x00000001 /* CRC error */
bogdanm 15:4892fe388435 167 #define TSV0_LEN_CHKERR 0x00000002 /* Length Check Error */
bogdanm 15:4892fe388435 168 #define TSV0_LEN_OUTRNG 0x00000004 /* Length Out of Range */
bogdanm 15:4892fe388435 169 #define TSV0_DONE 0x00000008 /* Tramsmission Completed */
bogdanm 15:4892fe388435 170 #define TSV0_MCAST 0x00000010 /* Multicast Destination */
bogdanm 15:4892fe388435 171 #define TSV0_BCAST 0x00000020 /* Broadcast Destination */
bogdanm 15:4892fe388435 172 #define TSV0_PKT_DEFER 0x00000040 /* Packet Deferred */
bogdanm 15:4892fe388435 173 #define TSV0_EXC_DEFER 0x00000080 /* Excessive Packet Deferral */
bogdanm 15:4892fe388435 174 #define TSV0_EXC_COLL 0x00000100 /* Excessive Collision */
bogdanm 15:4892fe388435 175 #define TSV0_LATE_COLL 0x00000200 /* Late Collision Occured */
bogdanm 15:4892fe388435 176 #define TSV0_GIANT 0x00000400 /* Giant Frame */
bogdanm 15:4892fe388435 177 #define TSV0_UNDERRUN 0x00000800 /* Buffer Underrun */
bogdanm 15:4892fe388435 178 #define TSV0_BYTES 0x0FFFF000 /* Total Bytes Transferred */
bogdanm 15:4892fe388435 179 #define TSV0_CTRL_FRAME 0x10000000 /* Control Frame */
bogdanm 15:4892fe388435 180 #define TSV0_PAUSE 0x20000000 /* Pause Frame */
bogdanm 15:4892fe388435 181 #define TSV0_BACK_PRESS 0x40000000 /* Backpressure Method Applied */
bogdanm 15:4892fe388435 182 #define TSV0_VLAN 0x80000000 /* VLAN Frame */
bogdanm 15:4892fe388435 183
bogdanm 15:4892fe388435 184 /* Transmit Status Vector 1 Register */
bogdanm 15:4892fe388435 185 #define TSV1_BYTE_CNT 0x0000FFFF /* Transmit Byte Count */
bogdanm 15:4892fe388435 186 #define TSV1_COLL_CNT 0x000F0000 /* Transmit Collision Count */
bogdanm 15:4892fe388435 187
bogdanm 15:4892fe388435 188 /* Receive Status Vector Register */
bogdanm 15:4892fe388435 189 #define RSV_BYTE_CNT 0x0000FFFF /* Receive Byte Count */
bogdanm 15:4892fe388435 190 #define RSV_PKT_IGNORED 0x00010000 /* Packet Previously Ignored */
bogdanm 15:4892fe388435 191 #define RSV_RXDV_SEEN 0x00020000 /* RXDV Event Previously Seen */
bogdanm 15:4892fe388435 192 #define RSV_CARR_SEEN 0x00040000 /* Carrier Event Previously Seen */
bogdanm 15:4892fe388435 193 #define RSV_REC_CODEV 0x00080000 /* Receive Code Violation */
bogdanm 15:4892fe388435 194 #define RSV_CRC_ERR 0x00100000 /* CRC Error */
bogdanm 15:4892fe388435 195 #define RSV_LEN_CHKERR 0x00200000 /* Length Check Error */
bogdanm 15:4892fe388435 196 #define RSV_LEN_OUTRNG 0x00400000 /* Length Out of Range */
bogdanm 15:4892fe388435 197 #define RSV_REC_OK 0x00800000 /* Frame Received OK */
bogdanm 15:4892fe388435 198 #define RSV_MCAST 0x01000000 /* Multicast Frame */
bogdanm 15:4892fe388435 199 #define RSV_BCAST 0x02000000 /* Broadcast Frame */
bogdanm 15:4892fe388435 200 #define RSV_DRIB_NIBB 0x04000000 /* Dribble Nibble */
bogdanm 15:4892fe388435 201 #define RSV_CTRL_FRAME 0x08000000 /* Control Frame */
bogdanm 15:4892fe388435 202 #define RSV_PAUSE 0x10000000 /* Pause Frame */
bogdanm 15:4892fe388435 203 #define RSV_UNSUPP_OPC 0x20000000 /* Unsupported Opcode */
bogdanm 15:4892fe388435 204 #define RSV_VLAN 0x40000000 /* VLAN Frame */
bogdanm 15:4892fe388435 205
bogdanm 15:4892fe388435 206 /* Flow Control Counter Register */
bogdanm 15:4892fe388435 207 #define FCC_MIRR_CNT 0x0000FFFF /* Mirror Counter */
bogdanm 15:4892fe388435 208 #define FCC_PAUSE_TIM 0xFFFF0000 /* Pause Timer */
bogdanm 15:4892fe388435 209
bogdanm 15:4892fe388435 210 /* Flow Control Status Register */
bogdanm 15:4892fe388435 211 #define FCS_MIRR_CNT 0x0000FFFF /* Mirror Counter Current */
bogdanm 15:4892fe388435 212
bogdanm 15:4892fe388435 213 /* Receive Filter Control Register */
bogdanm 15:4892fe388435 214 #define RFC_UCAST_EN 0x00000001 /* Accept Unicast Frames Enable */
bogdanm 15:4892fe388435 215 #define RFC_BCAST_EN 0x00000002 /* Accept Broadcast Frames Enable */
bogdanm 15:4892fe388435 216 #define RFC_MCAST_EN 0x00000004 /* Accept Multicast Frames Enable */
bogdanm 15:4892fe388435 217 #define RFC_UCAST_HASH_EN 0x00000008 /* Accept Unicast Hash Filter Frames */
bogdanm 15:4892fe388435 218 #define RFC_MCAST_HASH_EN 0x00000010 /* Accept Multicast Hash Filter Fram.*/
bogdanm 15:4892fe388435 219 #define RFC_PERFECT_EN 0x00000020 /* Accept Perfect Match Enable */
bogdanm 15:4892fe388435 220 #define RFC_MAGP_WOL_EN 0x00001000 /* Magic Packet Filter WoL Enable */
bogdanm 15:4892fe388435 221 #define RFC_PFILT_WOL_EN 0x00002000 /* Perfect Filter WoL Enable */
bogdanm 15:4892fe388435 222
bogdanm 15:4892fe388435 223 /* Receive Filter WoL Status/Clear Registers */
bogdanm 15:4892fe388435 224 #define WOL_UCAST 0x00000001 /* Unicast Frame caused WoL */
bogdanm 15:4892fe388435 225 #define WOL_BCAST 0x00000002 /* Broadcast Frame caused WoL */
bogdanm 15:4892fe388435 226 #define WOL_MCAST 0x00000004 /* Multicast Frame caused WoL */
bogdanm 15:4892fe388435 227 #define WOL_UCAST_HASH 0x00000008 /* Unicast Hash Filter Frame WoL */
bogdanm 15:4892fe388435 228 #define WOL_MCAST_HASH 0x00000010 /* Multicast Hash Filter Frame WoL */
bogdanm 15:4892fe388435 229 #define WOL_PERFECT 0x00000020 /* Perfect Filter WoL */
bogdanm 15:4892fe388435 230 #define WOL_RX_FILTER 0x00000080 /* RX Filter caused WoL */
bogdanm 15:4892fe388435 231 #define WOL_MAG_PACKET 0x00000100 /* Magic Packet Filter caused WoL */
bogdanm 15:4892fe388435 232
bogdanm 15:4892fe388435 233 /* Interrupt Status/Enable/Clear/Set Registers */
bogdanm 15:4892fe388435 234 #define INT_RX_OVERRUN 0x00000001 /* Overrun Error in RX Queue */
bogdanm 15:4892fe388435 235 #define INT_RX_ERR 0x00000002 /* Receive Error */
bogdanm 15:4892fe388435 236 #define INT_RX_FIN 0x00000004 /* RX Finished Process Descriptors */
bogdanm 15:4892fe388435 237 #define INT_RX_DONE 0x00000008 /* Receive Done */
bogdanm 15:4892fe388435 238 #define INT_TX_UNDERRUN 0x00000010 /* Transmit Underrun */
bogdanm 15:4892fe388435 239 #define INT_TX_ERR 0x00000020 /* Transmit Error */
bogdanm 15:4892fe388435 240 #define INT_TX_FIN 0x00000040 /* TX Finished Process Descriptors */
bogdanm 15:4892fe388435 241 #define INT_TX_DONE 0x00000080 /* Transmit Done */
bogdanm 15:4892fe388435 242 #define INT_SOFT_INT 0x00001000 /* Software Triggered Interrupt */
bogdanm 15:4892fe388435 243 #define INT_WAKEUP 0x00002000 /* Wakeup Event Interrupt */
bogdanm 15:4892fe388435 244
bogdanm 15:4892fe388435 245 /* Power Down Register */
bogdanm 15:4892fe388435 246 #define PD_POWER_DOWN 0x80000000 /* Power Down MAC */
bogdanm 15:4892fe388435 247
bogdanm 15:4892fe388435 248 /* RX Descriptor Control Word */
bogdanm 15:4892fe388435 249 #define RCTRL_SIZE 0x000007FF /* Buffer size mask */
bogdanm 15:4892fe388435 250 #define RCTRL_INT 0x80000000 /* Generate RxDone Interrupt */
bogdanm 15:4892fe388435 251
bogdanm 15:4892fe388435 252 /* RX Status Hash CRC Word */
bogdanm 15:4892fe388435 253 #define RHASH_SA 0x000001FF /* Hash CRC for Source Address */
bogdanm 15:4892fe388435 254 #define RHASH_DA 0x001FF000 /* Hash CRC for Destination Address */
bogdanm 15:4892fe388435 255
bogdanm 15:4892fe388435 256 /* RX Status Information Word */
bogdanm 15:4892fe388435 257 #define RINFO_SIZE 0x000007FF /* Data size in bytes */
bogdanm 15:4892fe388435 258 #define RINFO_CTRL_FRAME 0x00040000 /* Control Frame */
bogdanm 15:4892fe388435 259 #define RINFO_VLAN 0x00080000 /* VLAN Frame */
bogdanm 15:4892fe388435 260 #define RINFO_FAIL_FILT 0x00100000 /* RX Filter Failed */
bogdanm 15:4892fe388435 261 #define RINFO_MCAST 0x00200000 /* Multicast Frame */
bogdanm 15:4892fe388435 262 #define RINFO_BCAST 0x00400000 /* Broadcast Frame */
bogdanm 15:4892fe388435 263 #define RINFO_CRC_ERR 0x00800000 /* CRC Error in Frame */
bogdanm 15:4892fe388435 264 #define RINFO_SYM_ERR 0x01000000 /* Symbol Error from PHY */
bogdanm 15:4892fe388435 265 #define RINFO_LEN_ERR 0x02000000 /* Length Error */
bogdanm 15:4892fe388435 266 #define RINFO_RANGE_ERR 0x04000000 /* Range Error (exceeded max. size) */
bogdanm 15:4892fe388435 267 #define RINFO_ALIGN_ERR 0x08000000 /* Alignment Error */
bogdanm 15:4892fe388435 268 #define RINFO_OVERRUN 0x10000000 /* Receive overrun */
bogdanm 15:4892fe388435 269 #define RINFO_NO_DESCR 0x20000000 /* No new Descriptor available */
bogdanm 15:4892fe388435 270 #define RINFO_LAST_FLAG 0x40000000 /* Last Fragment in Frame */
bogdanm 15:4892fe388435 271 #define RINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
bogdanm 15:4892fe388435 272
bogdanm 15:4892fe388435 273 //#define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_CRC_ERR | RINFO_SYM_ERR | RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)
bogdanm 15:4892fe388435 274 #define RINFO_ERR_MASK (RINFO_FAIL_FILT | RINFO_SYM_ERR | \
bogdanm 15:4892fe388435 275 RINFO_LEN_ERR | RINFO_ALIGN_ERR | RINFO_OVERRUN)
bogdanm 15:4892fe388435 276
bogdanm 15:4892fe388435 277
bogdanm 15:4892fe388435 278 /* TX Descriptor Control Word */
bogdanm 15:4892fe388435 279 #define TCTRL_SIZE 0x000007FF /* Size of data buffer in bytes */
bogdanm 15:4892fe388435 280 #define TCTRL_OVERRIDE 0x04000000 /* Override Default MAC Registers */
bogdanm 15:4892fe388435 281 #define TCTRL_HUGE 0x08000000 /* Enable Huge Frame */
bogdanm 15:4892fe388435 282 #define TCTRL_PAD 0x10000000 /* Pad short Frames to 64 bytes */
bogdanm 15:4892fe388435 283 #define TCTRL_CRC 0x20000000 /* Append a hardware CRC to Frame */
bogdanm 15:4892fe388435 284 #define TCTRL_LAST 0x40000000 /* Last Descriptor for TX Frame */
bogdanm 15:4892fe388435 285 #define TCTRL_INT 0x80000000 /* Generate TxDone Interrupt */
bogdanm 15:4892fe388435 286
bogdanm 15:4892fe388435 287 /* TX Status Information Word */
bogdanm 15:4892fe388435 288 #define TINFO_COL_CNT 0x01E00000 /* Collision Count */
bogdanm 15:4892fe388435 289 #define TINFO_DEFER 0x02000000 /* Packet Deferred (not an error) */
bogdanm 15:4892fe388435 290 #define TINFO_EXCESS_DEF 0x04000000 /* Excessive Deferral */
bogdanm 15:4892fe388435 291 #define TINFO_EXCESS_COL 0x08000000 /* Excessive Collision */
bogdanm 15:4892fe388435 292 #define TINFO_LATE_COL 0x10000000 /* Late Collision Occured */
bogdanm 15:4892fe388435 293 #define TINFO_UNDERRUN 0x20000000 /* Transmit Underrun */
bogdanm 15:4892fe388435 294 #define TINFO_NO_DESCR 0x40000000 /* No new Descriptor available */
bogdanm 15:4892fe388435 295 #define TINFO_ERR 0x80000000 /* Error Occured (OR of all errors) */
bogdanm 15:4892fe388435 296
bogdanm 15:4892fe388435 297 /* ENET Device Revision ID */
bogdanm 15:4892fe388435 298 #define OLD_EMAC_MODULE_ID 0x39022000 /* Rev. ID for first rev '-' */
bogdanm 15:4892fe388435 299
bogdanm 15:4892fe388435 300 /* DP83848C PHY Registers */
bogdanm 15:4892fe388435 301 #define PHY_REG_BMCR 0x00 /* Basic Mode Control Register */
bogdanm 15:4892fe388435 302 #define PHY_REG_BMSR 0x01 /* Basic Mode Status Register */
bogdanm 15:4892fe388435 303 #define PHY_REG_IDR1 0x02 /* PHY Identifier 1 */
bogdanm 15:4892fe388435 304 #define PHY_REG_IDR2 0x03 /* PHY Identifier 2 */
bogdanm 15:4892fe388435 305 #define PHY_REG_ANAR 0x04 /* Auto-Negotiation Advertisement */
bogdanm 15:4892fe388435 306 #define PHY_REG_ANLPAR 0x05 /* Auto-Neg. Link Partner Abitily */
bogdanm 15:4892fe388435 307 #define PHY_REG_ANER 0x06 /* Auto-Neg. Expansion Register */
bogdanm 15:4892fe388435 308 #define PHY_REG_ANNPTR 0x07 /* Auto-Neg. Next Page TX */
bogdanm 15:4892fe388435 309
bogdanm 15:4892fe388435 310 /* PHY Extended Registers */
bogdanm 15:4892fe388435 311 #define PHY_REG_STS 0x10 /* Status Register */
bogdanm 15:4892fe388435 312 #define PHY_REG_MICR 0x11 /* MII Interrupt Control Register */
bogdanm 15:4892fe388435 313 #define PHY_REG_MISR 0x12 /* MII Interrupt Status Register */
bogdanm 15:4892fe388435 314 #define PHY_REG_FCSCR 0x14 /* False Carrier Sense Counter */
bogdanm 15:4892fe388435 315 #define PHY_REG_RECR 0x15 /* Receive Error Counter */
bogdanm 15:4892fe388435 316 #define PHY_REG_PCSR 0x16 /* PCS Sublayer Config. and Status */
bogdanm 15:4892fe388435 317 #define PHY_REG_RBR 0x17 /* RMII and Bypass Register */
bogdanm 15:4892fe388435 318 #define PHY_REG_LEDCR 0x18 /* LED Direct Control Register */
bogdanm 15:4892fe388435 319 #define PHY_REG_PHYCR 0x19 /* PHY Control Register */
bogdanm 15:4892fe388435 320 #define PHY_REG_10BTSCR 0x1A /* 10Base-T Status/Control Register */
bogdanm 15:4892fe388435 321 #define PHY_REG_CDCTRL1 0x1B /* CD Test Control and BIST Extens. */
bogdanm 15:4892fe388435 322 #define PHY_REG_EDCR 0x1D /* Energy Detect Control Register */
bogdanm 15:4892fe388435 323
bogdanm 15:4892fe388435 324 #define PHY_REG_SCSR 0x1F /* PHY Special Control/Status Register */
bogdanm 15:4892fe388435 325
bogdanm 15:4892fe388435 326 #define PHY_FULLD_100M 0x2100 /* Full Duplex 100Mbit */
bogdanm 15:4892fe388435 327 #define PHY_HALFD_100M 0x2000 /* Half Duplex 100Mbit */
bogdanm 15:4892fe388435 328 #define PHY_FULLD_10M 0x0100 /* Full Duplex 10Mbit */
bogdanm 15:4892fe388435 329 #define PHY_HALFD_10M 0x0000 /* Half Duplex 10MBit */
bogdanm 15:4892fe388435 330 #define PHY_AUTO_NEG 0x3000 /* Select Auto Negotiation */
bogdanm 15:4892fe388435 331
bogdanm 15:4892fe388435 332 #define DP83848C_DEF_ADR 0x0100 /* Default PHY device address */
bogdanm 15:4892fe388435 333 #define DP83848C_ID 0x20005C90 /* PHY Identifier - DP83848C */
bogdanm 15:4892fe388435 334
bogdanm 15:4892fe388435 335 #define LAN8720_ID 0x0007C0F0 /* PHY Identifier - LAN8720 */
bogdanm 15:4892fe388435 336
bogdanm 15:4892fe388435 337 #define PHY_STS_LINK 0x0001 /* PHY Status Link Mask */
bogdanm 15:4892fe388435 338 #define PHY_STS_SPEED 0x0002 /* PHY Status Speed Mask */
bogdanm 15:4892fe388435 339 #define PHY_STS_DUPLEX 0x0004 /* PHY Status Duplex Mask */
bogdanm 15:4892fe388435 340
bogdanm 15:4892fe388435 341 #define PHY_BMCR_RESET 0x8000 /* PHY Reset */
bogdanm 15:4892fe388435 342
bogdanm 15:4892fe388435 343 #define PHY_BMSR_LINK 0x0004 /* PHY BMSR Link valid */
bogdanm 15:4892fe388435 344
bogdanm 15:4892fe388435 345 #define PHY_SCSR_100MBIT 0x0008 /* Speed: 1=100 MBit, 0=10Mbit */
bogdanm 15:4892fe388435 346 #define PHY_SCSR_DUPLEX 0x0010 /* PHY Duplex Mask */
bogdanm 15:4892fe388435 347
bogdanm 15:4892fe388435 348
bogdanm 15:4892fe388435 349 static int phy_read(unsigned int PhyReg);
bogdanm 15:4892fe388435 350 static int phy_write(unsigned int PhyReg, unsigned short Data);
bogdanm 15:4892fe388435 351
bogdanm 15:4892fe388435 352 static void txdscr_init(void);
bogdanm 15:4892fe388435 353 static void rxdscr_init(void);
bogdanm 15:4892fe388435 354
bogdanm 15:4892fe388435 355 #if defined (__ICCARM__)
bogdanm 15:4892fe388435 356 # define AHBSRAM1
bogdanm 15:4892fe388435 357 #elif defined(TOOLCHAIN_GCC_CR)
bogdanm 15:4892fe388435 358 # define AHBSRAM1 __attribute__((section(".data.$RamPeriph32")))
bogdanm 15:4892fe388435 359 #else
bogdanm 15:4892fe388435 360 # define AHBSRAM1 __attribute__((section("AHBSRAM1"),aligned))
bogdanm 15:4892fe388435 361 #endif
bogdanm 15:4892fe388435 362
bogdanm 15:4892fe388435 363 AHBSRAM1 volatile uint8_t rxbuf[NUM_RX_FRAG][ETH_FRAG_SIZE];
bogdanm 15:4892fe388435 364 AHBSRAM1 volatile uint8_t txbuf[NUM_TX_FRAG][ETH_FRAG_SIZE];
bogdanm 15:4892fe388435 365 AHBSRAM1 volatile RX_DESC_TypeDef rxdesc[NUM_RX_FRAG];
bogdanm 15:4892fe388435 366 AHBSRAM1 volatile RX_STAT_TypeDef rxstat[NUM_RX_FRAG];
bogdanm 15:4892fe388435 367 AHBSRAM1 volatile TX_DESC_TypeDef txdesc[NUM_TX_FRAG];
bogdanm 15:4892fe388435 368 AHBSRAM1 volatile TX_STAT_TypeDef txstat[NUM_TX_FRAG];
bogdanm 15:4892fe388435 369
bogdanm 15:4892fe388435 370
bogdanm 15:4892fe388435 371 #if NEW_LOGIC
bogdanm 15:4892fe388435 372 static int rx_consume_offset = -1;
bogdanm 15:4892fe388435 373 static int tx_produce_offset = -1;
bogdanm 15:4892fe388435 374 #else
bogdanm 15:4892fe388435 375 static int send_doff = 0;
bogdanm 15:4892fe388435 376 static int send_idx = -1;
bogdanm 15:4892fe388435 377 static int send_size = 0;
bogdanm 15:4892fe388435 378
bogdanm 15:4892fe388435 379 static int receive_soff = 0;
bogdanm 15:4892fe388435 380 static int receive_idx = -1;
bogdanm 15:4892fe388435 381 #endif
bogdanm 15:4892fe388435 382
bogdanm 15:4892fe388435 383 static uint32_t phy_id = 0;
bogdanm 15:4892fe388435 384
bogdanm 15:4892fe388435 385 static inline int rinc(int idx, int mod) {
bogdanm 15:4892fe388435 386 ++idx;
bogdanm 15:4892fe388435 387 idx %= mod;
bogdanm 15:4892fe388435 388 return idx;
bogdanm 15:4892fe388435 389 }
bogdanm 15:4892fe388435 390
bogdanm 15:4892fe388435 391 //extern unsigned int SystemFrequency;
bogdanm 15:4892fe388435 392 static inline unsigned int clockselect() {
bogdanm 15:4892fe388435 393 if(SystemCoreClock < 10000000) {
bogdanm 15:4892fe388435 394 return 1;
bogdanm 15:4892fe388435 395 } else if(SystemCoreClock < 15000000) {
bogdanm 15:4892fe388435 396 return 2;
bogdanm 15:4892fe388435 397 } else if(SystemCoreClock < 20000000) {
bogdanm 15:4892fe388435 398 return 3;
bogdanm 15:4892fe388435 399 } else if(SystemCoreClock < 25000000) {
bogdanm 15:4892fe388435 400 return 4;
bogdanm 15:4892fe388435 401 } else if(SystemCoreClock < 35000000) {
bogdanm 15:4892fe388435 402 return 5;
bogdanm 15:4892fe388435 403 } else if(SystemCoreClock < 50000000) {
bogdanm 15:4892fe388435 404 return 6;
bogdanm 15:4892fe388435 405 } else if(SystemCoreClock < 70000000) {
bogdanm 15:4892fe388435 406 return 7;
bogdanm 15:4892fe388435 407 } else if(SystemCoreClock < 80000000) {
bogdanm 15:4892fe388435 408 return 8;
bogdanm 15:4892fe388435 409 } else if(SystemCoreClock < 90000000) {
bogdanm 15:4892fe388435 410 return 9;
bogdanm 15:4892fe388435 411 } else if(SystemCoreClock < 100000000) {
bogdanm 15:4892fe388435 412 return 10;
bogdanm 15:4892fe388435 413 } else if(SystemCoreClock < 120000000) {
bogdanm 15:4892fe388435 414 return 11;
bogdanm 15:4892fe388435 415 } else if(SystemCoreClock < 130000000) {
bogdanm 15:4892fe388435 416 return 12;
bogdanm 15:4892fe388435 417 } else if(SystemCoreClock < 140000000) {
bogdanm 15:4892fe388435 418 return 13;
bogdanm 15:4892fe388435 419 } else if(SystemCoreClock < 150000000) {
bogdanm 15:4892fe388435 420 return 15;
bogdanm 15:4892fe388435 421 } else if(SystemCoreClock < 160000000) {
bogdanm 15:4892fe388435 422 return 16;
bogdanm 15:4892fe388435 423 } else {
bogdanm 15:4892fe388435 424 return 0;
bogdanm 15:4892fe388435 425 }
bogdanm 15:4892fe388435 426 }
bogdanm 15:4892fe388435 427
bogdanm 15:4892fe388435 428 #ifndef min
bogdanm 15:4892fe388435 429 #define min(x, y) (((x)<(y))?(x):(y))
bogdanm 15:4892fe388435 430 #endif
bogdanm 15:4892fe388435 431
bogdanm 15:4892fe388435 432 /*----------------------------------------------------------------------------
bogdanm 15:4892fe388435 433 Ethernet Device initialize
bogdanm 15:4892fe388435 434 *----------------------------------------------------------------------------*/
bogdanm 15:4892fe388435 435 int ethernet_init() {
bogdanm 15:4892fe388435 436 int regv, tout;
bogdanm 15:4892fe388435 437 char mac[ETHERNET_ADDR_SIZE];
bogdanm 15:4892fe388435 438 unsigned int clock = clockselect();
bogdanm 15:4892fe388435 439
bogdanm 15:4892fe388435 440 LPC_SC->PCONP |= 0x40000000; /* Power Up the EMAC controller. */
bogdanm 15:4892fe388435 441
bogdanm 15:4892fe388435 442 LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */
bogdanm 15:4892fe388435 443 LPC_IOCON->P1_0 |= 0x01; /* ENET_TXD0 */
bogdanm 15:4892fe388435 444 LPC_IOCON->P1_1 &= ~0x07;
bogdanm 15:4892fe388435 445 LPC_IOCON->P1_1 |= 0x01; /* ENET_TXD1 */
bogdanm 15:4892fe388435 446 LPC_IOCON->P1_4 &= ~0x07;
bogdanm 15:4892fe388435 447 LPC_IOCON->P1_4 |= 0x01; /* ENET_TXEN */
bogdanm 15:4892fe388435 448 LPC_IOCON->P1_8 &= ~0x07;
bogdanm 15:4892fe388435 449 LPC_IOCON->P1_8 |= 0x01; /* ENET_CRS */
bogdanm 15:4892fe388435 450 LPC_IOCON->P1_9 &= ~0x07;
bogdanm 15:4892fe388435 451 LPC_IOCON->P1_9 |= 0x01; /* ENET_RXD0 */
bogdanm 15:4892fe388435 452 LPC_IOCON->P1_10 &= ~0x07;
bogdanm 15:4892fe388435 453 LPC_IOCON->P1_10 |= 0x01; /* ENET_RXD1 */
bogdanm 15:4892fe388435 454 LPC_IOCON->P1_14 &= ~0x07;
bogdanm 15:4892fe388435 455 LPC_IOCON->P1_14 |= 0x01; /* ENET_RX_ER */
bogdanm 15:4892fe388435 456 LPC_IOCON->P1_15 &= ~0x07;
bogdanm 15:4892fe388435 457 LPC_IOCON->P1_15 |= 0x01; /* ENET_REF_CLK */
bogdanm 15:4892fe388435 458 LPC_IOCON->P1_16 &= ~0x07; /* ENET/PHY I/O config */
bogdanm 15:4892fe388435 459 LPC_IOCON->P1_16 |= 0x01; /* ENET_MDC */
bogdanm 15:4892fe388435 460 LPC_IOCON->P1_17 &= ~0x07;
bogdanm 15:4892fe388435 461 LPC_IOCON->P1_17 |= 0x01; /* ENET_MDIO */
bogdanm 15:4892fe388435 462
bogdanm 15:4892fe388435 463 /* Reset all EMAC internal modules. */
bogdanm 15:4892fe388435 464 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX |
bogdanm 15:4892fe388435 465 MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES;
bogdanm 15:4892fe388435 466 LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM;
bogdanm 15:4892fe388435 467
bogdanm 15:4892fe388435 468 for(tout = 100; tout; tout--) __NOP(); /* A short delay after reset. */
bogdanm 15:4892fe388435 469
bogdanm 15:4892fe388435 470 LPC_EMAC->MAC1 = MAC1_PASS_ALL; /* Initialize MAC control registers. */
bogdanm 15:4892fe388435 471 LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
bogdanm 15:4892fe388435 472 LPC_EMAC->MAXF = ETH_MAX_FLEN;
bogdanm 15:4892fe388435 473 LPC_EMAC->CLRT = CLRT_DEF;
bogdanm 15:4892fe388435 474 LPC_EMAC->IPGR = IPGR_DEF;
bogdanm 15:4892fe388435 475
bogdanm 15:4892fe388435 476 LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; /* Enable Reduced MII interface. */
bogdanm 15:4892fe388435 477
bogdanm 15:4892fe388435 478 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL; /* Set clock */
bogdanm 15:4892fe388435 479 LPC_EMAC->MCFG |= MCFG_RES_MII; /* and reset */
bogdanm 15:4892fe388435 480
bogdanm 15:4892fe388435 481 for(tout = 100; tout; tout--) __NOP(); /* A short delay */
bogdanm 15:4892fe388435 482
bogdanm 15:4892fe388435 483 LPC_EMAC->MCFG = (clock << 0x2) & MCFG_CLK_SEL;
bogdanm 15:4892fe388435 484 LPC_EMAC->MCMD = 0;
bogdanm 15:4892fe388435 485
bogdanm 15:4892fe388435 486 LPC_EMAC->SUPP = SUPP_RES_RMII; /* Reset Reduced MII Logic. */
bogdanm 15:4892fe388435 487
bogdanm 15:4892fe388435 488 for (tout = 100; tout; tout--) __NOP(); /* A short delay */
bogdanm 15:4892fe388435 489
bogdanm 15:4892fe388435 490 LPC_EMAC->SUPP = 0;
bogdanm 15:4892fe388435 491
bogdanm 15:4892fe388435 492 phy_write(PHY_REG_BMCR, PHY_BMCR_RESET); /* perform PHY reset */
bogdanm 15:4892fe388435 493 for(tout = 0x20000; ; tout--) { /* Wait for hardware reset to end. */
bogdanm 15:4892fe388435 494 regv = phy_read(PHY_REG_BMCR);
bogdanm 15:4892fe388435 495 if(regv < 0 || tout == 0) {
bogdanm 15:4892fe388435 496 return -1; /* Error */
bogdanm 15:4892fe388435 497 }
bogdanm 15:4892fe388435 498 if(!(regv & PHY_BMCR_RESET)) {
bogdanm 15:4892fe388435 499 break; /* Reset complete. */
bogdanm 15:4892fe388435 500 }
bogdanm 15:4892fe388435 501 }
bogdanm 15:4892fe388435 502
bogdanm 15:4892fe388435 503 phy_id = (phy_read(PHY_REG_IDR1) << 16);
bogdanm 15:4892fe388435 504 phy_id |= (phy_read(PHY_REG_IDR2) & 0XFFF0);
bogdanm 15:4892fe388435 505
bogdanm 15:4892fe388435 506 if (phy_id != DP83848C_ID && phy_id != LAN8720_ID) {
bogdanm 15:4892fe388435 507 error("Unknown Ethernet PHY (%x)", (unsigned int)phy_id);
bogdanm 15:4892fe388435 508 }
bogdanm 15:4892fe388435 509
bogdanm 15:4892fe388435 510 ethernet_set_link(-1, 0);
bogdanm 15:4892fe388435 511
bogdanm 15:4892fe388435 512 /* Set the Ethernet MAC Address registers */
bogdanm 15:4892fe388435 513 ethernet_address(mac);
bogdanm 15:4892fe388435 514 LPC_EMAC->SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4];
bogdanm 15:4892fe388435 515 LPC_EMAC->SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2];
bogdanm 15:4892fe388435 516 LPC_EMAC->SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0];
bogdanm 15:4892fe388435 517
bogdanm 15:4892fe388435 518 txdscr_init(); /* initialize DMA TX Descriptor */
bogdanm 15:4892fe388435 519 rxdscr_init(); /* initialize DMA RX Descriptor */
bogdanm 15:4892fe388435 520
bogdanm 15:4892fe388435 521 LPC_EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
bogdanm 15:4892fe388435 522 /* Receive Broadcast, Perfect Match Packets */
bogdanm 15:4892fe388435 523
bogdanm 15:4892fe388435 524 LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; /* Enable EMAC interrupts. */
bogdanm 15:4892fe388435 525 LPC_EMAC->IntClear = 0xFFFF; /* Reset all interrupts */
bogdanm 15:4892fe388435 526
bogdanm 15:4892fe388435 527 LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); /* Enable receive and transmit mode of MAC Ethernet core */
bogdanm 15:4892fe388435 528 LPC_EMAC->MAC1 |= MAC1_REC_EN;
bogdanm 15:4892fe388435 529
bogdanm 15:4892fe388435 530 #if NEW_LOGIC
bogdanm 15:4892fe388435 531 rx_consume_offset = -1;
bogdanm 15:4892fe388435 532 tx_produce_offset = -1;
bogdanm 15:4892fe388435 533 #else
bogdanm 15:4892fe388435 534 send_doff = 0;
bogdanm 15:4892fe388435 535 send_idx = -1;
bogdanm 15:4892fe388435 536 send_size = 0;
bogdanm 15:4892fe388435 537
bogdanm 15:4892fe388435 538 receive_soff = 0;
bogdanm 15:4892fe388435 539 receive_idx = -1;
bogdanm 15:4892fe388435 540 #endif
bogdanm 15:4892fe388435 541
bogdanm 15:4892fe388435 542 return 0;
bogdanm 15:4892fe388435 543 }
bogdanm 15:4892fe388435 544
bogdanm 15:4892fe388435 545 /*----------------------------------------------------------------------------
bogdanm 15:4892fe388435 546 Ethernet Device Uninitialize
bogdanm 15:4892fe388435 547 *----------------------------------------------------------------------------*/
bogdanm 15:4892fe388435 548 void ethernet_free() {
bogdanm 15:4892fe388435 549 LPC_EMAC->IntEnable &= ~(INT_RX_DONE | INT_TX_DONE);
bogdanm 15:4892fe388435 550 LPC_EMAC->IntClear = 0xFFFF;
bogdanm 15:4892fe388435 551
bogdanm 15:4892fe388435 552 LPC_SC->PCONP &= ~0x40000000; /* Power down the EMAC controller. */
bogdanm 15:4892fe388435 553
bogdanm 15:4892fe388435 554 LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */
bogdanm 15:4892fe388435 555 LPC_IOCON->P1_1 &= ~0x07;
bogdanm 15:4892fe388435 556 LPC_IOCON->P1_4 &= ~0x07;
bogdanm 15:4892fe388435 557 LPC_IOCON->P1_8 &= ~0x07;
bogdanm 15:4892fe388435 558 LPC_IOCON->P1_9 &= ~0x07;
bogdanm 15:4892fe388435 559 LPC_IOCON->P1_10 &= ~0x07;
bogdanm 15:4892fe388435 560 LPC_IOCON->P1_14 &= ~0x07;
bogdanm 15:4892fe388435 561 LPC_IOCON->P1_15 &= ~0x07;
bogdanm 15:4892fe388435 562 LPC_IOCON->P1_16 &= ~0x07; /* ENET/PHY I/O config */
bogdanm 15:4892fe388435 563 LPC_IOCON->P1_17 &= ~0x07;
bogdanm 15:4892fe388435 564 }
bogdanm 15:4892fe388435 565
bogdanm 15:4892fe388435 566 // if(TxProduceIndex == TxConsumeIndex) buffer array is empty
bogdanm 15:4892fe388435 567 // if(TxProduceIndex == TxConsumeIndex - 1) buffer is full, should not fill
bogdanm 15:4892fe388435 568 // TxProduceIndex - The buffer that will/is being fileld by driver, s/w increment
bogdanm 15:4892fe388435 569 // TxConsumeIndex - The buffer that will/is beign sent by hardware
bogdanm 15:4892fe388435 570
bogdanm 15:4892fe388435 571 int ethernet_write(const char *data, int slen) {
bogdanm 15:4892fe388435 572
bogdanm 15:4892fe388435 573 #if NEW_LOGIC
bogdanm 15:4892fe388435 574
bogdanm 15:4892fe388435 575 if(tx_produce_offset < 0) { // mark as active if not already
bogdanm 15:4892fe388435 576 tx_produce_offset = 0;
bogdanm 15:4892fe388435 577 }
bogdanm 15:4892fe388435 578
bogdanm 15:4892fe388435 579 int index = LPC_EMAC->TxProduceIndex;
bogdanm 15:4892fe388435 580
bogdanm 15:4892fe388435 581 int remaining = ETH_MAX_FLEN - tx_produce_offset - 4; // bytes written plus checksum
bogdanm 15:4892fe388435 582 int requested = slen;
bogdanm 15:4892fe388435 583 int ncopy = min(remaining, requested);
bogdanm 15:4892fe388435 584
bogdanm 15:4892fe388435 585 void *pdst = (void *)(txdesc[index].Packet + tx_produce_offset);
bogdanm 15:4892fe388435 586 void *psrc = (void *)(data);
bogdanm 15:4892fe388435 587
bogdanm 15:4892fe388435 588 if(ncopy > 0 ){
bogdanm 15:4892fe388435 589 if(data != NULL) {
bogdanm 15:4892fe388435 590 memcpy(pdst, psrc, ncopy);
bogdanm 15:4892fe388435 591 } else {
bogdanm 15:4892fe388435 592 memset(pdst, 0, ncopy);
bogdanm 15:4892fe388435 593 }
bogdanm 15:4892fe388435 594 }
bogdanm 15:4892fe388435 595
bogdanm 15:4892fe388435 596 tx_produce_offset += ncopy;
bogdanm 15:4892fe388435 597
bogdanm 15:4892fe388435 598 return ncopy;
bogdanm 15:4892fe388435 599
bogdanm 15:4892fe388435 600 #else
bogdanm 15:4892fe388435 601 void *pdst, *psrc;
bogdanm 15:4892fe388435 602 const int dlen = ETH_FRAG_SIZE;
bogdanm 15:4892fe388435 603 int copy = 0;
bogdanm 15:4892fe388435 604 int soff = 0;
bogdanm 15:4892fe388435 605
bogdanm 15:4892fe388435 606 if(send_idx == -1) {
bogdanm 15:4892fe388435 607 send_idx = LPC_EMAC->TxProduceIndex;
bogdanm 15:4892fe388435 608 }
bogdanm 15:4892fe388435 609
bogdanm 15:4892fe388435 610 if(slen + send_doff > ethernet_MTU_SIZE) {
bogdanm 15:4892fe388435 611 return -1;
bogdanm 15:4892fe388435 612 }
bogdanm 15:4892fe388435 613
bogdanm 15:4892fe388435 614 do {
bogdanm 15:4892fe388435 615 copy = min(slen - soff, dlen - send_doff);
bogdanm 15:4892fe388435 616 pdst = (void *)(txdesc[send_idx].Packet + send_doff);
bogdanm 15:4892fe388435 617 psrc = (void *)(data + soff);
bogdanm 15:4892fe388435 618 if(send_doff + copy > ETH_FRAG_SIZE) {
bogdanm 15:4892fe388435 619 txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT);
bogdanm 15:4892fe388435 620 send_idx = rinc(send_idx, NUM_TX_FRAG);
bogdanm 15:4892fe388435 621 send_doff = 0;
bogdanm 15:4892fe388435 622 }
bogdanm 15:4892fe388435 623
bogdanm 15:4892fe388435 624 if(data != NULL) {
bogdanm 15:4892fe388435 625 memcpy(pdst, psrc, copy);
bogdanm 15:4892fe388435 626 } else {
bogdanm 15:4892fe388435 627 memset(pdst, 0, copy);
bogdanm 15:4892fe388435 628 }
bogdanm 15:4892fe388435 629
bogdanm 15:4892fe388435 630 soff += copy;
bogdanm 15:4892fe388435 631 send_doff += copy;
bogdanm 15:4892fe388435 632 send_size += copy;
bogdanm 15:4892fe388435 633 } while(soff != slen);
bogdanm 15:4892fe388435 634
bogdanm 15:4892fe388435 635 return soff;
bogdanm 15:4892fe388435 636 #endif
bogdanm 15:4892fe388435 637 }
bogdanm 15:4892fe388435 638
bogdanm 15:4892fe388435 639 int ethernet_send() {
bogdanm 15:4892fe388435 640
bogdanm 15:4892fe388435 641 #if NEW_LOGIC
bogdanm 15:4892fe388435 642 if(tx_produce_offset < 0) { // no buffer active
bogdanm 15:4892fe388435 643 return -1;
bogdanm 15:4892fe388435 644 }
bogdanm 15:4892fe388435 645
bogdanm 15:4892fe388435 646 // ensure there is a link
bogdanm 15:4892fe388435 647 if(!ethernet_link()) {
bogdanm 15:4892fe388435 648 return -2;
bogdanm 15:4892fe388435 649 }
bogdanm 15:4892fe388435 650
bogdanm 15:4892fe388435 651 // we have been writing in to a buffer, so finalise it
bogdanm 15:4892fe388435 652 int size = tx_produce_offset;
bogdanm 15:4892fe388435 653 int index = LPC_EMAC->TxProduceIndex;
bogdanm 15:4892fe388435 654 txdesc[index].Ctrl = (tx_produce_offset-1) | (TCTRL_INT | TCTRL_LAST);
bogdanm 15:4892fe388435 655
bogdanm 15:4892fe388435 656 // Increment ProduceIndex to allow it to be sent
bogdanm 15:4892fe388435 657 // We can only do this if the next slot is free
bogdanm 15:4892fe388435 658 int next = rinc(index, NUM_TX_FRAG);
bogdanm 15:4892fe388435 659 while(next == LPC_EMAC->TxConsumeIndex) {
bogdanm 15:4892fe388435 660 for(int i=0; i<1000; i++) { __NOP(); }
bogdanm 15:4892fe388435 661 }
bogdanm 15:4892fe388435 662
bogdanm 15:4892fe388435 663 LPC_EMAC->TxProduceIndex = next;
bogdanm 15:4892fe388435 664 tx_produce_offset = -1;
bogdanm 15:4892fe388435 665 return size;
bogdanm 15:4892fe388435 666
bogdanm 15:4892fe388435 667 #else
bogdanm 15:4892fe388435 668 int s = send_size;
bogdanm 15:4892fe388435 669 txdesc[send_idx].Ctrl = (send_doff-1) | (TCTRL_INT | TCTRL_LAST);
bogdanm 15:4892fe388435 670 send_idx = rinc(send_idx, NUM_TX_FRAG);
bogdanm 15:4892fe388435 671 LPC_EMAC->TxProduceIndex = send_idx;
bogdanm 15:4892fe388435 672 send_doff = 0;
bogdanm 15:4892fe388435 673 send_idx = -1;
bogdanm 15:4892fe388435 674 send_size = 0;
bogdanm 15:4892fe388435 675 return s;
bogdanm 15:4892fe388435 676 #endif
bogdanm 15:4892fe388435 677 }
bogdanm 15:4892fe388435 678
bogdanm 15:4892fe388435 679 // RxConsmeIndex - The index of buffer the driver will/is reading from. Driver should inc once read
bogdanm 15:4892fe388435 680 // RxProduceIndex - The index of buffer that will/is being filled by MAC. H/w will inc once rxd
bogdanm 15:4892fe388435 681 //
bogdanm 15:4892fe388435 682 // if(RxConsumeIndex == RxProduceIndex) buffer array is empty
bogdanm 15:4892fe388435 683 // if(RxConsumeIndex == RxProduceIndex + 1) buffer array is full
bogdanm 15:4892fe388435 684
bogdanm 15:4892fe388435 685 // Recevies an arrived ethernet packet.
bogdanm 15:4892fe388435 686 // Receiving an ethernet packet will drop the last received ethernet packet
bogdanm 15:4892fe388435 687 // and make a new ethernet packet ready to read.
bogdanm 15:4892fe388435 688 // Returns size of packet, else 0 if nothing to receive
bogdanm 15:4892fe388435 689
bogdanm 15:4892fe388435 690 // We read from RxConsumeIndex from position rx_consume_offset
bogdanm 15:4892fe388435 691 // if rx_consume_offset < 0, then we have not recieved the RxConsumeIndex packet for reading
bogdanm 15:4892fe388435 692 // rx_consume_offset = -1 // no frame
bogdanm 15:4892fe388435 693 // rx_consume_offset = 0 // start of frame
bogdanm 15:4892fe388435 694 // Assumption: A fragment should alway be a whole frame
bogdanm 15:4892fe388435 695
bogdanm 15:4892fe388435 696 int ethernet_receive() {
bogdanm 15:4892fe388435 697 #if NEW_LOGIC
bogdanm 15:4892fe388435 698
bogdanm 15:4892fe388435 699 // if we are currently reading a valid RxConsume buffer, increment to the next one
bogdanm 15:4892fe388435 700 if(rx_consume_offset >= 0) {
bogdanm 15:4892fe388435 701 LPC_EMAC->RxConsumeIndex = rinc(LPC_EMAC->RxConsumeIndex, NUM_RX_FRAG);
bogdanm 15:4892fe388435 702 }
bogdanm 15:4892fe388435 703
bogdanm 15:4892fe388435 704 // if the buffer is empty, mark it as no valid buffer
bogdanm 15:4892fe388435 705 if(LPC_EMAC->RxConsumeIndex == LPC_EMAC->RxProduceIndex) {
bogdanm 15:4892fe388435 706 rx_consume_offset = -1;
bogdanm 15:4892fe388435 707 return 0;
bogdanm 15:4892fe388435 708 }
bogdanm 15:4892fe388435 709
bogdanm 15:4892fe388435 710 uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
bogdanm 15:4892fe388435 711 rx_consume_offset = 0;
bogdanm 15:4892fe388435 712
bogdanm 15:4892fe388435 713 // check if it is not marked as last or for errors
bogdanm 15:4892fe388435 714 if(!(info & RINFO_LAST_FLAG) || (info & RINFO_ERR_MASK)) {
bogdanm 15:4892fe388435 715 return -1;
bogdanm 15:4892fe388435 716 }
bogdanm 15:4892fe388435 717
bogdanm 15:4892fe388435 718 int size = (info & RINFO_SIZE) + 1;
bogdanm 15:4892fe388435 719 return size - 4; // don't include checksum bytes
bogdanm 15:4892fe388435 720
bogdanm 15:4892fe388435 721 #else
bogdanm 15:4892fe388435 722 if(receive_idx == -1) {
bogdanm 15:4892fe388435 723 receive_idx = LPC_EMAC->RxConsumeIndex;
bogdanm 15:4892fe388435 724 } else {
mbed_official 29:6ac4027eff2b 725 while(!(rxstat[receive_idx].Info & RINFO_LAST_FLAG) && ((uint32_t)receive_idx != LPC_EMAC->RxProduceIndex)) {
bogdanm 15:4892fe388435 726 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
bogdanm 15:4892fe388435 727 }
bogdanm 15:4892fe388435 728 unsigned int info = rxstat[receive_idx].Info;
bogdanm 15:4892fe388435 729 int slen = (info & RINFO_SIZE) + 1;
bogdanm 15:4892fe388435 730
bogdanm 15:4892fe388435 731 if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
bogdanm 15:4892fe388435 732 /* Invalid frame, ignore it and free buffer. */
bogdanm 15:4892fe388435 733 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
bogdanm 15:4892fe388435 734 }
bogdanm 15:4892fe388435 735 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
bogdanm 15:4892fe388435 736 receive_soff = 0;
bogdanm 15:4892fe388435 737
bogdanm 15:4892fe388435 738 LPC_EMAC->RxConsumeIndex = receive_idx;
bogdanm 15:4892fe388435 739 }
bogdanm 15:4892fe388435 740
mbed_official 29:6ac4027eff2b 741 if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex) {
bogdanm 15:4892fe388435 742 receive_idx = -1;
bogdanm 15:4892fe388435 743 return 0;
bogdanm 15:4892fe388435 744 }
bogdanm 15:4892fe388435 745
bogdanm 15:4892fe388435 746 return (rxstat[receive_idx].Info & RINFO_SIZE) - 3;
bogdanm 15:4892fe388435 747 #endif
bogdanm 15:4892fe388435 748 }
bogdanm 15:4892fe388435 749
bogdanm 15:4892fe388435 750 // Read from an recevied ethernet packet.
bogdanm 15:4892fe388435 751 // After receive returnd a number bigger than 0 it is
bogdanm 15:4892fe388435 752 // possible to read bytes from this packet.
bogdanm 15:4892fe388435 753 // Read will write up to size bytes into data.
bogdanm 15:4892fe388435 754 // It is possible to use read multible times.
bogdanm 15:4892fe388435 755 // Each time read will start reading after the last read byte before.
bogdanm 15:4892fe388435 756
bogdanm 15:4892fe388435 757 int ethernet_read(char *data, int dlen) {
bogdanm 15:4892fe388435 758 #if NEW_LOGIC
bogdanm 15:4892fe388435 759 // Check we have a valid buffer to read
bogdanm 15:4892fe388435 760 if(rx_consume_offset < 0) {
bogdanm 15:4892fe388435 761 return 0;
bogdanm 15:4892fe388435 762 }
bogdanm 15:4892fe388435 763
bogdanm 15:4892fe388435 764 // Assume 1 fragment block
bogdanm 15:4892fe388435 765 uint32_t info = rxstat[LPC_EMAC->RxConsumeIndex].Info;
bogdanm 15:4892fe388435 766 int size = (info & RINFO_SIZE) + 1 - 4; // exclude checksum
bogdanm 15:4892fe388435 767
bogdanm 15:4892fe388435 768 int remaining = size - rx_consume_offset;
bogdanm 15:4892fe388435 769 int requested = dlen;
bogdanm 15:4892fe388435 770 int ncopy = min(remaining, requested);
bogdanm 15:4892fe388435 771
bogdanm 15:4892fe388435 772 void *psrc = (void *)(rxdesc[LPC_EMAC->RxConsumeIndex].Packet + rx_consume_offset);
bogdanm 15:4892fe388435 773 void *pdst = (void *)(data);
bogdanm 15:4892fe388435 774
bogdanm 15:4892fe388435 775 if(data != NULL && ncopy > 0) {
bogdanm 15:4892fe388435 776 memcpy(pdst, psrc, ncopy);
bogdanm 15:4892fe388435 777 }
bogdanm 15:4892fe388435 778
bogdanm 15:4892fe388435 779 rx_consume_offset += ncopy;
bogdanm 15:4892fe388435 780
bogdanm 15:4892fe388435 781 return ncopy;
bogdanm 15:4892fe388435 782 #else
bogdanm 15:4892fe388435 783 int slen;
bogdanm 15:4892fe388435 784 int copy = 0;
bogdanm 15:4892fe388435 785 unsigned int more;
bogdanm 15:4892fe388435 786 unsigned int info;
bogdanm 15:4892fe388435 787 void *pdst, *psrc;
bogdanm 15:4892fe388435 788 int doff = 0;
bogdanm 15:4892fe388435 789
mbed_official 29:6ac4027eff2b 790 if((uint32_t)receive_idx == LPC_EMAC->RxProduceIndex || receive_idx == -1) {
bogdanm 15:4892fe388435 791 return 0;
bogdanm 15:4892fe388435 792 }
bogdanm 15:4892fe388435 793
bogdanm 15:4892fe388435 794 do {
bogdanm 15:4892fe388435 795 info = rxstat[receive_idx].Info;
bogdanm 15:4892fe388435 796 more = !(info & RINFO_LAST_FLAG);
bogdanm 15:4892fe388435 797 slen = (info & RINFO_SIZE) + 1;
bogdanm 15:4892fe388435 798
bogdanm 15:4892fe388435 799 if(slen > ethernet_MTU_SIZE || (info & RINFO_ERR_MASK)) {
bogdanm 15:4892fe388435 800 /* Invalid frame, ignore it and free buffer. */
bogdanm 15:4892fe388435 801 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
bogdanm 15:4892fe388435 802 } else {
bogdanm 15:4892fe388435 803
bogdanm 15:4892fe388435 804 copy = min(slen - receive_soff, dlen - doff);
bogdanm 15:4892fe388435 805 psrc = (void *)(rxdesc[receive_idx].Packet + receive_soff);
bogdanm 15:4892fe388435 806 pdst = (void *)(data + doff);
bogdanm 15:4892fe388435 807
bogdanm 15:4892fe388435 808 if(data != NULL) {
bogdanm 15:4892fe388435 809 /* check if Buffer available */
bogdanm 15:4892fe388435 810 memcpy(pdst, psrc, copy);
bogdanm 15:4892fe388435 811 }
bogdanm 15:4892fe388435 812
bogdanm 15:4892fe388435 813 receive_soff += copy;
bogdanm 15:4892fe388435 814 doff += copy;
bogdanm 15:4892fe388435 815
bogdanm 15:4892fe388435 816 if((more && (receive_soff == slen))) {
bogdanm 15:4892fe388435 817 receive_idx = rinc(receive_idx, NUM_RX_FRAG);
bogdanm 15:4892fe388435 818 receive_soff = 0;
bogdanm 15:4892fe388435 819 }
bogdanm 15:4892fe388435 820 }
bogdanm 15:4892fe388435 821 } while(more && !(doff == dlen) && !receive_soff);
bogdanm 15:4892fe388435 822
bogdanm 15:4892fe388435 823 return doff;
bogdanm 15:4892fe388435 824 #endif
bogdanm 15:4892fe388435 825 }
bogdanm 15:4892fe388435 826
bogdanm 15:4892fe388435 827 int ethernet_link(void) {
bogdanm 15:4892fe388435 828
bogdanm 15:4892fe388435 829 if (phy_id == DP83848C_ID) {
bogdanm 15:4892fe388435 830 return (phy_read(PHY_REG_STS) & PHY_STS_LINK);
bogdanm 15:4892fe388435 831 }
bogdanm 15:4892fe388435 832 else { // LAN8720_ID
bogdanm 15:4892fe388435 833 return (phy_read(PHY_REG_BMSR) & PHY_BMSR_LINK);
bogdanm 15:4892fe388435 834 }
bogdanm 15:4892fe388435 835 }
bogdanm 15:4892fe388435 836
bogdanm 15:4892fe388435 837 static int phy_write(unsigned int PhyReg, unsigned short Data) {
bogdanm 15:4892fe388435 838 unsigned int timeOut;
bogdanm 15:4892fe388435 839
bogdanm 15:4892fe388435 840 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
bogdanm 15:4892fe388435 841 LPC_EMAC->MWTD = Data;
bogdanm 15:4892fe388435 842
bogdanm 15:4892fe388435 843 for(timeOut = 0; timeOut < MII_WR_TOUT; timeOut++) { /* Wait until operation completed */
bogdanm 15:4892fe388435 844 if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
bogdanm 15:4892fe388435 845 return 0;
bogdanm 15:4892fe388435 846 }
bogdanm 15:4892fe388435 847 }
bogdanm 15:4892fe388435 848
bogdanm 15:4892fe388435 849 return -1;
bogdanm 15:4892fe388435 850 }
bogdanm 15:4892fe388435 851
bogdanm 15:4892fe388435 852
bogdanm 15:4892fe388435 853 static int phy_read(unsigned int PhyReg) {
bogdanm 15:4892fe388435 854 unsigned int timeOut;
bogdanm 15:4892fe388435 855
bogdanm 15:4892fe388435 856 LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
bogdanm 15:4892fe388435 857 LPC_EMAC->MCMD = MCMD_READ;
bogdanm 15:4892fe388435 858
bogdanm 15:4892fe388435 859 for(timeOut = 0; timeOut < MII_RD_TOUT; timeOut++) { /* Wait until operation completed */
bogdanm 15:4892fe388435 860 if((LPC_EMAC->MIND & MIND_BUSY) == 0) {
bogdanm 15:4892fe388435 861 LPC_EMAC->MCMD = 0;
bogdanm 15:4892fe388435 862 return LPC_EMAC->MRDD; /* Return a 16-bit value. */
bogdanm 15:4892fe388435 863 }
bogdanm 15:4892fe388435 864 }
bogdanm 15:4892fe388435 865
bogdanm 15:4892fe388435 866 return -1;
bogdanm 15:4892fe388435 867 }
bogdanm 15:4892fe388435 868
bogdanm 15:4892fe388435 869
bogdanm 15:4892fe388435 870 static void txdscr_init() {
bogdanm 15:4892fe388435 871 int i;
bogdanm 15:4892fe388435 872
bogdanm 15:4892fe388435 873 for(i = 0; i < NUM_TX_FRAG; i++) {
bogdanm 15:4892fe388435 874 txdesc[i].Packet = (uint32_t)&txbuf[i];
bogdanm 15:4892fe388435 875 txdesc[i].Ctrl = 0;
bogdanm 15:4892fe388435 876 txstat[i].Info = 0;
bogdanm 15:4892fe388435 877 }
bogdanm 15:4892fe388435 878
bogdanm 15:4892fe388435 879 LPC_EMAC->TxDescriptor = (uint32_t)txdesc; /* Set EMAC Transmit Descriptor Registers. */
bogdanm 15:4892fe388435 880 LPC_EMAC->TxStatus = (uint32_t)txstat;
bogdanm 15:4892fe388435 881 LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1;
bogdanm 15:4892fe388435 882
bogdanm 15:4892fe388435 883 LPC_EMAC->TxProduceIndex = 0; /* Tx Descriptors Point to 0 */
bogdanm 15:4892fe388435 884 }
bogdanm 15:4892fe388435 885
bogdanm 15:4892fe388435 886
bogdanm 15:4892fe388435 887 static void rxdscr_init() {
bogdanm 15:4892fe388435 888 int i;
bogdanm 15:4892fe388435 889
bogdanm 15:4892fe388435 890 for(i = 0; i < NUM_RX_FRAG; i++) {
bogdanm 15:4892fe388435 891 rxdesc[i].Packet = (uint32_t)&rxbuf[i];
bogdanm 15:4892fe388435 892 rxdesc[i].Ctrl = RCTRL_INT | (ETH_FRAG_SIZE-1);
bogdanm 15:4892fe388435 893 rxstat[i].Info = 0;
bogdanm 15:4892fe388435 894 rxstat[i].HashCRC = 0;
bogdanm 15:4892fe388435 895 }
bogdanm 15:4892fe388435 896
bogdanm 15:4892fe388435 897 LPC_EMAC->RxDescriptor = (uint32_t)rxdesc; /* Set EMAC Receive Descriptor Registers. */
bogdanm 15:4892fe388435 898 LPC_EMAC->RxStatus = (uint32_t)rxstat;
bogdanm 15:4892fe388435 899 LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1;
bogdanm 15:4892fe388435 900
bogdanm 15:4892fe388435 901 LPC_EMAC->RxConsumeIndex = 0; /* Rx Descriptors Point to 0 */
bogdanm 15:4892fe388435 902 }
bogdanm 15:4892fe388435 903
bogdanm 15:4892fe388435 904 void ethernet_address(char *mac) {
bogdanm 15:4892fe388435 905 mbed_mac_address(mac);
bogdanm 15:4892fe388435 906 }
bogdanm 15:4892fe388435 907
bogdanm 15:4892fe388435 908 void ethernet_set_link(int speed, int duplex) {
bogdanm 15:4892fe388435 909 unsigned short phy_data;
bogdanm 15:4892fe388435 910 int tout;
bogdanm 15:4892fe388435 911
bogdanm 15:4892fe388435 912 if((speed < 0) || (speed > 1)) {
bogdanm 15:4892fe388435 913 phy_data = PHY_AUTO_NEG;
bogdanm 15:4892fe388435 914 } else {
bogdanm 15:4892fe388435 915 phy_data = (((unsigned short) speed << 13) |
bogdanm 15:4892fe388435 916 ((unsigned short) duplex << 8));
bogdanm 15:4892fe388435 917 }
bogdanm 15:4892fe388435 918
bogdanm 15:4892fe388435 919 phy_write(PHY_REG_BMCR, phy_data);
bogdanm 15:4892fe388435 920
bogdanm 15:4892fe388435 921 for (tout = 100; tout; tout--) { __NOP(); } /* A short delay */
bogdanm 15:4892fe388435 922
bogdanm 15:4892fe388435 923 switch(phy_id) {
bogdanm 15:4892fe388435 924 case DP83848C_ID:
bogdanm 15:4892fe388435 925 phy_data = phy_read(PHY_REG_STS);
bogdanm 15:4892fe388435 926
bogdanm 15:4892fe388435 927 if(phy_data & PHY_STS_DUPLEX) {
bogdanm 15:4892fe388435 928 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
bogdanm 15:4892fe388435 929 LPC_EMAC->Command |= CR_FULL_DUP;
bogdanm 15:4892fe388435 930 LPC_EMAC->IPGT = IPGT_FULL_DUP;
bogdanm 15:4892fe388435 931 } else {
bogdanm 15:4892fe388435 932 LPC_EMAC->MAC2 &= ~MAC2_FULL_DUP;
bogdanm 15:4892fe388435 933 LPC_EMAC->Command &= ~CR_FULL_DUP;
bogdanm 15:4892fe388435 934 LPC_EMAC->IPGT = IPGT_HALF_DUP;
bogdanm 15:4892fe388435 935 }
bogdanm 15:4892fe388435 936
bogdanm 15:4892fe388435 937 if(phy_data & PHY_STS_SPEED) {
bogdanm 15:4892fe388435 938 LPC_EMAC->SUPP &= ~SUPP_SPEED;
bogdanm 15:4892fe388435 939 } else {
bogdanm 15:4892fe388435 940 LPC_EMAC->SUPP |= SUPP_SPEED;
bogdanm 15:4892fe388435 941 }
bogdanm 15:4892fe388435 942 break;
bogdanm 15:4892fe388435 943
bogdanm 15:4892fe388435 944 case LAN8720_ID:
bogdanm 15:4892fe388435 945 phy_data = phy_read(PHY_REG_SCSR);
bogdanm 15:4892fe388435 946
bogdanm 15:4892fe388435 947 if (phy_data & PHY_SCSR_DUPLEX) {
bogdanm 15:4892fe388435 948 LPC_EMAC->MAC2 |= MAC2_FULL_DUP;
bogdanm 15:4892fe388435 949 LPC_EMAC->Command |= CR_FULL_DUP;
bogdanm 15:4892fe388435 950 LPC_EMAC->IPGT = IPGT_FULL_DUP;
bogdanm 15:4892fe388435 951 } else {
bogdanm 15:4892fe388435 952 LPC_EMAC->Command &= ~CR_FULL_DUP;
bogdanm 15:4892fe388435 953 LPC_EMAC->IPGT = IPGT_HALF_DUP;
bogdanm 15:4892fe388435 954 }
bogdanm 15:4892fe388435 955
bogdanm 15:4892fe388435 956 if(phy_data & PHY_SCSR_100MBIT) {
bogdanm 15:4892fe388435 957 LPC_EMAC->SUPP |= SUPP_SPEED;
bogdanm 15:4892fe388435 958 } else {
bogdanm 15:4892fe388435 959 LPC_EMAC->SUPP &= ~SUPP_SPEED;
bogdanm 15:4892fe388435 960 }
bogdanm 15:4892fe388435 961
bogdanm 15:4892fe388435 962 break;
bogdanm 15:4892fe388435 963 }
bogdanm 15:4892fe388435 964 }
mbed_official 22:dbd009839d5e 965
mbed_official 22:dbd009839d5e 966 /*
mbed_official 22:dbd009839d5e 967 * The Embedded Artists LPC4088 QuickStart Board has an eeprom with a unique
mbed_official 22:dbd009839d5e 968 * 48 bit ID. This ID is used as MAC address.
mbed_official 22:dbd009839d5e 969 */
mbed_official 22:dbd009839d5e 970
mbed_official 22:dbd009839d5e 971 #include "i2c_api.h"
mbed_official 22:dbd009839d5e 972
mbed_official 22:dbd009839d5e 973 static int _macRetrieved = 0;
mbed_official 22:dbd009839d5e 974 static char _macAddr[6] = {0x00,0x02,0xF7,0xF0,0x00,0x00};
mbed_official 22:dbd009839d5e 975 #define EEPROM_24AA02E48_ADDR (0xA0)
mbed_official 22:dbd009839d5e 976
mbed_official 22:dbd009839d5e 977 void mbed_mac_address(char *mac) {
mbed_official 22:dbd009839d5e 978
mbed_official 22:dbd009839d5e 979 if (_macRetrieved == 0) {
mbed_official 22:dbd009839d5e 980 char tmp[6];
mbed_official 22:dbd009839d5e 981 i2c_t i2cObj;
mbed_official 22:dbd009839d5e 982
mbed_official 22:dbd009839d5e 983 i2c_init(&i2cObj, P0_27, P0_28);
mbed_official 22:dbd009839d5e 984
mbed_official 22:dbd009839d5e 985 do {
mbed_official 22:dbd009839d5e 986 // the unique ID is at offset 0xFA
mbed_official 22:dbd009839d5e 987 tmp[0] = 0xFA;
mbed_official 22:dbd009839d5e 988 if (i2c_write(&i2cObj, EEPROM_24AA02E48_ADDR, tmp, 1, 1) != 1) {
mbed_official 22:dbd009839d5e 989 break; // failed to write
mbed_official 22:dbd009839d5e 990 }
mbed_official 22:dbd009839d5e 991
mbed_official 22:dbd009839d5e 992
mbed_official 22:dbd009839d5e 993 if (i2c_read(&i2cObj, EEPROM_24AA02E48_ADDR, tmp, 6, 1) != 6) {
mbed_official 22:dbd009839d5e 994 break; // failed to read
mbed_official 22:dbd009839d5e 995 }
mbed_official 22:dbd009839d5e 996
mbed_official 22:dbd009839d5e 997 memcpy(_macAddr, tmp, 6);
mbed_official 22:dbd009839d5e 998
mbed_official 22:dbd009839d5e 999 } while(0);
mbed_official 22:dbd009839d5e 1000
mbed_official 22:dbd009839d5e 1001 // We always consider the MAC address to be retrieved even though
mbed_official 22:dbd009839d5e 1002 // reading from the eeprom failed. If it wasn't possible to read
mbed_official 22:dbd009839d5e 1003 // from eeprom the default address will be used.
mbed_official 22:dbd009839d5e 1004 _macRetrieved = 1;
mbed_official 22:dbd009839d5e 1005 }
mbed_official 22:dbd009839d5e 1006
mbed_official 22:dbd009839d5e 1007 memcpy(mac, _macAddr, 6);
mbed_official 22:dbd009839d5e 1008 }