Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file lm3s_eth.c
Sergunb 0:8918a71cdbe9 3 * @brief Luminary Stellaris LM3S Ethernet controller
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 26 * @version 1.7.6
Sergunb 0:8918a71cdbe9 27 **/
Sergunb 0:8918a71cdbe9 28
Sergunb 0:8918a71cdbe9 29 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 30 #define TRACE_LEVEL NIC_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 31
Sergunb 0:8918a71cdbe9 32 //LM3S6965 device?
Sergunb 0:8918a71cdbe9 33 #if defined(LM3S6965)
Sergunb 0:8918a71cdbe9 34 #include "lm3s6965.h"
Sergunb 0:8918a71cdbe9 35 //LM3S9B92 device?
Sergunb 0:8918a71cdbe9 36 #elif defined(LM3S9B92)
Sergunb 0:8918a71cdbe9 37 #include "lm3s9b92.h"
Sergunb 0:8918a71cdbe9 38 #endif
Sergunb 0:8918a71cdbe9 39
Sergunb 0:8918a71cdbe9 40 //Dependencies
Sergunb 0:8918a71cdbe9 41 #include "inc/hw_ints.h"
Sergunb 0:8918a71cdbe9 42 #include "inc/hw_memmap.h"
Sergunb 0:8918a71cdbe9 43 #include "inc/hw_types.h"
Sergunb 0:8918a71cdbe9 44 #include "driverlib/gpio.h"
Sergunb 0:8918a71cdbe9 45 #include "driverlib/interrupt.h"
Sergunb 0:8918a71cdbe9 46 #include "driverlib/sysctl.h"
Sergunb 0:8918a71cdbe9 47 #include "core/net.h"
Sergunb 0:8918a71cdbe9 48 #include "drivers/lm3s_eth.h"
Sergunb 0:8918a71cdbe9 49 #include "debug.h"
Sergunb 0:8918a71cdbe9 50
Sergunb 0:8918a71cdbe9 51 //Underlying network interface
Sergunb 0:8918a71cdbe9 52 static NetInterface *nicDriverInterface;
Sergunb 0:8918a71cdbe9 53
Sergunb 0:8918a71cdbe9 54 //IAR EWARM compiler?
Sergunb 0:8918a71cdbe9 55 #if defined(__ICCARM__)
Sergunb 0:8918a71cdbe9 56
Sergunb 0:8918a71cdbe9 57 //Transmit buffer
Sergunb 0:8918a71cdbe9 58 #pragma data_alignment = 4
Sergunb 0:8918a71cdbe9 59 static uint8_t txBuffer[ETH_MAX_FRAME_SIZE + 2];
Sergunb 0:8918a71cdbe9 60 //Receive buffer
Sergunb 0:8918a71cdbe9 61 #pragma data_alignment = 4
Sergunb 0:8918a71cdbe9 62 static uint8_t rxBuffer[ETH_MAX_FRAME_SIZE];
Sergunb 0:8918a71cdbe9 63
Sergunb 0:8918a71cdbe9 64 //Keil MDK-ARM or GCC compiler?
Sergunb 0:8918a71cdbe9 65 #else
Sergunb 0:8918a71cdbe9 66
Sergunb 0:8918a71cdbe9 67 //Transmit buffer
Sergunb 0:8918a71cdbe9 68 static uint8_t txBuffer[ETH_MAX_FRAME_SIZE + 2] __attribute__((aligned(4)));
Sergunb 0:8918a71cdbe9 69 //Receive buffer
Sergunb 0:8918a71cdbe9 70 static uint8_t rxBuffer[ETH_MAX_FRAME_SIZE] __attribute__((aligned(4)));
Sergunb 0:8918a71cdbe9 71
Sergunb 0:8918a71cdbe9 72 #endif
Sergunb 0:8918a71cdbe9 73
Sergunb 0:8918a71cdbe9 74
Sergunb 0:8918a71cdbe9 75 /**
Sergunb 0:8918a71cdbe9 76 * @brief Stellaris LM3S Ethernet driver
Sergunb 0:8918a71cdbe9 77 **/
Sergunb 0:8918a71cdbe9 78
Sergunb 0:8918a71cdbe9 79 const NicDriver lm3sEthDriver =
Sergunb 0:8918a71cdbe9 80 {
Sergunb 0:8918a71cdbe9 81 NIC_TYPE_ETHERNET,
Sergunb 0:8918a71cdbe9 82 ETH_MTU,
Sergunb 0:8918a71cdbe9 83 lm3sEthInit,
Sergunb 0:8918a71cdbe9 84 lm3sEthTick,
Sergunb 0:8918a71cdbe9 85 lm3sEthEnableIrq,
Sergunb 0:8918a71cdbe9 86 lm3sEthDisableIrq,
Sergunb 0:8918a71cdbe9 87 lm3sEthEventHandler,
Sergunb 0:8918a71cdbe9 88 lm3sEthSendPacket,
Sergunb 0:8918a71cdbe9 89 lm3sEthSetMulticastFilter,
Sergunb 0:8918a71cdbe9 90 NULL,
Sergunb 0:8918a71cdbe9 91 NULL,
Sergunb 0:8918a71cdbe9 92 NULL,
Sergunb 0:8918a71cdbe9 93 TRUE,
Sergunb 0:8918a71cdbe9 94 TRUE,
Sergunb 0:8918a71cdbe9 95 TRUE,
Sergunb 0:8918a71cdbe9 96 FALSE
Sergunb 0:8918a71cdbe9 97 };
Sergunb 0:8918a71cdbe9 98
Sergunb 0:8918a71cdbe9 99
Sergunb 0:8918a71cdbe9 100 /**
Sergunb 0:8918a71cdbe9 101 * @brief Stellaris LM3S Ethernet controller initialization
Sergunb 0:8918a71cdbe9 102 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 103 * @return Error code
Sergunb 0:8918a71cdbe9 104 **/
Sergunb 0:8918a71cdbe9 105
Sergunb 0:8918a71cdbe9 106 error_t lm3sEthInit(NetInterface *interface)
Sergunb 0:8918a71cdbe9 107 {
Sergunb 0:8918a71cdbe9 108 uint_t div;
Sergunb 0:8918a71cdbe9 109
Sergunb 0:8918a71cdbe9 110 //Debug message
Sergunb 0:8918a71cdbe9 111 TRACE_INFO("Initializing Stellaris LM3S Ethernet controller...\r\n");
Sergunb 0:8918a71cdbe9 112
Sergunb 0:8918a71cdbe9 113 //Save underlying network interface
Sergunb 0:8918a71cdbe9 114 nicDriverInterface = interface;
Sergunb 0:8918a71cdbe9 115
Sergunb 0:8918a71cdbe9 116 //Enable Ethernet controller clock
Sergunb 0:8918a71cdbe9 117 SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
Sergunb 0:8918a71cdbe9 118 //Reset Ethernet controller
Sergunb 0:8918a71cdbe9 119 SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
Sergunb 0:8918a71cdbe9 120
Sergunb 0:8918a71cdbe9 121 //GPIO configuration
Sergunb 0:8918a71cdbe9 122 lm3sEthInitGpio(interface);
Sergunb 0:8918a71cdbe9 123
Sergunb 0:8918a71cdbe9 124 //The MDC clock frequency cannot exceed 2.5MHz
Sergunb 0:8918a71cdbe9 125 div = SysCtlClockGet() / (2 * 2500000) - 1;
Sergunb 0:8918a71cdbe9 126 //Adjust MDC clock frequency
Sergunb 0:8918a71cdbe9 127 MAC_MDV_R = div & MAC_MDV_DIV_M;
Sergunb 0:8918a71cdbe9 128
Sergunb 0:8918a71cdbe9 129 //Reset PHY transceiver
Sergunb 0:8918a71cdbe9 130 lm3sEthWritePhyReg(PHY_MR0, PHY_MR0_RESET);
Sergunb 0:8918a71cdbe9 131 //Wait for the reset to complete
Sergunb 0:8918a71cdbe9 132 while(lm3sEthReadPhyReg(PHY_MR0) & PHY_MR0_RESET);
Sergunb 0:8918a71cdbe9 133
Sergunb 0:8918a71cdbe9 134 //Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 135 lm3sEthDumpPhyReg();
Sergunb 0:8918a71cdbe9 136
Sergunb 0:8918a71cdbe9 137 //Configure LED0 and LED1
Sergunb 0:8918a71cdbe9 138 lm3sEthWritePhyReg(PHY_MR23, PHY_MR23_LED0_RXTX | PHY_MR23_LED1_LINK);
Sergunb 0:8918a71cdbe9 139
Sergunb 0:8918a71cdbe9 140 //Set the MAC address
Sergunb 0:8918a71cdbe9 141 MAC_IA0_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
Sergunb 0:8918a71cdbe9 142 MAC_IA1_R = interface->macAddr.w[2];
Sergunb 0:8918a71cdbe9 143
Sergunb 0:8918a71cdbe9 144 //Enable automatic CRC generation and packet padding
Sergunb 0:8918a71cdbe9 145 MAC_TCTL_R = MAC_TCTL_DUPLEX | MAC_TCTL_CRC | MAC_TCTL_PADEN;
Sergunb 0:8918a71cdbe9 146 //Flush the receive FIFO and enable CRC verification
Sergunb 0:8918a71cdbe9 147 MAC_RCTL_R = MAC_RCTL_RSTFIFO | MAC_RCTL_BADCRC;
Sergunb 0:8918a71cdbe9 148
Sergunb 0:8918a71cdbe9 149 //Configure Ethernet interrupts
Sergunb 0:8918a71cdbe9 150 MAC_IM_R = MAC_IM_PHYINTM | MAC_IM_TXEMPM | MAC_IM_RXINTM;
Sergunb 0:8918a71cdbe9 151 //Configure PHY interrupts
Sergunb 0:8918a71cdbe9 152 lm3sEthWritePhyReg(PHY_MR17, PHY_MR17_LSCHG_IE);
Sergunb 0:8918a71cdbe9 153
Sergunb 0:8918a71cdbe9 154 //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
Sergunb 0:8918a71cdbe9 155 IntPriorityGroupingSet(LM3S_ETH_IRQ_PRIORITY_GROUPING);
Sergunb 0:8918a71cdbe9 156 //Configure Ethernet interrupt priority
Sergunb 0:8918a71cdbe9 157 IntPrioritySet(INT_ETH, LM3S_ETH_IRQ_PRIORITY);
Sergunb 0:8918a71cdbe9 158
Sergunb 0:8918a71cdbe9 159 //Enable transmitter
Sergunb 0:8918a71cdbe9 160 MAC_TCTL_R |= MAC_TCTL_TXEN;
Sergunb 0:8918a71cdbe9 161 //Enable receiver
Sergunb 0:8918a71cdbe9 162 MAC_RCTL_R |= MAC_RCTL_RXEN;
Sergunb 0:8918a71cdbe9 163
Sergunb 0:8918a71cdbe9 164 //Accept any packets from the upper layer
Sergunb 0:8918a71cdbe9 165 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 166
Sergunb 0:8918a71cdbe9 167 //Successful initialization
Sergunb 0:8918a71cdbe9 168 return NO_ERROR;
Sergunb 0:8918a71cdbe9 169 }
Sergunb 0:8918a71cdbe9 170
Sergunb 0:8918a71cdbe9 171
Sergunb 0:8918a71cdbe9 172 //EK-LM3S6965 evaluation board?
Sergunb 0:8918a71cdbe9 173 #if defined(USE_EK_LM3S6965)
Sergunb 0:8918a71cdbe9 174
Sergunb 0:8918a71cdbe9 175 /**
Sergunb 0:8918a71cdbe9 176 * @brief GPIO configuration
Sergunb 0:8918a71cdbe9 177 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 178 **/
Sergunb 0:8918a71cdbe9 179
Sergunb 0:8918a71cdbe9 180 void lm3sEthInitGpio(NetInterface *interface)
Sergunb 0:8918a71cdbe9 181 {
Sergunb 0:8918a71cdbe9 182 //Enable GPIO clock
Sergunb 0:8918a71cdbe9 183 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
Sergunb 0:8918a71cdbe9 184
Sergunb 0:8918a71cdbe9 185 //Configure status LEDs
Sergunb 0:8918a71cdbe9 186 GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);
Sergunb 0:8918a71cdbe9 187 }
Sergunb 0:8918a71cdbe9 188
Sergunb 0:8918a71cdbe9 189 #endif
Sergunb 0:8918a71cdbe9 190
Sergunb 0:8918a71cdbe9 191
Sergunb 0:8918a71cdbe9 192 /**
Sergunb 0:8918a71cdbe9 193 * @brief Stellaris LM3S Ethernet timer handler
Sergunb 0:8918a71cdbe9 194 *
Sergunb 0:8918a71cdbe9 195 * This routine is periodically called by the TCP/IP stack to
Sergunb 0:8918a71cdbe9 196 * handle periodic operations such as polling the link state
Sergunb 0:8918a71cdbe9 197 *
Sergunb 0:8918a71cdbe9 198 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 199 **/
Sergunb 0:8918a71cdbe9 200
Sergunb 0:8918a71cdbe9 201 void lm3sEthTick(NetInterface *interface)
Sergunb 0:8918a71cdbe9 202 {
Sergunb 0:8918a71cdbe9 203 }
Sergunb 0:8918a71cdbe9 204
Sergunb 0:8918a71cdbe9 205
Sergunb 0:8918a71cdbe9 206 /**
Sergunb 0:8918a71cdbe9 207 * @brief Enable interrupts
Sergunb 0:8918a71cdbe9 208 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 209 **/
Sergunb 0:8918a71cdbe9 210
Sergunb 0:8918a71cdbe9 211 void lm3sEthEnableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 212 {
Sergunb 0:8918a71cdbe9 213 //Enable Ethernet interrupts
Sergunb 0:8918a71cdbe9 214 IntEnable(INT_ETH);
Sergunb 0:8918a71cdbe9 215 }
Sergunb 0:8918a71cdbe9 216
Sergunb 0:8918a71cdbe9 217
Sergunb 0:8918a71cdbe9 218 /**
Sergunb 0:8918a71cdbe9 219 * @brief Disable interrupts
Sergunb 0:8918a71cdbe9 220 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 221 **/
Sergunb 0:8918a71cdbe9 222
Sergunb 0:8918a71cdbe9 223 void lm3sEthDisableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 224 {
Sergunb 0:8918a71cdbe9 225 //Disable Ethernet interrupts
Sergunb 0:8918a71cdbe9 226 IntDisable(INT_ETH);
Sergunb 0:8918a71cdbe9 227 }
Sergunb 0:8918a71cdbe9 228
Sergunb 0:8918a71cdbe9 229
Sergunb 0:8918a71cdbe9 230 /**
Sergunb 0:8918a71cdbe9 231 * @brief Stellaris LM3S Ethernet interrupt service routine
Sergunb 0:8918a71cdbe9 232 **/
Sergunb 0:8918a71cdbe9 233
Sergunb 0:8918a71cdbe9 234 void ETH_IRQHandler(void)
Sergunb 0:8918a71cdbe9 235 {
Sergunb 0:8918a71cdbe9 236 bool_t flag;
Sergunb 0:8918a71cdbe9 237 uint32_t status;
Sergunb 0:8918a71cdbe9 238
Sergunb 0:8918a71cdbe9 239 //Enter interrupt service routine
Sergunb 0:8918a71cdbe9 240 osEnterIsr();
Sergunb 0:8918a71cdbe9 241
Sergunb 0:8918a71cdbe9 242 //This flag will be set if a higher priority task must be woken
Sergunb 0:8918a71cdbe9 243 flag = FALSE;
Sergunb 0:8918a71cdbe9 244
Sergunb 0:8918a71cdbe9 245 //Read interrupt status register
Sergunb 0:8918a71cdbe9 246 status = MAC_RIS_R;
Sergunb 0:8918a71cdbe9 247
Sergunb 0:8918a71cdbe9 248 //PHY interrupt?
Sergunb 0:8918a71cdbe9 249 if(status & MAC_RIS_PHYINT)
Sergunb 0:8918a71cdbe9 250 {
Sergunb 0:8918a71cdbe9 251 //Disable PHYINT interrupt
Sergunb 0:8918a71cdbe9 252 MAC_IM_R &= ~MAC_IM_PHYINTM;
Sergunb 0:8918a71cdbe9 253
Sergunb 0:8918a71cdbe9 254 //Set event flag
Sergunb 0:8918a71cdbe9 255 nicDriverInterface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 256 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 257 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 258 }
Sergunb 0:8918a71cdbe9 259
Sergunb 0:8918a71cdbe9 260 //Transmit FIFO empty?
Sergunb 0:8918a71cdbe9 261 if(status & MAC_RIS_TXEMP)
Sergunb 0:8918a71cdbe9 262 {
Sergunb 0:8918a71cdbe9 263 //Acknowledge TXEMP interrupt
Sergunb 0:8918a71cdbe9 264 MAC_IACK_R = MAC_IACK_TXEMP;
Sergunb 0:8918a71cdbe9 265
Sergunb 0:8918a71cdbe9 266 //Check whether the transmit FIFO is available for writing
Sergunb 0:8918a71cdbe9 267 if(!(MAC_TR_R & MAC_TR_NEWTX))
Sergunb 0:8918a71cdbe9 268 {
Sergunb 0:8918a71cdbe9 269 //Notify the TCP/IP stack that the transmitter is ready to send
Sergunb 0:8918a71cdbe9 270 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
Sergunb 0:8918a71cdbe9 271 }
Sergunb 0:8918a71cdbe9 272 }
Sergunb 0:8918a71cdbe9 273
Sergunb 0:8918a71cdbe9 274 //Packet received?
Sergunb 0:8918a71cdbe9 275 if(status & MAC_RIS_RXINT)
Sergunb 0:8918a71cdbe9 276 {
Sergunb 0:8918a71cdbe9 277 //Disable RXINT interrupt
Sergunb 0:8918a71cdbe9 278 MAC_IM_R &= ~MAC_IM_RXINTM;
Sergunb 0:8918a71cdbe9 279
Sergunb 0:8918a71cdbe9 280 //Set event flag
Sergunb 0:8918a71cdbe9 281 nicDriverInterface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 282 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 283 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 284 }
Sergunb 0:8918a71cdbe9 285
Sergunb 0:8918a71cdbe9 286 //Leave interrupt service routine
Sergunb 0:8918a71cdbe9 287 osExitIsr(flag);
Sergunb 0:8918a71cdbe9 288 }
Sergunb 0:8918a71cdbe9 289
Sergunb 0:8918a71cdbe9 290
Sergunb 0:8918a71cdbe9 291 /**
Sergunb 0:8918a71cdbe9 292 * @brief Stellaris LM3S Ethernet event handler
Sergunb 0:8918a71cdbe9 293 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 294 **/
Sergunb 0:8918a71cdbe9 295
Sergunb 0:8918a71cdbe9 296 void lm3sEthEventHandler(NetInterface *interface)
Sergunb 0:8918a71cdbe9 297 {
Sergunb 0:8918a71cdbe9 298 uint32_t status;
Sergunb 0:8918a71cdbe9 299 uint16_t value;
Sergunb 0:8918a71cdbe9 300
Sergunb 0:8918a71cdbe9 301 //Read interrupt status register
Sergunb 0:8918a71cdbe9 302 status = MAC_RIS_R;
Sergunb 0:8918a71cdbe9 303
Sergunb 0:8918a71cdbe9 304 //PHY interrupt?
Sergunb 0:8918a71cdbe9 305 if(status & MAC_RIS_PHYINT)
Sergunb 0:8918a71cdbe9 306 {
Sergunb 0:8918a71cdbe9 307 //Acknowledge PHYINT interrupt
Sergunb 0:8918a71cdbe9 308 MAC_IACK_R = MAC_IACK_PHYINT;
Sergunb 0:8918a71cdbe9 309 //Read PHY interrupt status register
Sergunb 0:8918a71cdbe9 310 value = lm3sEthReadPhyReg(PHY_MR17);
Sergunb 0:8918a71cdbe9 311
Sergunb 0:8918a71cdbe9 312 //Check whether the link state has changed
Sergunb 0:8918a71cdbe9 313 if(value & PHY_MR17_LSCHG_IE)
Sergunb 0:8918a71cdbe9 314 {
Sergunb 0:8918a71cdbe9 315 //Read PHY status register
Sergunb 0:8918a71cdbe9 316 value = lm3sEthReadPhyReg(PHY_MR1);
Sergunb 0:8918a71cdbe9 317
Sergunb 0:8918a71cdbe9 318 //Check link state
Sergunb 0:8918a71cdbe9 319 if(value & PHY_MR1_LINK)
Sergunb 0:8918a71cdbe9 320 {
Sergunb 0:8918a71cdbe9 321 //Read PHY diagnostic register
Sergunb 0:8918a71cdbe9 322 value = lm3sEthReadPhyReg(PHY_MR18);
Sergunb 0:8918a71cdbe9 323
Sergunb 0:8918a71cdbe9 324 //Get current speed
Sergunb 0:8918a71cdbe9 325 if(value & PHY_MR18_RATE)
Sergunb 0:8918a71cdbe9 326 {
Sergunb 0:8918a71cdbe9 327 //100BASE-TX operation
Sergunb 0:8918a71cdbe9 328 interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
Sergunb 0:8918a71cdbe9 329 }
Sergunb 0:8918a71cdbe9 330 else
Sergunb 0:8918a71cdbe9 331 {
Sergunb 0:8918a71cdbe9 332 //10BASE-T operation
Sergunb 0:8918a71cdbe9 333 interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
Sergunb 0:8918a71cdbe9 334 }
Sergunb 0:8918a71cdbe9 335
Sergunb 0:8918a71cdbe9 336 //Get current duplex mode
Sergunb 0:8918a71cdbe9 337 if(value & PHY_MR18_DPLX)
Sergunb 0:8918a71cdbe9 338 {
Sergunb 0:8918a71cdbe9 339 //Full-Duplex mode
Sergunb 0:8918a71cdbe9 340 interface->duplexMode = NIC_FULL_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 341 //Update MAC configuration
Sergunb 0:8918a71cdbe9 342 MAC_TCTL_R |= MAC_TCTL_DUPLEX;
Sergunb 0:8918a71cdbe9 343 }
Sergunb 0:8918a71cdbe9 344 else
Sergunb 0:8918a71cdbe9 345 {
Sergunb 0:8918a71cdbe9 346 //Half-Duplex mode
Sergunb 0:8918a71cdbe9 347 interface->duplexMode = NIC_HALF_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 348 //Update MAC configuration
Sergunb 0:8918a71cdbe9 349 MAC_TCTL_R &= ~MAC_TCTL_DUPLEX;
Sergunb 0:8918a71cdbe9 350 }
Sergunb 0:8918a71cdbe9 351
Sergunb 0:8918a71cdbe9 352 //Update link state
Sergunb 0:8918a71cdbe9 353 interface->linkState = TRUE;
Sergunb 0:8918a71cdbe9 354 }
Sergunb 0:8918a71cdbe9 355 else
Sergunb 0:8918a71cdbe9 356 {
Sergunb 0:8918a71cdbe9 357 //Update link state
Sergunb 0:8918a71cdbe9 358 interface->linkState = FALSE;
Sergunb 0:8918a71cdbe9 359 }
Sergunb 0:8918a71cdbe9 360
Sergunb 0:8918a71cdbe9 361 //Process link state change event
Sergunb 0:8918a71cdbe9 362 nicNotifyLinkChange(interface);
Sergunb 0:8918a71cdbe9 363 }
Sergunb 0:8918a71cdbe9 364 }
Sergunb 0:8918a71cdbe9 365
Sergunb 0:8918a71cdbe9 366 //Packet received?
Sergunb 0:8918a71cdbe9 367 if(status & MAC_RIS_RXINT)
Sergunb 0:8918a71cdbe9 368 {
Sergunb 0:8918a71cdbe9 369 //Acknowledge RXINT interrupt
Sergunb 0:8918a71cdbe9 370 MAC_IACK_R = MAC_IACK_RXINT;
Sergunb 0:8918a71cdbe9 371
Sergunb 0:8918a71cdbe9 372 //Process all the pending packets
Sergunb 0:8918a71cdbe9 373 while(MAC_NP_R & MAC_NP_NPR_M)
Sergunb 0:8918a71cdbe9 374 {
Sergunb 0:8918a71cdbe9 375 //Read incoming packet
Sergunb 0:8918a71cdbe9 376 lm3sEthReceivePacket(interface);
Sergunb 0:8918a71cdbe9 377 }
Sergunb 0:8918a71cdbe9 378 }
Sergunb 0:8918a71cdbe9 379
Sergunb 0:8918a71cdbe9 380 //Re-enable Ethernet interrupts
Sergunb 0:8918a71cdbe9 381 MAC_IM_R = MAC_IM_PHYINTM | MAC_IM_TXEMPM | MAC_IM_RXINTM;
Sergunb 0:8918a71cdbe9 382 }
Sergunb 0:8918a71cdbe9 383
Sergunb 0:8918a71cdbe9 384
Sergunb 0:8918a71cdbe9 385 /**
Sergunb 0:8918a71cdbe9 386 * @brief Send a packet
Sergunb 0:8918a71cdbe9 387 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 388 * @param[in] buffer Multi-part buffer containing the data to send
Sergunb 0:8918a71cdbe9 389 * @param[in] offset Offset to the first data byte
Sergunb 0:8918a71cdbe9 390 * @return Error code
Sergunb 0:8918a71cdbe9 391 **/
Sergunb 0:8918a71cdbe9 392
Sergunb 0:8918a71cdbe9 393 error_t lm3sEthSendPacket(NetInterface *interface,
Sergunb 0:8918a71cdbe9 394 const NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 395 {
Sergunb 0:8918a71cdbe9 396 size_t i;
Sergunb 0:8918a71cdbe9 397 size_t length;
Sergunb 0:8918a71cdbe9 398 uint32_t *p;
Sergunb 0:8918a71cdbe9 399
Sergunb 0:8918a71cdbe9 400 //Retrieve the length of the packet
Sergunb 0:8918a71cdbe9 401 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 402
Sergunb 0:8918a71cdbe9 403 //Check the frame length
Sergunb 0:8918a71cdbe9 404 if(length < sizeof(EthHeader) || length > ETH_MAX_FRAME_SIZE)
Sergunb 0:8918a71cdbe9 405 {
Sergunb 0:8918a71cdbe9 406 //The transmitter can accept another packet
Sergunb 0:8918a71cdbe9 407 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 408 //Report an error
Sergunb 0:8918a71cdbe9 409 return ERROR_INVALID_LENGTH;
Sergunb 0:8918a71cdbe9 410 }
Sergunb 0:8918a71cdbe9 411
Sergunb 0:8918a71cdbe9 412 //Make sure the transmit FIFO is available for writing
Sergunb 0:8918a71cdbe9 413 if(MAC_TR_R & MAC_TR_NEWTX)
Sergunb 0:8918a71cdbe9 414 return ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 415
Sergunb 0:8918a71cdbe9 416 //Copy user data
Sergunb 0:8918a71cdbe9 417 netBufferRead(txBuffer + 2, buffer, offset, length);
Sergunb 0:8918a71cdbe9 418
Sergunb 0:8918a71cdbe9 419 //The packet is preceded by a 16-bit length field
Sergunb 0:8918a71cdbe9 420 txBuffer[0] = LSB(length - sizeof(EthHeader));
Sergunb 0:8918a71cdbe9 421 txBuffer[1] = MSB(length - sizeof(EthHeader));
Sergunb 0:8918a71cdbe9 422
Sergunb 0:8918a71cdbe9 423 //Point to the beginning of the packet
Sergunb 0:8918a71cdbe9 424 p = (uint32_t *) txBuffer;
Sergunb 0:8918a71cdbe9 425 //Compute the length of the packet in 32-bit words
Sergunb 0:8918a71cdbe9 426 length = (length + 5) / 4;
Sergunb 0:8918a71cdbe9 427
Sergunb 0:8918a71cdbe9 428 //Copy packet to transmit FIFO
Sergunb 0:8918a71cdbe9 429 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 430 MAC_DATA_R = p[i];
Sergunb 0:8918a71cdbe9 431
Sergunb 0:8918a71cdbe9 432 //Start transmitting
Sergunb 0:8918a71cdbe9 433 MAC_TR_R = MAC_TR_NEWTX;
Sergunb 0:8918a71cdbe9 434
Sergunb 0:8918a71cdbe9 435 //Data successfully written
Sergunb 0:8918a71cdbe9 436 return NO_ERROR;
Sergunb 0:8918a71cdbe9 437 }
Sergunb 0:8918a71cdbe9 438
Sergunb 0:8918a71cdbe9 439
Sergunb 0:8918a71cdbe9 440 /**
Sergunb 0:8918a71cdbe9 441 * @brief Receive a packet
Sergunb 0:8918a71cdbe9 442 * @return Error code
Sergunb 0:8918a71cdbe9 443 **/
Sergunb 0:8918a71cdbe9 444
Sergunb 0:8918a71cdbe9 445 error_t lm3sEthReceivePacket(NetInterface *interface)
Sergunb 0:8918a71cdbe9 446 {
Sergunb 0:8918a71cdbe9 447 error_t error;
Sergunb 0:8918a71cdbe9 448 size_t i;
Sergunb 0:8918a71cdbe9 449 size_t n;
Sergunb 0:8918a71cdbe9 450 size_t length;
Sergunb 0:8918a71cdbe9 451 uint32_t data;
Sergunb 0:8918a71cdbe9 452 uint16_t *p;
Sergunb 0:8918a71cdbe9 453
Sergunb 0:8918a71cdbe9 454 //Make sure the FIFO is not empty
Sergunb 0:8918a71cdbe9 455 if(MAC_NP_R & MAC_NP_NPR_M)
Sergunb 0:8918a71cdbe9 456 {
Sergunb 0:8918a71cdbe9 457 //Read the first word
Sergunb 0:8918a71cdbe9 458 data = MAC_DATA_R;
Sergunb 0:8918a71cdbe9 459 //Retrieve the total length of the packet
Sergunb 0:8918a71cdbe9 460 length = data & 0xFFFF;
Sergunb 0:8918a71cdbe9 461
Sergunb 0:8918a71cdbe9 462 //Make sure the length field is valid
Sergunb 0:8918a71cdbe9 463 if(length > 2)
Sergunb 0:8918a71cdbe9 464 {
Sergunb 0:8918a71cdbe9 465 //Point to the beginning of the buffer
Sergunb 0:8918a71cdbe9 466 p = (uint16_t *) rxBuffer;
Sergunb 0:8918a71cdbe9 467
Sergunb 0:8918a71cdbe9 468 //Retrieve the length of the frame
Sergunb 0:8918a71cdbe9 469 length -= 2;
Sergunb 0:8918a71cdbe9 470 //Limit the number of data to be read
Sergunb 0:8918a71cdbe9 471 n = MIN(length, ETH_MAX_FRAME_SIZE);
Sergunb 0:8918a71cdbe9 472
Sergunb 0:8918a71cdbe9 473 //Copy the first half word
Sergunb 0:8918a71cdbe9 474 if(n > 0)
Sergunb 0:8918a71cdbe9 475 *(p++) = (uint16_t) (data >> 16);
Sergunb 0:8918a71cdbe9 476
Sergunb 0:8918a71cdbe9 477 //Copy data from receive FIFO
Sergunb 0:8918a71cdbe9 478 for(i = 2; i < n; i += 4)
Sergunb 0:8918a71cdbe9 479 {
Sergunb 0:8918a71cdbe9 480 //Read a 32-bit word from the FIFO
Sergunb 0:8918a71cdbe9 481 data = MAC_DATA_R;
Sergunb 0:8918a71cdbe9 482 //Write the 32-bit to the receive buffer
Sergunb 0:8918a71cdbe9 483 *(p++) = (uint16_t) data;
Sergunb 0:8918a71cdbe9 484 *(p++) = (uint16_t) (data >> 16);
Sergunb 0:8918a71cdbe9 485 }
Sergunb 0:8918a71cdbe9 486
Sergunb 0:8918a71cdbe9 487 //Skip the remaining bytes
Sergunb 0:8918a71cdbe9 488 while(i < length)
Sergunb 0:8918a71cdbe9 489 {
Sergunb 0:8918a71cdbe9 490 //Read a 32-bit word from the FIFO
Sergunb 0:8918a71cdbe9 491 data = MAC_DATA_R;
Sergunb 0:8918a71cdbe9 492 //Increment byte counter
Sergunb 0:8918a71cdbe9 493 i += 4;
Sergunb 0:8918a71cdbe9 494 }
Sergunb 0:8918a71cdbe9 495
Sergunb 0:8918a71cdbe9 496 //Valid packet received
Sergunb 0:8918a71cdbe9 497 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 498 }
Sergunb 0:8918a71cdbe9 499 else
Sergunb 0:8918a71cdbe9 500 {
Sergunb 0:8918a71cdbe9 501 //Disable receiver
Sergunb 0:8918a71cdbe9 502 MAC_RCTL_R &= ~MAC_RCTL_RXEN;
Sergunb 0:8918a71cdbe9 503 //Flush the receive FIFO
Sergunb 0:8918a71cdbe9 504 MAC_RCTL_R |= MAC_RCTL_RSTFIFO;
Sergunb 0:8918a71cdbe9 505 //Re-enable receiver
Sergunb 0:8918a71cdbe9 506 MAC_RCTL_R |= MAC_RCTL_RXEN;
Sergunb 0:8918a71cdbe9 507
Sergunb 0:8918a71cdbe9 508 //The packet is not valid
Sergunb 0:8918a71cdbe9 509 error = ERROR_INVALID_PACKET;
Sergunb 0:8918a71cdbe9 510 }
Sergunb 0:8918a71cdbe9 511 }
Sergunb 0:8918a71cdbe9 512 else
Sergunb 0:8918a71cdbe9 513 {
Sergunb 0:8918a71cdbe9 514 //No more data in the receive buffer
Sergunb 0:8918a71cdbe9 515 error = ERROR_BUFFER_EMPTY;
Sergunb 0:8918a71cdbe9 516 }
Sergunb 0:8918a71cdbe9 517
Sergunb 0:8918a71cdbe9 518 //Check whether a valid packet has been received
Sergunb 0:8918a71cdbe9 519 if(!error)
Sergunb 0:8918a71cdbe9 520 {
Sergunb 0:8918a71cdbe9 521 //Pass the packet to the upper layer
Sergunb 0:8918a71cdbe9 522 nicProcessPacket(interface, rxBuffer, n);
Sergunb 0:8918a71cdbe9 523 }
Sergunb 0:8918a71cdbe9 524
Sergunb 0:8918a71cdbe9 525 //Return status code
Sergunb 0:8918a71cdbe9 526 return error;
Sergunb 0:8918a71cdbe9 527 }
Sergunb 0:8918a71cdbe9 528
Sergunb 0:8918a71cdbe9 529
Sergunb 0:8918a71cdbe9 530 /**
Sergunb 0:8918a71cdbe9 531 * @brief Configure multicast MAC address filtering
Sergunb 0:8918a71cdbe9 532 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 533 * @return Error code
Sergunb 0:8918a71cdbe9 534 **/
Sergunb 0:8918a71cdbe9 535
Sergunb 0:8918a71cdbe9 536 error_t lm3sEthSetMulticastFilter(NetInterface *interface)
Sergunb 0:8918a71cdbe9 537 {
Sergunb 0:8918a71cdbe9 538 uint_t i;
Sergunb 0:8918a71cdbe9 539 bool_t acceptMulticast;
Sergunb 0:8918a71cdbe9 540
Sergunb 0:8918a71cdbe9 541 //This flag will be set if multicast addresses should be accepted
Sergunb 0:8918a71cdbe9 542 acceptMulticast = FALSE;
Sergunb 0:8918a71cdbe9 543
Sergunb 0:8918a71cdbe9 544 //The MAC filter table contains the multicast MAC addresses
Sergunb 0:8918a71cdbe9 545 //to accept when receiving an Ethernet frame
Sergunb 0:8918a71cdbe9 546 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 547 {
Sergunb 0:8918a71cdbe9 548 //Valid entry?
Sergunb 0:8918a71cdbe9 549 if(interface->macMulticastFilter[i].refCount > 0)
Sergunb 0:8918a71cdbe9 550 {
Sergunb 0:8918a71cdbe9 551 //Accept multicast addresses
Sergunb 0:8918a71cdbe9 552 acceptMulticast = TRUE;
Sergunb 0:8918a71cdbe9 553 //We are done
Sergunb 0:8918a71cdbe9 554 break;
Sergunb 0:8918a71cdbe9 555 }
Sergunb 0:8918a71cdbe9 556 }
Sergunb 0:8918a71cdbe9 557
Sergunb 0:8918a71cdbe9 558 //Enable the reception of multicast frames if necessary
Sergunb 0:8918a71cdbe9 559 if(acceptMulticast)
Sergunb 0:8918a71cdbe9 560 MAC_RCTL_R |= MAC_RCTL_AMUL;
Sergunb 0:8918a71cdbe9 561 else
Sergunb 0:8918a71cdbe9 562 MAC_RCTL_R &= ~MAC_RCTL_AMUL;
Sergunb 0:8918a71cdbe9 563
Sergunb 0:8918a71cdbe9 564 //Successful processing
Sergunb 0:8918a71cdbe9 565 return NO_ERROR;
Sergunb 0:8918a71cdbe9 566 }
Sergunb 0:8918a71cdbe9 567
Sergunb 0:8918a71cdbe9 568
Sergunb 0:8918a71cdbe9 569 /**
Sergunb 0:8918a71cdbe9 570 * @brief Write PHY register
Sergunb 0:8918a71cdbe9 571 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 572 * @param[in] data Register value
Sergunb 0:8918a71cdbe9 573 **/
Sergunb 0:8918a71cdbe9 574
Sergunb 0:8918a71cdbe9 575 void lm3sEthWritePhyReg(uint8_t address, uint16_t data)
Sergunb 0:8918a71cdbe9 576 {
Sergunb 0:8918a71cdbe9 577 //Data to be written in the PHY register
Sergunb 0:8918a71cdbe9 578 MAC_MTXD_R = data & MAC_MTXD_MDTX_M;
Sergunb 0:8918a71cdbe9 579 //Start a write operation
Sergunb 0:8918a71cdbe9 580 MAC_MCTL_R = (address << 3) | MAC_MCTL_WRITE | MAC_MCTL_START;
Sergunb 0:8918a71cdbe9 581
Sergunb 0:8918a71cdbe9 582 //Wait for the write to complete
Sergunb 0:8918a71cdbe9 583 while(MAC_MCTL_R & MAC_MCTL_START);
Sergunb 0:8918a71cdbe9 584 }
Sergunb 0:8918a71cdbe9 585
Sergunb 0:8918a71cdbe9 586
Sergunb 0:8918a71cdbe9 587 /**
Sergunb 0:8918a71cdbe9 588 * @brief Read PHY register
Sergunb 0:8918a71cdbe9 589 * @param[in] address PHY register address
Sergunb 0:8918a71cdbe9 590 * @return Register value
Sergunb 0:8918a71cdbe9 591 **/
Sergunb 0:8918a71cdbe9 592
Sergunb 0:8918a71cdbe9 593 uint16_t lm3sEthReadPhyReg(uint8_t address)
Sergunb 0:8918a71cdbe9 594 {
Sergunb 0:8918a71cdbe9 595 //Start a read operation
Sergunb 0:8918a71cdbe9 596 MAC_MCTL_R = (address << 3) | MAC_MCTL_START;
Sergunb 0:8918a71cdbe9 597
Sergunb 0:8918a71cdbe9 598 //Wait for the read to complete
Sergunb 0:8918a71cdbe9 599 while(MAC_MCTL_R & MAC_MCTL_START);
Sergunb 0:8918a71cdbe9 600
Sergunb 0:8918a71cdbe9 601 //Return PHY register contents
Sergunb 0:8918a71cdbe9 602 return MAC_MRXD_R & MAC_MRXD_MDRX_M;
Sergunb 0:8918a71cdbe9 603 }
Sergunb 0:8918a71cdbe9 604
Sergunb 0:8918a71cdbe9 605
Sergunb 0:8918a71cdbe9 606 /**
Sergunb 0:8918a71cdbe9 607 * @brief Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 608 **/
Sergunb 0:8918a71cdbe9 609
Sergunb 0:8918a71cdbe9 610 void lm3sEthDumpPhyReg(void)
Sergunb 0:8918a71cdbe9 611 {
Sergunb 0:8918a71cdbe9 612 uint8_t i;
Sergunb 0:8918a71cdbe9 613
Sergunb 0:8918a71cdbe9 614 //Loop through PHY registers
Sergunb 0:8918a71cdbe9 615 for(i = 0; i < 32; i++)
Sergunb 0:8918a71cdbe9 616 {
Sergunb 0:8918a71cdbe9 617 //Display current PHY register
Sergunb 0:8918a71cdbe9 618 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, lm3sEthReadPhyReg(i));
Sergunb 0:8918a71cdbe9 619 }
Sergunb 0:8918a71cdbe9 620
Sergunb 0:8918a71cdbe9 621 //Terminate with a line feed
Sergunb 0:8918a71cdbe9 622 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 623 }
Sergunb 0:8918a71cdbe9 624