Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32f107_eth.c Source File

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