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