stm32f2xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32f2xx_eth_driver.c
3  * @brief STM32F2 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 "stm32f2xx.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 Stm32f2xxTxDmaDesc *txCurDmaDesc;
79 //Pointer to the current RX DMA descriptor
80 static Stm32f2xxRxDmaDesc *rxCurDmaDesc;
81 
82 
83 /**
84  * @brief STM32F2 Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief STM32F2 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 STM32F2 Ethernet MAC...\r\n");
120 
121  //Save underlying network interface
122  nicDriverInterface = interface;
123 
124  //GPIO configuration
125  stm32f2xxEthInitGpio(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_Div62;
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  stm32f2xxEthInitDmaDesc(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(STM32F2XX_ETH_IRQ_PRIORITY_GROUPING);
200 
201  //Configure Ethernet interrupt priority
202  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F2XX_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 //STM3220G-EVAL, Nucleo-F207ZG, or MCBSTM32F200 evaluation board?
219 #if defined(USE_STM322xG_EVAL) || defined(USE_STM32F2XX_NUCLEO_144) || \
220  defined(USE_MCBSTM32F200)
221 
222 /**
223  * @brief GPIO configuration
224  * @param[in] interface Underlying network interface
225  **/
226 
227 void stm32f2xxEthInitGpio(NetInterface *interface)
228 {
229  GPIO_InitTypeDef GPIO_InitStructure;
230 
231 //STM3220G-EVAL evaluation board?
232 #if defined(USE_STM322xG_EVAL)
233  //Enable SYSCFG clock
234  __HAL_RCC_SYSCFG_CLK_ENABLE();
235 
236  //Enable GPIO clocks
237  __HAL_RCC_GPIOA_CLK_ENABLE();
238  __HAL_RCC_GPIOB_CLK_ENABLE();
239  __HAL_RCC_GPIOC_CLK_ENABLE();
240  __HAL_RCC_GPIOG_CLK_ENABLE();
241  __HAL_RCC_GPIOH_CLK_ENABLE();
242  __HAL_RCC_GPIOI_CLK_ENABLE();
243 
244  //Configure MCO1 (PA8) as an output
245  GPIO_InitStructure.Pin = GPIO_PIN_8;
246  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
247  GPIO_InitStructure.Pull = GPIO_NOPULL;
248  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
249  GPIO_InitStructure.Alternate = GPIO_AF0_MCO;
250  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
251 
252  //Configure MCO1 pin to output the HSE clock (25MHz)
253  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
254 
255  //Select MII interface mode
256  SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
257 
258  //Configure MII pins
259  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
260  GPIO_InitStructure.Pull = GPIO_NOPULL;
261  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
262  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
263 
264  //Configure ETH_MII_RX_CLK (PA1), ETH_MDIO (PA2) and ETH_MII_RX_DV (PA7)
265  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
266  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
267 
268  //Configure ETH_MII_TXD3 (PB8)
269  GPIO_InitStructure.Pin = GPIO_PIN_8;
270  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
271 
272  //Configure ETH_MDC (PC1), ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3),
273  //ETH_MII_RXD0 (PC4) and ETH_MII_RXD1 (PC5)
274  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
275  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
276 
277  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
278  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
279  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
280 
281  //Configure ETH_MII_CRS (PH2), ETH_MII_COL (PH3), ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
282  GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_6 | GPIO_PIN_7;
283  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
284 
285  //Configure ETH_MII_RX_ER (PI10)
286  GPIO_InitStructure.Pin = GPIO_PIN_10;
287  HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
288 
289 //Nucleo-F207ZG evaluation board?
290 #elif defined(USE_STM32F2XX_NUCLEO_144)
291  //Enable SYSCFG clock
292  __HAL_RCC_SYSCFG_CLK_ENABLE();
293 
294  //Enable GPIO clocks
295  __HAL_RCC_GPIOA_CLK_ENABLE();
296  __HAL_RCC_GPIOB_CLK_ENABLE();
297  __HAL_RCC_GPIOC_CLK_ENABLE();
298  __HAL_RCC_GPIOG_CLK_ENABLE();
299 
300  //Select RMII interface mode
301  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
302 
303  //Configure RMII pins
304  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
305  GPIO_InitStructure.Pull = GPIO_NOPULL;
306  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
307  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
308 
309  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
310  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
311  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
312 
313  //Configure ETH_RMII_TXD1 (PB13)
314  GPIO_InitStructure.Pin = GPIO_PIN_13;
315  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
316 
317  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
318  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
319  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
320 
321  //Configure RMII_TX_EN (PG11) and ETH_RMII_TXD0 (PG13)
322  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13;
323  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
324 
325 //MCBSTM32F200 evaluation board?
326 #elif defined(USE_MCBSTM32F200)
327  //Enable SYSCFG clock
328  __HAL_RCC_SYSCFG_CLK_ENABLE();
329 
330  //Enable GPIO clocks
331  __HAL_RCC_GPIOA_CLK_ENABLE();
332  __HAL_RCC_GPIOC_CLK_ENABLE();
333  __HAL_RCC_GPIOG_CLK_ENABLE();
334 
335  //Select RMII interface mode
336  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
337 
338  //Configure RMII pins
339  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
340  GPIO_InitStructure.Pull = GPIO_NOPULL;
341  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
342  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
343 
344  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
345  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
346  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
347 
348  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
349  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
350  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
351 
352  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
353  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
354  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
355 #endif
356 }
357 
358 #endif
359 
360 
361 /**
362  * @brief Initialize DMA descriptor lists
363  * @param[in] interface Underlying network interface
364  **/
365 
367 {
368  uint_t i;
369 
370  //Initialize TX DMA descriptor list
371  for(i = 0; i < STM32F2XX_ETH_TX_BUFFER_COUNT; i++)
372  {
373  //Use chain structure rather than ring structure
374  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
375  //Initialize transmit buffer size
376  txDmaDesc[i].tdes1 = 0;
377  //Transmit buffer address
378  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
379  //Next descriptor address
380  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
381  //Reserved fields
382  txDmaDesc[i].tdes4 = 0;
383  txDmaDesc[i].tdes5 = 0;
384  //Transmit frame time stamp
385  txDmaDesc[i].tdes6 = 0;
386  txDmaDesc[i].tdes7 = 0;
387  }
388 
389  //The last descriptor is chained to the first entry
390  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
391  //Point to the very first descriptor
392  txCurDmaDesc = &txDmaDesc[0];
393 
394  //Initialize RX DMA descriptor list
395  for(i = 0; i < STM32F2XX_ETH_RX_BUFFER_COUNT; i++)
396  {
397  //The descriptor is initially owned by the DMA
398  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
399  //Use chain structure rather than ring structure
401  //Receive buffer address
402  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
403  //Next descriptor address
404  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
405  //Extended status
406  rxDmaDesc[i].rdes4 = 0;
407  //Reserved field
408  rxDmaDesc[i].rdes5 = 0;
409  //Receive frame time stamp
410  rxDmaDesc[i].rdes6 = 0;
411  rxDmaDesc[i].rdes7 = 0;
412  }
413 
414  //The last descriptor is chained to the first entry
415  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
416  //Point to the very first descriptor
417  rxCurDmaDesc = &rxDmaDesc[0];
418 
419  //Start location of the TX descriptor list
420  ETH->DMATDLAR = (uint32_t) txDmaDesc;
421  //Start location of the RX descriptor list
422  ETH->DMARDLAR = (uint32_t) rxDmaDesc;
423 }
424 
425 
426 /**
427  * @brief STM32F2 Ethernet MAC timer handler
428  *
429  * This routine is periodically called by the TCP/IP stack to
430  * handle periodic operations such as polling the link state
431  *
432  * @param[in] interface Underlying network interface
433  **/
434 
436 {
437  //Handle periodic operations
438  interface->phyDriver->tick(interface);
439 }
440 
441 
442 /**
443  * @brief Enable interrupts
444  * @param[in] interface Underlying network interface
445  **/
446 
448 {
449  //Enable Ethernet MAC interrupts
450  NVIC_EnableIRQ(ETH_IRQn);
451  //Enable Ethernet PHY interrupts
452  interface->phyDriver->enableIrq(interface);
453 }
454 
455 
456 /**
457  * @brief Disable interrupts
458  * @param[in] interface Underlying network interface
459  **/
460 
462 {
463  //Disable Ethernet MAC interrupts
464  NVIC_DisableIRQ(ETH_IRQn);
465  //Disable Ethernet PHY interrupts
466  interface->phyDriver->disableIrq(interface);
467 }
468 
469 
470 /**
471  * @brief STM32F2 Ethernet MAC interrupt service routine
472  **/
473 
474 void ETH_IRQHandler(void)
475 {
476  bool_t flag;
477  uint32_t status;
478 
479  //Interrupt service routine prologue
480  osEnterIsr();
481 
482  //This flag will be set if a higher priority task must be woken
483  flag = FALSE;
484 
485  //Read DMA status register
486  status = ETH->DMASR;
487 
488  //A packet has been transmitted?
489  if(status & ETH_DMASR_TS)
490  {
491  //Clear TS interrupt flag
492  ETH->DMASR = ETH_DMASR_TS;
493 
494  //Check whether the TX buffer is available for writing
495  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
496  {
497  //Notify the TCP/IP stack that the transmitter is ready to send
498  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
499  }
500  }
501 
502  //A packet has been received?
503  if(status & ETH_DMASR_RS)
504  {
505  //Disable RIE interrupt
506  ETH->DMAIER &= ~ETH_DMAIER_RIE;
507 
508  //Set event flag
509  nicDriverInterface->nicEvent = TRUE;
510  //Notify the TCP/IP stack of the event
511  flag |= osSetEventFromIsr(&netEvent);
512  }
513 
514  //Clear NIS interrupt flag
515  ETH->DMASR = ETH_DMASR_NIS;
516 
517  //Interrupt service routine epilogue
518  osExitIsr(flag);
519 }
520 
521 
522 /**
523  * @brief STM32F2 Ethernet MAC event handler
524  * @param[in] interface Underlying network interface
525  **/
526 
528 {
529  error_t error;
530 
531  //Packet received?
532  if(ETH->DMASR & ETH_DMASR_RS)
533  {
534  //Clear interrupt flag
535  ETH->DMASR = ETH_DMASR_RS;
536 
537  //Process all pending packets
538  do
539  {
540  //Read incoming packet
541  error = stm32f2xxEthReceivePacket(interface);
542 
543  //No more data in the receive buffer?
544  } while(error != ERROR_BUFFER_EMPTY);
545  }
546 
547  //Re-enable DMA interrupts
548  ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
549 }
550 
551 
552 /**
553  * @brief Send a packet
554  * @param[in] interface Underlying network interface
555  * @param[in] buffer Multi-part buffer containing the data to send
556  * @param[in] offset Offset to the first data byte
557  * @return Error code
558  **/
559 
561  const NetBuffer *buffer, size_t offset)
562 {
563  size_t length;
564 
565  //Retrieve the length of the packet
566  length = netBufferGetLength(buffer) - offset;
567 
568  //Check the frame length
570  {
571  //The transmitter can accept another packet
572  osSetEvent(&interface->nicTxEvent);
573  //Report an error
574  return ERROR_INVALID_LENGTH;
575  }
576 
577  //Make sure the current buffer is available for writing
578  if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)
579  return ERROR_FAILURE;
580 
581  //Copy user data to the transmit buffer
582  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
583 
584  //Write the number of bytes to send
585  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
586  //Set LS and FS flags as the data fits in a single buffer
587  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
588  //Give the ownership of the descriptor to the DMA
589  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
590 
591  //Clear TBUS flag to resume processing
592  ETH->DMASR = ETH_DMASR_TBUS;
593  //Instruct the DMA to poll the transmit descriptor list
594  ETH->DMATPDR = 0;
595 
596  //Point to the next descriptor in the list
597  txCurDmaDesc = (Stm32f2xxTxDmaDesc *) txCurDmaDesc->tdes3;
598 
599  //Check whether the next buffer is available for writing
600  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
601  {
602  //The transmitter can accept another packet
603  osSetEvent(&interface->nicTxEvent);
604  }
605 
606  //Data successfully written
607  return NO_ERROR;
608 }
609 
610 
611 /**
612  * @brief Receive a packet
613  * @param[in] interface Underlying network interface
614  * @return Error code
615  **/
616 
618 {
619  error_t error;
620  size_t n;
621 
622  //The current buffer is available for reading?
623  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN))
624  {
625  //FS and LS flags should be set
626  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS))
627  {
628  //Make sure no error occurred
629  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES))
630  {
631  //Retrieve the length of the frame
632  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
633  //Limit the number of data to read
635 
636  //Pass the packet to the upper layer
637  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
638 
639  //Valid packet received
640  error = NO_ERROR;
641  }
642  else
643  {
644  //The received packet contains an error
645  error = ERROR_INVALID_PACKET;
646  }
647  }
648  else
649  {
650  //The packet is not valid
651  error = ERROR_INVALID_PACKET;
652  }
653 
654  //Give the ownership of the descriptor back to the DMA
655  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
656  //Point to the next descriptor in the list
657  rxCurDmaDesc = (Stm32f2xxRxDmaDesc *) rxCurDmaDesc->rdes3;
658  }
659  else
660  {
661  //No more data in the receive buffer
662  error = ERROR_BUFFER_EMPTY;
663  }
664 
665  //Clear RBUS flag to resume processing
666  ETH->DMASR = ETH_DMASR_RBUS;
667  //Instruct the DMA to poll the receive descriptor list
668  ETH->DMARPDR = 0;
669 
670  //Return status code
671  return error;
672 }
673 
674 
675 /**
676  * @brief Configure MAC address filtering
677  * @param[in] interface Underlying network interface
678  * @return Error code
679  **/
680 
682 {
683  uint_t i;
684  uint_t j;
685  uint_t k;
686  uint32_t crc;
687  uint32_t hashTable[2];
688  MacAddr unicastMacAddr[3];
689  MacFilterEntry *entry;
690 
691  //Debug message
692  TRACE_DEBUG("Updating MAC filter...\r\n");
693 
694  //The MAC supports 3 additional addresses for unicast perfect filtering
695  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
696  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
697  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
698 
699  //The hash table is used for multicast address filtering
700  hashTable[0] = 0;
701  hashTable[1] = 0;
702 
703  //The MAC address filter contains the list of MAC addresses to accept
704  //when receiving an Ethernet frame
705  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
706  {
707  //Point to the current entry
708  entry = &interface->macAddrFilter[i];
709 
710  //Valid entry?
711  if(entry->refCount > 0)
712  {
713  //Multicast address?
714  if(macIsMulticastAddr(&entry->addr))
715  {
716  //Compute CRC over the current MAC address
717  crc = stm32f2xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
718 
719  //The upper 6 bits in the CRC register are used to index the
720  //contents of the hash table
721  k = (crc >> 26) & 0x3F;
722 
723  //Update hash table contents
724  hashTable[k / 32] |= (1 << (k % 32));
725  }
726  else
727  {
728  //Up to 3 additional MAC addresses can be specified
729  if(j < 3)
730  {
731  //Save the unicast address
732  unicastMacAddr[j++] = entry->addr;
733  }
734  }
735  }
736  }
737 
738  //Configure the first unicast address filter
739  if(j >= 1)
740  {
741  //When the AE bit is set, the entry is used for perfect filtering
742  ETH->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
743  ETH->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACA1HR_AE;
744  }
745  else
746  {
747  //When the AE bit is cleared, the entry is ignored
748  ETH->MACA1LR = 0;
749  ETH->MACA1HR = 0;
750  }
751 
752  //Configure the second unicast address filter
753  if(j >= 2)
754  {
755  //When the AE bit is set, the entry is used for perfect filtering
756  ETH->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
757  ETH->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACA2HR_AE;
758  }
759  else
760  {
761  //When the AE bit is cleared, the entry is ignored
762  ETH->MACA2LR = 0;
763  ETH->MACA2HR = 0;
764  }
765 
766  //Configure the third unicast address filter
767  if(j >= 3)
768  {
769  //When the AE bit is set, the entry is used for perfect filtering
770  ETH->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
771  ETH->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACA3HR_AE;
772  }
773  else
774  {
775  //When the AE bit is cleared, the entry is ignored
776  ETH->MACA3LR = 0;
777  ETH->MACA3HR = 0;
778  }
779 
780  //Configure the multicast address filter
781  ETH->MACHTLR = hashTable[0];
782  ETH->MACHTHR = hashTable[1];
783 
784  //Debug message
785  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
786  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
787 
788  //Successful processing
789  return NO_ERROR;
790 }
791 
792 
793 /**
794  * @brief Adjust MAC configuration parameters for proper operation
795  * @param[in] interface Underlying network interface
796  * @return Error code
797  **/
798 
800 {
801  uint32_t config;
802 
803  //Read current MAC configuration
804  config = ETH->MACCR;
805 
806  //10BASE-T or 100BASE-TX operation mode?
807  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
808  config |= ETH_MACCR_FES;
809  else
810  config &= ~ETH_MACCR_FES;
811 
812  //Half-duplex or full-duplex mode?
813  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
814  config |= ETH_MACCR_DM;
815  else
816  config &= ~ETH_MACCR_DM;
817 
818  //Update MAC configuration register
819  ETH->MACCR = config;
820 
821  //Successful processing
822  return NO_ERROR;
823 }
824 
825 
826 /**
827  * @brief Write PHY register
828  * @param[in] opcode Access type (2 bits)
829  * @param[in] phyAddr PHY address (5 bits)
830  * @param[in] regAddr Register address (5 bits)
831  * @param[in] data Register value
832  **/
833 
834 void stm32f2xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
835  uint8_t regAddr, uint16_t data)
836 {
837  uint32_t temp;
838 
839  //Valid opcode?
840  if(opcode == SMI_OPCODE_WRITE)
841  {
842  //Take care not to alter MDC clock configuration
843  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
844  //Set up a write operation
845  temp |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
846  //PHY address
847  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
848  //Register address
849  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
850 
851  //Data to be written in the PHY register
852  ETH->MACMIIDR = data & ETH_MACMIIDR_MD;
853 
854  //Start a write operation
855  ETH->MACMIIAR = temp;
856  //Wait for the write to complete
857  while(ETH->MACMIIAR & ETH_MACMIIAR_MB)
858  {
859  }
860  }
861  else
862  {
863  //The MAC peripheral only supports standard Clause 22 opcodes
864  }
865 }
866 
867 
868 /**
869  * @brief Read PHY register
870  * @param[in] opcode Access type (2 bits)
871  * @param[in] phyAddr PHY address (5 bits)
872  * @param[in] regAddr Register address (5 bits)
873  * @return Register value
874  **/
875 
876 uint16_t stm32f2xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
877  uint8_t regAddr)
878 {
879  uint16_t data;
880  uint32_t temp;
881 
882  //Valid opcode?
883  if(opcode == SMI_OPCODE_READ)
884  {
885  //Take care not to alter MDC clock configuration
886  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
887  //Set up a read operation
888  temp |= ETH_MACMIIAR_MB;
889  //PHY address
890  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
891  //Register address
892  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
893 
894  //Start a read operation
895  ETH->MACMIIAR = temp;
896  //Wait for the read to complete
897  while(ETH->MACMIIAR & ETH_MACMIIAR_MB)
898  {
899  }
900 
901  //Get register value
902  data = ETH->MACMIIDR & ETH_MACMIIDR_MD;
903  }
904  else
905  {
906  //The MAC peripheral only supports standard Clause 22 opcodes
907  data = 0;
908  }
909 
910  //Return the value of the PHY register
911  return data;
912 }
913 
914 
915 /**
916  * @brief CRC calculation
917  * @param[in] data Pointer to the data over which to calculate the CRC
918  * @param[in] length Number of bytes to process
919  * @return Resulting CRC value
920  **/
921 
922 uint32_t stm32f2xxEthCalcCrc(const void *data, size_t length)
923 {
924  uint_t i;
925  uint_t j;
926 
927  //Point to the data over which to calculate the CRC
928  const uint8_t *p = (uint8_t *) data;
929  //CRC preset value
930  uint32_t crc = 0xFFFFFFFF;
931 
932  //Loop through data
933  for(i = 0; i < length; i++)
934  {
935  //The message is processed bit by bit
936  for(j = 0; j < 8; j++)
937  {
938  //Update CRC value
939  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
940  crc = (crc << 1) ^ 0x04C11DB7;
941  else
942  crc = crc << 1;
943  }
944  }
945 
946  //Return CRC value
947  return ~crc;
948 }
#define txDmaDesc
MacAddr addr
MAC address.
Definition: ethernet.h:222
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
#define STM32F2XX_ETH_RX_BUFFER_COUNT
uint32_t stm32f2xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
Generic error code.
Definition: error.h:45
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:110
#define rxDmaDesc
#define txBuffer
void stm32f2xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define SMI_OPCODE_READ
Definition: nic.h:63
#define ETH_RDES0_OWN
__start_packed struct @108 MacAddr
MAC address.
#define ETH_RDES0_FL
Enhanced TX DMA descriptor.
#define TRUE
Definition: os_port.h:50
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define STM32F2XX_ETH_IRQ_SUB_PRIORITY
#define SMI_OPCODE_WRITE
Definition: nic.h:62
uint8_t opcode
Definition: dns_common.h:172
void stm32f2xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t stm32f2xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void ETH_IRQHandler(void)
STM32F2 Ethernet MAC interrupt service routine.
#define ETH_TDES0_IC
#define STM32F2XX_ETH_IRQ_PRIORITY_GROUPING
error_t stm32f2xxEthInit(NetInterface *interface)
STM32F2 Ethernet MAC initialization.
void stm32f2xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
#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:672
Enhanced RX DMA descriptor.
NIC driver.
Definition: nic.h:179
void stm32f2xxEthTick(NetInterface *interface)
STM32F2 Ethernet MAC timer handler.
#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.
void stm32f2xxEthEventHandler(NetInterface *interface)
STM32F2 Ethernet MAC event handler.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
#define ETH_TDES0_LS
#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
#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
unsigned int uint_t
Definition: compiler_port.h:45
const NicDriver stm32f2xxEthDriver
STM32F2 Ethernet MAC driver.
uint8_t data[]
Definition: dtls_misc.h:169
#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 STM32F2XX_ETH_IRQ_GROUP_PRIORITY
void stm32f2xxEthInitGpio(NetInterface *interface)
STM32F2 Ethernet MAC controller.
#define osExitIsr(flag)
#define ETH_TDES0_TCH
void stm32f2xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define ETH_TDES1_TBS1
#define STM32F2XX_ETH_RX_BUFFER_SIZE
uint16_t stm32f2xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t stm32f2xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define osEnterIsr()
#define ETH_RDES1_RBS1
uint8_t length
Definition: dtls_misc.h:142
uint8_t n
#define STM32F2XX_ETH_TX_BUFFER_SIZE
#define FALSE
Definition: os_port.h:46
error_t stm32f2xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
int bool_t
Definition: compiler_port.h:49
#define STM32F2XX_ETH_TX_BUFFER_COUNT
#define ETH_RDES0_FS
MAC filter table entry.
Definition: ethernet.h:220
#define ETH_RDES0_ES
#define TRACE_DEBUG(...)
Definition: debug.h:106
error_t stm32f2xxEthReceivePacket(NetInterface *interface)
Receive a packet.