stm32f2x7_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32f2x7_eth_driver.c
3  * @brief STM32F207/217 Ethernet MAC controller
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NIC_TRACE_LEVEL
31 
32 //Dependencies
33 #include "stm32f2xx.h"
34 #include "core/net.h"
36 #include "debug.h"
37 
38 //Underlying network interface
39 static NetInterface *nicDriverInterface;
40 
41 //IAR EWARM compiler?
42 #if defined(__ICCARM__)
43 
44 //Transmit buffer
45 #pragma data_alignment = 4
47 //Receive buffer
48 #pragma data_alignment = 4
50 //Transmit DMA descriptors
51 #pragma data_alignment = 4
53 //Receive DMA descriptors
54 #pragma data_alignment = 4
56 
57 //Keil MDK-ARM or GCC compiler?
58 #else
59 
60 //Transmit buffer
62  __attribute__((aligned(4)));
63 //Receive buffer
65  __attribute__((aligned(4)));
66 //Transmit DMA descriptors
68  __attribute__((aligned(4)));
69 //Receive DMA descriptors
71  __attribute__((aligned(4)));
72 
73 #endif
74 
75 //Pointer to the current TX DMA descriptor
76 static Stm32f2x7TxDmaDesc *txCurDmaDesc;
77 //Pointer to the current RX DMA descriptor
78 static Stm32f2x7RxDmaDesc *rxCurDmaDesc;
79 
80 
81 /**
82  * @brief STM32F207/217 Ethernet MAC driver
83  **/
84 
86 {
88  ETH_MTU,
99  TRUE,
100  TRUE,
101  TRUE,
102  FALSE
103 };
104 
105 
106 /**
107  * @brief STM32F207/217 Ethernet MAC initialization
108  * @param[in] interface Underlying network interface
109  * @return Error code
110  **/
111 
113 {
114  error_t error;
115 
116  //Debug message
117  TRACE_INFO("Initializing STM32F2x7 Ethernet MAC...\r\n");
118 
119  //Save underlying network interface
120  nicDriverInterface = interface;
121 
122  //GPIO configuration
123  stm32f2x7EthInitGpio(interface);
124 
125 #if defined(USE_HAL_DRIVER)
126  //Enable Ethernet MAC clock
127  __HAL_RCC_ETHMAC_CLK_ENABLE();
128  __HAL_RCC_ETHMACTX_CLK_ENABLE();
129  __HAL_RCC_ETHMACRX_CLK_ENABLE();
130 
131  //Reset Ethernet MAC peripheral
132  __HAL_RCC_ETHMAC_FORCE_RESET();
133  __HAL_RCC_ETHMAC_RELEASE_RESET();
134 
135 #elif defined(USE_STDPERIPH_DRIVER)
136  //Enable Ethernet MAC clock
137  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC |
138  RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);
139 
140  //Reset Ethernet MAC peripheral
141  RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, ENABLE);
142  RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, DISABLE);
143 #endif
144 
145  //Perform a software reset
146  ETH->DMABMR |= ETH_DMABMR_SR;
147  //Wait for the reset to complete
148  while(ETH->DMABMR & ETH_DMABMR_SR);
149 
150  //Adjust MDC clock range depending on HCLK frequency
151  ETH->MACMIIAR = ETH_MACMIIAR_CR_Div62;
152 
153  //PHY transceiver initialization
154  error = interface->phyDriver->init(interface);
155  //Failed to initialize PHY transceiver?
156  if(error)
157  return error;
158 
159  //Use default MAC configuration
160  ETH->MACCR = ETH_MACCR_ROD;
161 
162  //Set the MAC address
163  ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
164  ETH->MACA0HR = interface->macAddr.w[2];
165 
166  //Initialize hash table
167  ETH->MACHTLR = 0;
168  ETH->MACHTHR = 0;
169 
170  //Configure the receive filter
171  ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_HM;
172  //Disable flow control
173  ETH->MACFCR = 0;
174  //Enable store and forward mode
175  ETH->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF;
176 
177  //Configure DMA bus mode
178  ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_RDP_1Beat |
179  ETH_DMABMR_RTPR_1_1 | ETH_DMABMR_PBL_1Beat | ETH_DMABMR_EDE;
180 
181  //Initialize DMA descriptor lists
182  stm32f2x7EthInitDmaDesc(interface);
183 
184  //Prevent interrupts from being generated when the transmit statistic
185  //counters reach half their maximum value
186  ETH->MMCTIMR = ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM;
187 
188  //Prevent interrupts from being generated when the receive statistic
189  //counters reach half their maximum value
190  ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM;
191 
192  //Disable MAC interrupts
193  ETH->MACIMR = ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM;
194  //Enable the desired DMA interrupts
195  ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
196 
197  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
198  NVIC_SetPriorityGrouping(STM32F2X7_ETH_IRQ_PRIORITY_GROUPING);
199 
200  //Configure Ethernet interrupt priority
201  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F2X7_ETH_IRQ_PRIORITY_GROUPING,
203 
204  //Enable MAC transmission and reception
205  ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
206  //Enable DMA transmission and reception
207  ETH->DMAOMR |= ETH_DMAOMR_ST | ETH_DMAOMR_SR;
208 
209  //Accept any packets from the upper layer
210  osSetEvent(&interface->nicTxEvent);
211 
212  //Successful initialization
213  return NO_ERROR;
214 }
215 
216 
217 //STM3220G-EVAL, MCBSTM32F200 or Nucleo-F207ZG evaluation board?
218 #if defined(USE_STM322xG_EVAL) || defined(USE_MCBSTM32F200) || \
219  defined(USE_STM32F2XX_NUCLEO_144)
220 
221 /**
222  * @brief GPIO configuration
223  * @param[in] interface Underlying network interface
224  **/
225 
226 void stm32f2x7EthInitGpio(NetInterface *interface)
227 {
228  GPIO_InitTypeDef GPIO_InitStructure;
229 
230 //STM3220G-EVAL evaluation board?
231 #if defined(USE_STM322xG_EVAL) && defined(USE_HAL_DRIVER)
232  //Enable SYSCFG clock
233  __HAL_RCC_SYSCFG_CLK_ENABLE();
234 
235  //Enable GPIO clocks
236  __HAL_RCC_GPIOA_CLK_ENABLE();
237  __HAL_RCC_GPIOB_CLK_ENABLE();
238  __HAL_RCC_GPIOC_CLK_ENABLE();
239  __HAL_RCC_GPIOG_CLK_ENABLE();
240  __HAL_RCC_GPIOH_CLK_ENABLE();
241  __HAL_RCC_GPIOI_CLK_ENABLE();
242 
243  //Configure MCO1 (PA8) as an output
244  GPIO_InitStructure.Pin = GPIO_PIN_8;
245  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
246  GPIO_InitStructure.Pull = GPIO_NOPULL;
247  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
248  GPIO_InitStructure.Alternate = GPIO_AF0_MCO;
249  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
250 
251  //Configure MCO1 pin to output the HSE clock (25MHz)
252  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
253 
254  //Select MII interface mode
255  SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
256 
257  //Configure MII pins
258  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
259  GPIO_InitStructure.Pull = GPIO_NOPULL;
260  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
261  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
262 
263  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
264  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
265  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
266 
267  //Configure ETH_PPS_OUT (PB5) and ETH_MII_TXD3 (PB8)
268  GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_8;
269  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
270 
271  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
272  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
273  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
274  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
275 
276  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
277  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
278  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
279 
280  //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
281  GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7;
282  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
283 
284  //Configure ETH_MII_RX_ER (PI10)
285  GPIO_InitStructure.Pin = GPIO_PIN_10;
286  HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
287 
288 #elif defined(USE_STM322xG_EVAL) && defined(USE_STDPERIPH_DRIVER)
289  //Enable SYSCFG clock
290  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
291 
292  //Enable GPIO clocks
293  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
294  RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG |
295  RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI, ENABLE);
296 
297  //Configure MCO1 (PA8) as an output
298  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
299  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
300  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
301  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
302  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
303  GPIO_Init(GPIOA, &GPIO_InitStructure);
304 
305  //Configure MCO1 pin to output the HSE clock (25MHz)
306  RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
307 
308  //Select MII interface mode
309  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
310 
311  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
312  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
313  GPIO_Init(GPIOA, &GPIO_InitStructure);
314  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
315  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
316  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
317 
318  //Configure ETH_PPS_OUT (PB5) and ETH_MII_TXD3 (PB8)
319  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8;
320  GPIO_Init(GPIOB, &GPIO_InitStructure);
321  GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_ETH);
322  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_ETH);
323 
324  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
325  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
326  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
327  GPIO_Init(GPIOC, &GPIO_InitStructure);
328  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
329  GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_ETH);
330  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_ETH);
331  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
332  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
333 
334  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
335  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
336  GPIO_Init(GPIOG, &GPIO_InitStructure);
337  GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH);
338  GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH);
339  GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
340 
341  //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
342  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;
343  GPIO_Init(GPIOH, &GPIO_InitStructure);
344  GPIO_PinAFConfig(GPIOH, GPIO_PinSource2, GPIO_AF_ETH);
345  GPIO_PinAFConfig(GPIOH, GPIO_PinSource3, GPIO_AF_ETH);
346  GPIO_PinAFConfig(GPIOH, GPIO_PinSource6, GPIO_AF_ETH);
347  GPIO_PinAFConfig(GPIOH, GPIO_PinSource7, GPIO_AF_ETH);
348 
349  //Configure ETH_MII_RX_ER (PI10)
350  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
351  GPIO_Init(GPIOI, &GPIO_InitStructure);
352  GPIO_PinAFConfig(GPIOI, GPIO_PinSource10, GPIO_AF_ETH);
353 
354 //MCBSTM32F200 evaluation board?
355 #elif defined(USE_MCBSTM32F200) && defined(USE_HAL_DRIVER)
356  //Enable SYSCFG clock
357  __HAL_RCC_SYSCFG_CLK_ENABLE();
358 
359  //Enable GPIO clocks
360  __HAL_RCC_GPIOA_CLK_ENABLE();
361  __HAL_RCC_GPIOC_CLK_ENABLE();
362  __HAL_RCC_GPIOG_CLK_ENABLE();
363 
364  //Select RMII interface mode
365  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
366 
367  //Configure RMII pins
368  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
369  GPIO_InitStructure.Pull = GPIO_NOPULL;
370  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
371  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
372 
373  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
374  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
375  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
376 
377  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
378  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
379  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
380 
381  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
382  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
383  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
384 
385 #elif defined(USE_MCBSTM32F200) && defined(USE_STDPERIPH_DRIVER)
386  //Enable SYSCFG clock
387  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
388 
389  //Enable GPIO clocks
390  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
391  RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE);
392 
393  //Select RMII interface mode
394  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
395 
396  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
397  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
398  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
399  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
400  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
401  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
402  GPIO_Init(GPIOA, &GPIO_InitStructure);
403  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
404  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
405  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
406 
407  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
408  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
409  GPIO_Init(GPIOC, &GPIO_InitStructure);
410  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
411  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
412  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
413 
414  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
415  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
416  GPIO_Init(GPIOG, &GPIO_InitStructure);
417  GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH);
418  GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH);
419  GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
420 
421 //Nucleo-F207ZG evaluation board?
422 #elif defined(USE_STM32F2XX_NUCLEO_144)
423  //Enable SYSCFG clock
424  __HAL_RCC_SYSCFG_CLK_ENABLE();
425 
426  //Enable GPIO clocks
427  __HAL_RCC_GPIOA_CLK_ENABLE();
428  __HAL_RCC_GPIOB_CLK_ENABLE();
429  __HAL_RCC_GPIOC_CLK_ENABLE();
430  __HAL_RCC_GPIOG_CLK_ENABLE();
431 
432  //Select RMII interface mode
433  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
434 
435  //Configure RMII pins
436  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
437  GPIO_InitStructure.Pull = GPIO_NOPULL;
438  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
439  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
440 
441  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
442  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
443  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
444 
445  //Configure ETH_RMII_TXD1 (PB13)
446  GPIO_InitStructure.Pin = GPIO_PIN_13;
447  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
448 
449  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
450  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
451  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
452 
453  //Configure RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13)
454  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13;
455  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
456 #endif
457 }
458 
459 #endif
460 
461 
462 /**
463  * @brief Initialize DMA descriptor lists
464  * @param[in] interface Underlying network interface
465  **/
466 
468 {
469  uint_t i;
470 
471  //Initialize TX DMA descriptor list
472  for(i = 0; i < STM32F2X7_ETH_TX_BUFFER_COUNT; i++)
473  {
474  //Use chain structure rather than ring structure
475  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
476  //Initialize transmit buffer size
477  txDmaDesc[i].tdes1 = 0;
478  //Transmit buffer address
479  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
480  //Next descriptor address
481  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
482  //Reserved fields
483  txDmaDesc[i].tdes4 = 0;
484  txDmaDesc[i].tdes5 = 0;
485  //Transmit frame time stamp
486  txDmaDesc[i].tdes6 = 0;
487  txDmaDesc[i].tdes7 = 0;
488  }
489 
490  //The last descriptor is chained to the first entry
491  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
492  //Point to the very first descriptor
493  txCurDmaDesc = &txDmaDesc[0];
494 
495  //Initialize RX DMA descriptor list
496  for(i = 0; i < STM32F2X7_ETH_RX_BUFFER_COUNT; i++)
497  {
498  //The descriptor is initially owned by the DMA
499  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
500  //Use chain structure rather than ring structure
502  //Receive buffer address
503  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
504  //Next descriptor address
505  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
506  //Extended status
507  rxDmaDesc[i].rdes4 = 0;
508  //Reserved field
509  rxDmaDesc[i].rdes5 = 0;
510  //Receive frame time stamp
511  rxDmaDesc[i].rdes6 = 0;
512  rxDmaDesc[i].rdes7 = 0;
513  }
514 
515  //The last descriptor is chained to the first entry
516  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
517  //Point to the very first descriptor
518  rxCurDmaDesc = &rxDmaDesc[0];
519 
520  //Start location of the TX descriptor list
521  ETH->DMATDLAR = (uint32_t) txDmaDesc;
522  //Start location of the RX descriptor list
523  ETH->DMARDLAR = (uint32_t) rxDmaDesc;
524 }
525 
526 
527 /**
528  * @brief STM32F207/217 Ethernet MAC timer handler
529  *
530  * This routine is periodically called by the TCP/IP stack to
531  * handle periodic operations such as polling the link state
532  *
533  * @param[in] interface Underlying network interface
534  **/
535 
537 {
538  //Handle periodic operations
539  interface->phyDriver->tick(interface);
540 }
541 
542 
543 /**
544  * @brief Enable interrupts
545  * @param[in] interface Underlying network interface
546  **/
547 
549 {
550  //Enable Ethernet MAC interrupts
551  NVIC_EnableIRQ(ETH_IRQn);
552  //Enable Ethernet PHY interrupts
553  interface->phyDriver->enableIrq(interface);
554 }
555 
556 
557 /**
558  * @brief Disable interrupts
559  * @param[in] interface Underlying network interface
560  **/
561 
563 {
564  //Disable Ethernet MAC interrupts
565  NVIC_DisableIRQ(ETH_IRQn);
566  //Disable Ethernet PHY interrupts
567  interface->phyDriver->disableIrq(interface);
568 }
569 
570 
571 /**
572  * @brief STM32F207/217 Ethernet MAC interrupt service routine
573  **/
574 
575 void ETH_IRQHandler(void)
576 {
577  bool_t flag;
578  uint32_t status;
579 
580  //Enter interrupt service routine
581  osEnterIsr();
582 
583  //This flag will be set if a higher priority task must be woken
584  flag = FALSE;
585 
586  //Read DMA status register
587  status = ETH->DMASR;
588 
589  //A packet has been transmitted?
590  if(status & ETH_DMASR_TS)
591  {
592  //Clear TS interrupt flag
593  ETH->DMASR = ETH_DMASR_TS;
594 
595  //Check whether the TX buffer is available for writing
596  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
597  {
598  //Notify the TCP/IP stack that the transmitter is ready to send
599  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
600  }
601  }
602 
603  //A packet has been received?
604  if(status & ETH_DMASR_RS)
605  {
606  //Disable RIE interrupt
607  ETH->DMAIER &= ~ETH_DMAIER_RIE;
608 
609  //Set event flag
610  nicDriverInterface->nicEvent = TRUE;
611  //Notify the TCP/IP stack of the event
612  flag |= osSetEventFromIsr(&netEvent);
613  }
614 
615  //Clear NIS interrupt flag
616  ETH->DMASR = ETH_DMASR_NIS;
617 
618  //Leave interrupt service routine
619  osExitIsr(flag);
620 }
621 
622 
623 /**
624  * @brief STM32F207/217 Ethernet MAC event handler
625  * @param[in] interface Underlying network interface
626  **/
627 
629 {
630  error_t error;
631 
632  //Packet received?
633  if(ETH->DMASR & ETH_DMASR_RS)
634  {
635  //Clear interrupt flag
636  ETH->DMASR = ETH_DMASR_RS;
637 
638  //Process all pending packets
639  do
640  {
641  //Read incoming packet
642  error = stm32f2x7EthReceivePacket(interface);
643 
644  //No more data in the receive buffer?
645  } while(error != ERROR_BUFFER_EMPTY);
646  }
647 
648  //Re-enable DMA interrupts
649  ETH->DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
650 }
651 
652 
653 /**
654  * @brief Send a packet
655  * @param[in] interface Underlying network interface
656  * @param[in] buffer Multi-part buffer containing the data to send
657  * @param[in] offset Offset to the first data byte
658  * @return Error code
659  **/
660 
662  const NetBuffer *buffer, size_t offset)
663 {
664  size_t length;
665 
666  //Retrieve the length of the packet
667  length = netBufferGetLength(buffer) - offset;
668 
669  //Check the frame length
671  {
672  //The transmitter can accept another packet
673  osSetEvent(&interface->nicTxEvent);
674  //Report an error
675  return ERROR_INVALID_LENGTH;
676  }
677 
678  //Make sure the current buffer is available for writing
679  if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)
680  return ERROR_FAILURE;
681 
682  //Copy user data to the transmit buffer
683  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
684 
685  //Write the number of bytes to send
686  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
687  //Set LS and FS flags as the data fits in a single buffer
688  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
689  //Give the ownership of the descriptor to the DMA
690  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
691 
692  //Clear TBUS flag to resume processing
693  ETH->DMASR = ETH_DMASR_TBUS;
694  //Instruct the DMA to poll the transmit descriptor list
695  ETH->DMATPDR = 0;
696 
697  //Point to the next descriptor in the list
698  txCurDmaDesc = (Stm32f2x7TxDmaDesc *) txCurDmaDesc->tdes3;
699 
700  //Check whether the next buffer is available for writing
701  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
702  {
703  //The transmitter can accept another packet
704  osSetEvent(&interface->nicTxEvent);
705  }
706 
707  //Data successfully written
708  return NO_ERROR;
709 }
710 
711 
712 /**
713  * @brief Receive a packet
714  * @param[in] interface Underlying network interface
715  * @return Error code
716  **/
717 
719 {
720  error_t error;
721  size_t n;
722 
723  //The current buffer is available for reading?
724  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN))
725  {
726  //FS and LS flags should be set
727  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS))
728  {
729  //Make sure no error occurred
730  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES))
731  {
732  //Retrieve the length of the frame
733  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
734  //Limit the number of data to read
736 
737  //Pass the packet to the upper layer
738  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
739 
740  //Valid packet received
741  error = NO_ERROR;
742  }
743  else
744  {
745  //The received packet contains an error
746  error = ERROR_INVALID_PACKET;
747  }
748  }
749  else
750  {
751  //The packet is not valid
752  error = ERROR_INVALID_PACKET;
753  }
754 
755  //Give the ownership of the descriptor back to the DMA
756  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
757  //Point to the next descriptor in the list
758  rxCurDmaDesc = (Stm32f2x7RxDmaDesc *) rxCurDmaDesc->rdes3;
759  }
760  else
761  {
762  //No more data in the receive buffer
763  error = ERROR_BUFFER_EMPTY;
764  }
765 
766  //Clear RBUS flag to resume processing
767  ETH->DMASR = ETH_DMASR_RBUS;
768  //Instruct the DMA to poll the receive descriptor list
769  ETH->DMARPDR = 0;
770 
771  //Return status code
772  return error;
773 }
774 
775 
776 /**
777  * @brief Configure MAC address filtering
778  * @param[in] interface Underlying network interface
779  * @return Error code
780  **/
781 
783 {
784  uint_t i;
785  uint_t k;
786  uint32_t crc;
787  uint32_t hashTable[2];
788  MacFilterEntry *entry;
789 
790  //Debug message
791  TRACE_DEBUG("Updating STM32F2x7 hash table...\r\n");
792 
793  //Clear hash table
794  hashTable[0] = 0;
795  hashTable[1] = 0;
796 
797  //The MAC address filter contains the list of MAC addresses to accept
798  //when receiving an Ethernet frame
799  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
800  {
801  //Point to the current entry
802  entry = &interface->macAddrFilter[i];
803 
804  //Valid entry?
805  if(entry->refCount > 0)
806  {
807  //Compute CRC over the current MAC address
808  crc = stm32f2x7EthCalcCrc(&entry->addr, sizeof(MacAddr));
809 
810  //The upper 6 bits in the CRC register are used to index the
811  //contents of the hash table
812  k = (crc >> 26) & 0x3F;
813 
814  //Update hash table contents
815  hashTable[k / 32] |= (1 << (k % 32));
816  }
817  }
818 
819  //Write the hash table
820  ETH->MACHTLR = hashTable[0];
821  ETH->MACHTHR = hashTable[1];
822 
823  //Debug message
824  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
825  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
826 
827  //Successful processing
828  return NO_ERROR;
829 }
830 
831 
832 /**
833  * @brief Adjust MAC configuration parameters for proper operation
834  * @param[in] interface Underlying network interface
835  * @return Error code
836  **/
837 
839 {
840  uint32_t config;
841 
842  //Read current MAC configuration
843  config = ETH->MACCR;
844 
845  //10BASE-T or 100BASE-TX operation mode?
846  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
847  config |= ETH_MACCR_FES;
848  else
849  config &= ~ETH_MACCR_FES;
850 
851  //Half-duplex or full-duplex mode?
852  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
853  config |= ETH_MACCR_DM;
854  else
855  config &= ~ETH_MACCR_DM;
856 
857  //Update MAC configuration register
858  ETH->MACCR = config;
859 
860  //Successful processing
861  return NO_ERROR;
862 }
863 
864 
865 /**
866  * @brief Write PHY register
867  * @param[in] phyAddr PHY address
868  * @param[in] regAddr Register address
869  * @param[in] data Register value
870  **/
871 
872 void stm32f2x7EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
873 {
874  uint32_t value;
875 
876  //Take care not to alter MDC clock configuration
877  value = ETH->MACMIIAR & ETH_MACMIIAR_CR;
878  //Set up a write operation
879  value |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
880  //PHY address
881  value |= (phyAddr << 11) & ETH_MACMIIAR_PA;
882  //Register address
883  value |= (regAddr << 6) & ETH_MACMIIAR_MR;
884 
885  //Data to be written in the PHY register
886  ETH->MACMIIDR = data & ETH_MACMIIDR_MD;
887 
888  //Start a write operation
889  ETH->MACMIIAR = value;
890  //Wait for the write to complete
891  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
892 }
893 
894 
895 /**
896  * @brief Read PHY register
897  * @param[in] phyAddr PHY address
898  * @param[in] regAddr Register address
899  * @return Register value
900  **/
901 
902 uint16_t stm32f2x7EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
903 {
904  uint32_t value;
905 
906  //Take care not to alter MDC clock configuration
907  value = ETH->MACMIIAR & ETH_MACMIIAR_CR;
908  //Set up a read operation
909  value |= ETH_MACMIIAR_MB;
910  //PHY address
911  value |= (phyAddr << 11) & ETH_MACMIIAR_PA;
912  //Register address
913  value |= (regAddr << 6) & ETH_MACMIIAR_MR;
914 
915  //Start a read operation
916  ETH->MACMIIAR = value;
917  //Wait for the read to complete
918  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
919 
920  //Return PHY register contents
921  return ETH->MACMIIDR & ETH_MACMIIDR_MD;
922 }
923 
924 
925 /**
926  * @brief CRC calculation
927  * @param[in] data Pointer to the data over which to calculate the CRC
928  * @param[in] length Number of bytes to process
929  * @return Resulting CRC value
930  **/
931 
932 uint32_t stm32f2x7EthCalcCrc(const void *data, size_t length)
933 {
934  uint_t i;
935  uint_t j;
936 
937  //Point to the data over which to calculate the CRC
938  const uint8_t *p = (uint8_t *) data;
939  //CRC preset value
940  uint32_t crc = 0xFFFFFFFF;
941 
942  //Loop through data
943  for(i = 0; i < length; i++)
944  {
945  //The message is processed bit by bit
946  for(j = 0; j < 8; j++)
947  {
948  //Update CRC value
949  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
950  crc = (crc << 1) ^ 0x04C11DB7;
951  else
952  crc = crc << 1;
953  }
954  }
955 
956  //Return CRC value
957  return ~crc;
958 }
error_t stm32f2x7EthReceivePacket(NetInterface *interface)
Receive a packet.
#define txDmaDesc
MacAddr addr
MAC address.
Definition: ethernet.h:210
error_t stm32f2x7EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
error_t stm32f2x7EthInit(NetInterface *interface)
STM32F207/217 Ethernet MAC initialization.
#define STM32F2X7_ETH_IRQ_SUB_PRIORITY
error_t stm32f2x7EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
TCP/IP stack core.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
error_t stm32f2x7EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
Generic error code.
Definition: error.h:43
#define rxDmaDesc
#define txBuffer
void stm32f2x7EthEventHandler(NetInterface *interface)
STM32F207/217 Ethernet MAC event handler.
void stm32f2x7EthInitGpio(NetInterface *interface)
#define ETH_RDES0_OWN
void ETH_IRQHandler(void)
STM32F207/217 Ethernet MAC interrupt service routine.
#define ETH_RDES0_FL
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
#define STM32F2X7_ETH_TX_BUFFER_SIZE
void stm32f2x7EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
STM32F207/217 Ethernet MAC controller.
#define ETH_TDES0_IC
uint16_t stm32f2x7EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
Enhanced TX DMA descriptor.
#define ETH_TDES0_OWN
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:670
NIC driver.
Definition: nic.h:161
#define STM32F2X7_ETH_RX_BUFFER_SIZE
#define ETH_TDES0_FS
#define STM32F2X7_ETH_TX_BUFFER_COUNT
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define MIN(a, b)
Definition: os_port.h:60
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define STM32F2X7_ETH_IRQ_GROUP_PRIORITY
void stm32f2x7EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define ETH_TDES0_LS
#define TRACE_INFO(...)
Definition: debug.h:86
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:82
Ethernet interface.
Definition: nic.h:69
Enhanced RX DMA descriptor.
Success.
Definition: error.h:42
#define rxBuffer
#define ETH_RDES0_LS
OsEvent netEvent
Definition: net.c:72
void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:239
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:211
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
#define STM32F2X7_ETH_RX_BUFFER_COUNT
__start_packed struct @112 MacAddr
MAC address.
uint8_t data[]
Definition: dtls_misc.h:167
#define NetInterface
Definition: net.h:34
const NicDriver stm32f2x7EthDriver
STM32F207/217 Ethernet MAC driver.
#define ETH_RDES1_RCH
uint8_t value[]
Definition: dtls_misc.h:141
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
#define osExitIsr(flag)
#define ETH_TDES0_TCH
void stm32f2x7EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define ETH_TDES1_TBS1
void stm32f2x7EthTick(NetInterface *interface)
STM32F207/217 Ethernet MAC timer handler.
#define osEnterIsr()
#define ETH_RDES1_RBS1
uint8_t length
Definition: dtls_misc.h:140
void stm32f2x7EthDisableIrq(NetInterface *interface)
Disable interrupts.
uint8_t n
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
uint32_t stm32f2x7EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define ETH_RDES0_FS
MAC filter table entry.
Definition: ethernet.h:208
#define ETH_RDES0_ES
#define TRACE_DEBUG(...)
Definition: debug.h:98
#define STM32F2X7_ETH_IRQ_PRIORITY_GROUPING