stm32f4x7_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32f4x7_eth_driver.c
3  * @brief STM32F407/417/427/437 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 "stm32f4xx.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 Stm32f4x7TxDmaDesc *txCurDmaDesc;
77 //Pointer to the current RX DMA descriptor
78 static Stm32f4x7RxDmaDesc *rxCurDmaDesc;
79 
80 
81 /**
82  * @brief STM32F407/417/427/437 Ethernet MAC driver
83  **/
84 
86 {
88  ETH_MTU,
99  TRUE,
100  TRUE,
101  TRUE,
102  FALSE
103 };
104 
105 
106 /**
107  * @brief STM32F407/417/427/437 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 STM32F4x7 Ethernet MAC...\r\n");
118 
119  //Save underlying network interface
120  nicDriverInterface = interface;
121 
122  //GPIO configuration
123  stm32f4x7EthInitGpio(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_Div102;
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  stm32f4x7EthInitDmaDesc(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(STM32F4X7_ETH_IRQ_PRIORITY_GROUPING);
199 
200  //Configure Ethernet interrupt priority
201  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F4X7_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 //STM3240G-EVAL, STM32F4-DISCOVERY, MCBSTM32F400, STM32-E407
218 //or STM-P407 evaluation board?
219 #if defined(USE_STM324xG_EVAL) || defined(USE_STM32F4_DISCOVERY) || \
220  defined(USE_MCBSTM32F400) || defined(USE_STM32_E407) || defined(USE_STM32_P407)
221 
222 /**
223  * @brief GPIO configuration
224  * @param[in] interface Underlying network interface
225  **/
226 
227 void stm32f4x7EthInitGpio(NetInterface *interface)
228 {
229  GPIO_InitTypeDef GPIO_InitStructure;
230 
231 //STM3240G-EVAL evaluation board?
232 #if defined(USE_STM324xG_EVAL) && defined(USE_HAL_DRIVER)
233  //Enable SYSCFG clock
234  __HAL_RCC_SYSCFG_CLK_ENABLE();
235 
236  //Enable GPIO clocks
237  __HAL_RCC_GPIOA_CLK_ENABLE();
238  __HAL_RCC_GPIOB_CLK_ENABLE();
239  __HAL_RCC_GPIOC_CLK_ENABLE();
240  __HAL_RCC_GPIOG_CLK_ENABLE();
241  __HAL_RCC_GPIOH_CLK_ENABLE();
242  __HAL_RCC_GPIOI_CLK_ENABLE();
243 
244  //Configure MCO1 (PA8) as an output
245  GPIO_InitStructure.Pin = GPIO_PIN_8;
246  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
247  GPIO_InitStructure.Pull = GPIO_NOPULL;
248  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
249  GPIO_InitStructure.Alternate = GPIO_AF0_MCO;
250  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
251 
252  //Configure MCO1 pin to output the HSE clock (25MHz)
253  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
254 
255  //Select MII interface mode
256  SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
257 
258  //Configure MII pins
259  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
260  GPIO_InitStructure.Pull = GPIO_NOPULL;
261  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
262  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
263 
264  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
265  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
266  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
267 
268  //Configure ETH_PPS_OUT (PB5) and ETH_MII_TXD3 (PB8)
269  GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_8;
270  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
271 
272  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
273  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
274  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
275  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
276 
277  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
278  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
279  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
280 
281  //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
282  GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7;
283  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
284 
285  //Configure ETH_MII_RX_ER (PI10)
286  GPIO_InitStructure.Pin = GPIO_PIN_10;
287  HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
288 
289 #elif defined(USE_STM324xG_EVAL) && defined(USE_STDPERIPH_DRIVER)
290  //Enable SYSCFG clock
291  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
292 
293  //Enable GPIO clocks
294  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
295  RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG |
296  RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI, ENABLE);
297 
298  //Configure MCO1 (PA8) as an output
299  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
300  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
301  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
302  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
303  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
304  GPIO_Init(GPIOA, &GPIO_InitStructure);
305 
306  //Configure MCO1 pin to output the HSE clock (25MHz)
307  RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1);
308 
309  //Select MII interface mode
310  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII);
311 
312  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
313  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
314  GPIO_Init(GPIOA, &GPIO_InitStructure);
315  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
316  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
317  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
318 
319  //Configure ETH_PPS_OUT (PB5) and ETH_MII_TXD3 (PB8)
320  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8;
321  GPIO_Init(GPIOB, &GPIO_InitStructure);
322  GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_ETH);
323  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_ETH);
324 
325  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
326  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
327  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;
328  GPIO_Init(GPIOC, &GPIO_InitStructure);
329  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
330  GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_ETH);
331  GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_ETH);
332  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
333  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
334 
335  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
336  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
337  GPIO_Init(GPIOG, &GPIO_InitStructure);
338  GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH);
339  GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH);
340  GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
341 
342  //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
343  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_6 | GPIO_Pin_7;
344  GPIO_Init(GPIOH, &GPIO_InitStructure);
345  GPIO_PinAFConfig(GPIOH, GPIO_PinSource2, GPIO_AF_ETH);
346  GPIO_PinAFConfig(GPIOH, GPIO_PinSource3, GPIO_AF_ETH);
347  GPIO_PinAFConfig(GPIOH, GPIO_PinSource6, GPIO_AF_ETH);
348  GPIO_PinAFConfig(GPIOH, GPIO_PinSource7, GPIO_AF_ETH);
349 
350  //Configure ETH_MII_RX_ER (PI10)
351  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
352  GPIO_Init(GPIOI, &GPIO_InitStructure);
353  GPIO_PinAFConfig(GPIOI, GPIO_PinSource10, GPIO_AF_ETH);
354 
355 //STM32F4-DISCOVERY evaluation board?
356 #elif defined(USE_STM32F4_DISCOVERY) && defined(USE_HAL_DRIVER)
357  //Enable SYSCFG clock
358  __HAL_RCC_SYSCFG_CLK_ENABLE();
359 
360  //Enable GPIO clocks
361  __HAL_RCC_GPIOA_CLK_ENABLE();
362  __HAL_RCC_GPIOB_CLK_ENABLE();
363  __HAL_RCC_GPIOC_CLK_ENABLE();
364 
365  //Select RMII interface mode
366  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
367 
368  //Configure RMII pins
369  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
370  GPIO_InitStructure.Pull = GPIO_NOPULL;
371  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
372  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
373 
374  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
375  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
376  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
377 
378  //Configure ETH_RMII_TX_EN (PB11), ETH_RMII_TXD0 (PB12) and ETH_RMII_TXD1 (PB13)
379  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
380  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
381 
382  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
383  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
384  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
385 
386 #elif defined(USE_STM32F4_DISCOVERY) && defined(USE_STDPERIPH_DRIVER)
387  //Enable SYSCFG clock
388  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
389 
390  //Enable GPIO clocks
391  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
392  RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);
393 
394  //Select RMII interface mode
395  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
396 
397  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
398  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
399  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
400  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
401  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
402  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
403  GPIO_Init(GPIOA, &GPIO_InitStructure);
404  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
405  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
406  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
407 
408  //Configure ETH_RMII_TX_EN (PB11), ETH_RMII_TXD0 (PB12) and ETH_RMII_TXD1 (PB13)
409  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
410  GPIO_Init(GPIOB, &GPIO_InitStructure);
411  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH);
412  GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_ETH);
413  GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_ETH);
414 
415  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
416  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
417  GPIO_Init(GPIOC, &GPIO_InitStructure);
418  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
419  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
420  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
421 
422 //MCBSTM32F400 evaluation board?
423 #elif defined(USE_MCBSTM32F400) && defined(USE_HAL_DRIVER)
424  //Enable SYSCFG clock
425  __HAL_RCC_SYSCFG_CLK_ENABLE();
426 
427  //Enable GPIO clocks
428  __HAL_RCC_GPIOA_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_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
446  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
447  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
448 
449  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
450  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
451  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
452 
453 #elif defined(USE_MCBSTM32F400) && defined(USE_STDPERIPH_DRIVER)
454  //Enable SYSCFG clock
455  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
456 
457  //Enable GPIO clocks
458  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
459  RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE);
460 
461  //Select RMII interface mode
462  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
463 
464  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
465  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
466  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
467  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
468  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
469  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
470  GPIO_Init(GPIOA, &GPIO_InitStructure);
471  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
472  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
473  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
474 
475  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
476  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
477  GPIO_Init(GPIOC, &GPIO_InitStructure);
478  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
479  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
480  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
481 
482  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
483  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
484  GPIO_Init(GPIOG, &GPIO_InitStructure);
485  GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH);
486  GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH);
487  GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
488 
489 //STM32-E407 evaluation board?
490 #elif defined(USE_STM32_E407) && defined(USE_HAL_DRIVER)
491  //Enable SYSCFG clock
492  __HAL_RCC_SYSCFG_CLK_ENABLE();
493 
494  //Enable GPIO clocks
495  __HAL_RCC_GPIOA_CLK_ENABLE();
496  __HAL_RCC_GPIOC_CLK_ENABLE();
497  __HAL_RCC_GPIOG_CLK_ENABLE();
498 
499  //Select RMII interface mode
500  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
501 
502  //Configure RMII pins
503  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
504  GPIO_InitStructure.Pull = GPIO_NOPULL;
505  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
506  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
507 
508  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
509  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
510  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
511 
512  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
513  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
514  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
515 
516  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
517  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
518  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
519 
520  //Configure PHY_RST (PG6)
521  GPIO_InitStructure.Pin = GPIO_PIN_6;
522  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
523  GPIO_InitStructure.Pull = GPIO_NOPULL;
524  GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
525  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
526 
527  //Reset PHY transceiver
528  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
529  sleep(10);
530 
531  //Take the PHY transceiver out of reset
532  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_SET);
533  sleep(10);
534 
535 #elif defined(USE_STM32_E407) && defined(USE_STDPERIPH_DRIVER)
536  //Enable SYSCFG clock
537  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
538 
539  //Enable GPIO clocks
540  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA |
541  RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE);
542 
543  //Select RMII interface mode
544  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
545 
546  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
547  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
548  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
549  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
550  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
551  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
552  GPIO_Init(GPIOA, &GPIO_InitStructure);
553  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
554  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
555  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
556 
557  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
558  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
559  GPIO_Init(GPIOC, &GPIO_InitStructure);
560  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
561  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
562  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
563 
564  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
565  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14;
566  GPIO_Init(GPIOG, &GPIO_InitStructure);
567  GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_ETH);
568  GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH);
569  GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
570 
571  //Configure PHY_RST (PG6)
572  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
573  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
574  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
575  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
576  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
577  GPIO_Init(GPIOG, &GPIO_InitStructure);
578 
579  //Reset PHY transceiver
580  GPIO_ResetBits(GPIOG, GPIO_Pin_6);
581  sleep(10);
582 
583  //Take the PHY transceiver out of reset
584  GPIO_SetBits(GPIOG, GPIO_Pin_6);
585  sleep(10);
586 
587 //STM32-P407 evaluation board?
588 #elif defined(USE_STM32_P407) && defined(USE_HAL_DRIVER)
589  //Enable SYSCFG clock
590  __HAL_RCC_SYSCFG_CLK_ENABLE();
591 
592  //Enable GPIO clocks
593  __HAL_RCC_GPIOA_CLK_ENABLE();
594  __HAL_RCC_GPIOB_CLK_ENABLE();
595  __HAL_RCC_GPIOC_CLK_ENABLE();
596  __HAL_RCC_GPIOG_CLK_ENABLE();
597 
598  //Select RMII interface mode
599  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
600 
601  //Configure RMII pins
602  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
603  GPIO_InitStructure.Pull = GPIO_NOPULL;
604  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
605  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
606 
607  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
608  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
609  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
610 
611  //Configure ETH_RMII_TX_EN (PB11)
612  GPIO_InitStructure.Pin = GPIO_PIN_11;
613  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
614 
615  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
616  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
617  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
618 
619  //Configure ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
620  GPIO_InitStructure.Pin = GPIO_PIN_13 | GPIO_PIN_14;
621  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
622 
623 #elif defined(USE_STM32_P407) && defined(USE_STDPERIPH_DRIVER)
624  //Enable SYSCFG clock
625  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
626 
627  //Enable GPIO clocks
628  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
629  RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOG, ENABLE);
630 
631  //Select RMII interface mode
632  SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
633 
634  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
635  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
636  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
637  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
638  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
639  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
640  GPIO_Init(GPIOA, &GPIO_InitStructure);
641  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
642  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
643  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
644 
645  //Configure ETH_RMII_TX_EN (PB11)
646  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
647  GPIO_Init(GPIOB, &GPIO_InitStructure);
648  GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH);
649 
650  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
651  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
652  GPIO_Init(GPIOC, &GPIO_InitStructure);
653  GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
654  GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
655  GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
656 
657  //Configure ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
658  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
659  GPIO_Init(GPIOG, &GPIO_InitStructure);
660  GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH);
661  GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
662 #endif
663 }
664 
665 #endif
666 
667 
668 /**
669  * @brief Initialize DMA descriptor lists
670  * @param[in] interface Underlying network interface
671  **/
672 
674 {
675  uint_t i;
676 
677  //Initialize TX DMA descriptor list
678  for(i = 0; i < STM32F4X7_ETH_TX_BUFFER_COUNT; i++)
679  {
680  //Use chain structure rather than ring structure
681  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
682  //Initialize transmit buffer size
683  txDmaDesc[i].tdes1 = 0;
684  //Transmit buffer address
685  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
686  //Next descriptor address
687  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
688  //Reserved fields
689  txDmaDesc[i].tdes4 = 0;
690  txDmaDesc[i].tdes5 = 0;
691  //Transmit frame time stamp
692  txDmaDesc[i].tdes6 = 0;
693  txDmaDesc[i].tdes7 = 0;
694  }
695 
696  //The last descriptor is chained to the first entry
697  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
698  //Point to the very first descriptor
699  txCurDmaDesc = &txDmaDesc[0];
700 
701  //Initialize RX DMA descriptor list
702  for(i = 0; i < STM32F4X7_ETH_RX_BUFFER_COUNT; i++)
703  {
704  //The descriptor is initially owned by the DMA
705  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
706  //Use chain structure rather than ring structure
708  //Receive buffer address
709  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
710  //Next descriptor address
711  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
712  //Extended status
713  rxDmaDesc[i].rdes4 = 0;
714  //Reserved field
715  rxDmaDesc[i].rdes5 = 0;
716  //Receive frame time stamp
717  rxDmaDesc[i].rdes6 = 0;
718  rxDmaDesc[i].rdes7 = 0;
719  }
720 
721  //The last descriptor is chained to the first entry
722  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
723  //Point to the very first descriptor
724  rxCurDmaDesc = &rxDmaDesc[0];
725 
726  //Start location of the TX descriptor list
727  ETH->DMATDLAR = (uint32_t) txDmaDesc;
728  //Start location of the RX descriptor list
729  ETH->DMARDLAR = (uint32_t) rxDmaDesc;
730 }
731 
732 
733 /**
734  * @brief STM32F407/417/427/437 Ethernet MAC timer handler
735  *
736  * This routine is periodically called by the TCP/IP stack to
737  * handle periodic operations such as polling the link state
738  *
739  * @param[in] interface Underlying network interface
740  **/
741 
743 {
744  //Handle periodic operations
745  interface->phyDriver->tick(interface);
746 }
747 
748 
749 /**
750  * @brief Enable interrupts
751  * @param[in] interface Underlying network interface
752  **/
753 
755 {
756  //Enable Ethernet MAC interrupts
757  NVIC_EnableIRQ(ETH_IRQn);
758  //Enable Ethernet PHY interrupts
759  interface->phyDriver->enableIrq(interface);
760 }
761 
762 
763 /**
764  * @brief Disable interrupts
765  * @param[in] interface Underlying network interface
766  **/
767 
769 {
770  //Disable Ethernet MAC interrupts
771  NVIC_DisableIRQ(ETH_IRQn);
772  //Disable Ethernet PHY interrupts
773  interface->phyDriver->disableIrq(interface);
774 }
775 
776 
777 /**
778  * @brief STM32F407/417/427/437 Ethernet MAC interrupt service routine
779  **/
780 
781 void ETH_IRQHandler(void)
782 {
783  bool_t flag;
784  uint32_t status;
785 
786  //Enter interrupt service routine
787  osEnterIsr();
788 
789  //This flag will be set if a higher priority task must be woken
790  flag = FALSE;
791 
792  //Read DMA status register
793  status = ETH->DMASR;
794 
795  //A packet has been transmitted?
796  if(status & ETH_DMASR_TS)
797  {
798  //Clear TS interrupt flag
799  ETH->DMASR = ETH_DMASR_TS;
800 
801  //Check whether the TX buffer is available for writing
802  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
803  {
804  //Notify the TCP/IP stack that the transmitter is ready to send
805  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
806  }
807  }
808 
809  //A packet has been received?
810  if(status & ETH_DMASR_RS)
811  {
812  //Disable RIE interrupt
813  ETH->DMAIER &= ~ETH_DMAIER_RIE;
814 
815  //Set event flag
816  nicDriverInterface->nicEvent = TRUE;
817  //Notify the TCP/IP stack of the event
818  flag |= osSetEventFromIsr(&netEvent);
819  }
820 
821  //Clear NIS interrupt flag
822  ETH->DMASR = ETH_DMASR_NIS;
823 
824  //Leave interrupt service routine
825  osExitIsr(flag);
826 }
827 
828 
829 /**
830  * @brief STM32F407/417/427/437 Ethernet MAC event handler
831  * @param[in] interface Underlying network interface
832  **/
833 
835 {
836  error_t error;
837 
838  //Packet received?
839  if(ETH->DMASR & ETH_DMASR_RS)
840  {
841  //Clear interrupt flag
842  ETH->DMASR = ETH_DMASR_RS;
843 
844  //Process all pending packets
845  do
846  {
847  //Read incoming packet
848  error = stm32f4x7EthReceivePacket(interface);
849 
850  //No more data in the receive buffer?
851  } while(error != ERROR_BUFFER_EMPTY);
852  }
853 
854  //Re-enable DMA interrupts
855  ETH->DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
856 }
857 
858 
859 /**
860  * @brief Send a packet
861  * @param[in] interface Underlying network interface
862  * @param[in] buffer Multi-part buffer containing the data to send
863  * @param[in] offset Offset to the first data byte
864  * @return Error code
865  **/
866 
868  const NetBuffer *buffer, size_t offset)
869 {
870  size_t length;
871 
872  //Retrieve the length of the packet
873  length = netBufferGetLength(buffer) - offset;
874 
875  //Check the frame length
877  {
878  //The transmitter can accept another packet
879  osSetEvent(&interface->nicTxEvent);
880  //Report an error
881  return ERROR_INVALID_LENGTH;
882  }
883 
884  //Make sure the current buffer is available for writing
885  if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)
886  return ERROR_FAILURE;
887 
888  //Copy user data to the transmit buffer
889  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
890 
891  //Write the number of bytes to send
892  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
893  //Set LS and FS flags as the data fits in a single buffer
894  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
895  //Give the ownership of the descriptor to the DMA
896  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
897 
898  //Clear TBUS flag to resume processing
899  ETH->DMASR = ETH_DMASR_TBUS;
900  //Instruct the DMA to poll the transmit descriptor list
901  ETH->DMATPDR = 0;
902 
903  //Point to the next descriptor in the list
904  txCurDmaDesc = (Stm32f4x7TxDmaDesc *) txCurDmaDesc->tdes3;
905 
906  //Check whether the next buffer is available for writing
907  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
908  {
909  //The transmitter can accept another packet
910  osSetEvent(&interface->nicTxEvent);
911  }
912 
913  //Data successfully written
914  return NO_ERROR;
915 }
916 
917 
918 /**
919  * @brief Receive a packet
920  * @param[in] interface Underlying network interface
921  * @return Error code
922  **/
923 
925 {
926  error_t error;
927  size_t n;
928 
929  //The current buffer is available for reading?
930  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN))
931  {
932  //FS and LS flags should be set
933  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS))
934  {
935  //Make sure no error occurred
936  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES))
937  {
938  //Retrieve the length of the frame
939  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
940  //Limit the number of data to read
942 
943  //Pass the packet to the upper layer
944  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
945 
946  //Valid packet received
947  error = NO_ERROR;
948  }
949  else
950  {
951  //The received packet contains an error
952  error = ERROR_INVALID_PACKET;
953  }
954  }
955  else
956  {
957  //The packet is not valid
958  error = ERROR_INVALID_PACKET;
959  }
960 
961  //Give the ownership of the descriptor back to the DMA
962  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
963  //Point to the next descriptor in the list
964  rxCurDmaDesc = (Stm32f4x7RxDmaDesc *) rxCurDmaDesc->rdes3;
965  }
966  else
967  {
968  //No more data in the receive buffer
969  error = ERROR_BUFFER_EMPTY;
970  }
971 
972  //Clear RBUS flag to resume processing
973  ETH->DMASR = ETH_DMASR_RBUS;
974  //Instruct the DMA to poll the receive descriptor list
975  ETH->DMARPDR = 0;
976 
977  //Return status code
978  return error;
979 }
980 
981 
982 /**
983  * @brief Configure MAC address filtering
984  * @param[in] interface Underlying network interface
985  * @return Error code
986  **/
987 
989 {
990  uint_t i;
991  uint_t k;
992  uint32_t crc;
993  uint32_t hashTable[2];
994  MacFilterEntry *entry;
995 
996  //Debug message
997  TRACE_DEBUG("Updating STM32F4x7 hash table...\r\n");
998 
999  //Clear hash table
1000  hashTable[0] = 0;
1001  hashTable[1] = 0;
1002 
1003  //The MAC address filter contains the list of MAC addresses to accept
1004  //when receiving an Ethernet frame
1005  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
1006  {
1007  //Point to the current entry
1008  entry = &interface->macAddrFilter[i];
1009 
1010  //Valid entry?
1011  if(entry->refCount > 0)
1012  {
1013  //Compute CRC over the current MAC address
1014  crc = stm32f4x7EthCalcCrc(&entry->addr, sizeof(MacAddr));
1015 
1016  //The upper 6 bits in the CRC register are used to index the
1017  //contents of the hash table
1018  k = (crc >> 26) & 0x3F;
1019 
1020  //Update hash table contents
1021  hashTable[k / 32] |= (1 << (k % 32));
1022  }
1023  }
1024 
1025  //Write the hash table
1026  ETH->MACHTLR = hashTable[0];
1027  ETH->MACHTHR = hashTable[1];
1028 
1029  //Debug message
1030  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
1031  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
1032 
1033  //Successful processing
1034  return NO_ERROR;
1035 }
1036 
1037 
1038 /**
1039  * @brief Adjust MAC configuration parameters for proper operation
1040  * @param[in] interface Underlying network interface
1041  * @return Error code
1042  **/
1043 
1045 {
1046  uint32_t config;
1047 
1048  //Read current MAC configuration
1049  config = ETH->MACCR;
1050 
1051  //10BASE-T or 100BASE-TX operation mode?
1052  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1053  config |= ETH_MACCR_FES;
1054  else
1055  config &= ~ETH_MACCR_FES;
1056 
1057  //Half-duplex or full-duplex mode?
1058  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1059  config |= ETH_MACCR_DM;
1060  else
1061  config &= ~ETH_MACCR_DM;
1062 
1063  //Update MAC configuration register
1064  ETH->MACCR = config;
1065 
1066  //Successful processing
1067  return NO_ERROR;
1068 }
1069 
1070 
1071 /**
1072  * @brief Write PHY register
1073  * @param[in] phyAddr PHY address
1074  * @param[in] regAddr Register address
1075  * @param[in] data Register value
1076  **/
1077 
1078 void stm32f4x7EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
1079 {
1080  uint32_t value;
1081 
1082  //Take care not to alter MDC clock configuration
1083  value = ETH->MACMIIAR & ETH_MACMIIAR_CR;
1084  //Set up a write operation
1085  value |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
1086  //PHY address
1087  value |= (phyAddr << 11) & ETH_MACMIIAR_PA;
1088  //Register address
1089  value |= (regAddr << 6) & ETH_MACMIIAR_MR;
1090 
1091  //Data to be written in the PHY register
1092  ETH->MACMIIDR = data & ETH_MACMIIDR_MD;
1093 
1094  //Start a write operation
1095  ETH->MACMIIAR = value;
1096  //Wait for the write to complete
1097  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
1098 }
1099 
1100 
1101 /**
1102  * @brief Read PHY register
1103  * @param[in] phyAddr PHY address
1104  * @param[in] regAddr Register address
1105  * @return Register value
1106  **/
1107 
1108 uint16_t stm32f4x7EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
1109 {
1110  uint32_t value;
1111 
1112  //Take care not to alter MDC clock configuration
1113  value = ETH->MACMIIAR & ETH_MACMIIAR_CR;
1114  //Set up a read operation
1115  value |= ETH_MACMIIAR_MB;
1116  //PHY address
1117  value |= (phyAddr << 11) & ETH_MACMIIAR_PA;
1118  //Register address
1119  value |= (regAddr << 6) & ETH_MACMIIAR_MR;
1120 
1121  //Start a read operation
1122  ETH->MACMIIAR = value;
1123  //Wait for the read to complete
1124  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
1125 
1126  //Return PHY register contents
1127  return ETH->MACMIIDR & ETH_MACMIIDR_MD;
1128 }
1129 
1130 
1131 /**
1132  * @brief CRC calculation
1133  * @param[in] data Pointer to the data over which to calculate the CRC
1134  * @param[in] length Number of bytes to process
1135  * @return Resulting CRC value
1136  **/
1137 
1138 uint32_t stm32f4x7EthCalcCrc(const void *data, size_t length)
1139 {
1140  uint_t i;
1141  uint_t j;
1142 
1143  //Point to the data over which to calculate the CRC
1144  const uint8_t *p = (uint8_t *) data;
1145  //CRC preset value
1146  uint32_t crc = 0xFFFFFFFF;
1147 
1148  //Loop through data
1149  for(i = 0; i < length; i++)
1150  {
1151  //The message is processed bit by bit
1152  for(j = 0; j < 8; j++)
1153  {
1154  //Update CRC value
1155  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
1156  crc = (crc << 1) ^ 0x04C11DB7;
1157  else
1158  crc = crc << 1;
1159  }
1160  }
1161 
1162  //Return CRC value
1163  return ~crc;
1164 }
#define txDmaDesc
MacAddr addr
MAC address.
Definition: ethernet.h:210
error_t stm32f4x7EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
TCP/IP stack core.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
error_t stm32f4x7EthReceivePacket(NetInterface *interface)
Receive a packet.
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
uint16_t stm32f4x7EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
Generic error code.
Definition: error.h:43
#define rxDmaDesc
#define txBuffer
#define STM32F4X7_ETH_IRQ_PRIORITY_GROUPING
#define sleep(delay)
Definition: os_port.h:126
#define ETH_RDES0_OWN
void stm32f4x7EthEventHandler(NetInterface *interface)
STM32F407/417/427/437 Ethernet MAC event handler.
#define ETH_RDES0_FL
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
error_t stm32f4x7EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t stm32f4x7EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define ETH_TDES0_IC
Enhanced TX DMA descriptor.
#define ETH_TDES0_OWN
void ETH_IRQHandler(void)
STM32F407/417/427/437 Ethernet MAC interrupt service routine.
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 ETH_TDES0_FS
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 ETH_TDES0_LS
#define STM32F4X7_ETH_TX_BUFFER_COUNT
#define TRACE_INFO(...)
Definition: debug.h:86
uint16_t regAddr
#define STM32F4X7_ETH_IRQ_SUB_PRIORITY
#define ETH_MTU
Definition: ethernet.h:82
Enhanced RX DMA descriptor.
Ethernet interface.
Definition: nic.h:69
#define STM32F4X7_ETH_RX_BUFFER_COUNT
Success.
Definition: error.h:42
void stm32f4x7EthEnableIrq(NetInterface *interface)
Enable interrupts.
#define rxBuffer
#define ETH_RDES0_LS
void stm32f4x7EthTick(NetInterface *interface)
STM32F407/417/427/437 Ethernet MAC timer handler.
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
#define STM32F4X7_ETH_TX_BUFFER_SIZE
void stm32f4x7EthDisableIrq(NetInterface *interface)
Disable interrupts.
void stm32f4x7EthInitGpio(NetInterface *interface)
unsigned int uint_t
Definition: compiler_port.h:43
__start_packed struct @112 MacAddr
MAC address.
void stm32f4x7EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
uint8_t data[]
Definition: dtls_misc.h:167
#define NetInterface
Definition: net.h:34
#define STM32F4X7_ETH_IRQ_GROUP_PRIORITY
#define ETH_RDES1_RCH
uint8_t value[]
Definition: dtls_misc.h:141
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
uint32_t stm32f4x7EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define STM32F4X7_ETH_RX_BUFFER_SIZE
#define osExitIsr(flag)
#define ETH_TDES0_TCH
void stm32f4x7EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ETH_TDES1_TBS1
#define osEnterIsr()
#define ETH_RDES1_RBS1
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
const NicDriver stm32f4x7EthDriver
STM32F407/417/427/437 Ethernet MAC driver.
#define ETH_RDES0_FS
MAC filter table entry.
Definition: ethernet.h:208
#define ETH_RDES0_ES
#define TRACE_DEBUG(...)
Definition: debug.h:98
error_t stm32f4x7EthInit(NetInterface *interface)
STM32F407/417/427/437 Ethernet MAC initialization.
STM32F407/417/427/437 Ethernet MAC controller.