Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32f4x9_eth.c Source File

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