Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
stm32f2x7_eth.c
00001 /** 00002 * @file stm32f2x7_eth.c 00003 * @brief STM32F207/217 Ethernet MAC controller 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL NIC_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "stm32f2xx.h" 00034 #include "core/net.h" 00035 #include "drivers/stm32f2x7_eth.h" 00036 #include "debug.h" 00037 00038 //Underlying network interface 00039 static NetInterface *nicDriverInterface; 00040 00041 //IAR EWARM compiler? 00042 #if defined(__ICCARM__) 00043 00044 //Transmit buffer 00045 #pragma data_alignment = 4 00046 static uint8_t txBuffer[STM32F2X7_ETH_TX_BUFFER_COUNT][STM32F2X7_ETH_TX_BUFFER_SIZE]; 00047 //Receive buffer 00048 #pragma data_alignment = 4 00049 static uint8_t rxBuffer[STM32F2X7_ETH_RX_BUFFER_COUNT][STM32F2X7_ETH_RX_BUFFER_SIZE]; 00050 //Transmit DMA descriptors 00051 #pragma data_alignment = 4 00052 static Stm32f2x7TxDmaDesc txDmaDesc[STM32F2X7_ETH_TX_BUFFER_COUNT]; 00053 //Receive DMA descriptors 00054 #pragma data_alignment = 4 00055 static Stm32f2x7RxDmaDesc rxDmaDesc[STM32F2X7_ETH_RX_BUFFER_COUNT]; 00056 00057 //Keil MDK-ARM or GCC compiler? 00058 #else 00059 00060 //Transmit buffer 00061 static uint8_t txBuffer[STM32F2X7_ETH_TX_BUFFER_COUNT][STM32F2X7_ETH_TX_BUFFER_SIZE] 00062 __attribute__((aligned(4))); 00063 //Receive buffer 00064 static uint8_t rxBuffer[STM32F2X7_ETH_RX_BUFFER_COUNT][STM32F2X7_ETH_RX_BUFFER_SIZE] 00065 __attribute__((aligned(4))); 00066 //Transmit DMA descriptors 00067 static Stm32f2x7TxDmaDesc txDmaDesc[STM32F2X7_ETH_TX_BUFFER_COUNT] 00068 __attribute__((aligned(4))); 00069 //Receive DMA descriptors 00070 static Stm32f2x7RxDmaDesc rxDmaDesc[STM32F2X7_ETH_RX_BUFFER_COUNT] 00071 __attribute__((aligned(4))); 00072 00073 #endif 00074 00075 //Pointer to the current TX DMA descriptor 00076 static Stm32f2x7TxDmaDesc *txCurDmaDesc; 00077 //Pointer to the current RX DMA descriptor 00078 static Stm32f2x7RxDmaDesc *rxCurDmaDesc; 00079 00080 00081 /** 00082 * @brief STM32F207/217 Ethernet MAC driver 00083 **/ 00084 00085 const NicDriver stm32f2x7EthDriver = 00086 { 00087 NIC_TYPE_ETHERNET, 00088 ETH_MTU, 00089 stm32f2x7EthInit, 00090 stm32f2x7EthTick, 00091 stm32f2x7EthEnableIrq, 00092 stm32f2x7EthDisableIrq, 00093 stm32f2x7EthEventHandler, 00094 stm32f2x7EthSendPacket, 00095 stm32f2x7EthSetMulticastFilter, 00096 stm32f2x7EthUpdateMacConfig, 00097 stm32f2x7EthWritePhyReg, 00098 stm32f2x7EthReadPhyReg, 00099 TRUE, 00100 TRUE, 00101 TRUE, 00102 FALSE 00103 }; 00104 00105 00106 /** 00107 * @brief STM32F207/217 Ethernet MAC initialization 00108 * @param[in] interface Underlying network interface 00109 * @return Error code 00110 **/ 00111 00112 error_t stm32f2x7EthInit(NetInterface *interface) 00113 { 00114 error_t error; 00115 00116 //Debug message 00117 TRACE_INFO("Initializing STM32F2x7 Ethernet MAC...\r\n"); 00118 00119 //Save underlying network interface 00120 nicDriverInterface = interface; 00121 00122 //GPIO configuration 00123 stm32f2x7EthInitGpio(interface); 00124 00125 #if defined(USE_HAL_DRIVER) 00126 //Enable Ethernet MAC clock 00127 __HAL_RCC_ETHMAC_CLK_ENABLE(); 00128 __HAL_RCC_ETHMACTX_CLK_ENABLE(); 00129 __HAL_RCC_ETHMACRX_CLK_ENABLE(); 00130 00131 //Reset Ethernet MAC peripheral 00132 __HAL_RCC_ETHMAC_FORCE_RESET(); 00133 __HAL_RCC_ETHMAC_RELEASE_RESET(); 00134 00135 #elif defined(USE_STDPERIPH_DRIVER) 00136 //Enable Ethernet MAC clock 00137 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | 00138 RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx, ENABLE); 00139 00140 //Reset Ethernet MAC peripheral 00141 RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, ENABLE); 00142 RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, DISABLE); 00143 #endif 00144 00145 //Perform a software reset 00146 ETH->DMABMR |= ETH_DMABMR_SR; 00147 //Wait for the reset to complete 00148 while(ETH->DMABMR & ETH_DMABMR_SR); 00149 00150 //Adjust MDC clock range depending on HCLK frequency 00151 ETH->MACMIIAR = ETH_MACMIIAR_CR_Div62; 00152 00153 //PHY transceiver initialization 00154 error = interface->phyDriver->init(interface); 00155 //Failed to initialize PHY transceiver? 00156 if(error) 00157 return error; 00158 00159 //Use default MAC configuration 00160 ETH->MACCR = ETH_MACCR_ROD; 00161 00162 //Set the MAC address 00163 ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00164 ETH->MACA0HR = interface->macAddr.w[2]; 00165 00166 //Initialize hash table 00167 ETH->MACHTLR = 0; 00168 ETH->MACHTHR = 0; 00169 00170 //Configure the receive filter 00171 ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_HM; 00172 //Disable flow control 00173 ETH->MACFCR = 0; 00174 //Enable store and forward mode 00175 ETH->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF; 00176 00177 //Configure DMA bus mode 00178 ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_RDP_1Beat | 00179 ETH_DMABMR_RTPR_1_1 | ETH_DMABMR_PBL_1Beat | ETH_DMABMR_EDE; 00180 00181 //Initialize DMA descriptor lists 00182 stm32f2x7EthInitDmaDesc(interface); 00183 00184 //Prevent interrupts from being generated when the transmit statistic 00185 //counters reach half their maximum value 00186 ETH->MMCTIMR = ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM; 00187 00188 //Prevent interrupts from being generated when the receive statistic 00189 //counters reach half their maximum value 00190 ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM; 00191 00192 //Disable MAC interrupts 00193 ETH->MACIMR = ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM; 00194 //Enable the desired DMA interrupts 00195 ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; 00196 00197 //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority) 00198 NVIC_SetPriorityGrouping(STM32F2X7_ETH_IRQ_PRIORITY_GROUPING); 00199 00200 //Configure Ethernet interrupt priority 00201 NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F2X7_ETH_IRQ_PRIORITY_GROUPING, 00202 STM32F2X7_ETH_IRQ_GROUP_PRIORITY, STM32F2X7_ETH_IRQ_SUB_PRIORITY)); 00203 00204 //Enable MAC transmission and reception 00205 ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE; 00206 //Enable DMA transmission and reception 00207 ETH->DMAOMR |= ETH_DMAOMR_ST | ETH_DMAOMR_SR; 00208 00209 //Accept any packets from the upper layer 00210 osSetEvent(&interface->nicTxEvent); 00211 00212 //Successful initialization 00213 return NO_ERROR; 00214 } 00215 00216 00217 //STM3220G-EVAL, MCBSTM32F200 or Nucleo-F207ZG evaluation board? 00218 #if defined(USE_STM322xG_EVAL) || defined(USE_MCBSTM32F200) || \ 00219 defined(USE_STM32F2XX_NUCLEO_144) 00220 00221 /** 00222 * @brief GPIO configuration 00223 * @param[in] interface Underlying network interface 00224 **/ 00225 00226 void stm32f2x7EthInitGpio(NetInterface *interface) 00227 { 00228 GPIO_InitTypeDef GPIO_InitStructure; 00229 00230 //STM3220G-EVAL evaluation board? 00231 #if defined(USE_STM322xG_EVAL) && defined(USE_HAL_DRIVER) 00232 //Enable SYSCFG clock 00233 __HAL_RCC_SYSCFG_CLK_ENABLE(); 00234 00235 //Enable GPIO clocks 00236 __HAL_RCC_GPIOA_CLK_ENABLE(); 00237 __HAL_RCC_GPIOB_CLK_ENABLE(); 00238 __HAL_RCC_GPIOC_CLK_ENABLE(); 00239 __HAL_RCC_GPIOG_CLK_ENABLE(); 00240 __HAL_RCC_GPIOH_CLK_ENABLE(); 00241 __HAL_RCC_GPIOI_CLK_ENABLE(); 00242 00243 //Configure MCO1 (PA8) as an output 00244 GPIO_InitStructure.Pin = GPIO_PIN_8; 00245 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00246 GPIO_InitStructure.Pull = GPIO_NOPULL; 00247 GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; 00248 GPIO_InitStructure.Alternate = GPIO_AF0_MCO; 00249 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 00250 00251 //Configure MCO1 pin to output the HSE clock (25MHz) 00252 HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1); 00253 00254 //Select MII interface mode 00255 SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL; 00256 00257 //Configure MII pins 00258 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00259 GPIO_InitStructure.Pull = GPIO_NOPULL; 00260 GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; 00261 GPIO_InitStructure.Alternate = GPIO_AF11_ETH; 00262 00263 //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7) 00264 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; 00265 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 00266 00267 //Configure ETH_PPS_OUT (PB5) and ETH_MII_TXD3 (PB8) 00268 GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_8; 00269 HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); 00270 00271 //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3), 00272 //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5) 00273 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; 00274 HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); 00275 00276 //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14) 00277 GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14; 00278 HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); 00279 00280 //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7) 00281 GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7; 00282 HAL_GPIO_Init(GPIOH, &GPIO_InitStructure); 00283 00284 //Configure ETH_MII_RX_ER (PI10) 00285 GPIO_InitStructure.Pin = GPIO_PIN_10; 00286 HAL_GPIO_Init(GPIOI, &GPIO_InitStructure); 00287 00288 #elif defined(USE_STM322xG_EVAL) && defined(USE_STDPERIPH_DRIVER) 00289 //Enable SYSCFG clock 00290 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 00291 00292 //Enable GPIO clocks 00293 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | 00294 RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG | 00295 RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI, ENABLE); 00296 00297 //Configure MCO1 (PA8) as an output 00298 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 00299 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 00300 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 00301 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 00302 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 00303 GPIO_Init(GPIOA, &GPIO_InitStructure); 00304 00305 //Configure MCO1 pin to output the HSE clock (25MHz) 00306 RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1); 00307 00308 //Select MII interface mode 00309 SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII); 00310 00311 //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7) 00312 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7; 00313 GPIO_Init(GPIOA, &GPIO_InitStructure); 00314 GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH); 00315 GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH); 00316 GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH); 00317 00318 //Configure ETH_PPS_OUT (PB5) and ETH_MII_TXD3 (PB8) 00319 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8; 00320 GPIO_Init(GPIOB, &GPIO_InitStructure); 00321 GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_ETH); 00322 GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_ETH); 00323 00324 //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3), 00325 //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5) 00326 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; 00327 GPIO_Init(GPIOC, &GPIO_InitStructure); 00328 GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH); 00329 GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_ETH); 00330 GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_ETH); 00331 GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH); 00332 GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH); 00333 00334 //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14) 00335 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14; 00336 GPIO_Init(GPIOG, &GPIO_InitStructure); 00337 GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH); 00338 GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH); 00339 GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH); 00340 00341 //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7) 00342 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7; 00343 GPIO_Init(GPIOH, &GPIO_InitStructure); 00344 GPIO_PinAFConfig(GPIOH, GPIO_PinSource2, GPIO_AF_ETH); 00345 GPIO_PinAFConfig(GPIOH, GPIO_PinSource3, GPIO_AF_ETH); 00346 GPIO_PinAFConfig(GPIOH, GPIO_PinSource6, GPIO_AF_ETH); 00347 GPIO_PinAFConfig(GPIOH, GPIO_PinSource7, GPIO_AF_ETH); 00348 00349 //Configure ETH_MII_RX_ER (PI10) 00350 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 00351 GPIO_Init(GPIOI, &GPIO_InitStructure); 00352 GPIO_PinAFConfig(GPIOI, GPIO_PinSource10, GPIO_AF_ETH); 00353 00354 //MCBSTM32F200 evaluation board? 00355 #elif defined(USE_MCBSTM32F200) && defined(USE_HAL_DRIVER) 00356 //Enable SYSCFG clock 00357 __HAL_RCC_SYSCFG_CLK_ENABLE(); 00358 00359 //Enable GPIO clocks 00360 __HAL_RCC_GPIOA_CLK_ENABLE(); 00361 __HAL_RCC_GPIOC_CLK_ENABLE(); 00362 __HAL_RCC_GPIOG_CLK_ENABLE(); 00363 00364 //Select RMII interface mode 00365 SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; 00366 00367 //Configure RMII pins 00368 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00369 GPIO_InitStructure.Pull = GPIO_NOPULL; 00370 GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; 00371 GPIO_InitStructure.Alternate = GPIO_AF11_ETH; 00372 00373 //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7) 00374 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; 00375 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 00376 00377 //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5) 00378 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; 00379 HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); 00380 00381 //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14) 00382 GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14; 00383 HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); 00384 00385 #elif defined(USE_MCBSTM32F200) && defined(USE_STDPERIPH_DRIVER) 00386 //Enable SYSCFG clock 00387 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); 00388 00389 //Enable GPIO clocks 00390 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | 00391 RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE); 00392 00393 //Select RMII interface mode 00394 SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII); 00395 00396 //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7) 00397 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7; 00398 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 00399 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; 00400 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 00401 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 00402 GPIO_Init(GPIOA, &GPIO_InitStructure); 00403 GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH); 00404 GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH); 00405 GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH); 00406 00407 //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5) 00408 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5; 00409 GPIO_Init(GPIOC, &GPIO_InitStructure); 00410 GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH); 00411 GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH); 00412 GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH); 00413 00414 //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14) 00415 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14; 00416 GPIO_Init(GPIOG, &GPIO_InitStructure); 00417 GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH); 00418 GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH); 00419 GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH); 00420 00421 //Nucleo-F207ZG evaluation board? 00422 #elif defined(USE_STM32F2XX_NUCLEO_144) 00423 //Enable SYSCFG clock 00424 __HAL_RCC_SYSCFG_CLK_ENABLE(); 00425 00426 //Enable GPIO clocks 00427 __HAL_RCC_GPIOA_CLK_ENABLE(); 00428 __HAL_RCC_GPIOB_CLK_ENABLE(); 00429 __HAL_RCC_GPIOC_CLK_ENABLE(); 00430 __HAL_RCC_GPIOG_CLK_ENABLE(); 00431 00432 //Select RMII interface mode 00433 SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; 00434 00435 //Configure RMII pins 00436 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00437 GPIO_InitStructure.Pull = GPIO_NOPULL; 00438 GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; 00439 GPIO_InitStructure.Alternate = GPIO_AF11_ETH; 00440 00441 //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7) 00442 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; 00443 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 00444 00445 //Configure ETH_RMII_TXD1 (PB13) 00446 GPIO_InitStructure.Pin = GPIO_PIN_13; 00447 HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); 00448 00449 //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5) 00450 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; 00451 HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); 00452 00453 //Configure RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) 00454 GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13; 00455 HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); 00456 #endif 00457 } 00458 00459 #endif 00460 00461 00462 /** 00463 * @brief Initialize DMA descriptor lists 00464 * @param[in] interface Underlying network interface 00465 **/ 00466 00467 void stm32f2x7EthInitDmaDesc(NetInterface *interface) 00468 { 00469 uint_t i; 00470 00471 //Initialize TX DMA descriptor list 00472 for(i = 0; i < STM32F2X7_ETH_TX_BUFFER_COUNT; i++) 00473 { 00474 //Use chain structure rather than ring structure 00475 txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH; 00476 //Initialize transmit buffer size 00477 txDmaDesc[i].tdes1 = 0; 00478 //Transmit buffer address 00479 txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i]; 00480 //Next descriptor address 00481 txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1]; 00482 //Reserved fields 00483 txDmaDesc[i].tdes4 = 0; 00484 txDmaDesc[i].tdes5 = 0; 00485 //Transmit frame time stamp 00486 txDmaDesc[i].tdes6 = 0; 00487 txDmaDesc[i].tdes7 = 0; 00488 } 00489 00490 //The last descriptor is chained to the first entry 00491 txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0]; 00492 //Point to the very first descriptor 00493 txCurDmaDesc = &txDmaDesc[0]; 00494 00495 //Initialize RX DMA descriptor list 00496 for(i = 0; i < STM32F2X7_ETH_RX_BUFFER_COUNT; i++) 00497 { 00498 //The descriptor is initially owned by the DMA 00499 rxDmaDesc[i].rdes0 = ETH_RDES0_OWN; 00500 //Use chain structure rather than ring structure 00501 rxDmaDesc[i].rdes1 = ETH_RDES1_RCH | (STM32F2X7_ETH_RX_BUFFER_SIZE & ETH_RDES1_RBS1); 00502 //Receive buffer address 00503 rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i]; 00504 //Next descriptor address 00505 rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1]; 00506 //Extended status 00507 rxDmaDesc[i].rdes4 = 0; 00508 //Reserved field 00509 rxDmaDesc[i].rdes5 = 0; 00510 //Receive frame time stamp 00511 rxDmaDesc[i].rdes6 = 0; 00512 rxDmaDesc[i].rdes7 = 0; 00513 } 00514 00515 //The last descriptor is chained to the first entry 00516 rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0]; 00517 //Point to the very first descriptor 00518 rxCurDmaDesc = &rxDmaDesc[0]; 00519 00520 //Start location of the TX descriptor list 00521 ETH->DMATDLAR = (uint32_t) txDmaDesc; 00522 //Start location of the RX descriptor list 00523 ETH->DMARDLAR = (uint32_t) rxDmaDesc; 00524 } 00525 00526 00527 /** 00528 * @brief STM32F207/217 Ethernet MAC timer handler 00529 * 00530 * This routine is periodically called by the TCP/IP stack to 00531 * handle periodic operations such as polling the link state 00532 * 00533 * @param[in] interface Underlying network interface 00534 **/ 00535 00536 void stm32f2x7EthTick(NetInterface *interface) 00537 { 00538 //Handle periodic operations 00539 interface->phyDriver->tick(interface); 00540 } 00541 00542 00543 /** 00544 * @brief Enable interrupts 00545 * @param[in] interface Underlying network interface 00546 **/ 00547 00548 void stm32f2x7EthEnableIrq(NetInterface *interface) 00549 { 00550 //Enable Ethernet MAC interrupts 00551 NVIC_EnableIRQ(ETH_IRQn); 00552 //Enable Ethernet PHY interrupts 00553 interface->phyDriver->enableIrq(interface); 00554 } 00555 00556 00557 /** 00558 * @brief Disable interrupts 00559 * @param[in] interface Underlying network interface 00560 **/ 00561 00562 void stm32f2x7EthDisableIrq(NetInterface *interface) 00563 { 00564 //Disable Ethernet MAC interrupts 00565 NVIC_DisableIRQ(ETH_IRQn); 00566 //Disable Ethernet PHY interrupts 00567 interface->phyDriver->disableIrq(interface); 00568 } 00569 00570 00571 /** 00572 * @brief STM32F207/217 Ethernet MAC interrupt service routine 00573 **/ 00574 00575 void ETH_IRQHandler(void) 00576 { 00577 bool_t flag; 00578 uint32_t status; 00579 00580 //Enter interrupt service routine 00581 osEnterIsr(); 00582 00583 //This flag will be set if a higher priority task must be woken 00584 flag = FALSE; 00585 00586 //Read DMA status register 00587 status = ETH->DMASR; 00588 00589 //A packet has been transmitted? 00590 if(status & ETH_DMASR_TS) 00591 { 00592 //Clear TS interrupt flag 00593 ETH->DMASR = ETH_DMASR_TS; 00594 00595 //Check whether the TX buffer is available for writing 00596 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00597 { 00598 //Notify the TCP/IP stack that the transmitter is ready to send 00599 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00600 } 00601 } 00602 00603 //A packet has been received? 00604 if(status & ETH_DMASR_RS) 00605 { 00606 //Disable RIE interrupt 00607 ETH->DMAIER &= ~ETH_DMAIER_RIE; 00608 00609 //Set event flag 00610 nicDriverInterface->nicEvent = TRUE; 00611 //Notify the TCP/IP stack of the event 00612 flag |= osSetEventFromIsr(&netEvent); 00613 } 00614 00615 //Clear NIS interrupt flag 00616 ETH->DMASR = ETH_DMASR_NIS; 00617 00618 //Leave interrupt service routine 00619 osExitIsr(flag); 00620 } 00621 00622 00623 /** 00624 * @brief STM32F207/217 Ethernet MAC event handler 00625 * @param[in] interface Underlying network interface 00626 **/ 00627 00628 void stm32f2x7EthEventHandler(NetInterface *interface) 00629 { 00630 error_t error; 00631 00632 //Packet received? 00633 if(ETH->DMASR & ETH_DMASR_RS) 00634 { 00635 //Clear interrupt flag 00636 ETH->DMASR = ETH_DMASR_RS; 00637 00638 //Process all pending packets 00639 do 00640 { 00641 //Read incoming packet 00642 error = stm32f2x7EthReceivePacket(interface); 00643 00644 //No more data in the receive buffer? 00645 } while(error != ERROR_BUFFER_EMPTY); 00646 } 00647 00648 //Re-enable DMA interrupts 00649 ETH->DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; 00650 } 00651 00652 00653 /** 00654 * @brief Send a packet 00655 * @param[in] interface Underlying network interface 00656 * @param[in] buffer Multi-part buffer containing the data to send 00657 * @param[in] offset Offset to the first data byte 00658 * @return Error code 00659 **/ 00660 00661 error_t stm32f2x7EthSendPacket(NetInterface *interface, 00662 const NetBuffer *buffer, size_t offset) 00663 { 00664 size_t length; 00665 00666 //Retrieve the length of the packet 00667 length = netBufferGetLength(buffer) - offset; 00668 00669 //Check the frame length 00670 if(length > STM32F2X7_ETH_TX_BUFFER_SIZE) 00671 { 00672 //The transmitter can accept another packet 00673 osSetEvent(&interface->nicTxEvent); 00674 //Report an error 00675 return ERROR_INVALID_LENGTH; 00676 } 00677 00678 //Make sure the current buffer is available for writing 00679 if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN) 00680 return ERROR_FAILURE; 00681 00682 //Copy user data to the transmit buffer 00683 netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length); 00684 00685 //Write the number of bytes to send 00686 txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1; 00687 //Set LS and FS flags as the data fits in a single buffer 00688 txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS; 00689 //Give the ownership of the descriptor to the DMA 00690 txCurDmaDesc->tdes0 |= ETH_TDES0_OWN; 00691 00692 //Clear TBUS flag to resume processing 00693 ETH->DMASR = ETH_DMASR_TBUS; 00694 //Instruct the DMA to poll the transmit descriptor list 00695 ETH->DMATPDR = 0; 00696 00697 //Point to the next descriptor in the list 00698 txCurDmaDesc = (Stm32f2x7TxDmaDesc *) txCurDmaDesc->tdes3; 00699 00700 //Check whether the next buffer is available for writing 00701 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00702 { 00703 //The transmitter can accept another packet 00704 osSetEvent(&interface->nicTxEvent); 00705 } 00706 00707 //Data successfully written 00708 return NO_ERROR; 00709 } 00710 00711 00712 /** 00713 * @brief Receive a packet 00714 * @param[in] interface Underlying network interface 00715 * @return Error code 00716 **/ 00717 00718 error_t stm32f2x7EthReceivePacket(NetInterface *interface) 00719 { 00720 error_t error; 00721 size_t n; 00722 00723 //The current buffer is available for reading? 00724 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN)) 00725 { 00726 //FS and LS flags should be set 00727 if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS)) 00728 { 00729 //Make sure no error occurred 00730 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES)) 00731 { 00732 //Retrieve the length of the frame 00733 n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16; 00734 //Limit the number of data to read 00735 n = MIN(n, STM32F2X7_ETH_RX_BUFFER_SIZE); 00736 00737 //Pass the packet to the upper layer 00738 nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n); 00739 00740 //Valid packet received 00741 error = NO_ERROR; 00742 } 00743 else 00744 { 00745 //The received packet contains an error 00746 error = ERROR_INVALID_PACKET; 00747 } 00748 } 00749 else 00750 { 00751 //The packet is not valid 00752 error = ERROR_INVALID_PACKET; 00753 } 00754 00755 //Give the ownership of the descriptor back to the DMA 00756 rxCurDmaDesc->rdes0 = ETH_RDES0_OWN; 00757 //Point to the next descriptor in the list 00758 rxCurDmaDesc = (Stm32f2x7RxDmaDesc *) rxCurDmaDesc->rdes3; 00759 } 00760 else 00761 { 00762 //No more data in the receive buffer 00763 error = ERROR_BUFFER_EMPTY; 00764 } 00765 00766 //Clear RBUS flag to resume processing 00767 ETH->DMASR = ETH_DMASR_RBUS; 00768 //Instruct the DMA to poll the receive descriptor list 00769 ETH->DMARPDR = 0; 00770 00771 //Return status code 00772 return error; 00773 } 00774 00775 00776 /** 00777 * @brief Configure multicast MAC address filtering 00778 * @param[in] interface Underlying network interface 00779 * @return Error code 00780 **/ 00781 00782 error_t stm32f2x7EthSetMulticastFilter(NetInterface *interface) 00783 { 00784 uint_t i; 00785 uint_t k; 00786 uint32_t crc; 00787 uint32_t hashTable[2]; 00788 MacFilterEntry *entry; 00789 00790 //Debug message 00791 TRACE_DEBUG("Updating STM32F2x7 hash table...\r\n"); 00792 00793 //Clear hash table 00794 hashTable[0] = 0; 00795 hashTable[1] = 0; 00796 00797 //The MAC filter table contains the multicast MAC addresses 00798 //to accept when receiving an Ethernet frame 00799 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00800 { 00801 //Point to the current entry 00802 entry = &interface->macMulticastFilter[i]; 00803 00804 //Valid entry? 00805 if(entry->refCount > 0) 00806 { 00807 //Compute CRC over the current MAC address 00808 crc = stm32f2x7EthCalcCrc(&entry->addr, sizeof(MacAddr)); 00809 00810 //The upper 6 bits in the CRC register are used to index the 00811 //contents of the hash table 00812 k = (crc >> 26) & 0x3F; 00813 00814 //Update hash table contents 00815 hashTable[k / 32] |= (1 << (k % 32)); 00816 } 00817 } 00818 00819 //Write the hash table 00820 ETH->MACHTLR = hashTable[0]; 00821 ETH->MACHTHR = hashTable[1]; 00822 00823 //Debug message 00824 TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR); 00825 TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR); 00826 00827 //Successful processing 00828 return NO_ERROR; 00829 } 00830 00831 00832 /** 00833 * @brief Adjust MAC configuration parameters for proper operation 00834 * @param[in] interface Underlying network interface 00835 * @return Error code 00836 **/ 00837 00838 error_t stm32f2x7EthUpdateMacConfig(NetInterface *interface) 00839 { 00840 uint32_t config; 00841 00842 //Read current MAC configuration 00843 config = ETH->MACCR; 00844 00845 //10BASE-T or 100BASE-TX operation mode? 00846 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00847 config |= ETH_MACCR_FES; 00848 else 00849 config &= ~ETH_MACCR_FES; 00850 00851 //Half-duplex or full-duplex mode? 00852 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00853 config |= ETH_MACCR_DM; 00854 else 00855 config &= ~ETH_MACCR_DM; 00856 00857 //Update MAC configuration register 00858 ETH->MACCR = config; 00859 00860 //Successful processing 00861 return NO_ERROR; 00862 } 00863 00864 00865 /** 00866 * @brief Write PHY register 00867 * @param[in] phyAddr PHY address 00868 * @param[in] regAddr Register address 00869 * @param[in] data Register value 00870 **/ 00871 00872 void stm32f2x7EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00873 { 00874 uint32_t value; 00875 00876 //Take care not to alter MDC clock configuration 00877 value = ETH->MACMIIAR & ETH_MACMIIAR_CR; 00878 //Set up a write operation 00879 value |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; 00880 //PHY address 00881 value |= (phyAddr << 11) & ETH_MACMIIAR_PA; 00882 //Register address 00883 value |= (regAddr << 6) & ETH_MACMIIAR_MR; 00884 00885 //Data to be written in the PHY register 00886 ETH->MACMIIDR = data & ETH_MACMIIDR_MD; 00887 00888 //Start a write operation 00889 ETH->MACMIIAR = value; 00890 //Wait for the write to complete 00891 while(ETH->MACMIIAR & ETH_MACMIIAR_MB); 00892 } 00893 00894 00895 /** 00896 * @brief Read PHY register 00897 * @param[in] phyAddr PHY address 00898 * @param[in] regAddr Register address 00899 * @return Register value 00900 **/ 00901 00902 uint16_t stm32f2x7EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00903 { 00904 uint32_t value; 00905 00906 //Take care not to alter MDC clock configuration 00907 value = ETH->MACMIIAR & ETH_MACMIIAR_CR; 00908 //Set up a read operation 00909 value |= ETH_MACMIIAR_MB; 00910 //PHY address 00911 value |= (phyAddr << 11) & ETH_MACMIIAR_PA; 00912 //Register address 00913 value |= (regAddr << 6) & ETH_MACMIIAR_MR; 00914 00915 //Start a read operation 00916 ETH->MACMIIAR = value; 00917 //Wait for the read to complete 00918 while(ETH->MACMIIAR & ETH_MACMIIAR_MB); 00919 00920 //Return PHY register contents 00921 return ETH->MACMIIDR & ETH_MACMIIDR_MD; 00922 } 00923 00924 00925 /** 00926 * @brief CRC calculation 00927 * @param[in] data Pointer to the data over which to calculate the CRC 00928 * @param[in] length Number of bytes to process 00929 * @return Resulting CRC value 00930 **/ 00931 00932 uint32_t stm32f2x7EthCalcCrc(const void *data, size_t length) 00933 { 00934 uint_t i; 00935 uint_t j; 00936 00937 //Point to the data over which to calculate the CRC 00938 const uint8_t *p = (uint8_t *) data; 00939 //CRC preset value 00940 uint32_t crc = 0xFFFFFFFF; 00941 00942 //Loop through data 00943 for(i = 0; i < length; i++) 00944 { 00945 //The message is processed bit by bit 00946 for(j = 0; j < 8; j++) 00947 { 00948 //Update CRC value 00949 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00950 crc = (crc << 1) ^ 0x04C11DB7; 00951 else 00952 crc = crc << 1; 00953 } 00954 } 00955 00956 //Return CRC value 00957 return ~crc; 00958 } 00959
Generated on Tue Jul 12 2022 17:10:16 by
