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