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 tm4c129_eth.c
Sergunb 0:8918a71cdbe9 3 * @brief Tiva TM4C129 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 //TM4C1294NCPDT device?
Sergunb 0:8918a71cdbe9 33 #if defined(PART_TM4C1294NCPDT)
Sergunb 0:8918a71cdbe9 34 #include "tm4c1294ncpdt.h"
Sergunb 0:8918a71cdbe9 35 //TM4C129XNCZAD device?
Sergunb 0:8918a71cdbe9 36 #elif defined(PART_TM4C129XNCZAD)
Sergunb 0:8918a71cdbe9 37 #include "tm4c129xnczad.h"
Sergunb 0:8918a71cdbe9 38 #endif
Sergunb 0:8918a71cdbe9 39
Sergunb 0:8918a71cdbe9 40 //Dependencies
Sergunb 0:8918a71cdbe9 41 #include <stdint.h>
Sergunb 0:8918a71cdbe9 42 #include <stdbool.h>
Sergunb 0:8918a71cdbe9 43 #include "inc/hw_emac.h"
Sergunb 0:8918a71cdbe9 44 #include "inc/hw_memmap.h"
Sergunb 0:8918a71cdbe9 45 #include "inc/hw_types.h"
Sergunb 0:8918a71cdbe9 46 #include "driverlib/gpio.h"
Sergunb 0:8918a71cdbe9 47 #include "driverlib/interrupt.h"
Sergunb 0:8918a71cdbe9 48 #include "driverlib/pin_map.h"
Sergunb 0:8918a71cdbe9 49 #include "driverlib/sysctl.h"
Sergunb 0:8918a71cdbe9 50 #include "core/net.h"
Sergunb 0:8918a71cdbe9 51 #include "drivers/tm4c129_eth.h"
Sergunb 0:8918a71cdbe9 52 #include "debug.h"
Sergunb 0:8918a71cdbe9 53
Sergunb 0:8918a71cdbe9 54 //Underlying network interface
Sergunb 0:8918a71cdbe9 55 static NetInterface *nicDriverInterface;
Sergunb 0:8918a71cdbe9 56
Sergunb 0:8918a71cdbe9 57 //IAR EWARM compiler?
Sergunb 0:8918a71cdbe9 58 #if defined(__ICCARM__)
Sergunb 0:8918a71cdbe9 59
Sergunb 0:8918a71cdbe9 60 //Transmit buffer
Sergunb 0:8918a71cdbe9 61 #pragma data_alignment = 4
Sergunb 0:8918a71cdbe9 62 static uint8_t txBuffer[TM4C129_ETH_TX_BUFFER_COUNT][TM4C129_ETH_TX_BUFFER_SIZE];
Sergunb 0:8918a71cdbe9 63 //Receive buffer
Sergunb 0:8918a71cdbe9 64 #pragma data_alignment = 4
Sergunb 0:8918a71cdbe9 65 static uint8_t rxBuffer[TM4C129_ETH_RX_BUFFER_COUNT][TM4C129_ETH_RX_BUFFER_SIZE];
Sergunb 0:8918a71cdbe9 66 //Transmit DMA descriptors
Sergunb 0:8918a71cdbe9 67 #pragma data_alignment = 4
Sergunb 0:8918a71cdbe9 68 static Tm4c129TxDmaDesc txDmaDesc[TM4C129_ETH_TX_BUFFER_COUNT];
Sergunb 0:8918a71cdbe9 69 //Receive DMA descriptors
Sergunb 0:8918a71cdbe9 70 #pragma data_alignment = 4
Sergunb 0:8918a71cdbe9 71 static Tm4c129RxDmaDesc rxDmaDesc[TM4C129_ETH_RX_BUFFER_COUNT];
Sergunb 0:8918a71cdbe9 72
Sergunb 0:8918a71cdbe9 73 //Keil MDK-ARM or GCC compiler?
Sergunb 0:8918a71cdbe9 74 #else
Sergunb 0:8918a71cdbe9 75
Sergunb 0:8918a71cdbe9 76 //Transmit buffer
Sergunb 0:8918a71cdbe9 77 static uint8_t txBuffer[TM4C129_ETH_TX_BUFFER_COUNT][TM4C129_ETH_TX_BUFFER_SIZE]
Sergunb 0:8918a71cdbe9 78 __attribute__((aligned(4)));
Sergunb 0:8918a71cdbe9 79 //Receive buffer
Sergunb 0:8918a71cdbe9 80 static uint8_t rxBuffer[TM4C129_ETH_RX_BUFFER_COUNT][TM4C129_ETH_RX_BUFFER_SIZE]
Sergunb 0:8918a71cdbe9 81 __attribute__((aligned(4)));
Sergunb 0:8918a71cdbe9 82 //Transmit DMA descriptors
Sergunb 0:8918a71cdbe9 83 static Tm4c129TxDmaDesc txDmaDesc[TM4C129_ETH_TX_BUFFER_COUNT]
Sergunb 0:8918a71cdbe9 84 __attribute__((aligned(4)));
Sergunb 0:8918a71cdbe9 85 //Receive DMA descriptors
Sergunb 0:8918a71cdbe9 86 static Tm4c129RxDmaDesc rxDmaDesc[TM4C129_ETH_RX_BUFFER_COUNT]
Sergunb 0:8918a71cdbe9 87 __attribute__((aligned(4)));
Sergunb 0:8918a71cdbe9 88
Sergunb 0:8918a71cdbe9 89 #endif
Sergunb 0:8918a71cdbe9 90
Sergunb 0:8918a71cdbe9 91 //Pointer to the current TX DMA descriptor
Sergunb 0:8918a71cdbe9 92 static Tm4c129TxDmaDesc *txCurDmaDesc;
Sergunb 0:8918a71cdbe9 93 //Pointer to the current RX DMA descriptor
Sergunb 0:8918a71cdbe9 94 static Tm4c129RxDmaDesc *rxCurDmaDesc;
Sergunb 0:8918a71cdbe9 95
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97 /**
Sergunb 0:8918a71cdbe9 98 * @brief Tiva TM4C129 Ethernet MAC driver
Sergunb 0:8918a71cdbe9 99 **/
Sergunb 0:8918a71cdbe9 100
Sergunb 0:8918a71cdbe9 101 const NicDriver tm4c129EthDriver =
Sergunb 0:8918a71cdbe9 102 {
Sergunb 0:8918a71cdbe9 103 NIC_TYPE_ETHERNET,
Sergunb 0:8918a71cdbe9 104 ETH_MTU,
Sergunb 0:8918a71cdbe9 105 tm4c129EthInit,
Sergunb 0:8918a71cdbe9 106 tm4c129EthTick,
Sergunb 0:8918a71cdbe9 107 tm4c129EthEnableIrq,
Sergunb 0:8918a71cdbe9 108 tm4c129EthDisableIrq,
Sergunb 0:8918a71cdbe9 109 tm4c129EthEventHandler,
Sergunb 0:8918a71cdbe9 110 tm4c129EthSendPacket,
Sergunb 0:8918a71cdbe9 111 tm4c129EthSetMulticastFilter,
Sergunb 0:8918a71cdbe9 112 NULL,
Sergunb 0:8918a71cdbe9 113 NULL,
Sergunb 0:8918a71cdbe9 114 NULL,
Sergunb 0:8918a71cdbe9 115 TRUE,
Sergunb 0:8918a71cdbe9 116 TRUE,
Sergunb 0:8918a71cdbe9 117 TRUE,
Sergunb 0:8918a71cdbe9 118 FALSE
Sergunb 0:8918a71cdbe9 119 };
Sergunb 0:8918a71cdbe9 120
Sergunb 0:8918a71cdbe9 121
Sergunb 0:8918a71cdbe9 122 /**
Sergunb 0:8918a71cdbe9 123 * @brief Tiva TM4C129 Ethernet MAC initialization
Sergunb 0:8918a71cdbe9 124 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 125 * @return Error code
Sergunb 0:8918a71cdbe9 126 **/
Sergunb 0:8918a71cdbe9 127
Sergunb 0:8918a71cdbe9 128 error_t tm4c129EthInit(NetInterface *interface)
Sergunb 0:8918a71cdbe9 129 {
Sergunb 0:8918a71cdbe9 130 //Debug message
Sergunb 0:8918a71cdbe9 131 TRACE_INFO("Initializing Tiva TM4C129 Ethernet controller...\r\n");
Sergunb 0:8918a71cdbe9 132
Sergunb 0:8918a71cdbe9 133 //Save underlying network interface
Sergunb 0:8918a71cdbe9 134 nicDriverInterface = interface;
Sergunb 0:8918a71cdbe9 135
Sergunb 0:8918a71cdbe9 136 //Enable Ethernet controller clock
Sergunb 0:8918a71cdbe9 137 SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
Sergunb 0:8918a71cdbe9 138 //Reset Ethernet controller
Sergunb 0:8918a71cdbe9 139 SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
Sergunb 0:8918a71cdbe9 140 //Wait for the reset to complete
Sergunb 0:8918a71cdbe9 141 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));
Sergunb 0:8918a71cdbe9 142
Sergunb 0:8918a71cdbe9 143 //Enable internal PHY clock
Sergunb 0:8918a71cdbe9 144 SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
Sergunb 0:8918a71cdbe9 145 //Reset internal PHY
Sergunb 0:8918a71cdbe9 146 SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
Sergunb 0:8918a71cdbe9 147 //Wait for the reset to complete
Sergunb 0:8918a71cdbe9 148 while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EPHY0));
Sergunb 0:8918a71cdbe9 149
Sergunb 0:8918a71cdbe9 150 //GPIO configuration
Sergunb 0:8918a71cdbe9 151 tm4c129EthInitGpio(interface);
Sergunb 0:8918a71cdbe9 152
Sergunb 0:8918a71cdbe9 153 //Perform a software reset
Sergunb 0:8918a71cdbe9 154 EMAC0_DMABUSMOD_R |= EMAC_DMABUSMOD_SWR;
Sergunb 0:8918a71cdbe9 155 //Wait for the reset to complete
Sergunb 0:8918a71cdbe9 156 while(EMAC0_DMABUSMOD_R & EMAC_DMABUSMOD_SWR);
Sergunb 0:8918a71cdbe9 157
Sergunb 0:8918a71cdbe9 158 //Adjust MDC clock range depending on SYSCLK frequency
Sergunb 0:8918a71cdbe9 159 EMAC0_MIIADDR_R = EMAC_MIIADDR_CR_100_150;
Sergunb 0:8918a71cdbe9 160
Sergunb 0:8918a71cdbe9 161 //Reset PHY transceiver
Sergunb 0:8918a71cdbe9 162 tm4c129EthWritePhyReg(EPHY_BMCR, EPHY_BMCR_MIIRESET);
Sergunb 0:8918a71cdbe9 163 //Wait for the reset to complete
Sergunb 0:8918a71cdbe9 164 while(tm4c129EthReadPhyReg(EPHY_BMCR) & EPHY_BMCR_MIIRESET);
Sergunb 0:8918a71cdbe9 165
Sergunb 0:8918a71cdbe9 166 //Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 167 tm4c129EthDumpPhyReg();
Sergunb 0:8918a71cdbe9 168
Sergunb 0:8918a71cdbe9 169 //Configure LED0, LED1 and LED2
Sergunb 0:8918a71cdbe9 170 tm4c129EthWritePhyReg(EPHY_LEDCFG, EPHY_LEDCFG_LED0_TX |
Sergunb 0:8918a71cdbe9 171 EPHY_LEDCFG_LED1_RX | EPHY_LEDCFG_LED2_LINK);
Sergunb 0:8918a71cdbe9 172
Sergunb 0:8918a71cdbe9 173 //Configure PHY interrupts as desired
Sergunb 0:8918a71cdbe9 174 tm4c129EthWritePhyReg(EPHY_MISR1, EPHY_MISR1_LINKSTATEN);
Sergunb 0:8918a71cdbe9 175 //Enable PHY interrupts
Sergunb 0:8918a71cdbe9 176 tm4c129EthWritePhyReg(EPHY_SCR, EPHY_SCR_INTEN);
Sergunb 0:8918a71cdbe9 177
Sergunb 0:8918a71cdbe9 178 //Use default MAC configuration
Sergunb 0:8918a71cdbe9 179 EMAC0_CFG_R = EMAC_CFG_DRO;
Sergunb 0:8918a71cdbe9 180
Sergunb 0:8918a71cdbe9 181 //Set the MAC address
Sergunb 0:8918a71cdbe9 182 EMAC0_ADDR0L_R = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
Sergunb 0:8918a71cdbe9 183 EMAC0_ADDR0H_R = interface->macAddr.w[2];
Sergunb 0:8918a71cdbe9 184
Sergunb 0:8918a71cdbe9 185 //Initialize hash table
Sergunb 0:8918a71cdbe9 186 EMAC0_HASHTBLL_R = 0;
Sergunb 0:8918a71cdbe9 187 EMAC0_HASHTBLH_R = 0;
Sergunb 0:8918a71cdbe9 188
Sergunb 0:8918a71cdbe9 189 //Configure the receive filter
Sergunb 0:8918a71cdbe9 190 EMAC0_FRAMEFLTR_R = EMAC_FRAMEFLTR_HPF | EMAC_FRAMEFLTR_HMC;
Sergunb 0:8918a71cdbe9 191 //Disable flow control
Sergunb 0:8918a71cdbe9 192 EMAC0_FLOWCTL_R = 0;
Sergunb 0:8918a71cdbe9 193 //Enable store and forward mode
Sergunb 0:8918a71cdbe9 194 EMAC0_DMAOPMODE_R = EMAC_DMAOPMODE_RSF | EMAC_DMAOPMODE_TSF;
Sergunb 0:8918a71cdbe9 195
Sergunb 0:8918a71cdbe9 196 //Configure DMA bus mode
Sergunb 0:8918a71cdbe9 197 EMAC0_DMABUSMOD_R = EMAC_DMABUSMOD_AAL | EMAC_DMABUSMOD_USP | EMAC_DMABUSMOD_RPBL_1 |
Sergunb 0:8918a71cdbe9 198 EMAC_DMABUSMOD_PR_1_1 | EMAC_DMABUSMOD_PBL_1 | EMAC_DMABUSMOD_ATDS;
Sergunb 0:8918a71cdbe9 199
Sergunb 0:8918a71cdbe9 200 //Initialize DMA descriptor lists
Sergunb 0:8918a71cdbe9 201 tm4c129EthInitDmaDesc(interface);
Sergunb 0:8918a71cdbe9 202
Sergunb 0:8918a71cdbe9 203 //Prevent interrupts from being generated when the transmit statistic
Sergunb 0:8918a71cdbe9 204 //counters reach half their maximum value
Sergunb 0:8918a71cdbe9 205 EMAC0_MMCTXIM_R = EMAC_MMCTXIM_OCTCNT | EMAC_MMCTXIM_MCOLLGF |
Sergunb 0:8918a71cdbe9 206 EMAC_MMCTXIM_SCOLLGF | EMAC_MMCTXIM_GBF;
Sergunb 0:8918a71cdbe9 207
Sergunb 0:8918a71cdbe9 208 //Prevent interrupts from being generated when the receive statistic
Sergunb 0:8918a71cdbe9 209 //counters reach half their maximum value
Sergunb 0:8918a71cdbe9 210 EMAC0_MMCRXIM_R = EMAC_MMCRXIM_UCGF | EMAC_MMCRXIM_ALGNERR |
Sergunb 0:8918a71cdbe9 211 EMAC_MMCRXIM_CRCERR | EMAC_MMCRXIM_GBF;
Sergunb 0:8918a71cdbe9 212
Sergunb 0:8918a71cdbe9 213 //Disable MAC interrupts
Sergunb 0:8918a71cdbe9 214 EMAC0_IM_R = EMAC_IM_TSI | EMAC_IM_PMT;
Sergunb 0:8918a71cdbe9 215 //Enable the desired DMA interrupts
Sergunb 0:8918a71cdbe9 216 EMAC0_DMAIM_R = EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
Sergunb 0:8918a71cdbe9 217 //Enable PHY interrupts
Sergunb 0:8918a71cdbe9 218 EMAC0_EPHYIM_R = EMAC_EPHYIM_INT;
Sergunb 0:8918a71cdbe9 219
Sergunb 0:8918a71cdbe9 220 //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority)
Sergunb 0:8918a71cdbe9 221 IntPriorityGroupingSet(TM4C129_ETH_IRQ_PRIORITY_GROUPING);
Sergunb 0:8918a71cdbe9 222 //Configure Ethernet interrupt priority
Sergunb 0:8918a71cdbe9 223 IntPrioritySet(INT_EMAC0, TM4C129_ETH_IRQ_PRIORITY);
Sergunb 0:8918a71cdbe9 224
Sergunb 0:8918a71cdbe9 225 //Enable MAC transmission and reception
Sergunb 0:8918a71cdbe9 226 EMAC0_CFG_R |= EMAC_CFG_TE | EMAC_CFG_RE;
Sergunb 0:8918a71cdbe9 227 //Enable DMA transmission and reception
Sergunb 0:8918a71cdbe9 228 EMAC0_DMAOPMODE_R |= EMAC_DMAOPMODE_ST | EMAC_DMAOPMODE_SR;
Sergunb 0:8918a71cdbe9 229
Sergunb 0:8918a71cdbe9 230 //Accept any packets from the upper layer
Sergunb 0:8918a71cdbe9 231 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 232
Sergunb 0:8918a71cdbe9 233 //Successful initialization
Sergunb 0:8918a71cdbe9 234 return NO_ERROR;
Sergunb 0:8918a71cdbe9 235 }
Sergunb 0:8918a71cdbe9 236
Sergunb 0:8918a71cdbe9 237
Sergunb 0:8918a71cdbe9 238 //DK-TM4C129X or EK-TM4C1294XL evaluation board?
Sergunb 0:8918a71cdbe9 239 #if defined(USE_DK_TM4C129X) || defined(USE_EK_TM4C1294XL)
Sergunb 0:8918a71cdbe9 240
Sergunb 0:8918a71cdbe9 241 /**
Sergunb 0:8918a71cdbe9 242 * @brief GPIO configuration
Sergunb 0:8918a71cdbe9 243 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 244 **/
Sergunb 0:8918a71cdbe9 245
Sergunb 0:8918a71cdbe9 246 void tm4c129EthInitGpio(NetInterface *interface)
Sergunb 0:8918a71cdbe9 247 {
Sergunb 0:8918a71cdbe9 248 //DK-TM4C129X evaluation board?
Sergunb 0:8918a71cdbe9 249 #if defined(USE_DK_TM4C129X)
Sergunb 0:8918a71cdbe9 250 //Enable GPIO clocks
Sergunb 0:8918a71cdbe9 251 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
Sergunb 0:8918a71cdbe9 252 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
Sergunb 0:8918a71cdbe9 253
Sergunb 0:8918a71cdbe9 254 //Select the relevant alternate function for PF1, PK4 and PK6
Sergunb 0:8918a71cdbe9 255 GPIOPinConfigure(GPIO_PF1_EN0LED2);
Sergunb 0:8918a71cdbe9 256 GPIOPinConfigure(GPIO_PK4_EN0LED0);
Sergunb 0:8918a71cdbe9 257 GPIOPinConfigure(GPIO_PK6_EN0LED1);
Sergunb 0:8918a71cdbe9 258
Sergunb 0:8918a71cdbe9 259 //Configure Ethernet LED pins for proper operation
Sergunb 0:8918a71cdbe9 260 GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_1);
Sergunb 0:8918a71cdbe9 261 GPIOPinTypeEthernetLED(GPIO_PORTK_BASE, GPIO_PIN_4 | GPIO_PIN_6);
Sergunb 0:8918a71cdbe9 262
Sergunb 0:8918a71cdbe9 263 //EK-TM4C1294XL evaluation board?
Sergunb 0:8918a71cdbe9 264 #elif defined(USE_EK_TM4C1294XL)
Sergunb 0:8918a71cdbe9 265 //Enable GPIO clock
Sergunb 0:8918a71cdbe9 266 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
Sergunb 0:8918a71cdbe9 267
Sergunb 0:8918a71cdbe9 268 //Select the relevant alternate function for PF0 and PF4
Sergunb 0:8918a71cdbe9 269 GPIOPinConfigure(GPIO_PF0_EN0LED0);
Sergunb 0:8918a71cdbe9 270 GPIOPinConfigure(GPIO_PF4_EN0LED1);
Sergunb 0:8918a71cdbe9 271
Sergunb 0:8918a71cdbe9 272 //Configure Ethernet LED pins for proper operation
Sergunb 0:8918a71cdbe9 273 GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
Sergunb 0:8918a71cdbe9 274 #endif
Sergunb 0:8918a71cdbe9 275 }
Sergunb 0:8918a71cdbe9 276
Sergunb 0:8918a71cdbe9 277 #endif
Sergunb 0:8918a71cdbe9 278
Sergunb 0:8918a71cdbe9 279
Sergunb 0:8918a71cdbe9 280 /**
Sergunb 0:8918a71cdbe9 281 * @brief Initialize DMA descriptor lists
Sergunb 0:8918a71cdbe9 282 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 283 **/
Sergunb 0:8918a71cdbe9 284
Sergunb 0:8918a71cdbe9 285 void tm4c129EthInitDmaDesc(NetInterface *interface)
Sergunb 0:8918a71cdbe9 286 {
Sergunb 0:8918a71cdbe9 287 uint_t i;
Sergunb 0:8918a71cdbe9 288
Sergunb 0:8918a71cdbe9 289 //Initialize TX DMA descriptor list
Sergunb 0:8918a71cdbe9 290 for(i = 0; i < TM4C129_ETH_TX_BUFFER_COUNT; i++)
Sergunb 0:8918a71cdbe9 291 {
Sergunb 0:8918a71cdbe9 292 //Use chain structure rather than ring structure
Sergunb 0:8918a71cdbe9 293 txDmaDesc[i].tdes0 = EMAC_TDES0_IC | EMAC_TDES0_TCH;
Sergunb 0:8918a71cdbe9 294 //Initialize transmit buffer size
Sergunb 0:8918a71cdbe9 295 txDmaDesc[i].tdes1 = 0;
Sergunb 0:8918a71cdbe9 296 //Transmit buffer address
Sergunb 0:8918a71cdbe9 297 txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
Sergunb 0:8918a71cdbe9 298 //Next descriptor address
Sergunb 0:8918a71cdbe9 299 txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
Sergunb 0:8918a71cdbe9 300 //Reserved fields
Sergunb 0:8918a71cdbe9 301 txDmaDesc[i].tdes4 = 0;
Sergunb 0:8918a71cdbe9 302 txDmaDesc[i].tdes5 = 0;
Sergunb 0:8918a71cdbe9 303 //Transmit frame time stamp
Sergunb 0:8918a71cdbe9 304 txDmaDesc[i].tdes6 = 0;
Sergunb 0:8918a71cdbe9 305 txDmaDesc[i].tdes7 = 0;
Sergunb 0:8918a71cdbe9 306 }
Sergunb 0:8918a71cdbe9 307
Sergunb 0:8918a71cdbe9 308 //The last descriptor is chained to the first entry
Sergunb 0:8918a71cdbe9 309 txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
Sergunb 0:8918a71cdbe9 310 //Point to the very first descriptor
Sergunb 0:8918a71cdbe9 311 txCurDmaDesc = &txDmaDesc[0];
Sergunb 0:8918a71cdbe9 312
Sergunb 0:8918a71cdbe9 313 //Initialize RX DMA descriptor list
Sergunb 0:8918a71cdbe9 314 for(i = 0; i < TM4C129_ETH_RX_BUFFER_COUNT; i++)
Sergunb 0:8918a71cdbe9 315 {
Sergunb 0:8918a71cdbe9 316 //The descriptor is initially owned by the DMA
Sergunb 0:8918a71cdbe9 317 rxDmaDesc[i].rdes0 = EMAC_RDES0_OWN;
Sergunb 0:8918a71cdbe9 318 //Use chain structure rather than ring structure
Sergunb 0:8918a71cdbe9 319 rxDmaDesc[i].rdes1 = EMAC_RDES1_RCH | (TM4C129_ETH_RX_BUFFER_SIZE & EMAC_RDES1_RBS1);
Sergunb 0:8918a71cdbe9 320 //Receive buffer address
Sergunb 0:8918a71cdbe9 321 rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
Sergunb 0:8918a71cdbe9 322 //Next descriptor address
Sergunb 0:8918a71cdbe9 323 rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
Sergunb 0:8918a71cdbe9 324 //Extended status
Sergunb 0:8918a71cdbe9 325 rxDmaDesc[i].rdes4 = 0;
Sergunb 0:8918a71cdbe9 326 //Reserved field
Sergunb 0:8918a71cdbe9 327 rxDmaDesc[i].rdes5 = 0;
Sergunb 0:8918a71cdbe9 328 //Receive frame time stamp
Sergunb 0:8918a71cdbe9 329 rxDmaDesc[i].rdes6 = 0;
Sergunb 0:8918a71cdbe9 330 rxDmaDesc[i].rdes7 = 0;
Sergunb 0:8918a71cdbe9 331 }
Sergunb 0:8918a71cdbe9 332
Sergunb 0:8918a71cdbe9 333 //The last descriptor is chained to the first entry
Sergunb 0:8918a71cdbe9 334 rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
Sergunb 0:8918a71cdbe9 335 //Point to the very first descriptor
Sergunb 0:8918a71cdbe9 336 rxCurDmaDesc = &rxDmaDesc[0];
Sergunb 0:8918a71cdbe9 337
Sergunb 0:8918a71cdbe9 338 //Start location of the TX descriptor list
Sergunb 0:8918a71cdbe9 339 EMAC0_TXDLADDR_R = (uint32_t) txDmaDesc;
Sergunb 0:8918a71cdbe9 340 //Start location of the RX descriptor list
Sergunb 0:8918a71cdbe9 341 EMAC0_RXDLADDR_R = (uint32_t) rxDmaDesc;
Sergunb 0:8918a71cdbe9 342 }
Sergunb 0:8918a71cdbe9 343
Sergunb 0:8918a71cdbe9 344
Sergunb 0:8918a71cdbe9 345 /**
Sergunb 0:8918a71cdbe9 346 * @brief TM4C129 Ethernet MAC timer handler
Sergunb 0:8918a71cdbe9 347 *
Sergunb 0:8918a71cdbe9 348 * This routine is periodically called by the TCP/IP stack to
Sergunb 0:8918a71cdbe9 349 * handle periodic operations such as polling the link state
Sergunb 0:8918a71cdbe9 350 *
Sergunb 0:8918a71cdbe9 351 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 352 **/
Sergunb 0:8918a71cdbe9 353
Sergunb 0:8918a71cdbe9 354 void tm4c129EthTick(NetInterface *interface)
Sergunb 0:8918a71cdbe9 355 {
Sergunb 0:8918a71cdbe9 356 }
Sergunb 0:8918a71cdbe9 357
Sergunb 0:8918a71cdbe9 358
Sergunb 0:8918a71cdbe9 359 /**
Sergunb 0:8918a71cdbe9 360 * @brief Enable interrupts
Sergunb 0:8918a71cdbe9 361 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 362 **/
Sergunb 0:8918a71cdbe9 363
Sergunb 0:8918a71cdbe9 364 void tm4c129EthEnableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 365 {
Sergunb 0:8918a71cdbe9 366 //Enable Ethernet MAC interrupts
Sergunb 0:8918a71cdbe9 367 IntEnable(INT_EMAC0);
Sergunb 0:8918a71cdbe9 368 }
Sergunb 0:8918a71cdbe9 369
Sergunb 0:8918a71cdbe9 370
Sergunb 0:8918a71cdbe9 371 /**
Sergunb 0:8918a71cdbe9 372 * @brief Disable interrupts
Sergunb 0:8918a71cdbe9 373 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 374 **/
Sergunb 0:8918a71cdbe9 375
Sergunb 0:8918a71cdbe9 376 void tm4c129EthDisableIrq(NetInterface *interface)
Sergunb 0:8918a71cdbe9 377 {
Sergunb 0:8918a71cdbe9 378 //Disable Ethernet MAC interrupts
Sergunb 0:8918a71cdbe9 379 IntDisable(INT_EMAC0);
Sergunb 0:8918a71cdbe9 380 }
Sergunb 0:8918a71cdbe9 381
Sergunb 0:8918a71cdbe9 382
Sergunb 0:8918a71cdbe9 383 /**
Sergunb 0:8918a71cdbe9 384 * @brief TM4C129 Ethernet MAC interrupt service routine
Sergunb 0:8918a71cdbe9 385 **/
Sergunb 0:8918a71cdbe9 386
Sergunb 0:8918a71cdbe9 387 void EMAC0_Handler(void)
Sergunb 0:8918a71cdbe9 388 {
Sergunb 0:8918a71cdbe9 389 bool_t flag;
Sergunb 0:8918a71cdbe9 390 uint32_t status;
Sergunb 0:8918a71cdbe9 391
Sergunb 0:8918a71cdbe9 392 //Enter interrupt service routine
Sergunb 0:8918a71cdbe9 393 osEnterIsr();
Sergunb 0:8918a71cdbe9 394
Sergunb 0:8918a71cdbe9 395 //This flag will be set if a higher priority task must be woken
Sergunb 0:8918a71cdbe9 396 flag = FALSE;
Sergunb 0:8918a71cdbe9 397
Sergunb 0:8918a71cdbe9 398 //Read PHY status register
Sergunb 0:8918a71cdbe9 399 status = EMAC0_EPHYRIS_R;
Sergunb 0:8918a71cdbe9 400
Sergunb 0:8918a71cdbe9 401 //PHY interrupt?
Sergunb 0:8918a71cdbe9 402 if(status & EMAC_EPHYRIS_INT)
Sergunb 0:8918a71cdbe9 403 {
Sergunb 0:8918a71cdbe9 404 //Disable PHY interrupt
Sergunb 0:8918a71cdbe9 405 EMAC0_EPHYIM_R &= ~EMAC_EPHYIM_INT;
Sergunb 0:8918a71cdbe9 406
Sergunb 0:8918a71cdbe9 407 //Set event flag
Sergunb 0:8918a71cdbe9 408 nicDriverInterface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 409 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 410 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 411 }
Sergunb 0:8918a71cdbe9 412
Sergunb 0:8918a71cdbe9 413 //Read DMA status register
Sergunb 0:8918a71cdbe9 414 status = EMAC0_DMARIS_R;
Sergunb 0:8918a71cdbe9 415
Sergunb 0:8918a71cdbe9 416 //A packet has been transmitted?
Sergunb 0:8918a71cdbe9 417 if(status & EMAC_DMARIS_TI)
Sergunb 0:8918a71cdbe9 418 {
Sergunb 0:8918a71cdbe9 419 //Clear TI interrupt flag
Sergunb 0:8918a71cdbe9 420 EMAC0_DMARIS_R = EMAC_DMARIS_TI;
Sergunb 0:8918a71cdbe9 421
Sergunb 0:8918a71cdbe9 422 //Check whether the TX buffer is available for writing
Sergunb 0:8918a71cdbe9 423 if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
Sergunb 0:8918a71cdbe9 424 {
Sergunb 0:8918a71cdbe9 425 //Notify the TCP/IP stack that the transmitter is ready to send
Sergunb 0:8918a71cdbe9 426 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
Sergunb 0:8918a71cdbe9 427 }
Sergunb 0:8918a71cdbe9 428 }
Sergunb 0:8918a71cdbe9 429
Sergunb 0:8918a71cdbe9 430 //A packet has been received?
Sergunb 0:8918a71cdbe9 431 if(status & EMAC_DMARIS_RI)
Sergunb 0:8918a71cdbe9 432 {
Sergunb 0:8918a71cdbe9 433 //Disable RIE interrupt
Sergunb 0:8918a71cdbe9 434 EMAC0_DMAIM_R &= ~EMAC_DMAIM_RIE;
Sergunb 0:8918a71cdbe9 435
Sergunb 0:8918a71cdbe9 436 //Set event flag
Sergunb 0:8918a71cdbe9 437 nicDriverInterface->nicEvent = TRUE;
Sergunb 0:8918a71cdbe9 438 //Notify the TCP/IP stack of the event
Sergunb 0:8918a71cdbe9 439 flag |= osSetEventFromIsr(&netEvent);
Sergunb 0:8918a71cdbe9 440 }
Sergunb 0:8918a71cdbe9 441
Sergunb 0:8918a71cdbe9 442 //Clear NIS interrupt flag
Sergunb 0:8918a71cdbe9 443 EMAC0_DMARIS_R = EMAC_DMARIS_NIS;
Sergunb 0:8918a71cdbe9 444
Sergunb 0:8918a71cdbe9 445 //Leave interrupt service routine
Sergunb 0:8918a71cdbe9 446 osExitIsr(flag);
Sergunb 0:8918a71cdbe9 447 }
Sergunb 0:8918a71cdbe9 448
Sergunb 0:8918a71cdbe9 449
Sergunb 0:8918a71cdbe9 450 /**
Sergunb 0:8918a71cdbe9 451 * @brief TM4C129 Ethernet MAC event handler
Sergunb 0:8918a71cdbe9 452 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 453 **/
Sergunb 0:8918a71cdbe9 454
Sergunb 0:8918a71cdbe9 455 void tm4c129EthEventHandler(NetInterface *interface)
Sergunb 0:8918a71cdbe9 456 {
Sergunb 0:8918a71cdbe9 457 error_t error;
Sergunb 0:8918a71cdbe9 458 uint32_t status;
Sergunb 0:8918a71cdbe9 459
Sergunb 0:8918a71cdbe9 460 //PHY interrupt?
Sergunb 0:8918a71cdbe9 461 if(EMAC0_EPHYRIS_R & EMAC_EPHYRIS_INT)
Sergunb 0:8918a71cdbe9 462 {
Sergunb 0:8918a71cdbe9 463 //Clear PHY interrupt flag
Sergunb 0:8918a71cdbe9 464 EMAC0_EPHYMISC_R = EMAC_EPHYMISC_INT;
Sergunb 0:8918a71cdbe9 465 //Read PHY interrupt status register
Sergunb 0:8918a71cdbe9 466 status = tm4c129EthReadPhyReg(EPHY_MISR1);
Sergunb 0:8918a71cdbe9 467
Sergunb 0:8918a71cdbe9 468 //Check whether the link state has changed?
Sergunb 0:8918a71cdbe9 469 if(status & EPHY_MISR1_LINKSTAT)
Sergunb 0:8918a71cdbe9 470 {
Sergunb 0:8918a71cdbe9 471 //Read BMSR register
Sergunb 0:8918a71cdbe9 472 status = tm4c129EthReadPhyReg(EPHY_BMSR);
Sergunb 0:8918a71cdbe9 473
Sergunb 0:8918a71cdbe9 474 //Check whether link is up?
Sergunb 0:8918a71cdbe9 475 if(status & EPHY_BMSR_LINKSTAT)
Sergunb 0:8918a71cdbe9 476 {
Sergunb 0:8918a71cdbe9 477 //Read PHY status register
Sergunb 0:8918a71cdbe9 478 status = tm4c129EthReadPhyReg(EPHY_STS);
Sergunb 0:8918a71cdbe9 479
Sergunb 0:8918a71cdbe9 480 //Check current speed
Sergunb 0:8918a71cdbe9 481 if(status & EPHY_STS_SPEED)
Sergunb 0:8918a71cdbe9 482 {
Sergunb 0:8918a71cdbe9 483 //10BASE-T operation
Sergunb 0:8918a71cdbe9 484 interface->linkSpeed = NIC_LINK_SPEED_10MBPS;
Sergunb 0:8918a71cdbe9 485 //Update MAC configuration
Sergunb 0:8918a71cdbe9 486 EMAC0_CFG_R &= ~EMAC_CFG_FES;
Sergunb 0:8918a71cdbe9 487 }
Sergunb 0:8918a71cdbe9 488 else
Sergunb 0:8918a71cdbe9 489 {
Sergunb 0:8918a71cdbe9 490 //100BASE-TX operation
Sergunb 0:8918a71cdbe9 491 interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
Sergunb 0:8918a71cdbe9 492 //Update MAC configuration
Sergunb 0:8918a71cdbe9 493 EMAC0_CFG_R |= EMAC_CFG_FES;
Sergunb 0:8918a71cdbe9 494 }
Sergunb 0:8918a71cdbe9 495
Sergunb 0:8918a71cdbe9 496 //Check current duplex mode
Sergunb 0:8918a71cdbe9 497 if(status & EPHY_STS_DUPLEX)
Sergunb 0:8918a71cdbe9 498 {
Sergunb 0:8918a71cdbe9 499 //Full-Duplex mode
Sergunb 0:8918a71cdbe9 500 interface->duplexMode = NIC_FULL_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 501 //Update MAC configuration
Sergunb 0:8918a71cdbe9 502 EMAC0_CFG_R |= EMAC_CFG_DUPM;
Sergunb 0:8918a71cdbe9 503 }
Sergunb 0:8918a71cdbe9 504 else
Sergunb 0:8918a71cdbe9 505 {
Sergunb 0:8918a71cdbe9 506 //Half-Duplex mode
Sergunb 0:8918a71cdbe9 507 interface->duplexMode = NIC_HALF_DUPLEX_MODE;
Sergunb 0:8918a71cdbe9 508 //Update MAC configuration
Sergunb 0:8918a71cdbe9 509 EMAC0_CFG_R &= ~EMAC_CFG_DUPM;
Sergunb 0:8918a71cdbe9 510 }
Sergunb 0:8918a71cdbe9 511
Sergunb 0:8918a71cdbe9 512 //Update link state
Sergunb 0:8918a71cdbe9 513 interface->linkState = TRUE;
Sergunb 0:8918a71cdbe9 514 }
Sergunb 0:8918a71cdbe9 515 else
Sergunb 0:8918a71cdbe9 516 {
Sergunb 0:8918a71cdbe9 517 //Update link state
Sergunb 0:8918a71cdbe9 518 interface->linkState = FALSE;
Sergunb 0:8918a71cdbe9 519 }
Sergunb 0:8918a71cdbe9 520
Sergunb 0:8918a71cdbe9 521 //Process link state change event
Sergunb 0:8918a71cdbe9 522 nicNotifyLinkChange(interface);
Sergunb 0:8918a71cdbe9 523 }
Sergunb 0:8918a71cdbe9 524 }
Sergunb 0:8918a71cdbe9 525
Sergunb 0:8918a71cdbe9 526 //Packet received?
Sergunb 0:8918a71cdbe9 527 if(EMAC0_DMARIS_R & EMAC_DMARIS_RI)
Sergunb 0:8918a71cdbe9 528 {
Sergunb 0:8918a71cdbe9 529 //Clear interrupt flag
Sergunb 0:8918a71cdbe9 530 EMAC0_DMARIS_R = EMAC_DMARIS_RI;
Sergunb 0:8918a71cdbe9 531
Sergunb 0:8918a71cdbe9 532 //Process all pending packets
Sergunb 0:8918a71cdbe9 533 do
Sergunb 0:8918a71cdbe9 534 {
Sergunb 0:8918a71cdbe9 535 //Read incoming packet
Sergunb 0:8918a71cdbe9 536 error = tm4c129EthReceivePacket(interface);
Sergunb 0:8918a71cdbe9 537
Sergunb 0:8918a71cdbe9 538 //No more data in the receive buffer?
Sergunb 0:8918a71cdbe9 539 } while(error != ERROR_BUFFER_EMPTY);
Sergunb 0:8918a71cdbe9 540 }
Sergunb 0:8918a71cdbe9 541
Sergunb 0:8918a71cdbe9 542 //Re-enable DMA interrupts
Sergunb 0:8918a71cdbe9 543 EMAC0_DMAIM_R |= EMAC_DMAIM_NIE | EMAC_DMAIM_RIE | EMAC_DMAIM_TIE;
Sergunb 0:8918a71cdbe9 544 //Re-enable PHY interrupts
Sergunb 0:8918a71cdbe9 545 EMAC0_EPHYIM_R |= EMAC_EPHYIM_INT;
Sergunb 0:8918a71cdbe9 546 }
Sergunb 0:8918a71cdbe9 547
Sergunb 0:8918a71cdbe9 548
Sergunb 0:8918a71cdbe9 549 /**
Sergunb 0:8918a71cdbe9 550 * @brief Send a packet
Sergunb 0:8918a71cdbe9 551 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 552 * @param[in] buffer Multi-part buffer containing the data to send
Sergunb 0:8918a71cdbe9 553 * @param[in] offset Offset to the first data byte
Sergunb 0:8918a71cdbe9 554 * @return Error code
Sergunb 0:8918a71cdbe9 555 **/
Sergunb 0:8918a71cdbe9 556
Sergunb 0:8918a71cdbe9 557 error_t tm4c129EthSendPacket(NetInterface *interface,
Sergunb 0:8918a71cdbe9 558 const NetBuffer *buffer, size_t offset)
Sergunb 0:8918a71cdbe9 559 {
Sergunb 0:8918a71cdbe9 560 size_t length;
Sergunb 0:8918a71cdbe9 561
Sergunb 0:8918a71cdbe9 562 //Retrieve the length of the packet
Sergunb 0:8918a71cdbe9 563 length = netBufferGetLength(buffer) - offset;
Sergunb 0:8918a71cdbe9 564
Sergunb 0:8918a71cdbe9 565 //Check the frame length
Sergunb 0:8918a71cdbe9 566 if(length > TM4C129_ETH_TX_BUFFER_SIZE)
Sergunb 0:8918a71cdbe9 567 {
Sergunb 0:8918a71cdbe9 568 //The transmitter can accept another packet
Sergunb 0:8918a71cdbe9 569 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 570 //Report an error
Sergunb 0:8918a71cdbe9 571 return ERROR_INVALID_LENGTH;
Sergunb 0:8918a71cdbe9 572 }
Sergunb 0:8918a71cdbe9 573
Sergunb 0:8918a71cdbe9 574 //Make sure the current buffer is available for writing
Sergunb 0:8918a71cdbe9 575 if(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN)
Sergunb 0:8918a71cdbe9 576 return ERROR_FAILURE;
Sergunb 0:8918a71cdbe9 577
Sergunb 0:8918a71cdbe9 578 //Copy user data to the transmit buffer
Sergunb 0:8918a71cdbe9 579 netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
Sergunb 0:8918a71cdbe9 580
Sergunb 0:8918a71cdbe9 581 //Write the number of bytes to send
Sergunb 0:8918a71cdbe9 582 txCurDmaDesc->tdes1 = length & EMAC_TDES1_TBS1;
Sergunb 0:8918a71cdbe9 583 //Set LS and FS flags as the data fits in a single buffer
Sergunb 0:8918a71cdbe9 584 txCurDmaDesc->tdes0 |= EMAC_TDES0_LS | EMAC_TDES0_FS;
Sergunb 0:8918a71cdbe9 585 //Give the ownership of the descriptor to the DMA
Sergunb 0:8918a71cdbe9 586 txCurDmaDesc->tdes0 |= EMAC_TDES0_OWN;
Sergunb 0:8918a71cdbe9 587
Sergunb 0:8918a71cdbe9 588 //Clear TU flag to resume processing
Sergunb 0:8918a71cdbe9 589 EMAC0_DMARIS_R = EMAC_DMARIS_TU;
Sergunb 0:8918a71cdbe9 590 //Instruct the DMA to poll the transmit descriptor list
Sergunb 0:8918a71cdbe9 591 EMAC0_TXPOLLD_R = 0;
Sergunb 0:8918a71cdbe9 592
Sergunb 0:8918a71cdbe9 593 //Point to the next descriptor in the list
Sergunb 0:8918a71cdbe9 594 txCurDmaDesc = (Tm4c129TxDmaDesc *) txCurDmaDesc->tdes3;
Sergunb 0:8918a71cdbe9 595
Sergunb 0:8918a71cdbe9 596 //Check whether the next buffer is available for writing
Sergunb 0:8918a71cdbe9 597 if(!(txCurDmaDesc->tdes0 & EMAC_TDES0_OWN))
Sergunb 0:8918a71cdbe9 598 {
Sergunb 0:8918a71cdbe9 599 //The transmitter can accept another packet
Sergunb 0:8918a71cdbe9 600 osSetEvent(&interface->nicTxEvent);
Sergunb 0:8918a71cdbe9 601 }
Sergunb 0:8918a71cdbe9 602
Sergunb 0:8918a71cdbe9 603 //Data successfully written
Sergunb 0:8918a71cdbe9 604 return NO_ERROR;
Sergunb 0:8918a71cdbe9 605 }
Sergunb 0:8918a71cdbe9 606
Sergunb 0:8918a71cdbe9 607
Sergunb 0:8918a71cdbe9 608 /**
Sergunb 0:8918a71cdbe9 609 * @brief Receive a packet
Sergunb 0:8918a71cdbe9 610 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 611 * @return Error code
Sergunb 0:8918a71cdbe9 612 **/
Sergunb 0:8918a71cdbe9 613
Sergunb 0:8918a71cdbe9 614 error_t tm4c129EthReceivePacket(NetInterface *interface)
Sergunb 0:8918a71cdbe9 615 {
Sergunb 0:8918a71cdbe9 616 error_t error;
Sergunb 0:8918a71cdbe9 617 size_t n;
Sergunb 0:8918a71cdbe9 618
Sergunb 0:8918a71cdbe9 619 //The current buffer is available for reading?
Sergunb 0:8918a71cdbe9 620 if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_OWN))
Sergunb 0:8918a71cdbe9 621 {
Sergunb 0:8918a71cdbe9 622 //FS and LS flags should be set
Sergunb 0:8918a71cdbe9 623 if((rxCurDmaDesc->rdes0 & EMAC_RDES0_FS) && (rxCurDmaDesc->rdes0 & EMAC_RDES0_LS))
Sergunb 0:8918a71cdbe9 624 {
Sergunb 0:8918a71cdbe9 625 //Make sure no error occurred
Sergunb 0:8918a71cdbe9 626 if(!(rxCurDmaDesc->rdes0 & EMAC_RDES0_ES))
Sergunb 0:8918a71cdbe9 627 {
Sergunb 0:8918a71cdbe9 628 //Retrieve the length of the frame
Sergunb 0:8918a71cdbe9 629 n = (rxCurDmaDesc->rdes0 & EMAC_RDES0_FL) >> 16;
Sergunb 0:8918a71cdbe9 630 //Limit the number of data to read
Sergunb 0:8918a71cdbe9 631 n = MIN(n, TM4C129_ETH_RX_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 632
Sergunb 0:8918a71cdbe9 633 //Pass the packet to the upper layer
Sergunb 0:8918a71cdbe9 634 nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
Sergunb 0:8918a71cdbe9 635
Sergunb 0:8918a71cdbe9 636 //Valid packet received
Sergunb 0:8918a71cdbe9 637 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 638 }
Sergunb 0:8918a71cdbe9 639 else
Sergunb 0:8918a71cdbe9 640 {
Sergunb 0:8918a71cdbe9 641 //The received packet contains an error
Sergunb 0:8918a71cdbe9 642 error = ERROR_INVALID_PACKET;
Sergunb 0:8918a71cdbe9 643 }
Sergunb 0:8918a71cdbe9 644 }
Sergunb 0:8918a71cdbe9 645 else
Sergunb 0:8918a71cdbe9 646 {
Sergunb 0:8918a71cdbe9 647 //The packet is not valid
Sergunb 0:8918a71cdbe9 648 error = ERROR_INVALID_PACKET;
Sergunb 0:8918a71cdbe9 649 }
Sergunb 0:8918a71cdbe9 650
Sergunb 0:8918a71cdbe9 651 //Give the ownership of the descriptor back to the DMA
Sergunb 0:8918a71cdbe9 652 rxCurDmaDesc->rdes0 = EMAC_RDES0_OWN;
Sergunb 0:8918a71cdbe9 653 //Point to the next descriptor in the list
Sergunb 0:8918a71cdbe9 654 rxCurDmaDesc = (Tm4c129RxDmaDesc *) rxCurDmaDesc->rdes3;
Sergunb 0:8918a71cdbe9 655 }
Sergunb 0:8918a71cdbe9 656 else
Sergunb 0:8918a71cdbe9 657 {
Sergunb 0:8918a71cdbe9 658 //No more data in the receive buffer
Sergunb 0:8918a71cdbe9 659 error = ERROR_BUFFER_EMPTY;
Sergunb 0:8918a71cdbe9 660 }
Sergunb 0:8918a71cdbe9 661
Sergunb 0:8918a71cdbe9 662 //Clear RU flag to resume processing
Sergunb 0:8918a71cdbe9 663 EMAC0_DMARIS_R = EMAC_DMARIS_RU;
Sergunb 0:8918a71cdbe9 664 //Instruct the DMA to poll the receive descriptor list
Sergunb 0:8918a71cdbe9 665 EMAC0_RXPOLLD_R = 0;
Sergunb 0:8918a71cdbe9 666
Sergunb 0:8918a71cdbe9 667 //Return status code
Sergunb 0:8918a71cdbe9 668 return error;
Sergunb 0:8918a71cdbe9 669 }
Sergunb 0:8918a71cdbe9 670
Sergunb 0:8918a71cdbe9 671
Sergunb 0:8918a71cdbe9 672 /**
Sergunb 0:8918a71cdbe9 673 * @brief Configure multicast MAC address filtering
Sergunb 0:8918a71cdbe9 674 * @param[in] interface Underlying network interface
Sergunb 0:8918a71cdbe9 675 * @return Error code
Sergunb 0:8918a71cdbe9 676 **/
Sergunb 0:8918a71cdbe9 677
Sergunb 0:8918a71cdbe9 678 error_t tm4c129EthSetMulticastFilter(NetInterface *interface)
Sergunb 0:8918a71cdbe9 679 {
Sergunb 0:8918a71cdbe9 680 uint_t i;
Sergunb 0:8918a71cdbe9 681 uint_t k;
Sergunb 0:8918a71cdbe9 682 uint32_t crc;
Sergunb 0:8918a71cdbe9 683 uint32_t hashTable[2];
Sergunb 0:8918a71cdbe9 684 MacFilterEntry *entry;
Sergunb 0:8918a71cdbe9 685
Sergunb 0:8918a71cdbe9 686 //Debug message
Sergunb 0:8918a71cdbe9 687 TRACE_DEBUG("Updating Tiva TM4C129 hash table...\r\n");
Sergunb 0:8918a71cdbe9 688
Sergunb 0:8918a71cdbe9 689 //Clear hash table
Sergunb 0:8918a71cdbe9 690 hashTable[0] = 0;
Sergunb 0:8918a71cdbe9 691 hashTable[1] = 0;
Sergunb 0:8918a71cdbe9 692
Sergunb 0:8918a71cdbe9 693 //The MAC filter table contains the multicast MAC addresses
Sergunb 0:8918a71cdbe9 694 //to accept when receiving an Ethernet frame
Sergunb 0:8918a71cdbe9 695 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++)
Sergunb 0:8918a71cdbe9 696 {
Sergunb 0:8918a71cdbe9 697 //Point to the current entry
Sergunb 0:8918a71cdbe9 698 entry = &interface->macMulticastFilter[i];
Sergunb 0:8918a71cdbe9 699
Sergunb 0:8918a71cdbe9 700 //Valid entry?
Sergunb 0:8918a71cdbe9 701 if(entry->refCount > 0)
Sergunb 0:8918a71cdbe9 702 {
Sergunb 0:8918a71cdbe9 703 //Compute CRC over the current MAC address
Sergunb 0:8918a71cdbe9 704 crc = tm4c129EthCalcCrc(&entry->addr, sizeof(MacAddr));
Sergunb 0:8918a71cdbe9 705
Sergunb 0:8918a71cdbe9 706 //The upper 6 bits in the CRC register are used to index the
Sergunb 0:8918a71cdbe9 707 //contents of the hash table
Sergunb 0:8918a71cdbe9 708 k = (crc >> 26) & 0x3F;
Sergunb 0:8918a71cdbe9 709
Sergunb 0:8918a71cdbe9 710 //Update hash table contents
Sergunb 0:8918a71cdbe9 711 hashTable[k / 32] |= (1 << (k % 32));
Sergunb 0:8918a71cdbe9 712 }
Sergunb 0:8918a71cdbe9 713 }
Sergunb 0:8918a71cdbe9 714
Sergunb 0:8918a71cdbe9 715 //Write the hash table
Sergunb 0:8918a71cdbe9 716 EMAC0_HASHTBLL_R = hashTable[0];
Sergunb 0:8918a71cdbe9 717 EMAC0_HASHTBLH_R = hashTable[1];
Sergunb 0:8918a71cdbe9 718
Sergunb 0:8918a71cdbe9 719 //Debug message
Sergunb 0:8918a71cdbe9 720 TRACE_DEBUG(" HASHTBLL = %08" PRIX32 "\r\n", EMAC0_HASHTBLL_R);
Sergunb 0:8918a71cdbe9 721 TRACE_DEBUG(" HASHTBLH = %08" PRIX32 "\r\n", EMAC0_HASHTBLH_R);
Sergunb 0:8918a71cdbe9 722
Sergunb 0:8918a71cdbe9 723 //Successful processing
Sergunb 0:8918a71cdbe9 724 return NO_ERROR;
Sergunb 0:8918a71cdbe9 725 }
Sergunb 0:8918a71cdbe9 726
Sergunb 0:8918a71cdbe9 727
Sergunb 0:8918a71cdbe9 728 /**
Sergunb 0:8918a71cdbe9 729 * @brief Write PHY register
Sergunb 0:8918a71cdbe9 730 * @param[in] regAddr Register address
Sergunb 0:8918a71cdbe9 731 * @param[in] data Register value
Sergunb 0:8918a71cdbe9 732 **/
Sergunb 0:8918a71cdbe9 733
Sergunb 0:8918a71cdbe9 734 void tm4c129EthWritePhyReg(uint8_t regAddr, uint16_t data)
Sergunb 0:8918a71cdbe9 735 {
Sergunb 0:8918a71cdbe9 736 uint32_t value;
Sergunb 0:8918a71cdbe9 737
Sergunb 0:8918a71cdbe9 738 //Take care not to alter MDC clock configuration
Sergunb 0:8918a71cdbe9 739 value = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
Sergunb 0:8918a71cdbe9 740 //Set up a write operation
Sergunb 0:8918a71cdbe9 741 value |= EMAC_MIIADDR_MIIW | EMAC_MIIADDR_MIIB;
Sergunb 0:8918a71cdbe9 742 //The address of the integrated PHY is 0
Sergunb 0:8918a71cdbe9 743 value |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
Sergunb 0:8918a71cdbe9 744 //Register address
Sergunb 0:8918a71cdbe9 745 value |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
Sergunb 0:8918a71cdbe9 746
Sergunb 0:8918a71cdbe9 747 //Data to be written in the PHY register
Sergunb 0:8918a71cdbe9 748 EMAC0_MIIDATA_R = data & EMAC_MIIDATA_DATA_M;
Sergunb 0:8918a71cdbe9 749
Sergunb 0:8918a71cdbe9 750 //Start a write operation
Sergunb 0:8918a71cdbe9 751 EMAC0_MIIADDR_R = value;
Sergunb 0:8918a71cdbe9 752 //Wait for the write to complete
Sergunb 0:8918a71cdbe9 753 while(EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB);
Sergunb 0:8918a71cdbe9 754 }
Sergunb 0:8918a71cdbe9 755
Sergunb 0:8918a71cdbe9 756
Sergunb 0:8918a71cdbe9 757 /**
Sergunb 0:8918a71cdbe9 758 * @brief Read PHY register
Sergunb 0:8918a71cdbe9 759 * @param[in] regAddr Register address
Sergunb 0:8918a71cdbe9 760 * @return Register value
Sergunb 0:8918a71cdbe9 761 **/
Sergunb 0:8918a71cdbe9 762
Sergunb 0:8918a71cdbe9 763 uint16_t tm4c129EthReadPhyReg(uint8_t regAddr)
Sergunb 0:8918a71cdbe9 764 {
Sergunb 0:8918a71cdbe9 765 uint32_t value;
Sergunb 0:8918a71cdbe9 766
Sergunb 0:8918a71cdbe9 767 //Take care not to alter MDC clock configuration
Sergunb 0:8918a71cdbe9 768 value = EMAC0_MIIADDR_R & EMAC_MIIADDR_CR_M;
Sergunb 0:8918a71cdbe9 769 //Set up a read operation
Sergunb 0:8918a71cdbe9 770 value |= EMAC_MIIADDR_MIIB;
Sergunb 0:8918a71cdbe9 771 //The address of the integrated PHY is 0
Sergunb 0:8918a71cdbe9 772 value |= (0 << EMAC_MIIADDR_PLA_S) & EMAC_MIIADDR_PLA_M;
Sergunb 0:8918a71cdbe9 773 //Register address
Sergunb 0:8918a71cdbe9 774 value |= (regAddr << EMAC_MIIADDR_MII_S) & EMAC_MIIADDR_MII_M;
Sergunb 0:8918a71cdbe9 775
Sergunb 0:8918a71cdbe9 776 //Start a read operation
Sergunb 0:8918a71cdbe9 777 EMAC0_MIIADDR_R = value;
Sergunb 0:8918a71cdbe9 778 //Wait for the read to complete
Sergunb 0:8918a71cdbe9 779 while(EMAC0_MIIADDR_R & EMAC_MIIADDR_MIIB);
Sergunb 0:8918a71cdbe9 780
Sergunb 0:8918a71cdbe9 781 //Return PHY register contents
Sergunb 0:8918a71cdbe9 782 return EMAC0_MIIDATA_R & EMAC_MIIDATA_DATA_M;
Sergunb 0:8918a71cdbe9 783 }
Sergunb 0:8918a71cdbe9 784
Sergunb 0:8918a71cdbe9 785
Sergunb 0:8918a71cdbe9 786 /**
Sergunb 0:8918a71cdbe9 787 * @brief Dump PHY registers for debugging purpose
Sergunb 0:8918a71cdbe9 788 **/
Sergunb 0:8918a71cdbe9 789
Sergunb 0:8918a71cdbe9 790 void tm4c129EthDumpPhyReg(void)
Sergunb 0:8918a71cdbe9 791 {
Sergunb 0:8918a71cdbe9 792 uint8_t i;
Sergunb 0:8918a71cdbe9 793
Sergunb 0:8918a71cdbe9 794 //Loop through PHY registers
Sergunb 0:8918a71cdbe9 795 for(i = 0; i < 32; i++)
Sergunb 0:8918a71cdbe9 796 {
Sergunb 0:8918a71cdbe9 797 //Display current PHY register
Sergunb 0:8918a71cdbe9 798 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, tm4c129EthReadPhyReg(i));
Sergunb 0:8918a71cdbe9 799 }
Sergunb 0:8918a71cdbe9 800
Sergunb 0:8918a71cdbe9 801 //Terminate with a line feed
Sergunb 0:8918a71cdbe9 802 TRACE_DEBUG("\r\n");
Sergunb 0:8918a71cdbe9 803 }
Sergunb 0:8918a71cdbe9 804
Sergunb 0:8918a71cdbe9 805
Sergunb 0:8918a71cdbe9 806 /**
Sergunb 0:8918a71cdbe9 807 * @brief CRC calculation
Sergunb 0:8918a71cdbe9 808 * @param[in] data Pointer to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 809 * @param[in] length Number of bytes to process
Sergunb 0:8918a71cdbe9 810 * @return Resulting CRC value
Sergunb 0:8918a71cdbe9 811 **/
Sergunb 0:8918a71cdbe9 812
Sergunb 0:8918a71cdbe9 813 uint32_t tm4c129EthCalcCrc(const void *data, size_t length)
Sergunb 0:8918a71cdbe9 814 {
Sergunb 0:8918a71cdbe9 815 uint_t i;
Sergunb 0:8918a71cdbe9 816 uint_t j;
Sergunb 0:8918a71cdbe9 817
Sergunb 0:8918a71cdbe9 818 //Point to the data over which to calculate the CRC
Sergunb 0:8918a71cdbe9 819 const uint8_t *p = (uint8_t *) data;
Sergunb 0:8918a71cdbe9 820 //CRC preset value
Sergunb 0:8918a71cdbe9 821 uint32_t crc = 0xFFFFFFFF;
Sergunb 0:8918a71cdbe9 822
Sergunb 0:8918a71cdbe9 823 //Loop through data
Sergunb 0:8918a71cdbe9 824 for(i = 0; i < length; i++)
Sergunb 0:8918a71cdbe9 825 {
Sergunb 0:8918a71cdbe9 826 //The message is processed bit by bit
Sergunb 0:8918a71cdbe9 827 for(j = 0; j < 8; j++)
Sergunb 0:8918a71cdbe9 828 {
Sergunb 0:8918a71cdbe9 829 //Update CRC value
Sergunb 0:8918a71cdbe9 830 if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
Sergunb 0:8918a71cdbe9 831 crc = (crc << 1) ^ 0x04C11DB7;
Sergunb 0:8918a71cdbe9 832 else
Sergunb 0:8918a71cdbe9 833 crc = crc << 1;
Sergunb 0:8918a71cdbe9 834 }
Sergunb 0:8918a71cdbe9 835 }
Sergunb 0:8918a71cdbe9 836
Sergunb 0:8918a71cdbe9 837 //Return CRC value
Sergunb 0:8918a71cdbe9 838 return ~crc;
Sergunb 0:8918a71cdbe9 839 }
Sergunb 0:8918a71cdbe9 840