Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32f7xx_eth.c Source File

stm32f7xx_eth.c

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