stm32f7xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32f7xx_eth_driver.c
3  * @brief STM32F746/756 Ethernet MAC controller
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL NIC_TRACE_LEVEL
31 
32 //Dependencies
33 #include "stm32f7xx.h"
34 #include "core/net.h"
36 #include "debug.h"
37 
38 //Underlying network interface
39 static NetInterface *nicDriverInterface;
40 
41 //IAR EWARM compiler?
42 #if defined(__ICCARM__)
43 
44 //Transmit buffer
45 #pragma data_alignment = 4
46 #pragma location = ".ram_no_cache"
48 //Receive buffer
49 #pragma data_alignment = 4
50 #pragma location = ".ram_no_cache"
52 //Transmit DMA descriptors
53 #pragma data_alignment = 4
54 #pragma location = ".ram_no_cache"
56 //Receive DMA descriptors
57 #pragma data_alignment = 4
58 #pragma location = ".ram_no_cache"
60 
61 //Keil MDK-ARM or GCC compiler?
62 #else
63 
64 //Transmit buffer
66  __attribute__((aligned(4), __section__(".ram_no_cache")));
67 //Receive buffer
69  __attribute__((aligned(4), __section__(".ram_no_cache")));
70 //Transmit DMA descriptors
72  __attribute__((aligned(4), __section__(".ram_no_cache")));
73 //Receive DMA descriptors
75  __attribute__((aligned(4), __section__(".ram_no_cache")));
76 
77 #endif
78 
79 //Pointer to the current TX DMA descriptor
80 static Stm32f7xxTxDmaDesc *txCurDmaDesc;
81 //Pointer to the current RX DMA descriptor
82 static Stm32f7xxRxDmaDesc *rxCurDmaDesc;
83 
84 
85 /**
86  * @brief STM32F746/756 Ethernet MAC driver
87  **/
88 
90 {
92  ETH_MTU,
103  TRUE,
104  TRUE,
105  TRUE,
106  FALSE
107 };
108 
109 
110 /**
111  * @brief STM32F746/756 Ethernet MAC initialization
112  * @param[in] interface Underlying network interface
113  * @return Error code
114  **/
115 
117 {
118  error_t error;
119 
120  //Debug message
121  TRACE_INFO("Initializing STM32F7xx Ethernet MAC...\r\n");
122 
123  //Save underlying network interface
124  nicDriverInterface = interface;
125 
126  //GPIO configuration
127  stm32f7xxEthInitGpio(interface);
128 
129  //Enable Ethernet MAC clock
130  __HAL_RCC_ETHMAC_CLK_ENABLE();
131  __HAL_RCC_ETHMACTX_CLK_ENABLE();
132  __HAL_RCC_ETHMACRX_CLK_ENABLE();
133 
134  //Reset Ethernet MAC peripheral
135  __HAL_RCC_ETHMAC_FORCE_RESET();
136  __HAL_RCC_ETHMAC_RELEASE_RESET();
137 
138  //Perform a software reset
139  ETH->DMABMR |= ETH_DMABMR_SR;
140  //Wait for the reset to complete
141  while(ETH->DMABMR & ETH_DMABMR_SR);
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
156  ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
157  ETH->MACA0HR = interface->macAddr.w[2];
158 
159  //Initialize hash table
160  ETH->MACHTLR = 0;
161  ETH->MACHTHR = 0;
162 
163  //Configure the receive filter
164  ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_HM;
165  //Disable flow control
166  ETH->MACFCR = 0;
167  //Enable store and forward mode
168  ETH->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF;
169 
170  //Configure DMA bus mode
171  ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_RDP_1Beat |
172  ETH_DMABMR_RTPR_1_1 | ETH_DMABMR_PBL_1Beat | ETH_DMABMR_EDE;
173 
174  //Initialize DMA descriptor lists
175  stm32f7xxEthInitDmaDesc(interface);
176 
177  //Prevent interrupts from being generated when the transmit statistic
178  //counters reach half their maximum value
179  ETH->MMCTIMR = ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM;
180 
181  //Prevent interrupts from being generated when the receive statistic
182  //counters reach half their maximum value
183  ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM;
184 
185  //Disable MAC interrupts
186  ETH->MACIMR = ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM;
187  //Enable the desired DMA interrupts
188  ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
189 
190  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
191  NVIC_SetPriorityGrouping(STM32F7XX_ETH_IRQ_PRIORITY_GROUPING);
192 
193  //Configure Ethernet interrupt priority
194  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F7XX_ETH_IRQ_PRIORITY_GROUPING,
196 
197  //Enable MAC transmission and reception
198  ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
199  //Enable DMA transmission and reception
200  ETH->DMAOMR |= ETH_DMAOMR_ST | ETH_DMAOMR_SR;
201 
202  //Accept any packets from the upper layer
203  osSetEvent(&interface->nicTxEvent);
204 
205  //Successful initialization
206  return NO_ERROR;
207 }
208 
209 
210 //STM32756G-EVAL, STM32F769I-EVAL, STM32F746G-DISCOVERY, STM32F769I-DISCOVERY
211 //Nucleo-F746ZG or Nucleo-F767ZI evaluation board?
212 #if defined(USE_STM32756G_EVAL) || defined(USE_STM32F769I_EVAL) || \
213  defined(USE_STM32746G_DISCO) || defined(USE_STM32F769I_DISCO) || \
214  defined(USE_STM32F7XX_NUCLEO_144)
215 
216 /**
217  * @brief GPIO configuration
218  * @param[in] interface Underlying network interface
219  **/
220 
221 void stm32f7xxEthInitGpio(NetInterface *interface)
222 {
223  GPIO_InitTypeDef GPIO_InitStructure;
224 
225 //STM32756G-EVAL or STM32F769I-EVAL evaluation board?
226 #if defined(USE_STM32756G_EVAL) || defined(USE_STM32F769I_EVAL)
227  //Enable SYSCFG clock
228  __HAL_RCC_SYSCFG_CLK_ENABLE();
229 
230  //Enable GPIO clocks
231  __HAL_RCC_GPIOA_CLK_ENABLE();
232  __HAL_RCC_GPIOC_CLK_ENABLE();
233  __HAL_RCC_GPIOE_CLK_ENABLE();
234  __HAL_RCC_GPIOG_CLK_ENABLE();
235  __HAL_RCC_GPIOH_CLK_ENABLE();
236  __HAL_RCC_GPIOI_CLK_ENABLE();
237 
238  //Configure MCO1 (PA8) as an output
239  GPIO_InitStructure.Pin = GPIO_PIN_8;
240  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
241  GPIO_InitStructure.Pull = GPIO_NOPULL;
242  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
243  GPIO_InitStructure.Alternate = GPIO_AF0_MCO;
244  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
245 
246  //Configure MCO1 pin to output the HSE clock (25MHz)
247  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1);
248 
249  //Select MII interface mode
250  SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL;
251 
252 #if defined(STM32F7XX_ETH_MDIO_PIN) && defined(STM32F7XX_ETH_MDC_PIN)
253  //Configure ETH_MDIO as a GPIO
254  GPIO_InitStructure.Pin = STM32F7XX_ETH_MDIO_PIN;
255  GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
256  GPIO_InitStructure.Pull = GPIO_PULLUP;
257  GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
258  HAL_GPIO_Init(STM32F7XX_ETH_MDIO_GPIO, &GPIO_InitStructure);
259 
260  //Configure ETH_MDC as a GPIO
261  GPIO_InitStructure.Pin = STM32F7XX_ETH_MDC_PIN;
262  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
263  GPIO_InitStructure.Pull = GPIO_NOPULL;
264  GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
265  HAL_GPIO_Init(STM32F7XX_ETH_MDC_GPIO, &GPIO_InitStructure);
266 
267  //Deassert MDC
268  HAL_GPIO_WritePin(STM32F7XX_ETH_MDC_GPIO,
269  STM32F7XX_ETH_MDC_PIN, GPIO_PIN_RESET);
270 #else
271  //Configure ETH_MDIO (PA2)
272  GPIO_InitStructure.Pin = GPIO_PIN_2;
273  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
274  GPIO_InitStructure.Pull = GPIO_PULLUP;
275  GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
276  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
277  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
278 
279  //Configure ETH_MDC (PC1)
280  GPIO_InitStructure.Pin = GPIO_PIN_1;
281  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
282  GPIO_InitStructure.Pull = GPIO_NOPULL;
283  GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
284  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
285  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
286 #endif
287 
288  //Configure MII pins
289  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
290  GPIO_InitStructure.Pull = GPIO_NOPULL;
291  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
292  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
293 
294  //Configure ETH_MII_CRS (PA0)
295  //GPIO_InitStructure.Pin = GPIO_PIN_0;
296  //HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
297 
298  //Configure ETH_MII_RX_CLK (PA1) and ETH_MII_RX_DV (PA7)
299  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_7;
300  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
301 
302  //Configure ETH_MII_TXD2 (PC2), ETH_MII_TX_CLK (PC3), ETH_MII_RXD0 (PC4)
303  //and ETH_MII_RXD1 (PC5)
304  GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
305  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
306 
307  //Configure ETH_MII_TXD3 (PE2)
308  GPIO_InitStructure.Pin = GPIO_PIN_2;
309  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
310 
311  //Configure ETH_MII_TX_EN (PG11), ETH_MII_TXD0 (PG13) and ETH_MII_TXD1 (PG14)
312  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
313  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
314 
315  //Configure ETH_MII_COL (PH3)
316  //GPIO_InitStructure.Pin = GPIO_PIN_3;
317  //HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
318 
319  //Configure ETH_MII_RXD2 (PH6) and ETH_MII_RXD3 (PH7)
320  GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7;
321  HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
322 
323  //Configure ETH_MII_RX_ER (PI10)
324  //GPIO_InitStructure.Pin = GPIO_PIN_10;
325  //HAL_GPIO_Init(GPIOI, &GPIO_InitStructure);
326 
327 //STM32F746G-DISCOVERY or STM32F769I-DISCOVERY evaluation board?
328 #elif defined(USE_STM32746G_DISCO) || defined(USE_STM32F769I_DISCO)
329  //Enable SYSCFG clock
330  __HAL_RCC_SYSCFG_CLK_ENABLE();
331 
332  //Enable GPIO clocks
333  __HAL_RCC_GPIOA_CLK_ENABLE();
334  __HAL_RCC_GPIOC_CLK_ENABLE();
335  __HAL_RCC_GPIOG_CLK_ENABLE();
336 
337  //Select RMII interface mode
338  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
339 
340  //Configure RMII pins
341  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
342  GPIO_InitStructure.Pull = GPIO_NOPULL;
343  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
344  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
345 
346  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
347  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
348  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
349 
350  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
351  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
352  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
353 
354  //Configure ETH_RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13) and ETH_RMII_TXD1 (PG14)
355  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14;
356  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
357 
358 //Nucleo-F746ZG or Nucleo-F767ZI evaluation board?
359 #elif defined(USE_STM32F7XX_NUCLEO_144)
360  //Enable SYSCFG clock
361  __HAL_RCC_SYSCFG_CLK_ENABLE();
362 
363  //Enable GPIO clocks
364  __HAL_RCC_GPIOA_CLK_ENABLE();
365  __HAL_RCC_GPIOB_CLK_ENABLE();
366  __HAL_RCC_GPIOC_CLK_ENABLE();
367  __HAL_RCC_GPIOG_CLK_ENABLE();
368 
369  //Select RMII interface mode
370  SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL;
371 
372  //Configure RMII pins
373  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
374  GPIO_InitStructure.Pull = GPIO_NOPULL;
375  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
376  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
377 
378  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
379  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
380  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
381 
382  //Configure ETH_RMII_TXD1 (PB13)
383  GPIO_InitStructure.Pin = GPIO_PIN_13;
384  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
385 
386  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
387  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
388  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
389 
390  //Configure RMII_TX_EN (PG11), ETH_RMII_TXD0 (PG13)
391  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13;
392  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
393 #endif
394 }
395 
396 #endif
397 
398 
399 /**
400  * @brief Initialize DMA descriptor lists
401  * @param[in] interface Underlying network interface
402  **/
403 
405 {
406  uint_t i;
407 
408  //Initialize TX DMA descriptor list
409  for(i = 0; i < STM32F7XX_ETH_TX_BUFFER_COUNT; i++)
410  {
411  //Use chain structure rather than ring structure
412  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
413  //Initialize transmit buffer size
414  txDmaDesc[i].tdes1 = 0;
415  //Transmit buffer address
416  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
417  //Next descriptor address
418  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
419  //Reserved fields
420  txDmaDesc[i].tdes4 = 0;
421  txDmaDesc[i].tdes5 = 0;
422  //Transmit frame time stamp
423  txDmaDesc[i].tdes6 = 0;
424  txDmaDesc[i].tdes7 = 0;
425  }
426 
427  //The last descriptor is chained to the first entry
428  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
429  //Point to the very first descriptor
430  txCurDmaDesc = &txDmaDesc[0];
431 
432  //Initialize RX DMA descriptor list
433  for(i = 0; i < STM32F7XX_ETH_RX_BUFFER_COUNT; i++)
434  {
435  //The descriptor is initially owned by the DMA
436  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
437  //Use chain structure rather than ring structure
439  //Receive buffer address
440  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
441  //Next descriptor address
442  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
443  //Extended status
444  rxDmaDesc[i].rdes4 = 0;
445  //Reserved field
446  rxDmaDesc[i].rdes5 = 0;
447  //Receive frame time stamp
448  rxDmaDesc[i].rdes6 = 0;
449  rxDmaDesc[i].rdes7 = 0;
450  }
451 
452  //The last descriptor is chained to the first entry
453  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
454  //Point to the very first descriptor
455  rxCurDmaDesc = &rxDmaDesc[0];
456 
457  //Start location of the TX descriptor list
458  ETH->DMATDLAR = (uint32_t) txDmaDesc;
459  //Start location of the RX descriptor list
460  ETH->DMARDLAR = (uint32_t) rxDmaDesc;
461 }
462 
463 
464 /**
465  * @brief STM32F746/756 Ethernet MAC timer handler
466  *
467  * This routine is periodically called by the TCP/IP stack to
468  * handle periodic operations such as polling the link state
469  *
470  * @param[in] interface Underlying network interface
471  **/
472 
474 {
475  //Handle periodic operations
476  interface->phyDriver->tick(interface);
477 }
478 
479 
480 /**
481  * @brief Enable interrupts
482  * @param[in] interface Underlying network interface
483  **/
484 
486 {
487  //Enable Ethernet MAC interrupts
488  NVIC_EnableIRQ(ETH_IRQn);
489  //Enable Ethernet PHY interrupts
490  interface->phyDriver->enableIrq(interface);
491 }
492 
493 
494 /**
495  * @brief Disable interrupts
496  * @param[in] interface Underlying network interface
497  **/
498 
500 {
501  //Disable Ethernet MAC interrupts
502  NVIC_DisableIRQ(ETH_IRQn);
503  //Disable Ethernet PHY interrupts
504  interface->phyDriver->disableIrq(interface);
505 }
506 
507 
508 /**
509  * @brief STM32F746/756 Ethernet MAC interrupt service routine
510  **/
511 
512 void ETH_IRQHandler(void)
513 {
514  bool_t flag;
515  uint32_t status;
516 
517  //Enter interrupt service routine
518  osEnterIsr();
519 
520  //This flag will be set if a higher priority task must be woken
521  flag = FALSE;
522 
523  //Read DMA status register
524  status = ETH->DMASR;
525 
526  //A packet has been transmitted?
527  if(status & ETH_DMASR_TS)
528  {
529  //Clear TS interrupt flag
530  ETH->DMASR = ETH_DMASR_TS;
531 
532  //Check whether the TX buffer is available for writing
533  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
534  {
535  //Notify the TCP/IP stack that the transmitter is ready to send
536  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
537  }
538  }
539 
540  //A packet has been received?
541  if(status & ETH_DMASR_RS)
542  {
543  //Disable RIE interrupt
544  ETH->DMAIER &= ~ETH_DMAIER_RIE;
545 
546  //Set event flag
547  nicDriverInterface->nicEvent = TRUE;
548  //Notify the TCP/IP stack of the event
549  flag |= osSetEventFromIsr(&netEvent);
550  }
551 
552  //Clear NIS interrupt flag
553  ETH->DMASR = ETH_DMASR_NIS;
554 
555  //Leave interrupt service routine
556  osExitIsr(flag);
557 }
558 
559 
560 /**
561  * @brief STM32F746/756 Ethernet MAC event handler
562  * @param[in] interface Underlying network interface
563  **/
564 
566 {
567  error_t error;
568 
569  //Packet received?
570  if(ETH->DMASR & ETH_DMASR_RS)
571  {
572  //Clear interrupt flag
573  ETH->DMASR = ETH_DMASR_RS;
574 
575  //Process all pending packets
576  do
577  {
578  //Read incoming packet
579  error = stm32f7xxEthReceivePacket(interface);
580 
581  //No more data in the receive buffer?
582  } while(error != ERROR_BUFFER_EMPTY);
583  }
584 
585  //Re-enable DMA interrupts
586  ETH->DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
587 }
588 
589 
590 /**
591  * @brief Send a packet
592  * @param[in] interface Underlying network interface
593  * @param[in] buffer Multi-part buffer containing the data to send
594  * @param[in] offset Offset to the first data byte
595  * @return Error code
596  **/
597 
599  const NetBuffer *buffer, size_t offset)
600 {
601  static uint8_t temp[STM32F7XX_ETH_TX_BUFFER_SIZE];
602  size_t length;
603 
604  //Retrieve the length of the packet
605  length = netBufferGetLength(buffer) - offset;
606 
607  //Check the frame length
609  {
610  //The transmitter can accept another packet
611  osSetEvent(&interface->nicTxEvent);
612  //Report an error
613  return ERROR_INVALID_LENGTH;
614  }
615 
616  //Make sure the current buffer is available for writing
617  if(txCurDmaDesc->tdes0 & ETH_TDES0_OWN)
618  return ERROR_FAILURE;
619 
620  //Copy user data to the transmit buffer
621  netBufferRead(temp, buffer, offset, length);
622  memcpy((uint8_t *) txCurDmaDesc->tdes2, temp, (length + 3) & ~3UL);
623 
624  //Write the number of bytes to send
625  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
626  //Set LS and FS flags as the data fits in a single buffer
627  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
628  //Give the ownership of the descriptor to the DMA
629  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
630 
631  //Data synchronization barrier
632  __DSB();
633 
634  //Clear TBUS flag to resume processing
635  ETH->DMASR = ETH_DMASR_TBUS;
636  //Instruct the DMA to poll the transmit descriptor list
637  ETH->DMATPDR = 0;
638 
639  //Point to the next descriptor in the list
640  txCurDmaDesc = (Stm32f7xxTxDmaDesc *) txCurDmaDesc->tdes3;
641 
642  //Check whether the next buffer is available for writing
643  if(!(txCurDmaDesc->tdes0 & ETH_TDES0_OWN))
644  {
645  //The transmitter can accept another packet
646  osSetEvent(&interface->nicTxEvent);
647  }
648 
649  //Data successfully written
650  return NO_ERROR;
651 }
652 
653 
654 /**
655  * @brief Receive a packet
656  * @param[in] interface Underlying network interface
657  * @return Error code
658  **/
659 
661 {
662  static uint8_t temp[STM32F7XX_ETH_RX_BUFFER_SIZE];
663  error_t error;
664  size_t n;
665 
666  //The current buffer is available for reading?
667  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_OWN))
668  {
669  //FS and LS flags should be set
670  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) && (rxCurDmaDesc->rdes0 & ETH_RDES0_LS))
671  {
672  //Make sure no error occurred
673  if(!(rxCurDmaDesc->rdes0 & ETH_RDES0_ES))
674  {
675  //Retrieve the length of the frame
676  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
677  //Limit the number of data to read
679 
680  //Copy data from the receive buffer
681  memcpy(temp, (uint8_t *) rxCurDmaDesc->rdes2, (n + 3) & ~3UL);
682 
683  //Pass the packet to the upper layer
684  nicProcessPacket(interface, temp, n);
685 
686  //Valid packet received
687  error = NO_ERROR;
688  }
689  else
690  {
691  //The received packet contains an error
692  error = ERROR_INVALID_PACKET;
693  }
694  }
695  else
696  {
697  //The packet is not valid
698  error = ERROR_INVALID_PACKET;
699  }
700 
701  //Give the ownership of the descriptor back to the DMA
702  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
703  //Point to the next descriptor in the list
704  rxCurDmaDesc = (Stm32f7xxRxDmaDesc *) rxCurDmaDesc->rdes3;
705  }
706  else
707  {
708  //No more data in the receive buffer
709  error = ERROR_BUFFER_EMPTY;
710  }
711 
712  //Clear RBUS flag to resume processing
713  ETH->DMASR = ETH_DMASR_RBUS;
714  //Instruct the DMA to poll the receive descriptor list
715  ETH->DMARPDR = 0;
716 
717  //Return status code
718  return error;
719 }
720 
721 
722 /**
723  * @brief Configure MAC address filtering
724  * @param[in] interface Underlying network interface
725  * @return Error code
726  **/
727 
729 {
730  uint_t i;
731  uint_t k;
732  uint32_t crc;
733  uint32_t hashTable[2];
734  MacFilterEntry *entry;
735 
736  //Debug message
737  TRACE_DEBUG("Updating STM32F7xx hash table...\r\n");
738 
739  //Clear hash table
740  hashTable[0] = 0;
741  hashTable[1] = 0;
742 
743  //The MAC address filter contains the list of MAC addresses to accept
744  //when receiving an Ethernet frame
745  for(i = 0; i < MAC_ADDR_FILTER_SIZE; i++)
746  {
747  //Point to the current entry
748  entry = &interface->macAddrFilter[i];
749 
750  //Valid entry?
751  if(entry->refCount > 0)
752  {
753  //Compute CRC over the current MAC address
754  crc = stm32f7xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
755 
756  //The upper 6 bits in the CRC register are used to index the
757  //contents of the hash table
758  k = (crc >> 26) & 0x3F;
759 
760  //Update hash table contents
761  hashTable[k / 32] |= (1 << (k % 32));
762  }
763  }
764 
765  //Write the hash table
766  ETH->MACHTLR = hashTable[0];
767  ETH->MACHTHR = hashTable[1];
768 
769  //Debug message
770  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
771  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
772 
773  //Successful processing
774  return NO_ERROR;
775 }
776 
777 
778 /**
779  * @brief Adjust MAC configuration parameters for proper operation
780  * @param[in] interface Underlying network interface
781  * @return Error code
782  **/
783 
785 {
786  uint32_t config;
787 
788  //Read current MAC configuration
789  config = ETH->MACCR;
790 
791  //10BASE-T or 100BASE-TX operation mode?
792  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
793  config |= ETH_MACCR_FES;
794  else
795  config &= ~ETH_MACCR_FES;
796 
797  //Half-duplex or full-duplex mode?
798  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
799  config |= ETH_MACCR_DM;
800  else
801  config &= ~ETH_MACCR_DM;
802 
803  //Update MAC configuration register
804  ETH->MACCR = config;
805 
806  //Successful processing
807  return NO_ERROR;
808 }
809 
810 
811 /**
812  * @brief Write PHY register
813  * @param[in] phyAddr PHY address
814  * @param[in] regAddr Register address
815  * @param[in] data Register value
816  **/
817 
818 void stm32f7xxEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
819 {
820 #if defined(STM32F7XX_ETH_MDC_PIN) && defined(STM32F7XX_ETH_MDIO_PIN)
821  //Synchronization pattern
823  //Start of frame
825  //Set up a write operation
827  //Write PHY address
828  stm32f7xxEthWriteSmi(phyAddr, 5);
829  //Write register address
831  //Turnaround
833  //Write register value
835  //Release MDIO
837 #else
838  uint32_t temp;
839 
840  //Take care not to alter MDC clock configuration
841  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
842  //Set up a write operation
843  temp |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
844  //PHY address
845  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
846  //Register address
847  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
848 
849  //Data to be written in the PHY register
850  ETH->MACMIIDR = data & ETH_MACMIIDR_MD;
851 
852  //Start a write operation
853  ETH->MACMIIAR = temp;
854  //Wait for the write to complete
855  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
856 #endif
857 }
858 
859 
860 /**
861  * @brief Read PHY register
862  * @param[in] phyAddr PHY address
863  * @param[in] regAddr Register address
864  * @return Register value
865  **/
866 
867 uint16_t stm32f7xxEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
868 {
869 #if defined(STM32F7XX_ETH_MDC_PIN) && defined(STM32F7XX_ETH_MDIO_PIN)
870  uint16_t data;
871 
872  //Synchronization pattern
874  //Start of frame
876  //Set up a read operation
878  //Write PHY address
879  stm32f7xxEthWriteSmi(phyAddr, 5);
880  //Write register address
882  //Turnaround to avoid contention
884  //Read register value
886  //Force the PHY to release the MDIO pin
888 #else
889  uint16_t data;
890  uint32_t temp;
891 
892  //Take care not to alter MDC clock configuration
893  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
894  //Set up a read operation
895  temp |= ETH_MACMIIAR_MB;
896  //PHY address
897  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
898  //Register address
899  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
900 
901  //Start a read operation
902  ETH->MACMIIAR = temp;
903  //Wait for the read to complete
904  while(ETH->MACMIIAR & ETH_MACMIIAR_MB);
905 
906  //Read register value
907  data = ETH->MACMIIDR & ETH_MACMIIDR_MD;
908 #endif
909 
910  //Return PHY register contents
911  return data;
912 }
913 
914 
915 /**
916  * @brief SMI write operation
917  * @param[in] data Raw data to be written
918  * @param[in] length Number of bits to be written
919  **/
920 
922 {
923 #if defined(STM32F7XX_ETH_MDC_PIN) && defined(STM32F7XX_ETH_MDIO_PIN)
924  GPIO_InitTypeDef GPIO_InitStructure;
925 
926  //Skip the most significant bits since they are meaningless
927  data <<= 32 - length;
928 
929  //Configure MDIO as an output
930  GPIO_InitStructure.Pin = STM32F7XX_ETH_MDIO_PIN;
931  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
932  GPIO_InitStructure.Pull = GPIO_NOPULL;
933  GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
934  HAL_GPIO_Init(STM32F7XX_ETH_MDIO_GPIO, &GPIO_InitStructure);
935 
936  //Write the specified number of bits
937  while(length--)
938  {
939  //Write MDIO
940  if(data & 0x80000000)
941  {
942  HAL_GPIO_WritePin(STM32F7XX_ETH_MDIO_GPIO,
943  STM32F7XX_ETH_MDIO_PIN, GPIO_PIN_SET);
944  }
945  else
946  {
947  HAL_GPIO_WritePin(STM32F7XX_ETH_MDIO_GPIO,
948  STM32F7XX_ETH_MDIO_PIN, GPIO_PIN_RESET);
949  }
950 
951  //Delay
952  usleep(1);
953 
954  //Assert MDC
955  HAL_GPIO_WritePin(STM32F7XX_ETH_MDC_GPIO,
956  STM32F7XX_ETH_MDC_PIN, GPIO_PIN_SET);
957 
958  //Delay
959  usleep(1);
960 
961  //Deassert MDC
962  HAL_GPIO_WritePin(STM32F7XX_ETH_MDC_GPIO,
963  STM32F7XX_ETH_MDC_PIN, GPIO_PIN_RESET);
964 
965  //Rotate data
966  data <<= 1;
967  }
968 #endif
969 }
970 
971 
972 /**
973  * @brief SMI read operation
974  * @param[in] length Number of bits to be read
975  * @return Data resulting from the MDIO read operation
976  **/
977 
979 {
980  uint32_t data = 0;
981 
982 #if defined(STM32F7XX_ETH_MDC_PIN) && defined(STM32F7XX_ETH_MDIO_PIN)
983  GPIO_InitTypeDef GPIO_InitStructure;
984 
985  //Configure MDIO as an input
986  GPIO_InitStructure.Pin = STM32F7XX_ETH_MDIO_PIN;
987  GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
988  GPIO_InitStructure.Pull = GPIO_PULLUP;
989  GPIO_InitStructure.Speed = GPIO_SPEED_MEDIUM;
990  HAL_GPIO_Init(STM32F7XX_ETH_MDIO_GPIO, &GPIO_InitStructure);
991 
992  //Read the specified number of bits
993  while(length--)
994  {
995  //Rotate data
996  data <<= 1;
997 
998  //Assert MDC
999  HAL_GPIO_WritePin(STM32F7XX_ETH_MDC_GPIO,
1000  STM32F7XX_ETH_MDC_PIN, GPIO_PIN_SET);
1001 
1002  //Delay
1003  usleep(1);
1004 
1005  //Deassert MDC
1006  HAL_GPIO_WritePin(STM32F7XX_ETH_MDC_GPIO,
1007  STM32F7XX_ETH_MDC_PIN, GPIO_PIN_RESET);
1008 
1009  //Delay
1010  usleep(1);
1011 
1012  //Check MDIO state
1013  if(HAL_GPIO_ReadPin(STM32F7XX_ETH_MDIO_GPIO, STM32F7XX_ETH_MDIO_PIN))
1014  data |= 0x00000001;
1015  }
1016 #endif
1017 
1018  //Return the received data
1019  return data;
1020 }
1021 
1022 
1023 /**
1024  * @brief CRC calculation
1025  * @param[in] data Pointer to the data over which to calculate the CRC
1026  * @param[in] length Number of bytes to process
1027  * @return Resulting CRC value
1028  **/
1029 
1030 uint32_t stm32f7xxEthCalcCrc(const void *data, size_t length)
1031 {
1032  uint_t i;
1033  uint_t j;
1034 
1035  //Point to the data over which to calculate the CRC
1036  const uint8_t *p = (uint8_t *) data;
1037  //CRC preset value
1038  uint32_t crc = 0xFFFFFFFF;
1039 
1040  //Loop through data
1041  for(i = 0; i < length; i++)
1042  {
1043  //The message is processed bit by bit
1044  for(j = 0; j < 8; j++)
1045  {
1046  //Update CRC value
1047  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
1048  crc = (crc << 1) ^ 0x04C11DB7;
1049  else
1050  crc = crc << 1;
1051  }
1052  }
1053 
1054  //Return CRC value
1055  return ~crc;
1056 }
#define txDmaDesc
MacAddr addr
MAC address.
Definition: ethernet.h:210
STM32F746/756 Ethernet MAC controller.
#define STM32F7XX_ETH_TX_BUFFER_COUNT
#define STM32F7XX_ETH_TX_BUFFER_SIZE
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
error_t stm32f7xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define ETH_RDES0_OWN
void stm32f7xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
void stm32f7xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define ETH_RDES0_FL
uint16_t stm32f7xxEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
Enhanced TX DMA descriptor.
#define TRUE
Definition: os_port.h:48
void stm32f7xxEthInitGpio(NetInterface *interface)
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:65
error_t stm32f7xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define STM32F7XX_ETH_IRQ_PRIORITY_GROUPING
void ETH_IRQHandler(void)
STM32F746/756 Ethernet MAC interrupt service routine.
#define STM32F7XX_ETH_RX_BUFFER_SIZE
void stm32f7xxEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t stm32f7xxEthInit(NetInterface *interface)
STM32F746/756 Ethernet MAC initialization.
#define ETH_TDES0_IC
uint32_t stm32f7xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
#define SMI_START
const NicDriver stm32f7xxEthDriver
STM32F746/756 Ethernet MAC driver.
#define ETH_TDES0_OWN
#define SMI_SYNC
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
Enhanced RX DMA descriptor.
#define usleep(delay)
Definition: os_port.h:122
NIC driver.
Definition: nic.h:161
#define ETH_TDES0_FS
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:86
#define MIN(a, b)
Definition: os_port.h:60
void stm32f7xxEthTick(NetInterface *interface)
STM32F746/756 Ethernet MAC timer handler.
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define ETH_TDES0_LS
#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.
void stm32f7xxEthWriteSmi(uint32_t data, uint_t length)
SMI write operation.
error_t
Error codes.
Definition: error.h:40
unsigned int uint_t
Definition: compiler_port.h:43
__start_packed struct @112 MacAddr
MAC address.
uint8_t data[]
Definition: dtls_misc.h:167
#define NetInterface
Definition: net.h:34
#define ETH_RDES1_RCH
uint32_t stm32f7xxEthReadSmi(uint_t length)
SMI read operation.
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
#define SMI_TA
#define SMI_READ
#define SMI_WRITE
error_t stm32f7xxEthReceivePacket(NetInterface *interface)
Receive a packet.
#define osExitIsr(flag)
#define ETH_TDES0_TCH
#define ETH_TDES1_TBS1
#define STM32F7XX_ETH_IRQ_GROUP_PRIORITY
void stm32f7xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
void stm32f7xxEthEventHandler(NetInterface *interface)
STM32F746/756 Ethernet MAC event handler.
#define osEnterIsr()
#define STM32F7XX_ETH_RX_BUFFER_COUNT
#define ETH_RDES1_RBS1
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define FALSE
Definition: os_port.h:44
error_t stm32f7xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
int bool_t
Definition: compiler_port.h:47
#define ETH_RDES0_FS
MAC filter table entry.
Definition: ethernet.h:208
#define ETH_RDES0_ES
#define TRACE_DEBUG(...)
Definition: debug.h:98
#define STM32F7XX_ETH_IRQ_SUB_PRIORITY