Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32f2x7_eth.c Source File

stm32f2x7_eth.c

Go to the documentation of this file.
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