Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
stm32f107_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file stm32f107_eth.c 00003 * @brief STM32F107 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 #if defined(USE_HAL_DRIVER) 00034 #include "stm32f1xx.h" 00035 #elif defined(USE_STDPERIPH_DRIVER) 00036 #include "stm32f10x.h" 00037 #endif 00038 00039 #include "core/net.h" 00040 #include "drivers/stm32f107_eth.h" 00041 #include "debug.h" 00042 00043 //Underlying network interface 00044 static NetInterface *nicDriverInterface; 00045 00046 //IAR EWARM compiler? 00047 #if defined(__ICCARM__) 00048 00049 //Transmit buffer 00050 #pragma data_alignment = 4 00051 static uint8_t txBuffer[STM32F107_ETH_TX_BUFFER_COUNT][STM32F107_ETH_TX_BUFFER_SIZE]; 00052 //Receive buffer 00053 #pragma data_alignment = 4 00054 static uint8_t rxBuffer[STM32F107_ETH_RX_BUFFER_COUNT][STM32F107_ETH_RX_BUFFER_SIZE]; 00055 //Transmit DMA descriptors 00056 #pragma data_alignment = 4 00057 static Stm32f107TxDmaDesc txDmaDesc[STM32F107_ETH_TX_BUFFER_COUNT]; 00058 //Receive DMA descriptors 00059 #pragma data_alignment = 4 00060 static Stm32f107RxDmaDesc rxDmaDesc[STM32F107_ETH_RX_BUFFER_COUNT]; 00061 00062 //Keil MDK-ARM or GCC compiler? 00063 #else 00064 00065 //Transmit buffer 00066 static uint8_t txBuffer[STM32F107_ETH_TX_BUFFER_COUNT][STM32F107_ETH_TX_BUFFER_SIZE] 00067 __attribute__((aligned(4))); 00068 //Receive buffer 00069 static uint8_t rxBuffer[STM32F107_ETH_RX_BUFFER_COUNT][STM32F107_ETH_RX_BUFFER_SIZE] 00070 __attribute__((aligned(4))); 00071 //Transmit DMA descriptors 00072 static Stm32f107TxDmaDesc txDmaDesc[STM32F107_ETH_TX_BUFFER_COUNT] 00073 __attribute__((aligned(4))); 00074 //Receive DMA descriptors 00075 static Stm32f107RxDmaDesc rxDmaDesc[STM32F107_ETH_RX_BUFFER_COUNT] 00076 __attribute__((aligned(4))); 00077 00078 #endif 00079 00080 //Pointer to the current TX DMA descriptor 00081 static Stm32f107TxDmaDesc *txCurDmaDesc; 00082 //Pointer to the current RX DMA descriptor 00083 static Stm32f107RxDmaDesc *rxCurDmaDesc; 00084 00085 00086 /** 00087 * @brief STM32F107 Ethernet MAC driver 00088 **/ 00089 00090 const NicDriver stm32f107EthDriver = 00091 { 00092 NIC_TYPE_ETHERNET, 00093 ETH_MTU, 00094 stm32f107EthInit, 00095 stm32f107EthTick, 00096 stm32f107EthEnableIrq, 00097 stm32f107EthDisableIrq, 00098 stm32f107EthEventHandler, 00099 stm32f107EthSendPacket, 00100 stm32f107EthSetMulticastFilter, 00101 stm32f107EthUpdateMacConfig, 00102 stm32f107EthWritePhyReg, 00103 stm32f107EthReadPhyReg, 00104 TRUE, 00105 TRUE, 00106 TRUE, 00107 FALSE 00108 }; 00109 00110 00111 /** 00112 * @brief STM32F107 Ethernet MAC initialization 00113 * @param[in] interface Underlying network interface 00114 * @return Error code 00115 **/ 00116 00117 error_t stm32f107EthInit(NetInterface *interface) 00118 { 00119 error_t error; 00120 00121 //Debug message 00122 TRACE_INFO("Initializing STM32F107 Ethernet MAC...\r\n"); 00123 00124 //Save underlying network interface 00125 nicDriverInterface = interface; 00126 00127 //GPIO configuration 00128 stm32f107EthInitGpio(interface); 00129 00130 #if defined(USE_HAL_DRIVER) 00131 //Enable Ethernet MAC clock 00132 __HAL_RCC_ETHMAC_CLK_ENABLE(); 00133 __HAL_RCC_ETHMACTX_CLK_ENABLE(); 00134 __HAL_RCC_ETHMACRX_CLK_ENABLE(); 00135 00136 //Reset Ethernet MAC peripheral 00137 __HAL_RCC_ETHMAC_FORCE_RESET(); 00138 __HAL_RCC_ETHMAC_RELEASE_RESET(); 00139 00140 #elif defined(USE_STDPERIPH_DRIVER) 00141 //Enable Ethernet MAC clock 00142 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | 00143 RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE); 00144 00145 //Reset Ethernet MAC peripheral 00146 RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, ENABLE); 00147 RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, DISABLE); 00148 #endif 00149 00150 //Perform a software reset 00151 ETH->DMABMR |= ETH_DMABMR_SR; 00152 //Wait for the reset to complete 00153 while(ETH->DMABMR & ETH_DMABMR_SR); 00154 00155 //Adjust MDC clock range depending on HCLK frequency 00156 #if defined(USE_HAL_DRIVER) 00157 ETH->MACMIIAR = ETH_MACMIIAR_CR_DIV42; 00158 #elif defined(USE_STDPERIPH_DRIVER) 00159 ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42; 00160 #endif 00161 00162 //PHY transceiver initialization 00163 error = interface->phyDriver->init(interface); 00164 //Failed to initialize PHY transceiver? 00165 if(error) 00166 return error; 00167 00168 //Use default MAC configuration 00169 ETH->MACCR = ETH_MACCR_ROD; 00170 00171 //Set the MAC address 00172 ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00173 ETH->MACA0HR = interface->macAddr.w[2]; 00174 00175 //Initialize hash table 00176 ETH->MACHTLR = 0; 00177 ETH->MACHTHR = 0; 00178 00179 //Configure the receive filter 00180 ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_HM; 00181 //Disable flow control 00182 ETH->MACFCR = 0; 00183 //Enable store and forward mode 00184 ETH->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF; 00185 00186 //Configure DMA bus mode 00187 ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_RDP_1Beat | 00188 ETH_DMABMR_RTPR_1_1 | ETH_DMABMR_PBL_1Beat; 00189 00190 //Initialize DMA descriptor lists 00191 stm32f107EthInitDmaDesc(interface); 00192 00193 //Prevent interrupts from being generated when the transmit statistic 00194 //counters reach half their maximum value 00195 ETH->MMCTIMR = ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM; 00196 00197 //Prevent interrupts from being generated when the receive statistic 00198 //counters reach half their maximum value 00199 ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM; 00200 00201 //Disable MAC interrupts 00202 ETH->MACIMR = ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM; 00203 //Enable the desired DMA interrupts 00204 ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; 00205 00206 //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority) 00207 NVIC_SetPriorityGrouping(STM32F107_ETH_IRQ_PRIORITY_GROUPING); 00208 00209 //Configure Ethernet interrupt priority 00210 NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F107_ETH_IRQ_PRIORITY_GROUPING, 00211 STM32F107_ETH_IRQ_GROUP_PRIORITY, STM32F107_ETH_IRQ_SUB_PRIORITY)); 00212 00213 //Enable MAC transmission and reception 00214 ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE; 00215 //Enable DMA transmission and reception 00216 ETH->DMAOMR |= ETH_DMAOMR_ST | ETH_DMAOMR_SR; 00217 00218 //Accept any packets from the upper layer 00219 osSetEvent(&interface->nicTxEvent); 00220 00221 //Successful initialization 00222 return NO_ERROR; 00223 } 00224 00225 00226 //STM3210C-EVAL or STM32-P107 evaluation board? 00227 #if defined(USE_STM3210C_EVAL) || defined(USE_STM32_P107) 00228 00229 /** 00230 * @brief GPIO configuration 00231 * @param[in] interface Underlying network interface 00232 **/ 00233 00234 void stm32f107EthInitGpio(NetInterface *interface) 00235 { 00236 GPIO_InitTypeDef GPIO_InitStructure; 00237 00238 //STM3210C-EVAL evaluation board? 00239 #if defined(USE_STM3210C_EVAL) && defined(USE_HAL_DRIVER) 00240 //Enable AFIO clock 00241 __HAL_RCC_AFIO_CLK_ENABLE(); 00242 00243 //Enable GPIO clocks 00244 __HAL_RCC_GPIOA_CLK_ENABLE(); 00245 __HAL_RCC_GPIOB_CLK_ENABLE(); 00246 __HAL_RCC_GPIOC_CLK_ENABLE(); 00247 __HAL_RCC_GPIOD_CLK_ENABLE(); 00248 00249 //Configure MCO (PA8) as an output 00250 GPIO_InitStructure.Pin = GPIO_PIN_8; 00251 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00252 GPIO_InitStructure.Pull = GPIO_NOPULL; 00253 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00254 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 00255 00256 //Configure MCO pin to output the HSE clock (25MHz) 00257 HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, 1); 00258 00259 //Select MII interface mode 00260 __HAL_AFIO_ETH_MII(); 00261 00262 //Configure MII_MDIO (PA2) 00263 GPIO_InitStructure.Pin = GPIO_PIN_2; 00264 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00265 GPIO_InitStructure.Pull = GPIO_NOPULL; 00266 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00267 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 00268 00269 //Configure MII_PPS_OUT (PB5), ETH_MII_TXD3 (PB8), MII_TX_EN (PB11), 00270 //MII_TXD0 (PB12) and MII_TXD1 (PB13) 00271 GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; 00272 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00273 GPIO_InitStructure.Pull = GPIO_NOPULL; 00274 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00275 HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); 00276 00277 //Configure MII_MDC (PC1) and MII_TXD2 (PC2) 00278 GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2; 00279 GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; 00280 GPIO_InitStructure.Pull = GPIO_NOPULL; 00281 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00282 HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); 00283 00284 //Configure ETH_MII_CRS (PA0), ETH_MII_RX_CLK (PA1) and ETH_MII_COL (PA3) 00285 GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3; 00286 GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT; 00287 GPIO_InitStructure.Pull = GPIO_NOPULL; 00288 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00289 HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 00290 00291 //Configure ETH_MII_RX_ER (PB10) 00292 GPIO_InitStructure.Pin = GPIO_PIN_10; 00293 GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT; 00294 GPIO_InitStructure.Pull = GPIO_NOPULL; 00295 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00296 HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); 00297 00298 //Configure ETH_MII_TX_CLK (PC3) 00299 GPIO_InitStructure.Pin = GPIO_PIN_3; 00300 GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT; 00301 GPIO_InitStructure.Pull = GPIO_NOPULL; 00302 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00303 HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); 00304 00305 //Configure ETH_MII_RX_DV (PD8), ETH_MII_RXD0 (PD9), ETH_MII_RXD1 (PD10), 00306 //ETH_MII_RXD2 (PD11) and ETH_MII_RXD3 (PD12) 00307 GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; 00308 GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT; 00309 GPIO_InitStructure.Pull = GPIO_NOPULL; 00310 GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; 00311 HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); 00312 00313 //Remap Ethernet pins 00314 __HAL_AFIO_REMAP_ETH_ENABLE(); 00315 00316 #elif defined(USE_STM3210C_EVAL) && defined(USE_STDPERIPH_DRIVER) 00317 //Enable AFIO clock 00318 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 00319 00320 //Enable GPIO clocks 00321 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | 00322 RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); 00323 00324 //Configure MCO (PA8) as an output 00325 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 00326 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00327 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00328 GPIO_Init(GPIOA, &GPIO_InitStructure); 00329 00330 //Configure MCO pin to output the HSE clock (25MHz) 00331 RCC_MCOConfig(RCC_MCO_HSE); 00332 00333 //Select MII interface mode 00334 GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_MII); 00335 00336 //Configure MII_MDIO (PA2) 00337 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 00338 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00339 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00340 GPIO_Init(GPIOA, &GPIO_InitStructure); 00341 00342 //Configure MII_PPS_OUT (PB5), ETH_MII_TXD3 (PB8), MII_TX_EN (PB11), 00343 //MII_TXD0 (PB12) and MII_TXD1 (PB13) 00344 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13; 00345 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00346 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00347 GPIO_Init(GPIOB, &GPIO_InitStructure); 00348 00349 //Configure MII_MDC (PC1) and MII_TXD2 (PC2) 00350 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; 00351 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00352 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00353 GPIO_Init(GPIOC, &GPIO_InitStructure); 00354 00355 //Configure ETH_MII_CRS (PA0), ETH_MII_RX_CLK (PA1) and ETH_MII_COL (PA3) 00356 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3; 00357 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00358 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 00359 GPIO_Init(GPIOA, &GPIO_InitStructure); 00360 00361 //Configure ETH_MII_RX_ER (PB10) 00362 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; 00363 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00364 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 00365 GPIO_Init(GPIOB, &GPIO_InitStructure); 00366 00367 //Configure ETH_MII_TX_CLK (PC3) 00368 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; 00369 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00370 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 00371 GPIO_Init(GPIOC, &GPIO_InitStructure); 00372 00373 //Configure ETH_MII_RX_DV (PD8), ETH_MII_RXD0 (PD9), ETH_MII_RXD1 (PD10), 00374 //ETH_MII_RXD2 (PD11) and ETH_MII_RXD3 (PD12) 00375 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12; 00376 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00377 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 00378 GPIO_Init(GPIOD, &GPIO_InitStructure); 00379 00380 //Remap Ethernet pins 00381 GPIO_PinRemapConfig(GPIO_Remap_ETH, ENABLE); 00382 00383 //STM32-P107 evaluation board? 00384 #elif defined(USE_STM32_P107) && defined(USE_STDPERIPH_DRIVER) 00385 //Enable AFIO clock 00386 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); 00387 00388 //Enable GPIO clocks 00389 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | 00390 RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); 00391 00392 //Configure MCO (PA8) as an output 00393 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 00394 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00395 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00396 GPIO_Init(GPIOA, &GPIO_InitStructure); 00397 00398 //Configure PLL3 to output a 50MHz clock 00399 RCC_PLL3Config(RCC_PLL3Mul_10); 00400 //Enable PLL3 00401 RCC_PLL3Cmd(ENABLE); 00402 00403 //Wait for the PLL3 to lock 00404 while(RCC_GetFlagStatus(RCC_FLAG_PLL3RDY) == RESET); 00405 00406 //Configure MCO pin to output the PLL3 clock 00407 RCC_MCOConfig(RCC_MCO_PLL3CLK); 00408 00409 //Select RMII interface mode 00410 GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII); 00411 00412 //Configure ETH_MDIO (PA2) 00413 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; 00414 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00415 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00416 GPIO_Init(GPIOA, &GPIO_InitStructure); 00417 00418 //Configure ETH_RMII_TX_EN (PB11), ETH_RMII_TXD0 (PB12) and ETH_RMII_TXD1 (PB13) 00419 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13; 00420 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00421 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00422 GPIO_Init(GPIOB, &GPIO_InitStructure); 00423 00424 //Configure ETH_MDC (PC1) 00425 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 00426 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00427 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 00428 GPIO_Init(GPIOC, &GPIO_InitStructure); 00429 00430 //Configure ETH_RMII_REF_CLK (PA1) and ETH_RMII_CRS_DV (PA7) 00431 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_7; 00432 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00433 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 00434 GPIO_Init(GPIOA, &GPIO_InitStructure); 00435 00436 //Configure ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5) 00437 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; 00438 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 00439 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 00440 GPIO_Init(GPIOC, &GPIO_InitStructure); 00441 00442 //Do not remap Ethernet pins 00443 GPIO_PinRemapConfig(GPIO_Remap_ETH, DISABLE); 00444 #endif 00445 } 00446 00447 #endif 00448 00449 00450 /** 00451 * @brief Initialize DMA descriptor lists 00452 * @param[in] interface Underlying network interface 00453 **/ 00454 00455 void stm32f107EthInitDmaDesc(NetInterface *interface) 00456 { 00457 uint_t i; 00458 00459 //Initialize TX DMA descriptor list 00460 for(i = 0; i < STM32F107_ETH_TX_BUFFER_COUNT; i++) 00461 { 00462 //Use chain structure rather than ring structure 00463 txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH; 00464 //Initialize transmit buffer size 00465 txDmaDesc[i].tdes1 = 0; 00466 //Transmit buffer address 00467 txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i]; 00468 //Next descriptor address 00469 txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1]; 00470 } 00471 00472 //The last descriptor is chained to the first entry 00473 txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0]; 00474 //Point to the very first descriptor 00475 txCurDmaDesc = &txDmaDesc[0]; 00476 00477 //Initialize RX DMA descriptor list 00478 for(i = 0; i < STM32F107_ETH_RX_BUFFER_COUNT; i++) 00479 { 00480 //The descriptor is initially owned by the DMA 00481 rxDmaDesc[i].rdes0 = ETH_RDES0_OWN; 00482 //Use chain structure rather than ring structure 00483 rxDmaDesc[i].rdes1 = ETH_RDES1_RCH | (STM32F107_ETH_RX_BUFFER_SIZE & ETH_RDES1_RBS1); 00484 //Receive buffer address 00485 rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i]; 00486 //Next descriptor address 00487 rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1]; 00488 } 00489 00490 //The last descriptor is chained to the first entry 00491 rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0]; 00492 //Point to the very first descriptor 00493 rxCurDmaDesc = &rxDmaDesc[0]; 00494 00495 //Start location of the TX descriptor list 00496 ETH->DMATDLAR = (uint32_t) txDmaDesc; 00497 //Start location of the RX descriptor list 00498 ETH->DMARDLAR = (uint32_t) rxDmaDesc; 00499 } 00500 00501 00502 /** 00503 * @brief STM32F107 Ethernet MAC timer handler 00504 * 00505 * This routine is periodically called by the TCP/IP stack to 00506 * handle periodic operations such as polling the link state 00507 * 00508 * @param[in] interface Underlying network interface 00509 **/ 00510 00511 void stm32f107EthTick(NetInterface *interface) 00512 { 00513 //Handle periodic operations 00514 interface->phyDriver->tick(interface); 00515 } 00516 00517 00518 /** 00519 * @brief Enable interrupts 00520 * @param[in] interface Underlying network interface 00521 **/ 00522 00523 void stm32f107EthEnableIrq(NetInterface *interface) 00524 { 00525 //Enable Ethernet MAC interrupts 00526 NVIC_EnableIRQ(ETH_IRQn); 00527 //Enable Ethernet PHY interrupts 00528 interface->phyDriver->enableIrq(interface); 00529 } 00530 00531 00532 /** 00533 * @brief Disable interrupts 00534 * @param[in] interface Underlying network interface 00535 **/ 00536 00537 void stm32f107EthDisableIrq(NetInterface *interface) 00538 { 00539 //Disable Ethernet MAC interrupts 00540 NVIC_DisableIRQ(ETH_IRQn); 00541 //Disable Ethernet PHY interrupts 00542 interface->phyDriver->disableIrq(interface); 00543 } 00544 00545 00546 /** 00547 * @brief STM32F107 Ethernet MAC interrupt service routine 00548 **/ 00549 00550 void ETH_IRQHandler(void) 00551 { 00552 bool_t flag; 00553 uint32_t status; 00554 00555 //Enter interrupt service routine 00556 osEnterIsr(); 00557 00558 //This flag will be set if a higher priority task must be woken 00559 flag = FALSE; 00560 00561 //Read DMA status register 00562 status = ETH->DMASR; 00563 00564 //A packet has been transmitted? 00565 if(status & ETH_DMASR_TS) 00566 { 00567 //Clear TS interrupt flag 00568 ETH->DMASR = ETH_DMASR_TS; 00569 00570 //Check whether the TX buffer is available for writing 00571 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00572 { 00573 //Notify the TCP/IP stack that the transmitter is ready to send 00574 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00575 } 00576 } 00577 00578 //A packet has been received? 00579 if(status & ETH_DMASR_RS) 00580 { 00581 //Disable RIE interrupt 00582 ETH->DMAIER &= ~ETH_DMAIER_RIE; 00583 00584 //Set event flag 00585 nicDriverInterface->nicEvent = TRUE; 00586 //Notify the TCP/IP stack of the event 00587 flag |= osSetEventFromIsr(&netEvent); 00588 } 00589 00590 //Clear NIS interrupt flag 00591 ETH->DMASR = ETH_DMASR_NIS; 00592 00593 //Leave interrupt service routine 00594 osExitIsr(flag); 00595 } 00596 00597 00598 /** 00599 * @brief STM32F107 Ethernet MAC event handler 00600 * @param[in] interface Underlying network interface 00601 **/ 00602 00603 void stm32f107EthEventHandler(NetInterface *interface) 00604 { 00605 error_t error; 00606 00607 //Packet received? 00608 if(ETH->DMASR & ETH_DMASR_RS) 00609 { 00610 //Clear interrupt flag 00611 ETH->DMASR = ETH_DMASR_RS; 00612 00613 //Process all pending packets 00614 do 00615 { 00616 //Read incoming packet 00617 error = stm32f107EthReceivePacket(interface); 00618 00619 //No more data in the receive buffer? 00620 } while(error != ERROR_BUFFER_EMPTY); 00621 } 00622 00623 //Re-enable DMA interrupts 00624 ETH->DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE; 00625 } 00626 00627 00628 /** 00629 * @brief Send a packet 00630 * @param[in] interface Underlying network interface 00631 * @param[in] buffer Multi-part buffer containing the data to send 00632 * @param[in] offset Offset to the first data byte 00633 * @return Error code 00634 **/ 00635 00636 error_t stm32f107EthSendPacket(NetInterface *interface, 00637 const NetBuffer *buffer, size_t offset) 00638 { 00639 size_t length; 00640 00641 //Retrieve the length of the packet 00642 length = netBufferGetLength(buffer) - offset; 00643 00644 //Check the frame length 00645 if(length > STM32F107_ETH_TX_BUFFER_SIZE) 00646 { 00647 //The transmitter can accept another packet 00648 osSetEvent(&interface->nicTxEvent); 00649 //Report an error 00650 return ERROR_INVALID_LENGTH; 00651 } 00652 00653 //Make sure the current buffer is available for writing 00654 if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN) 00655 return ERROR_FAILURE; 00656 00657 //Copy user data to the transmit buffer 00658 netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length); 00659 00660 //Write the number of bytes to send 00661 txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1; 00662 //Set LS and FS flags as the data fits in a single buffer 00663 txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS; 00664 //Give the ownership of the descriptor to the DMA 00665 txCurDmaDesc->tdes0 |= ETH_TDES0_OWN; 00666 00667 //Clear TBUS flag to resume processing 00668 ETH->DMASR = ETH_DMASR_TBUS; 00669 //Instruct the DMA to poll the transmit descriptor list 00670 ETH->DMATPDR = 0; 00671 00672 //Point to the next descriptor in the list 00673 txCurDmaDesc = (Stm32f107TxDmaDesc *) txCurDmaDesc->tdes3; 00674 00675 //Check whether the next buffer is available for writing 00676 if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)) 00677 { 00678 //The transmitter can accept another packet 00679 osSetEvent(&interface->nicTxEvent); 00680 } 00681 00682 //Data successfully written 00683 return NO_ERROR; 00684 } 00685 00686 00687 /** 00688 * @brief Receive a packet 00689 * @param[in] interface Underlying network interface 00690 * @return Error code 00691 **/ 00692 00693 error_t stm32f107EthReceivePacket(NetInterface *interface) 00694 { 00695 error_t error; 00696 size_t n; 00697 00698 //The current buffer is available for reading? 00699 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN)) 00700 { 00701 //FS and LS flags should be set 00702 if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS)) 00703 { 00704 //Make sure no error occurred 00705 if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES)) 00706 { 00707 //Retrieve the length of the frame 00708 n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16; 00709 //Limit the number of data to read 00710 n = MIN(n, STM32F107_ETH_RX_BUFFER_SIZE); 00711 00712 //Pass the packet to the upper layer 00713 nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n); 00714 00715 //Valid packet received 00716 error = NO_ERROR; 00717 } 00718 else 00719 { 00720 //The received packet contains an error 00721 error = ERROR_INVALID_PACKET; 00722 } 00723 } 00724 else 00725 { 00726 //The packet is not valid 00727 error = ERROR_INVALID_PACKET; 00728 } 00729 00730 //Give the ownership of the descriptor back to the DMA 00731 rxCurDmaDesc->rdes0 = ETH_RDES0_OWN; 00732 //Point to the next descriptor in the list 00733 rxCurDmaDesc = (Stm32f107RxDmaDesc *) rxCurDmaDesc->rdes3; 00734 } 00735 else 00736 { 00737 //No more data in the receive buffer 00738 error = ERROR_BUFFER_EMPTY; 00739 } 00740 00741 //Clear RBUS flag to resume processing 00742 ETH->DMASR = ETH_DMASR_RBUS; 00743 //Instruct the DMA to poll the receive descriptor list 00744 ETH->DMARPDR = 0; 00745 00746 //Return status code 00747 return error; 00748 } 00749 00750 00751 /** 00752 * @brief Configure multicast MAC address filtering 00753 * @param[in] interface Underlying network interface 00754 * @return Error code 00755 **/ 00756 00757 error_t stm32f107EthSetMulticastFilter(NetInterface *interface) 00758 { 00759 uint_t i; 00760 uint_t k; 00761 uint32_t crc; 00762 uint32_t hashTable[2]; 00763 MacFilterEntry *entry; 00764 00765 //Debug message 00766 TRACE_DEBUG("Updating STM32F107 hash table...\r\n"); 00767 00768 //Clear hash table 00769 hashTable[0] = 0; 00770 hashTable[1] = 0; 00771 00772 //The MAC filter table contains the multicast MAC addresses 00773 //to accept when receiving an Ethernet frame 00774 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00775 { 00776 //Point to the current entry 00777 entry = &interface->macMulticastFilter[i]; 00778 00779 //Valid entry? 00780 if(entry->refCount > 0) 00781 { 00782 //Compute CRC over the current MAC address 00783 crc = stm32f107EthCalcCrc(&entry->addr, sizeof(MacAddr)); 00784 00785 //The upper 6 bits in the CRC register are used to index the 00786 //contents of the hash table 00787 k = (crc >> 26) & 0x3F; 00788 00789 //Update hash table contents 00790 hashTable[k / 32] |= (1 << (k % 32)); 00791 } 00792 } 00793 00794 //Write the hash table 00795 ETH->MACHTLR = hashTable[0]; 00796 ETH->MACHTHR = hashTable[1]; 00797 00798 //Debug message 00799 TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR); 00800 TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR); 00801 00802 //Successful processing 00803 return NO_ERROR; 00804 } 00805 00806 00807 /** 00808 * @brief Adjust MAC configuration parameters for proper operation 00809 * @param[in] interface Underlying network interface 00810 * @return Error code 00811 **/ 00812 00813 error_t stm32f107EthUpdateMacConfig(NetInterface *interface) 00814 { 00815 uint32_t config ; 00816 00817 //Read current MAC configuration 00818 config = ETH->MACCR; 00819 00820 //10BASE-T or 100BASE-TX operation mode? 00821 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00822 config |= ETH_MACCR_FES; 00823 else 00824 config &= ~ETH_MACCR_FES; 00825 00826 //Half-duplex or full-duplex mode? 00827 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00828 config |= ETH_MACCR_DM; 00829 else 00830 config &= ~ETH_MACCR_DM; 00831 00832 //Update MAC configuration register 00833 ETH->MACCR = config; 00834 00835 //Successful processing 00836 return NO_ERROR; 00837 } 00838 00839 00840 /** 00841 * @brief Write PHY register 00842 * @param[in] phyAddr PHY address 00843 * @param[in] regAddr Register address 00844 * @param[in] data Register value 00845 **/ 00846 00847 void stm32f107EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00848 { 00849 uint32_t value; 00850 00851 //Take care not to alter MDC clock configuration 00852 value = ETH->MACMIIAR & ETH_MACMIIAR_CR; 00853 //Set up a write operation 00854 value |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; 00855 //PHY address 00856 value |= (phyAddr << 11) & ETH_MACMIIAR_PA; 00857 //Register address 00858 value |= (regAddr << 6) & ETH_MACMIIAR_MR; 00859 00860 //Data to be written in the PHY register 00861 ETH->MACMIIDR = data & ETH_MACMIIDR_MD; 00862 00863 //Start a write operation 00864 ETH->MACMIIAR = value; 00865 //Wait for the write to complete 00866 while(ETH->MACMIIAR & ETH_MACMIIAR_MB); 00867 } 00868 00869 00870 /** 00871 * @brief Read PHY register 00872 * @param[in] phyAddr PHY address 00873 * @param[in] regAddr Register address 00874 * @return Register value 00875 **/ 00876 00877 uint16_t stm32f107EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00878 { 00879 uint32_t value; 00880 00881 //Take care not to alter MDC clock configuration 00882 value = ETH->MACMIIAR & ETH_MACMIIAR_CR; 00883 //Set up a read operation 00884 value |= ETH_MACMIIAR_MB; 00885 //PHY address 00886 value |= (phyAddr << 11) & ETH_MACMIIAR_PA; 00887 //Register address 00888 value |= (regAddr << 6) & ETH_MACMIIAR_MR; 00889 00890 //Start a read operation 00891 ETH->MACMIIAR = value; 00892 //Wait for the read to complete 00893 while(ETH->MACMIIAR & ETH_MACMIIAR_MB); 00894 00895 //Return PHY register contents 00896 return ETH->MACMIIDR & ETH_MACMIIDR_MD; 00897 } 00898 00899 00900 /** 00901 * @brief CRC calculation 00902 * @param[in] data Pointer to the data over which to calculate the CRC 00903 * @param[in] length Number of bytes to process 00904 * @return Resulting CRC value 00905 **/ 00906 00907 uint32_t stm32f107EthCalcCrc(const void *data, size_t length) 00908 { 00909 uint_t i; 00910 uint_t j; 00911 00912 //Point to the data over which to calculate the CRC 00913 const uint8_t *p = (uint8_t *) data; 00914 //CRC preset value 00915 uint32_t crc = 0xFFFFFFFF; 00916 00917 //Loop through data 00918 for(i = 0; i < length; i++) 00919 { 00920 //The message is processed bit by bit 00921 for(j = 0; j < 8; j++) 00922 { 00923 //Update CRC value 00924 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00925 crc = (crc << 1) ^ 0x04C11DB7; 00926 else 00927 crc = crc << 1; 00928 } 00929 } 00930 00931 //Return CRC value 00932 return ~crc; 00933 } 00934
Generated on Tue Jul 12 2022 17:10:16 by
