stm32f4xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32f4xx_eth_driver.c
3  * @brief STM32F4 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "stm32f4xx.h"
36 
37 #ifndef USE_STDPERIPH_DRIVER
38  #include "stm32f4xx_hal.h"
39 #endif
40 
41 #include "core/net.h"
43 #include "debug.h"
44 
45 //Underlying network interface
46 static NetInterface *nicDriverInterface;
47 
48 //IAR EWARM compiler?
49 #if defined(__ICCARM__)
50 
51 //Transmit buffer
52 #pragma data_alignment = 4
54 //Receive buffer
55 #pragma data_alignment = 4
57 //Transmit DMA descriptors
58 #pragma data_alignment = 4
60 //Receive DMA descriptors
61 #pragma data_alignment = 4
63 
64 //Keil MDK-ARM or GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4)));
70 //Receive buffer
72  __attribute__((aligned(4)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(4)));
76 //Receive DMA descriptors
78  __attribute__((aligned(4)));
79 
80 #endif
81 
82 //Pointer to the current TX DMA descriptor
83 static Stm32f4xxTxDmaDesc *txCurDmaDesc;
84 //Pointer to the current RX DMA descriptor
85 static Stm32f4xxRxDmaDesc *rxCurDmaDesc;
86 
87 
88 /**
89  * @brief STM32F4 Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief STM32F4 Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122 
123  //Debug message
124  TRACE_INFO("Initializing STM32F4 Ethernet MAC...\r\n");
125 
126  //Save underlying network interface
127  nicDriverInterface = interface;
128 
129  //GPIO configuration
130  stm32f4xxEthInitGpio(interface);
131 
132 #ifdef USE_STDPERIPH_DRIVER
133  //Enable Ethernet MAC clock
134  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC |
135  RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);
136 
137  //Reset Ethernet MAC peripheral
138  RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, ENABLE);
139  RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_ETH_MAC, DISABLE);
140 #else
141  //Enable Ethernet MAC clock
142  __HAL_RCC_ETHMAC_CLK_ENABLE();
143  __HAL_RCC_ETHMACTX_CLK_ENABLE();
144  __HAL_RCC_ETHMACRX_CLK_ENABLE();
145 
146  //Reset Ethernet MAC peripheral
147  __HAL_RCC_ETHMAC_FORCE_RESET();
148  __HAL_RCC_ETHMAC_RELEASE_RESET();
149 #endif
150 
151  //Perform a software reset
152  ETH->DMABMR |= ETH_DMABMR_SR;
153  //Wait for the reset to complete
154  while((ETH->DMABMR & ETH_DMABMR_SR) != 0)
155  {
156  }
157 
158  //Adjust MDC clock range depending on HCLK frequency
159  ETH->MACMIIAR = ETH_MACMIIAR_CR_Div102;
160 
161  //Valid Ethernet PHY or switch driver?
162  if(interface->phyDriver != NULL)
163  {
164  //Ethernet PHY initialization
165  error = interface->phyDriver->init(interface);
166  }
167  else if(interface->switchDriver != NULL)
168  {
169  //Ethernet switch initialization
170  error = interface->switchDriver->init(interface);
171  }
172  else
173  {
174  //The interface is not properly configured
175  error = ERROR_FAILURE;
176  }
177 
178  //Any error to report?
179  if(error)
180  {
181  return error;
182  }
183 
184  //Use default MAC configuration
185  ETH->MACCR = ETH_MACCR_RESERVED15 | ETH_MACCR_ROD;
186 
187  //Configure MAC address filtering
189 
190  //Disable flow control
191  ETH->MACFCR = 0;
192  //Enable store and forward mode
193  ETH->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF;
194 
195  //Configure DMA bus mode
196  ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_RDP_32Beat |
197  ETH_DMABMR_RTPR_1_1 | ETH_DMABMR_PBL_32Beat | ETH_DMABMR_EDE;
198 
199  //Initialize DMA descriptor lists
200  stm32f4xxEthInitDmaDesc(interface);
201 
202  //Prevent interrupts from being generated when the transmit statistic
203  //counters reach half their maximum value
204  ETH->MMCTIMR = ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM;
205 
206  //Prevent interrupts from being generated when the receive statistic
207  //counters reach half their maximum value
208  ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM;
209 
210  //Disable MAC interrupts
211  ETH->MACIMR = ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM;
212  //Enable the desired DMA interrupts
213  ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
214 
215  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
216  NVIC_SetPriorityGrouping(STM32F4XX_ETH_IRQ_PRIORITY_GROUPING);
217 
218  //Configure Ethernet interrupt priority
219  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F4XX_ETH_IRQ_PRIORITY_GROUPING,
221 
222  //Enable MAC transmission and reception
223  ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
224  //Enable DMA transmission and reception
225  ETH->DMAOMR |= ETH_DMAOMR_ST | ETH_DMAOMR_SR;
226 
227  //Accept any packets from the upper layer
228  osSetEvent(&interface->nicTxEvent);
229 
230  //Successful initialization
231  return NO_ERROR;
232 }
233 
234 
235 /**
236  * @brief GPIO configuration
237  * @param[in] interface Underlying network interface
238  **/
239 
240 __weak_func void stm32f4xxEthInitGpio(NetInterface *interface)
241 {
242 //Nucleo-F429ZI or Nucleo-F439ZI evaluation board?
243 #if defined(USE_STM32F4XX_NUCLEO_144)
244  GPIO_InitTypeDef GPIO_InitStructure;
245 
246  //Enable SYSCFG clock
247  __HAL_RCC_SYSCFG_CLK_ENABLE();
248 
249  //Enable GPIO clocks
250  __HAL_RCC_GPIOA_CLK_ENABLE();
251  __HAL_RCC_GPIOB_CLK_ENABLE();
252  __HAL_RCC_GPIOC_CLK_ENABLE();
253  __HAL_RCC_GPIOG_CLK_ENABLE();
254 
255  //Select RMII interface mode
256  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
257 
258  //Configure RMII pins
259  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
260  GPIO_InitStructure.Pull = GPIO_NOPULL;
261  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
262  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
263 
264  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_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_RMII_TXD1 (PB13)
269  GPIO_InitStructure.Pin = GPIO_PIN_13;
270  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
271 
272  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
273  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
274  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
275 
276  //Configure RMII_TX_EN (PG11) and ETH_RMII_TXD0 (PG13)
277  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13;
278  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
279 
280 //STM32F4-Discovery evaluation board?
281 #elif defined(USE_STM32F4_DISCO)
282  GPIO_InitTypeDef GPIO_InitStructure;
283 
284  //Enable SYSCFG clock
285  __HAL_RCC_SYSCFG_CLK_ENABLE();
286 
287  //Enable GPIO clocks
288  __HAL_RCC_GPIOA_CLK_ENABLE();
289  __HAL_RCC_GPIOB_CLK_ENABLE();
290  __HAL_RCC_GPIOC_CLK_ENABLE();
291  __HAL_RCC_GPIOE_CLK_ENABLE();
292 
293  //Select RMII interface mode
294  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
295 
296  //Configure RMII pins
297  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
298  GPIO_InitStructure.Pull = GPIO_NOPULL;
299  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
300  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
301 
302  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
303  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
304  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
305 
306  //Configure ETH_RMII_TX_EN (PB11), ETH_RMII_TXD0 (PB12) and ETH_RMII_TXD1 (PB13)
307  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
308  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
309 
310  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
311  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
312  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
313 
314  //Configure PHY_RST (PE2)
315  GPIO_InitStructure.Pin = GPIO_PIN_2;
316  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
317  GPIO_InitStructure.Pull = GPIO_NOPULL;
318  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
319  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
320 
321  //Reset PHY transceiver
322  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);
323  sleep(10);
324  HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);
325  sleep(10);
326 
327 //STM3240G-EVAL or STM3241G-EVAL evaluation board?
328 #elif defined(USE_STM324xG_EVAL)
329  GPIO_InitTypeDef GPIO_InitStructure;
330 
331  //Enable SYSCFG clock
332  __HAL_RCC_SYSCFG_CLK_ENABLE();
333 
334  //Enable GPIO clocks
335  __HAL_RCC_GPIOA_CLK_ENABLE();
336  __HAL_RCC_GPIOB_CLK_ENABLE();
337  __HAL_RCC_GPIOC_CLK_ENABLE();
338  __HAL_RCC_GPIOG_CLK_ENABLE();
339  __HAL_RCC_GPIOH_CLK_ENABLE();
340  __HAL_RCC_GPIOI_CLK_ENABLE();
341 
342  //Configure MCO1 (PA8) as an output
343  GPIO_InitStructure.Pin = GPIO_PIN_8;
344  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
345  GPIO_InitStructure.Pull = GPIO_NOPULL;
346  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
347  GPIO_InitStructure.Alternate = GPIO_AF0_MCO;
348  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
349 
350  //Configure MCO1 pin to output the HSE clock (25MHz)
351  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
352 
353  //Select MII interface mode
354  SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
355 
356  //Configure MII pins
357  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
358  GPIO_InitStructure.Pull = GPIO_NOPULL;
359  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
360  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
361 
362  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
363  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
364  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
365 
366  //Configure ETH_MII_TXD3 (PB8)
367  GPIO_InitStructure.Pin = GPIO_PIN_8;
368  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
369 
370  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
371  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
372  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
373  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
374 
375  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
376  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
377  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
378 
379  //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6)
380  //and ETH_MII_RXD3 (PH7)
381  GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7;
382  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
383 
384  //Configure ETH_MII_RX_ER (PI10)
385  GPIO_InitStructure.Pin = GPIO_PIN_10;
386  HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
387 
388 //STM32429I-EVAL or STM32439I-EVAL evaluation board?
389 #elif defined(USE_STM324x9I_EVAL)
390  GPIO_InitTypeDef GPIO_InitStructure;
391 
392  //Enable SYSCFG clock
393  __HAL_RCC_SYSCFG_CLK_ENABLE();
394 
395  //Enable GPIO clocks
396  __HAL_RCC_GPIOA_CLK_ENABLE();
397  __HAL_RCC_GPIOB_CLK_ENABLE();
398  __HAL_RCC_GPIOC_CLK_ENABLE();
399  __HAL_RCC_GPIOG_CLK_ENABLE();
400  __HAL_RCC_GPIOH_CLK_ENABLE();
401  __HAL_RCC_GPIOI_CLK_ENABLE();
402 
403  //Configure MCO1 (PA8) as an output
404  GPIO_InitStructure.Pin = GPIO_PIN_8;
405  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
406  GPIO_InitStructure.Pull = GPIO_NOPULL;
407  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
408  GPIO_InitStructure.Alternate = GPIO_AF0_MCO;
409  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
410 
411  //Configure MCO1 pin to output the HSE clock (25MHz)
412  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
413 
414  //Select MII interface mode
415  SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
416 
417  //Configure MII pins
418  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
419  GPIO_InitStructure.Pull = GPIO_NOPULL;
420  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
421  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
422 
423  //Configure ETH_MII_CRS (PA0)
424  //GPIO_InitStructure.Pin = GPIO_PIN_0;
425  //HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
426 
427  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
428  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
429  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
430 
431  //Configure ETH_MII_TXD3 (PB8)
432  GPIO_InitStructure.Pin = GPIO_PIN_8;
433  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
434 
435  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
436  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
437  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
438  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
439 
440  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
441  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
442  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
443 
444  //Configure ETH_MII_COL (PH3)
445  //GPIO_InitStructure.Pin = GPIO_PIN_3;
446  //HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
447 
448  //Configure ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
449  GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
450  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
451 
452  //Configure ETH_MII_RX_ER (PI10)
453  //GPIO_InitStructure.Pin = GPIO_PIN_10;
454  //HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
455 
456 //STM32469I-EVAL evaluation board?
457 #elif defined(USE_STM32F469I_EVAL)
458  GPIO_InitTypeDef GPIO_InitStructure;
459 
460  //Enable SYSCFG clock
461  __HAL_RCC_SYSCFG_CLK_ENABLE();
462 
463  //Enable GPIO clocks
464  __HAL_RCC_GPIOA_CLK_ENABLE();
465  __HAL_RCC_GPIOC_CLK_ENABLE();
466  __HAL_RCC_GPIOE_CLK_ENABLE();
467  __HAL_RCC_GPIOG_CLK_ENABLE();
468  __HAL_RCC_GPIOH_CLK_ENABLE();
469  __HAL_RCC_GPIOI_CLK_ENABLE();
470 
471  //Configure MCO1 (PA8) as an output
472  GPIO_InitStructure.Pin = GPIO_PIN_8;
473  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
474  GPIO_InitStructure.Pull = GPIO_NOPULL;
475  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
476  GPIO_InitStructure.Alternate = GPIO_AF0_MCO;
477  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
478 
479  //Configure MCO1 pin to output the HSE clock (25MHz)
480  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
481 
482  //Select MII interface mode
483  SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
484 
485  //Configure MII pins
486  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
487  GPIO_InitStructure.Pull = GPIO_NOPULL;
488  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
489  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
490 
491  //Configure ETH_MII_CRS (PA0)
492  //GPIO_InitStructure.Pin = GPIO_PIN_0;
493  //HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
494 
495  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
496  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
497  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
498 
499  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
500  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
501  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
502  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
503 
504  //Configure ETH_MII_TXD3 (PE2)
505  GPIO_InitStructure.Pin = GPIO_PIN_2;
506  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
507 
508  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
509  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
510  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
511 
512  //Configure ETH_MII_COL (PH3)
513  //GPIO_InitStructure.Pin = GPIO_PIN_3;
514  //HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
515 
516  //Configure ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
517  GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
518  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
519 
520  //Configure ETH_MII_RX_ER (PI10)
521  //GPIO_InitStructure.Pin = GPIO_PIN_10;
522  //HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
523 
524 //MCBSTM32F400 evaluation board?
525 #elif defined(USE_MCBSTM32F400)
526  GPIO_InitTypeDef GPIO_InitStructure;
527 
528  //Enable SYSCFG clock
529  __HAL_RCC_SYSCFG_CLK_ENABLE();
530 
531  //Enable GPIO clocks
532  __HAL_RCC_GPIOA_CLK_ENABLE();
533  __HAL_RCC_GPIOC_CLK_ENABLE();
534  __HAL_RCC_GPIOG_CLK_ENABLE();
535 
536  //Select RMII interface mode
537  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
538 
539  //Configure RMII pins
540  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
541  GPIO_InitStructure.Pull = GPIO_NOPULL;
542  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
543  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
544 
545  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
546  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
547  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
548 
549  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
550  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
551  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
552 
553  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
554  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
555  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
556 
557 //STM32-E407 evaluation board?
558 #elif defined(USE_STM32_E407)
559  GPIO_InitTypeDef GPIO_InitStructure;
560 
561  //Enable SYSCFG clock
562  __HAL_RCC_SYSCFG_CLK_ENABLE();
563 
564  //Enable GPIO clocks
565  __HAL_RCC_GPIOA_CLK_ENABLE();
566  __HAL_RCC_GPIOC_CLK_ENABLE();
567  __HAL_RCC_GPIOG_CLK_ENABLE();
568 
569  //Select RMII interface mode
570  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
571 
572  //Configure RMII pins
573  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
574  GPIO_InitStructure.Pull = GPIO_NOPULL;
575  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
576  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
577 
578  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
579  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
580  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
581 
582  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
583  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
584  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
585 
586  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
587  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
588  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
589 
590  //Configure PHY_RST (PG6)
591  GPIO_InitStructure.Pin = GPIO_PIN_6;
592  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
593  GPIO_InitStructure.Pull = GPIO_NOPULL;
594  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
595  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
596 
597  //Reset PHY transceiver
598  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
599  sleep(10);
600  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_SET);
601  sleep(10);
602 
603 //STM32-P407 evaluation board?
604 #elif defined(USE_STM32_P407)
605  GPIO_InitTypeDef GPIO_InitStructure;
606 
607  //Enable SYSCFG clock
608  __HAL_RCC_SYSCFG_CLK_ENABLE();
609 
610  //Enable GPIO clocks
611  __HAL_RCC_GPIOA_CLK_ENABLE();
612  __HAL_RCC_GPIOB_CLK_ENABLE();
613  __HAL_RCC_GPIOC_CLK_ENABLE();
614  __HAL_RCC_GPIOG_CLK_ENABLE();
615 
616  //Select RMII interface mode
617  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
618 
619  //Configure RMII pins
620  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
621  GPIO_InitStructure.Pull = GPIO_NOPULL;
622  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
623  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
624 
625  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
626  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
627  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
628 
629  //Configure ETH_RMII_TX_EN (PB11)
630  GPIO_InitStructure.Pin = GPIO_PIN_11;
631  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
632 
633  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
634  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
635  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
636 
637  //Configure ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
638  GPIO_InitStructure.Pin = GPIO_PIN_13 | GPIO_PIN_14;
639  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
640 #endif
641 }
642 
643 
644 /**
645  * @brief Initialize DMA descriptor lists
646  * @param[in] interface Underlying network interface
647  **/
648 
650 {
651  uint_t i;
652 
653  //Initialize TX DMA descriptor list
654  for(i = 0; i < STM32F4XX_ETH_TX_BUFFER_COUNT; i++)
655  {
656  //Use chain structure rather than ring structure
657  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
658  //Initialize transmit buffer size
659  txDmaDesc[i].tdes1 = 0;
660  //Transmit buffer address
661  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
662  //Next descriptor address
663  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
664  //Reserved fields
665  txDmaDesc[i].tdes4 = 0;
666  txDmaDesc[i].tdes5 = 0;
667  //Transmit frame time stamp
668  txDmaDesc[i].tdes6 = 0;
669  txDmaDesc[i].tdes7 = 0;
670  }
671 
672  //The last descriptor is chained to the first entry
673  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
674  //Point to the very first descriptor
675  txCurDmaDesc = &txDmaDesc[0];
676 
677  //Initialize RX DMA descriptor list
678  for(i = 0; i < STM32F4XX_ETH_RX_BUFFER_COUNT; i++)
679  {
680  //The descriptor is initially owned by the DMA
681  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
682  //Use chain structure rather than ring structure
684  //Receive buffer address
685  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
686  //Next descriptor address
687  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
688  //Extended status
689  rxDmaDesc[i].rdes4 = 0;
690  //Reserved field
691  rxDmaDesc[i].rdes5 = 0;
692  //Receive frame time stamp
693  rxDmaDesc[i].rdes6 = 0;
694  rxDmaDesc[i].rdes7 = 0;
695  }
696 
697  //The last descriptor is chained to the first entry
698  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
699  //Point to the very first descriptor
700  rxCurDmaDesc = &rxDmaDesc[0];
701 
702  //Start location of the TX descriptor list
703  ETH->DMATDLAR = (uint32_t) txDmaDesc;
704  //Start location of the RX descriptor list
705  ETH->DMARDLAR = (uint32_t) rxDmaDesc;
706 }
707 
708 
709 /**
710  * @brief STM32F4 Ethernet MAC timer handler
711  *
712  * This routine is periodically called by the TCP/IP stack to handle periodic
713  * operations such as polling the link state
714  *
715  * @param[in] interface Underlying network interface
716  **/
717 
719 {
720  //Valid Ethernet PHY or switch driver?
721  if(interface->phyDriver != NULL)
722  {
723  //Handle periodic operations
724  interface->phyDriver->tick(interface);
725  }
726  else if(interface->switchDriver != NULL)
727  {
728  //Handle periodic operations
729  interface->switchDriver->tick(interface);
730  }
731  else
732  {
733  //Just for sanity
734  }
735 }
736 
737 
738 /**
739  * @brief Enable interrupts
740  * @param[in] interface Underlying network interface
741  **/
742 
744 {
745  //Enable Ethernet MAC interrupts
746  NVIC_EnableIRQ(ETH_IRQn);
747 
748  //Valid Ethernet PHY or switch driver?
749  if(interface->phyDriver != NULL)
750  {
751  //Enable Ethernet PHY interrupts
752  interface->phyDriver->enableIrq(interface);
753  }
754  else if(interface->switchDriver != NULL)
755  {
756  //Enable Ethernet switch interrupts
757  interface->switchDriver->enableIrq(interface);
758  }
759  else
760  {
761  //Just for sanity
762  }
763 }
764 
765 
766 /**
767  * @brief Disable interrupts
768  * @param[in] interface Underlying network interface
769  **/
770 
772 {
773  //Disable Ethernet MAC interrupts
774  NVIC_DisableIRQ(ETH_IRQn);
775 
776  //Valid Ethernet PHY or switch driver?
777  if(interface->phyDriver != NULL)
778  {
779  //Disable Ethernet PHY interrupts
780  interface->phyDriver->disableIrq(interface);
781  }
782  else if(interface->switchDriver != NULL)
783  {
784  //Disable Ethernet switch interrupts
785  interface->switchDriver->disableIrq(interface);
786  }
787  else
788  {
789  //Just for sanity
790  }
791 }
792 
793 
794 /**
795  * @brief STM32F4 Ethernet MAC interrupt service routine
796  **/
797 
798 void ETH_IRQHandler(void)
799 {
800  bool_t flag;
801  uint32_t status;
802 
803  //Interrupt service routine prologue
804  osEnterIsr();
805 
806  //This flag will be set if a higher priority task must be woken
807  flag = FALSE;
808 
809  //Read DMA status register
810  status = ETH->DMASR;
811 
812  //Packet transmitted?
813  if((status & ETH_DMASR_TS) != 0)
814  {
815  //Clear TS interrupt flag
816  ETH->DMASR = ETH_DMASR_TS;
817 
818  //Check whether the TX buffer is available for writing
819  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
820  {
821  //Notify the TCP/IP stack that the transmitter is ready to send
822  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
823  }
824  }
825 
826  //Packet received?
827  if((status & ETH_DMASR_RS) != 0)
828  {
829  //Clear RS interrupt flag
830  ETH->DMASR = ETH_DMASR_RS;
831 
832  //Set event flag
833  nicDriverInterface->nicEvent = TRUE;
834  //Notify the TCP/IP stack of the event
835  flag |= osSetEventFromIsr(&netEvent);
836  }
837 
838  //Clear NIS interrupt flag
839  ETH->DMASR = ETH_DMASR_NIS;
840 
841  //Interrupt service routine epilogue
842  osExitIsr(flag);
843 }
844 
845 
846 /**
847  * @brief STM32F4 Ethernet MAC event handler
848  * @param[in] interface Underlying network interface
849  **/
850 
852 {
853  error_t error;
854 
855  //Process all pending packets
856  do
857  {
858  //Read incoming packet
859  error = stm32f4xxEthReceivePacket(interface);
860 
861  //No more data in the receive buffer?
862  } while(error != ERROR_BUFFER_EMPTY);
863 }
864 
865 
866 /**
867  * @brief Send a packet
868  * @param[in] interface Underlying network interface
869  * @param[in] buffer Multi-part buffer containing the data to send
870  * @param[in] offset Offset to the first data byte
871  * @param[in] ancillary Additional options passed to the stack along with
872  * the packet
873  * @return Error code
874  **/
875 
877  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
878 {
879  size_t length;
880 
881  //Retrieve the length of the packet
882  length = netBufferGetLength(buffer) - offset;
883 
884  //Check the frame length
886  {
887  //The transmitter can accept another packet
888  osSetEvent(&interface->nicTxEvent);
889  //Report an error
890  return ERROR_INVALID_LENGTH;
891  }
892 
893  //Make sure the current buffer is available for writing
894  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
895  {
896  return ERROR_FAILURE;
897  }
898 
899  //Copy user data to the transmit buffer
900  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
901 
902  //Write the number of bytes to send
903  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
904  //Set LS and FS flags as the data fits in a single buffer
905  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
906  //Give the ownership of the descriptor to the DMA
907  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
908 
909  //Clear TBUS flag to resume processing
910  ETH->DMASR = ETH_DMASR_TBUS;
911  //Instruct the DMA to poll the transmit descriptor list
912  ETH->DMATPDR = 0;
913 
914  //Point to the next descriptor in the list
915  txCurDmaDesc = (Stm32f4xxTxDmaDesc *) txCurDmaDesc->tdes3;
916 
917  //Check whether the next buffer is available for writing
918  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
919  {
920  //The transmitter can accept another packet
921  osSetEvent(&interface->nicTxEvent);
922  }
923 
924  //Data successfully written
925  return NO_ERROR;
926 }
927 
928 
929 /**
930  * @brief Receive a packet
931  * @param[in] interface Underlying network interface
932  * @return Error code
933  **/
934 
936 {
937  error_t error;
938  size_t n;
939  NetRxAncillary ancillary;
940 
941  //Current buffer available for reading?
942  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
943  {
944  //FS and LS flags should be set
945  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
946  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
947  {
948  //Make sure no error occurred
949  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
950  {
951  //Retrieve the length of the frame
952  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
953  //Limit the number of data to read
955 
956  //Additional options can be passed to the stack along with the packet
957  ancillary = NET_DEFAULT_RX_ANCILLARY;
958 
959  //Pass the packet to the upper layer
960  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
961  &ancillary);
962 
963  //Valid packet received
964  error = NO_ERROR;
965  }
966  else
967  {
968  //The received packet contains an error
969  error = ERROR_INVALID_PACKET;
970  }
971  }
972  else
973  {
974  //The packet is not valid
975  error = ERROR_INVALID_PACKET;
976  }
977 
978  //Give the ownership of the descriptor back to the DMA
979  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
980  //Point to the next descriptor in the list
981  rxCurDmaDesc = (Stm32f4xxRxDmaDesc *) rxCurDmaDesc->rdes3;
982  }
983  else
984  {
985  //No more data in the receive buffer
986  error = ERROR_BUFFER_EMPTY;
987  }
988 
989  //Clear RBUS flag to resume processing
990  ETH->DMASR = ETH_DMASR_RBUS;
991  //Instruct the DMA to poll the receive descriptor list
992  ETH->DMARPDR = 0;
993 
994  //Return status code
995  return error;
996 }
997 
998 
999 /**
1000  * @brief Configure MAC address filtering
1001  * @param[in] interface Underlying network interface
1002  * @return Error code
1003  **/
1004 
1006 {
1007  uint_t i;
1008  uint_t j;
1009  uint_t k;
1010  uint32_t crc;
1011  uint32_t hashTable[2];
1012  MacAddr unicastMacAddr[3];
1013  MacFilterEntry *entry;
1014 
1015  //Debug message
1016  TRACE_DEBUG("Updating MAC filter...\r\n");
1017 
1018  //Promiscuous mode?
1019  if(interface->promiscuous)
1020  {
1021  //Pass all incoming frames regardless of their destination address
1022  ETH->MACFFR = ETH_MACFFR_PM;
1023  }
1024  else
1025  {
1026  //Set the MAC address of the station
1027  ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
1028  ETH->MACA0HR = interface->macAddr.w[2];
1029 
1030  //The MAC supports 3 additional addresses for unicast perfect filtering
1031  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
1032  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
1033  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
1034 
1035  //The hash table is used for multicast address filtering
1036  hashTable[0] = 0;
1037  hashTable[1] = 0;
1038 
1039  //The MAC address filter contains the list of MAC addresses to accept
1040  //when receiving an Ethernet frame
1041  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
1042  {
1043  //Point to the current entry
1044  entry = &interface->macAddrFilter[i];
1045 
1046  //Valid entry?
1047  if(entry->refCount > 0)
1048  {
1049  //Multicast address?
1050  if(macIsMulticastAddr(&entry->addr))
1051  {
1052  //Compute CRC over the current MAC address
1053  crc = stm32f4xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
1054 
1055  //The upper 6 bits in the CRC register are used to index the
1056  //contents of the hash table
1057  k = (crc >> 26) & 0x3F;
1058 
1059  //Update hash table contents
1060  hashTable[k / 32] |= (1 << (k % 32));
1061  }
1062  else
1063  {
1064  //Up to 3 additional MAC addresses can be specified
1065  if(j < 3)
1066  {
1067  //Save the unicast address
1068  unicastMacAddr[j++] = entry->addr;
1069  }
1070  }
1071  }
1072  }
1073 
1074  //Configure the first unicast address filter
1075  if(j >= 1)
1076  {
1077  //When the AE bit is set, the entry is used for perfect filtering
1078  ETH->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
1079  ETH->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACA1HR_AE;
1080  }
1081  else
1082  {
1083  //When the AE bit is cleared, the entry is ignored
1084  ETH->MACA1LR = 0;
1085  ETH->MACA1HR = 0;
1086  }
1087 
1088  //Configure the second unicast address filter
1089  if(j >= 2)
1090  {
1091  //When the AE bit is set, the entry is used for perfect filtering
1092  ETH->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
1093  ETH->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACA2HR_AE;
1094  }
1095  else
1096  {
1097  //When the AE bit is cleared, the entry is ignored
1098  ETH->MACA2LR = 0;
1099  ETH->MACA2HR = 0;
1100  }
1101 
1102  //Configure the third unicast address filter
1103  if(j >= 3)
1104  {
1105  //When the AE bit is set, the entry is used for perfect filtering
1106  ETH->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
1107  ETH->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACA3HR_AE;
1108  }
1109  else
1110  {
1111  //When the AE bit is cleared, the entry is ignored
1112  ETH->MACA3LR = 0;
1113  ETH->MACA3HR = 0;
1114  }
1115 
1116  //Check whether frames with a multicast destination address should be
1117  //accepted
1118  if(interface->acceptAllMulticast)
1119  {
1120  //Configure the receive filter
1121  ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_PAM;
1122  }
1123  else
1124  {
1125  //Configure the receive filter
1126  ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_HM;
1127 
1128  //Configure the multicast hash table
1129  ETH->MACHTLR = hashTable[0];
1130  ETH->MACHTHR = hashTable[1];
1131 
1132  //Debug message
1133  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
1134  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
1135  }
1136  }
1137 
1138  //Successful processing
1139  return NO_ERROR;
1140 }
1141 
1142 
1143 /**
1144  * @brief Adjust MAC configuration parameters for proper operation
1145  * @param[in] interface Underlying network interface
1146  * @return Error code
1147  **/
1148 
1150 {
1151  uint32_t config;
1152 
1153  //Read current MAC configuration
1154  config = ETH->MACCR;
1155 
1156  //10BASE-T or 100BASE-TX operation mode?
1157  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
1158  {
1159  config |= ETH_MACCR_FES;
1160  }
1161  else
1162  {
1163  config &= ~ETH_MACCR_FES;
1164  }
1165 
1166  //Half-duplex or full-duplex mode?
1167  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
1168  {
1169  config |= ETH_MACCR_DM;
1170  }
1171  else
1172  {
1173  config &= ~ETH_MACCR_DM;
1174  }
1175 
1176  //Update MAC configuration register
1177  ETH->MACCR = config;
1178 
1179  //Successful processing
1180  return NO_ERROR;
1181 }
1182 
1183 
1184 /**
1185  * @brief Write PHY register
1186  * @param[in] opcode Access type (2 bits)
1187  * @param[in] phyAddr PHY address (5 bits)
1188  * @param[in] regAddr Register address (5 bits)
1189  * @param[in] data Register value
1190  **/
1191 
1192 void stm32f4xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
1193  uint8_t regAddr, uint16_t data)
1194 {
1195  uint32_t temp;
1196 
1197  //Valid opcode?
1198  if(opcode == SMI_OPCODE_WRITE)
1199  {
1200  //Take care not to alter MDC clock configuration
1201  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
1202  //Set up a write operation
1203  temp |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
1204  //PHY address
1205  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
1206  //Register address
1207  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
1208 
1209  //Data to be written in the PHY register
1210  ETH->MACMIIDR = data & ETH_MACMIIDR_MD;
1211 
1212  //Start a write operation
1213  ETH->MACMIIAR = temp;
1214  //Wait for the write to complete
1215  while((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0)
1216  {
1217  }
1218  }
1219  else
1220  {
1221  //The MAC peripheral only supports standard Clause 22 opcodes
1222  }
1223 }
1224 
1225 
1226 /**
1227  * @brief Read PHY register
1228  * @param[in] opcode Access type (2 bits)
1229  * @param[in] phyAddr PHY address (5 bits)
1230  * @param[in] regAddr Register address (5 bits)
1231  * @return Register value
1232  **/
1233 
1234 uint16_t stm32f4xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1235  uint8_t regAddr)
1236 {
1237  uint16_t data;
1238  uint32_t temp;
1239 
1240  //Valid opcode?
1241  if(opcode == SMI_OPCODE_READ)
1242  {
1243  //Take care not to alter MDC clock configuration
1244  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
1245  //Set up a read operation
1246  temp |= ETH_MACMIIAR_MB;
1247  //PHY address
1248  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
1249  //Register address
1250  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
1251 
1252  //Start a read operation
1253  ETH->MACMIIAR = temp;
1254  //Wait for the read to complete
1255  while((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0)
1256  {
1257  }
1258 
1259  //Get register value
1260  data = ETH->MACMIIDR & ETH_MACMIIDR_MD;
1261  }
1262  else
1263  {
1264  //The MAC peripheral only supports standard Clause 22 opcodes
1265  data = 0;
1266  }
1267 
1268  //Return the value of the PHY register
1269  return data;
1270 }
1271 
1272 
1273 /**
1274  * @brief CRC calculation
1275  * @param[in] data Pointer to the data over which to calculate the CRC
1276  * @param[in] length Number of bytes to process
1277  * @return Resulting CRC value
1278  **/
1279 
1280 uint32_t stm32f4xxEthCalcCrc(const void *data, size_t length)
1281 {
1282  uint_t i;
1283  uint_t j;
1284  uint32_t crc;
1285  const uint8_t *p;
1286 
1287  //Point to the data over which to calculate the CRC
1288  p = (uint8_t *) data;
1289  //CRC preset value
1290  crc = 0xFFFFFFFF;
1291 
1292  //Loop through data
1293  for(i = 0; i < length; i++)
1294  {
1295  //The message is processed bit by bit
1296  for(j = 0; j < 8; j++)
1297  {
1298  //Update CRC value
1299  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1300  {
1301  crc = (crc << 1) ^ 0x04C11DB7;
1302  }
1303  else
1304  {
1305  crc = crc << 1;
1306  }
1307  }
1308  }
1309 
1310  //Return CRC value
1311  return ~crc;
1312 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
STM32F4 Ethernet MAC driver.
uint8_t opcode
Definition: dns_common.h:188
__weak_func void stm32f4xxEthInitGpio(NetInterface *interface)
GPIO configuration.
int bool_t
Definition: compiler_port.h:53
error_t stm32f4xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define netEvent
Definition: net_legacy.h:196
void stm32f4xxEthEventHandler(NetInterface *interface)
STM32F4 Ethernet MAC event handler.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
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:690
void stm32f4xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
void stm32f4xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define ETH_TDES1_TBS1
#define STM32F4XX_ETH_RX_BUFFER_SIZE
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
#define sleep(delay)
Definition: os_port.h:307
uint16_t stm32f4xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
#define ETH_RDES0_LS
#define STM32F4XX_ETH_IRQ_PRIORITY_GROUPING
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
error_t stm32f4xxEthReceivePacket(NetInterface *interface)
Receive a packet.
const NicDriver stm32f4xxEthDriver
STM32F4 Ethernet MAC driver.
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define STM32F4XX_ETH_RX_BUFFER_COUNT
void stm32f4xxEthTick(NetInterface *interface)
STM32F4 Ethernet MAC timer handler.
#define FALSE
Definition: os_port.h:46
#define ETH_RDES0_FL
error_t
Error codes.
Definition: error.h:43
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define ETH_RDES0_OWN
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:140
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
#define ETH_RDES0_FS
#define NetTxAncillary
Definition: net_misc.h:36
#define STM32F4XX_ETH_IRQ_SUB_PRIORITY
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:95
#define ETH_TDES0_OWN
uint8_t length
Definition: tcp.h:368
#define ETH_TDES0_TCH
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
#define ETH_RDES0_ES
#define rxBuffer
MacAddr
Definition: ethernet.h:195
#define ETH_TDES0_IC
void stm32f4xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define TRACE_DEBUG(...)
Definition: debug.h:107
Enhanced TX DMA descriptor.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
#define ETH_TDES0_FS
MAC filter table entry.
Definition: ethernet.h:262
#define ETH_RDES1_RCH
#define STM32F4XX_ETH_TX_BUFFER_SIZE
void ETH_IRQHandler(void)
STM32F4 Ethernet MAC interrupt service routine.
#define osEnterIsr()
void stm32f4xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t stm32f4xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define STM32F4XX_ETH_IRQ_GROUP_PRIORITY
error_t stm32f4xxEthInit(NetInterface *interface)
STM32F4 Ethernet MAC initialization.
#define rxDmaDesc
error_t stm32f4xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_TDES0_LS
Enhanced RX DMA descriptor.
#define txDmaDesc
#define ETH_RDES1_RBS1
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
#define ETH_MACCR_RESERVED15
NIC driver.
Definition: nic.h:286
#define STM32F4XX_ETH_TX_BUFFER_COUNT
uint32_t stm32f4xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83