stm32f107_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32f107_eth_driver.c
3  * @brief STM32F107 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 #if defined(USE_HAL_DRIVER)
34  #include "stm32f1xx.h"
35 #elif defined(USE_STDPERIPH_DRIVER)
36  #include "stm32f10x.h"
37 #endif
38 
39 #include "core/net.h"
41 #include "debug.h"
42 
43 //Underlying network interface
44 static NetInterface *nicDriverInterface;
45 
46 //IAR EWARM compiler?
47 #if defined(__ICCARM__)
48 
49 //Transmit buffer
50 #pragma data_alignment = 4
52 //Receive buffer
53 #pragma data_alignment = 4
55 //Transmit DMA descriptors
56 #pragma data_alignment = 4
58 //Receive DMA descriptors
59 #pragma data_alignment = 4
61 
62 //Keil MDK-ARM or GCC compiler?
63 #else
64 
65 //Transmit buffer
67  __attribute__((aligned(4)));
68 //Receive buffer
70  __attribute__((aligned(4)));
71 //Transmit DMA descriptors
73  __attribute__((aligned(4)));
74 //Receive DMA descriptors
76  __attribute__((aligned(4)));
77 
78 #endif
79 
80 //Pointer to the current TX DMA descriptor
81 static Stm32f107TxDmaDesc *txCurDmaDesc;
82 //Pointer to the current RX DMA descriptor
83 static Stm32f107RxDmaDesc *rxCurDmaDesc;
84 
85 
86 /**
87  * @brief STM32F107 Ethernet MAC driver
88  **/
89 
91 {
93  ETH_MTU,
104  TRUE,
105  TRUE,
106  TRUE,
107  FALSE
108 };
109 
110 
111 /**
112  * @brief STM32F107 Ethernet MAC initialization
113  * @param[in] interface Underlying network interface
114  * @return Error code
115  **/
116 
118 {
119  error_t error;
120 
121  //Debug message
122  TRACE_INFO("Initializing STM32F107 Ethernet MAC...\r\n");
123 
124  //Save underlying network interface
125  nicDriverInterface = interface;
126 
127  //GPIO configuration
128  stm32f107EthInitGpio(interface);
129 
130 #if defined(USE_HAL_DRIVER)
131  //Enable Ethernet MAC clock
132  __HAL_RCC_ETHMAC_CLK_ENABLE();
133  __HAL_RCC_ETHMACTX_CLK_ENABLE();
134  __HAL_RCC_ETHMACRX_CLK_ENABLE();
135 
136  //Reset Ethernet MAC peripheral
137  __HAL_RCC_ETHMAC_FORCE_RESET();
138  __HAL_RCC_ETHMAC_RELEASE_RESET();
139 
140 #elif defined(USE_STDPERIPH_DRIVER)
141  //Enable Ethernet MAC clock
142  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC |
143  RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
144 
145  //Reset Ethernet MAC peripheral
146  RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, ENABLE);
147  RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, DISABLE);
148 #endif
149 
150  //Perform a software reset
151  ETH->DMABMR |= ETH_DMABMR_SR;
152  //Wait for the reset to complete
153  while(ETH->DMABMR & ETH_DMABMR_SR);
154 
155 //Adjust MDC clock range depending on HCLK frequency
156 #if defined(USE_HAL_DRIVER)
157  ETH->MACMIIAR = ETH_MACMIIAR_CR_DIV42;
158 #elif defined(USE_STDPERIPH_DRIVER)
159  ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42;
160 #endif
161 
162  //PHY transceiver initialization
163  error = interface->phyDriver->init(interface);
164  //Failed to initialize PHY transceiver?
165  if(error)
166  return error;
167 
168  //Use default MAC configuration
169  ETH->MACCR = ETH_MACCR_ROD;
170 
171  //Set the MAC address
172  ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
173  ETH->MACA0HR = interface->macAddr.w[2];
174 
175  //Initialize hash table
176  ETH->MACHTLR = 0;
177  ETH->MACHTHR = 0;
178 
179  //Configure the receive filter
180  ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_HM;
181  //Disable flow control
182  ETH->MACFCR = 0;
183  //Enable store and forward mode
184  ETH->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF;
185 
186  //Configure DMA bus mode
187  ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_RDP_1Beat |
188  ETH_DMABMR_RTPR_1_1 | ETH_DMABMR_PBL_1Beat;
189 
190  //Initialize DMA descriptor lists
191  stm32f107EthInitDmaDesc(interface);
192 
193  //Prevent interrupts from being generated when the transmit statistic
194  //counters reach half their maximum value
195  ETH->MMCTIMR = ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM;
196 
197  //Prevent interrupts from being generated when the receive statistic
198  //counters reach half their maximum value
199  ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM;
200 
201  //Disable MAC interrupts
202  ETH->MACIMR = ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM;
203  //Enable the desired DMA interrupts
204  ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
205 
206  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
207  NVIC_SetPriorityGrouping(STM32F107_ETH_IRQ_PRIORITY_GROUPING);
208 
209  //Configure Ethernet interrupt priority
210  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F107_ETH_IRQ_PRIORITY_GROUPING,
212 
213  //Enable MAC transmission and reception
214  ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
215  //Enable DMA transmission and reception
216  ETH->DMAOMR |= ETH_DMAOMR_ST | ETH_DMAOMR_SR;
217 
218  //Accept any packets from the upper layer
219  osSetEvent(&interface->nicTxEvent);
220 
221  //Successful initialization
222  return NO_ERROR;
223 }
224 
225 
226 //STM3210C-EVAL or STM32-P107 evaluation board?
227 #if defined(USE_STM3210C_EVAL) || defined(USE_STM32_P107)
228 
229 /**
230  * @brief GPIO configuration
231  * @param[in] interface Underlying network interface
232  **/
233 
234 void stm32f107EthInitGpio(NetInterface *interface)
235 {
236  GPIO_InitTypeDef GPIO_InitStructure;
237 
238 //STM3210C-EVAL evaluation board?
239 #if defined(USE_STM3210C_EVAL) && defined(USE_HAL_DRIVER)
240  //Enable AFIO clock
241  __HAL_RCC_AFIO_CLK_ENABLE();
242 
243  //Enable GPIO clocks
244  __HAL_RCC_GPIOA_CLK_ENABLE();
245  __HAL_RCC_GPIOB_CLK_ENABLE();
246  __HAL_RCC_GPIOC_CLK_ENABLE();
247  __HAL_RCC_GPIOD_CLK_ENABLE();
248 
249  //Configure MCO (PA8) as an output
250  GPIO_InitStructure.Pin = GPIO_PIN_8;
251  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
252  GPIO_InitStructure.Pull = GPIO_NOPULL;
253  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
254  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
255 
256  //Configure MCO pin to output the HSE clock (25MHz)
257  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, 1);
258 
259  //Select MII interface mode
260  __HAL_AFIO_ETH_MII();
261 
262  //Configure MII_MDIO (PA2)
263  GPIO_InitStructure.Pin = GPIO_PIN_2;
264  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
265  GPIO_InitStructure.Pull = GPIO_NOPULL;
266  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
267  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
268 
269  //Configure MII_PPS_OUT (PB5), ETH_MII_TXD3 (PB8), MII_TX_EN (PB11),
270  //MII_TXD0 (PB12) and MII_TXD1 (PB13)
271  GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
272  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
273  GPIO_InitStructure.Pull = GPIO_NOPULL;
274  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
275  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
276 
277  //Configure MII_MDC (PC1) and MII_TXD2 (PC2)
278  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2;
279  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
280  GPIO_InitStructure.Pull = GPIO_NOPULL;
281  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
282  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
283 
284  //Configure ETH_MII_CRS (PA0), ETH_MII_RX_CLK (PA1) and ETH_MII_COL (PA3)
285  GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3;
286  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
287  GPIO_InitStructure.Pull = GPIO_NOPULL;
288  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
289  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
290 
291  //Configure ETH_MII_RX_ER (PB10)
292  GPIO_InitStructure.Pin = GPIO_PIN_10;
293  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
294  GPIO_InitStructure.Pull = GPIO_NOPULL;
295  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
296  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
297 
298  //Configure ETH_MII_TX_CLK (PC3)
299  GPIO_InitStructure.Pin = GPIO_PIN_3;
300  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
301  GPIO_InitStructure.Pull = GPIO_NOPULL;
302  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
303  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
304 
305  //Configure ETH_MII_RX_DV (PD8), ETH_MII_RXD0 (PD9), ETH_MII_RXD1 (PD10),
306  //ETH_MII_RXD2 (PD11) and ETH_MII_RXD3 (PD12)
307  GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
308  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
309  GPIO_InitStructure.Pull = GPIO_NOPULL;
310  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
311  HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
312 
313  //Remap Ethernet pins
314  __HAL_AFIO_REMAP_ETH_ENABLE();
315 
316 #elif defined(USE_STM3210C_EVAL) && defined(USE_STDPERIPH_DRIVER)
317  //Enable AFIO clock
318  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
319 
320  //Enable GPIO clocks
321  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
322  RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
323 
324  //Configure MCO (PA8) as an output
325  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
326  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
327  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
328  GPIO_Init(GPIOA, &GPIO_InitStructure);
329 
330  //Configure MCO pin to output the HSE clock (25MHz)
331  RCC_MCOConfig(RCC_MCO_HSE);
332 
333  //Select MII interface mode
334  GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_MII);
335 
336  //Configure MII_MDIO (PA2)
337  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
338  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
339  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
340  GPIO_Init(GPIOA, &GPIO_InitStructure);
341 
342  //Configure MII_PPS_OUT (PB5), ETH_MII_TXD3 (PB8), MII_TX_EN (PB11),
343  //MII_TXD0 (PB12) and MII_TXD1 (PB13)
344  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
345  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
346  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
347  GPIO_Init(GPIOB, &GPIO_InitStructure);
348 
349  //Configure MII_MDC (PC1) and MII_TXD2 (PC2)
350  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
351  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
352  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
353  GPIO_Init(GPIOC, &GPIO_InitStructure);
354 
355  //Configure ETH_MII_CRS (PA0), ETH_MII_RX_CLK (PA1) and ETH_MII_COL (PA3)
356  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3;
357  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
358  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
359  GPIO_Init(GPIOA, &GPIO_InitStructure);
360 
361  //Configure ETH_MII_RX_ER (PB10)
362  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
363  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
364  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
365  GPIO_Init(GPIOB, &GPIO_InitStructure);
366 
367  //Configure ETH_MII_TX_CLK (PC3)
368  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
369  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
370  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
371  GPIO_Init(GPIOC, &GPIO_InitStructure);
372 
373  //Configure ETH_MII_RX_DV (PD8), ETH_MII_RXD0 (PD9), ETH_MII_RXD1 (PD10),
374  //ETH_MII_RXD2 (PD11) and ETH_MII_RXD3 (PD12)
375  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
376  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
377  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
378  GPIO_Init(GPIOD, &GPIO_InitStructure);
379 
380  //Remap Ethernet pins
381  GPIO_PinRemapConfig(GPIO_Remap_ETH, ENABLE);
382 
383 //STM32-P107 evaluation board?
384 #elif defined(USE_STM32_P107) && defined(USE_HAL_DRIVER)
385  uint32_t temp;
386  //RCC_PeriphCLKInitTypeDef RCC_PeriphClkInitStruct;
387 
388  //Enable AFIO clock
389  __HAL_RCC_AFIO_CLK_ENABLE();
390 
391  //Enable GPIO clocks
392  __HAL_RCC_GPIOA_CLK_ENABLE();
393  __HAL_RCC_GPIOB_CLK_ENABLE();
394  __HAL_RCC_GPIOC_CLK_ENABLE();
395  __HAL_RCC_GPIOD_CLK_ENABLE();
396 
397  //Configure MCO (PA8) as an output
398  GPIO_InitStructure.Pin = GPIO_PIN_8;
399  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
400  GPIO_InitStructure.Pull = GPIO_NOPULL;
401  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
402  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
403 
404  //Configure PLL3 to output a 50MHz clock
405  temp = RCC->CFGR2 & ~RCC_CFGR2_PLL3MUL;
406  RCC->CFGR2 = temp | RCC_CFGR2_PLL3MUL10;
407 
408  //Enable PLL3
409  RCC->CR |= RCC_CR_PLL3ON;
410 
411  //Wait for the PLL3 to lock
412  while(!(RCC->CR & RCC_CR_PLL3RDY));
413 
414  //Configure MCO pin to output the PLL3 clock
415  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLL3CLK, 1);
416 
417  //Select RMII interface mode
418  __HAL_AFIO_ETH_RMII();
419 
420  //Configure MII_MDIO (PA2)
421  GPIO_InitStructure.Pin = GPIO_PIN_2;
422  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
423  GPIO_InitStructure.Pull = GPIO_NOPULL;
424  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
425  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
426 
427  //Configure ETH_RMII_TX_EN (PB11), ETH_RMII_TXD0 (PB12) and ETH_RMII_TXD1 (PB13)
428  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
429  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
430  GPIO_InitStructure.Pull = GPIO_NOPULL;
431  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
432  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
433 
434  //Configure ETH_MDC (PC1)
435  GPIO_InitStructure.Pin = GPIO_PIN_1;
436  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
437  GPIO_InitStructure.Pull = GPIO_NOPULL;
438  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
439  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
440 
441  //Configure ETH_RMII_REF_CLK (PA1) and ETH_RMII_CRS_DV (PA7)
442  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_7;
443  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
444  GPIO_InitStructure.Pull = GPIO_NOPULL;
445  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
446  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
447 
448  //Configure ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
449  GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5;
450  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
451  GPIO_InitStructure.Pull = GPIO_NOPULL;
452  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
453  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
454 
455  //Do not remap Ethernet pins
456  __HAL_AFIO_REMAP_ETH_DISABLE();
457 
458 //STM32-P107 evaluation board?
459 #elif defined(USE_STM32_P107) && defined(USE_STDPERIPH_DRIVER)
460  //Enable AFIO clock
461  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
462 
463  //Enable GPIO clocks
464  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
465  RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
466 
467  //Configure MCO (PA8) as an output
468  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
469  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
470  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
471  GPIO_Init(GPIOA, &GPIO_InitStructure);
472 
473  //Configure PLL3 to output a 50MHz clock
474  RCC_PLL3Config(RCC_PLL3Mul_10);
475  //Enable PLL3
476  RCC_PLL3Cmd(ENABLE);
477 
478  //Wait for the PLL3 to lock
479  while(RCC_GetFlagStatus(RCC_FLAG_PLL3RDY) == RESET);
480 
481  //Configure MCO pin to output the PLL3 clock
482  RCC_MCOConfig(RCC_MCO_PLL3CLK);
483 
484  //Select RMII interface mode
485  GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_RMII);
486 
487  //Configure ETH_MDIO (PA2)
488  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
489  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
490  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
491  GPIO_Init(GPIOA, &GPIO_InitStructure);
492 
493  //Configure ETH_RMII_TX_EN (PB11), ETH_RMII_TXD0 (PB12) and ETH_RMII_TXD1 (PB13)
494  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
495  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
496  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
497  GPIO_Init(GPIOB, &GPIO_InitStructure);
498 
499  //Configure ETH_MDC (PC1)
500  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
501  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
502  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
503  GPIO_Init(GPIOC, &GPIO_InitStructure);
504 
505  //Configure ETH_RMII_REF_CLK (PA1) and ETH_RMII_CRS_DV (PA7)
506  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_7;
507  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
508  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
509  GPIO_Init(GPIOA, &GPIO_InitStructure);
510 
511  //Configure ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
512  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
513  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
514  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
515  GPIO_Init(GPIOC, &GPIO_InitStructure);
516 
517  //Do not remap Ethernet pins
518  GPIO_PinRemapConfig(GPIO_Remap_ETH, DISABLE);
519 #endif
520 }
521 
522 #endif
523 
524 
525 /**
526  * @brief Initialize DMA descriptor lists
527  * @param[in] interface Underlying network interface
528  **/
529 
531 {
532  uint_t i;
533 
534  //Initialize TX DMA descriptor list
535  for(i = 0; i < STM32F107_ETH_TX_BUFFER_COUNT; i++)
536  {
537  //Use chain structure rather than ring structure
538  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
539  //Initialize transmit buffer size
540  txDmaDesc[i].tdes1 = 0;
541  //Transmit buffer address
542  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
543  //Next descriptor address
544  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
545  }
546 
547  //The last descriptor is chained to the first entry
548  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
549  //Point to the very first descriptor
550  txCurDmaDesc = &txDmaDesc[0];
551 
552  //Initialize RX DMA descriptor list
553  for(i = 0; i < STM32F107_ETH_RX_BUFFER_COUNT; i++)
554  {
555  //The descriptor is initially owned by the DMA
556  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
557  //Use chain structure rather than ring structure
559  //Receive buffer address
560  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
561  //Next descriptor address
562  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
563  }
564 
565  //The last descriptor is chained to the first entry
566  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
567  //Point to the very first descriptor
568  rxCurDmaDesc = &rxDmaDesc[0];
569 
570  //Start location of the TX descriptor list
571  ETH->DMATDLAR = (uint32_t) txDmaDesc;
572  //Start location of the RX descriptor list
573  ETH->DMARDLAR = (uint32_t) rxDmaDesc;
574 }
575 
576 
577 /**
578  * @brief STM32F107 Ethernet MAC timer handler
579  *
580  * This routine is periodically called by the TCP/IP stack to
581  * handle periodic operations such as polling the link state
582  *
583  * @param[in] interface Underlying network interface
584  **/
585 
587 {
588  //Handle periodic operations
589  interface->phyDriver->tick(interface);
590 }
591 
592 
593 /**
594  * @brief Enable interrupts
595  * @param[in] interface Underlying network interface
596  **/
597 
599 {
600  //Enable Ethernet MAC interrupts
601  NVIC_EnableIRQ(ETH_IRQn);
602  //Enable Ethernet PHY interrupts
603  interface->phyDriver->enableIrq(interface);
604 }
605 
606 
607 /**
608  * @brief Disable interrupts
609  * @param[in] interface Underlying network interface
610  **/
611 
613 {
614  //Disable Ethernet MAC interrupts
615  NVIC_DisableIRQ(ETH_IRQn);
616  //Disable Ethernet PHY interrupts
617  interface->phyDriver->disableIrq(interface);
618 }
619 
620 
621 /**
622  * @brief STM32F107 Ethernet MAC interrupt service routine
623  **/
624 
625 void ETH_IRQHandler(void)
626 {
627  bool_t flag;
628  uint32_t status;
629 
630  //Enter interrupt service routine
631  osEnterIsr();
632 
633  //This flag will be set if a higher priority task must be woken
634  flag = FALSE;
635 
636  //Read DMA status register
637  status = ETH->DMASR;
638 
639  //A packet has been transmitted?
640  if(status & ETH_DMASR_TS)
641  {
642  //Clear TS interrupt flag
643  ETH->DMASR = ETH_DMASR_TS;
644 
645  //Check whether the TX buffer is available for writing
646  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
647  {
648  //Notify the TCP/IP stack that the transmitter is ready to send
649  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
650  }
651  }
652 
653  //A packet has been received?
654  if(status & ETH_DMASR_RS)
655  {
656  //Disable RIE interrupt
657  ETH->DMAIER &= ~ETH_DMAIER_RIE;
658 
659  //Set event flag
660  nicDriverInterface->nicEvent = TRUE;
661  //Notify the TCP/IP stack of the event
662  flag |= osSetEventFromIsr(&netEvent);
663  }
664 
665  //Clear NIS interrupt flag
666  ETH->DMASR = ETH_DMASR_NIS;
667 
668  //Leave interrupt service routine
669  osExitIsr(flag);
670 }
671 
672 
673 /**
674  * @brief STM32F107 Ethernet MAC event handler
675  * @param[in] interface Underlying network interface
676  **/
677 
679 {
680  error_t error;
681 
682  //Packet received?
683  if(ETH->DMASR & ETH_DMASR_RS)
684  {
685  //Clear interrupt flag
686  ETH->DMASR = ETH_DMASR_RS;
687 
688  //Process all pending packets
689  do
690  {
691  //Read incoming packet
692  error = stm32f107EthReceivePacket(interface);
693 
694  //No more data in the receive buffer?
695  } while(error != ERROR_BUFFER_EMPTY);
696  }
697 
698  //Re-enable DMA interrupts
699  ETH->DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
700 }
701 
702 
703 /**
704  * @brief Send a packet
705  * @param[in] interface Underlying network interface
706  * @param[in] buffer Multi-part buffer containing the data to send
707  * @param[in] offset Offset to the first data byte
708  * @return Error code
709  **/
710 
712  const NetBuffer *buffer, size_t offset)
713 {
714  size_t length;
715 
716  //Retrieve the length of the packet
717  length = netBufferGetLength(buffer) - offset;
718 
719  //Check the frame length
721  {
722  //The transmitter can accept another packet
723  osSetEvent(&interface->nicTxEvent);
724  //Report an error
725  return ERROR_INVALID_LENGTH;
726  }
727 
728  //Make sure the current buffer is available for writing
729  if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)
730  return ERROR_FAILURE;
731 
732  //Copy user data to the transmit buffer
733  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
734 
735  //Write the number of bytes to send
736  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
737  //Set LS and FS flags as the data fits in a single buffer
738  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
739  //Give the ownership of the descriptor to the DMA
740  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
741 
742  //Clear TBUS flag to resume processing
743  ETH->DMASR = ETH_DMASR_TBUS;
744  //Instruct the DMA to poll the transmit descriptor list
745  ETH->DMATPDR = 0;
746 
747  //Point to the next descriptor in the list
748  txCurDmaDesc = (Stm32f107TxDmaDesc *) txCurDmaDesc->tdes3;
749 
750  //Check whether the next buffer is available for writing
751  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
752  {
753  //The transmitter can accept another packet
754  osSetEvent(&interface->nicTxEvent);
755  }
756 
757  //Data successfully written
758  return NO_ERROR;
759 }
760 
761 
762 /**
763  * @brief Receive a packet
764  * @param[in] interface Underlying network interface
765  * @return Error code
766  **/
767 
769 {
770  error_t error;
771  size_t n;
772 
773  //The current buffer is available for reading?
774  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN))
775  {
776  //FS and LS flags should be set
777  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS))
778  {
779  //Make sure no error occurred
780  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES))
781  {
782  //Retrieve the length of the frame
783  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
784  //Limit the number of data to read
786 
787  //Pass the packet to the upper layer
788  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
789 
790  //Valid packet received
791  error = NO_ERROR;
792  }
793  else
794  {
795  //The received packet contains an error
796  error = ERROR_INVALID_PACKET;
797  }
798  }
799  else
800  {
801  //The packet is not valid
802  error = ERROR_INVALID_PACKET;
803  }
804 
805  //Give the ownership of the descriptor back to the DMA
806  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
807  //Point to the next descriptor in the list
808  rxCurDmaDesc = (Stm32f107RxDmaDesc *) rxCurDmaDesc->rdes3;
809  }
810  else
811  {
812  //No more data in the receive buffer
813  error = ERROR_BUFFER_EMPTY;
814  }
815 
816  //Clear RBUS flag to resume processing
817  ETH->DMASR = ETH_DMASR_RBUS;
818  //Instruct the DMA to poll the receive descriptor list
819  ETH->DMARPDR = 0;
820 
821  //Return status code
822  return error;
823 }
824 
825 
826 /**
827  * @brief Configure MAC address filtering
828  * @param[in] interface Underlying network interface
829  * @return Error code
830  **/
831 
833 {
834  uint_t i;
835  uint_t k;
836  uint32_t crc;
837  uint32_t hashTable[2];
838  MacFilterEntry *entry;
839 
840  //Debug message
841  TRACE_DEBUG("Updating STM32F107 hash table...\r\n");
842 
843  //Clear hash table
844  hashTable[0] = 0;
845  hashTable[1] = 0;
846 
847  //The MAC address filter contains the list of MAC addresses to accept
848  //when receiving an Ethernet frame
849  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
850  {
851  //Point to the current entry
852  entry = &interface->macAddrFilter[i];
853 
854  //Valid entry?
855  if(entry->refCount > 0)
856  {
857  //Compute CRC over the current MAC address
858  crc = stm32f107EthCalcCrc(&entry->addr, sizeof(MacAddr));
859 
860  //The upper 6 bits in the CRC register are used to index the
861  //contents of the hash table
862  k = (crc >> 26) & 0x3F;
863 
864  //Update hash table contents
865  hashTable[k / 32] |= (1 << (k % 32));
866  }
867  }
868 
869  //Write the hash table
870  ETH->MACHTLR = hashTable[0];
871  ETH->MACHTHR = hashTable[1];
872 
873  //Debug message
874  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
875  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
876 
877  //Successful processing
878  return NO_ERROR;
879 }
880 
881 
882 /**
883  * @brief Adjust MAC configuration parameters for proper operation
884  * @param[in] interface Underlying network interface
885  * @return Error code
886  **/
887 
889 {
890  uint32_t config ;
891 
892  //Read current MAC configuration
893  config = ETH->MACCR;
894 
895  //10BASE-T or 100BASE-TX operation mode?
896  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
897  config |= ETH_MACCR_FES;
898  else
899  config &= ~ETH_MACCR_FES;
900 
901  //Half-duplex or full-duplex mode?
902  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
903  config |= ETH_MACCR_DM;
904  else
905  config &= ~ETH_MACCR_DM;
906 
907  //Update MAC configuration register
908  ETH->MACCR = config;
909 
910  //Successful processing
911  return NO_ERROR;
912 }
913 
914 
915 /**
916  * @brief Write PHY register
917  * @param[in] phyAddr PHY address
918  * @param[in] regAddr Register address
919  * @param[in] data Register value
920  **/
921 
922 void stm32f107EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
923 {
924  uint32_t value;
925 
926  //Take care not to alter MDC clock configuration
927  value = ETH->MACMIIAR & ETH_MACMIIAR_CR;
928  //Set up a write operation
929  value |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
930  //PHY address
931  value |= (phyAddr << 11) & ETH_MACMIIAR_PA;
932  //Register address
933  value |= (regAddr << 6) & ETH_MACMIIAR_MR;
934 
935  //Data to be written in the PHY register
936  ETH->MACMIIDR = data & ETH_MACMIIDR_MD;
937 
938  //Start a write operation
939  ETH->MACMIIAR = value;
940  //Wait for the write to complete
941  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
942 }
943 
944 
945 /**
946  * @brief Read PHY register
947  * @param[in] phyAddr PHY address
948  * @param[in] regAddr Register address
949  * @return Register value
950  **/
951 
952 uint16_t stm32f107EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
953 {
954  uint32_t value;
955 
956  //Take care not to alter MDC clock configuration
957  value = ETH->MACMIIAR & ETH_MACMIIAR_CR;
958  //Set up a read operation
959  value |= ETH_MACMIIAR_MB;
960  //PHY address
961  value |= (phyAddr << 11) & ETH_MACMIIAR_PA;
962  //Register address
963  value |= (regAddr << 6) & ETH_MACMIIAR_MR;
964 
965  //Start a read operation
966  ETH->MACMIIAR = value;
967  //Wait for the read to complete
968  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
969 
970  //Return PHY register contents
971  return ETH->MACMIIDR & ETH_MACMIIDR_MD;
972 }
973 
974 
975 /**
976  * @brief CRC calculation
977  * @param[in] data Pointer to the data over which to calculate the CRC
978  * @param[in] length Number of bytes to process
979  * @return Resulting CRC value
980  **/
981 
982 uint32_t stm32f107EthCalcCrc(const void *data, size_t length)
983 {
984  uint_t i;
985  uint_t j;
986 
987  //Point to the data over which to calculate the CRC
988  const uint8_t *p = (uint8_t *) data;
989  //CRC preset value
990  uint32_t crc = 0xFFFFFFFF;
991 
992  //Loop through data
993  for(i = 0; i < length; i++)
994  {
995  //The message is processed bit by bit
996  for(j = 0; j < 8; j++)
997  {
998  //Update CRC value
999  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
1000  crc = (crc << 1) ^ 0x04C11DB7;
1001  else
1002  crc = crc << 1;
1003  }
1004  }
1005 
1006  //Return CRC value
1007  return ~crc;
1008 }
#define txDmaDesc
MacAddr addr
MAC address.
Definition: ethernet.h:210
#define STM32F107_ETH_RX_BUFFER_SIZE
void stm32f107EthTick(NetInterface *interface)
STM32F107 Ethernet MAC timer handler.
#define STM32F107_ETH_TX_BUFFER_COUNT
#define STM32F107_ETH_IRQ_GROUP_PRIORITY
Transmit DMA descriptor.
TCP/IP stack core.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:295
Generic error code.
Definition: error.h:43
#define rxDmaDesc
#define txBuffer
void stm32f107EthDisableIrq(NetInterface *interface)
Disable interrupts.
void stm32f107EthEventHandler(NetInterface *interface)
STM32F107 Ethernet MAC event handler.
void stm32f107EthEnableIrq(NetInterface *interface)
Enable interrupts.
error_t stm32f107EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define ETH_RDES0_OWN
Receive DMA descriptor.
error_t stm32f107EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void stm32f107EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define ETH_RDES0_FL
error_t stm32f107EthInit(NetInterface *interface)
STM32F107 Ethernet MAC initialization.
#define TRUE
Definition: os_port.h:48
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
#define ETH_TDES0_IC
#define ETH_TDES0_OWN
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:670
NIC driver.
Definition: nic.h:161
const NicDriver stm32f107EthDriver
STM32F107 Ethernet MAC driver.
#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.
uint32_t stm32f107EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define ETH_TDES0_LS
void ETH_IRQHandler(void)
STM32F107 Ethernet MAC interrupt service routine.
#define STM32F107_ETH_TX_BUFFER_SIZE
#define TRACE_INFO(...)
Definition: debug.h:86
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:82
Ethernet interface.
Definition: nic.h:69
Success.
Definition: error.h:42
#define rxBuffer
#define ETH_RDES0_LS
OsEvent netEvent
Definition: net.c:72
void nicProcessPacket(NetInterface *interface, void *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:239
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:211
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t
Error codes.
Definition: error.h:40
error_t stm32f107EthReceivePacket(NetInterface *interface)
Receive a packet.
unsigned int uint_t
Definition: compiler_port.h:43
void stm32f107EthInitGpio(NetInterface *interface)
__start_packed struct @112 MacAddr
MAC address.
uint8_t data[]
Definition: dtls_misc.h:167
#define STM32F107_ETH_IRQ_SUB_PRIORITY
STM32F107 Ethernet MAC controller.
#define NetInterface
Definition: net.h:34
#define ETH_RDES1_RCH
uint8_t value[]
Definition: dtls_misc.h:141
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
error_t stm32f107EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define osExitIsr(flag)
#define ETH_TDES0_TCH
void stm32f107EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ETH_TDES1_TBS1
#define osEnterIsr()
#define STM32F107_ETH_RX_BUFFER_COUNT
uint16_t stm32f107EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#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
#define STM32F107_ETH_IRQ_PRIORITY_GROUPING
#define ETH_RDES0_FS
MAC filter table entry.
Definition: ethernet.h:208
#define ETH_RDES0_ES
#define TRACE_DEBUG(...)
Definition: debug.h:98