stm32f1xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32f1xx_eth_driver.c
3  * @brief STM32F1 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #ifdef USE_STDPERIPH_DRIVER
36  #include "stm32f10x.h"
37 #else
38  #include "stm32f1xx.h"
39  #include "stm32f1xx_hal.h"
40 #endif
41 
42 #include "core/net.h"
44 #include "debug.h"
45 
46 //Underlying network interface
47 static NetInterface *nicDriverInterface;
48 
49 //IAR EWARM compiler?
50 #if defined(__ICCARM__)
51 
52 //Transmit buffer
53 #pragma data_alignment = 4
55 //Receive buffer
56 #pragma data_alignment = 4
58 //Transmit DMA descriptors
59 #pragma data_alignment = 4
61 //Receive DMA descriptors
62 #pragma data_alignment = 4
64 
65 //Keil MDK-ARM or GCC compiler?
66 #else
67 
68 //Transmit buffer
70  __attribute__((aligned(4)));
71 //Receive buffer
73  __attribute__((aligned(4)));
74 //Transmit DMA descriptors
76  __attribute__((aligned(4)));
77 //Receive DMA descriptors
79  __attribute__((aligned(4)));
80 
81 #endif
82 
83 //Pointer to the current TX DMA descriptor
84 static Stm32f1xxTxDmaDesc *txCurDmaDesc;
85 //Pointer to the current RX DMA descriptor
86 static Stm32f1xxRxDmaDesc *rxCurDmaDesc;
87 
88 
89 /**
90  * @brief STM32F1 Ethernet MAC driver
91  **/
92 
94 {
96  ETH_MTU,
107  TRUE,
108  TRUE,
109  TRUE,
110  FALSE
111 };
112 
113 
114 /**
115  * @brief STM32F1 Ethernet MAC initialization
116  * @param[in] interface Underlying network interface
117  * @return Error code
118  **/
119 
121 {
122  error_t error;
123 
124  //Debug message
125  TRACE_INFO("Initializing STM32F1 Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //GPIO configuration
131  stm32f1xxEthInitGpio(interface);
132 
133 #ifdef USE_STDPERIPH_DRIVER
134  //Enable Ethernet MAC clock
135  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC |
136  RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
137 
138  //Reset Ethernet MAC peripheral
139  RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, ENABLE);
140  RCC_AHBPeriphResetCmd(RCC_AHBPeriph_ETH_MAC, DISABLE);
141 #else
142  //Enable Ethernet MAC clock
143  __HAL_RCC_ETHMAC_CLK_ENABLE();
144  __HAL_RCC_ETHMACTX_CLK_ENABLE();
145  __HAL_RCC_ETHMACRX_CLK_ENABLE();
146 
147  //Reset Ethernet MAC peripheral
148  __HAL_RCC_ETHMAC_FORCE_RESET();
149  __HAL_RCC_ETHMAC_RELEASE_RESET();
150 #endif
151 
152  //Perform a software reset
153  ETH->DMABMR |= ETH_DMABMR_SR;
154  //Wait for the reset to complete
155  while((ETH->DMABMR & ETH_DMABMR_SR) != 0)
156  {
157  }
158 
159  //Adjust MDC clock range depending on HCLK frequency
160  ETH->MACMIIAR = ETH_MACMIIAR_CR_DIV42;
161 
162  //Valid Ethernet PHY or switch driver?
163  if(interface->phyDriver != NULL)
164  {
165  //Ethernet PHY initialization
166  error = interface->phyDriver->init(interface);
167  }
168  else if(interface->switchDriver != NULL)
169  {
170  //Ethernet switch initialization
171  error = interface->switchDriver->init(interface);
172  }
173  else
174  {
175  //The interface is not properly configured
176  error = ERROR_FAILURE;
177  }
178 
179  //Any error to report?
180  if(error)
181  {
182  return error;
183  }
184 
185  //Use default MAC configuration
186  ETH->MACCR = ETH_MACCR_RESERVED15 | ETH_MACCR_ROD;
187 
188  //Configure MAC address filtering
190 
191  //Disable flow control
192  ETH->MACFCR = 0;
193  //Enable store and forward mode
194  ETH->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF;
195 
196  //Configure DMA bus mode
197  ETH->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_RDP_32Beat |
198  ETH_DMABMR_RTPR_1_1 | ETH_DMABMR_PBL_32Beat;
199 
200  //Initialize DMA descriptor lists
201  stm32f1xxEthInitDmaDesc(interface);
202 
203  //Prevent interrupts from being generated when the transmit statistic
204  //counters reach half their maximum value
205  ETH->MMCTIMR = ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM;
206 
207  //Prevent interrupts from being generated when the receive statistic
208  //counters reach half their maximum value
209  ETH->MMCRIMR = ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM;
210 
211  //Disable MAC interrupts
212  ETH->MACIMR = ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM;
213  //Enable the desired DMA interrupts
214  ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
215 
216  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
217  NVIC_SetPriorityGrouping(STM32F1XX_ETH_IRQ_PRIORITY_GROUPING);
218 
219  //Configure Ethernet interrupt priority
220  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32F1XX_ETH_IRQ_PRIORITY_GROUPING,
222 
223  //Enable MAC transmission and reception
224  ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
225  //Enable DMA transmission and reception
226  ETH->DMAOMR |= ETH_DMAOMR_ST | ETH_DMAOMR_SR;
227 
228  //Accept any packets from the upper layer
229  osSetEvent(&interface->nicTxEvent);
230 
231  //Successful initialization
232  return NO_ERROR;
233 }
234 
235 
236 /**
237  * @brief GPIO configuration
238  * @param[in] interface Underlying network interface
239  **/
240 
241 __weak_func void stm32f1xxEthInitGpio(NetInterface *interface)
242 {
243 //STM3210C-EVAL evaluation board?
244 #if defined(USE_STM3210C_EVAL)
245  GPIO_InitTypeDef GPIO_InitStructure;
246 
247  //Enable AFIO clock
248  __HAL_RCC_AFIO_CLK_ENABLE();
249 
250  //Enable GPIO clocks
251  __HAL_RCC_GPIOA_CLK_ENABLE();
252  __HAL_RCC_GPIOB_CLK_ENABLE();
253  __HAL_RCC_GPIOC_CLK_ENABLE();
254  __HAL_RCC_GPIOD_CLK_ENABLE();
255 
256  //Configure MCO (PA8) as an output
257  GPIO_InitStructure.Pin = GPIO_PIN_8;
258  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
259  GPIO_InitStructure.Pull = GPIO_NOPULL;
260  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
261  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
262 
263  //Configure MCO pin to output the HSE clock (25MHz)
264  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, 1);
265 
266  //Select MII interface mode
267  __HAL_AFIO_ETH_MII();
268 
269  //Configure MII_MDIO (PA2)
270  GPIO_InitStructure.Pin = GPIO_PIN_2;
271  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
272  GPIO_InitStructure.Pull = GPIO_NOPULL;
273  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
274  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
275 
276  //Configure ETH_MII_TXD3 (PB8), MII_TX_EN (PB11), MII_TXD0 (PB12)
277  //and MII_TXD1 (PB13)
278  GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
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(GPIOB, &GPIO_InitStructure);
283 
284  //Configure MII_MDC (PC1) and MII_TXD2 (PC2)
285  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2;
286  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
287  GPIO_InitStructure.Pull = GPIO_NOPULL;
288  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
289  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
290 
291  //Configure ETH_MII_CRS (PA0), ETH_MII_RX_CLK (PA1) and ETH_MII_COL (PA3)
292  GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3;
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(GPIOA, &GPIO_InitStructure);
297 
298  //Configure ETH_MII_RX_ER (PB10)
299  GPIO_InitStructure.Pin = GPIO_PIN_10;
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(GPIOB, &GPIO_InitStructure);
304 
305  //Configure ETH_MII_TX_CLK (PC3)
306  GPIO_InitStructure.Pin = GPIO_PIN_3;
307  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
308  GPIO_InitStructure.Pull = GPIO_NOPULL;
309  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
310  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
311 
312  //Configure ETH_MII_RX_DV (PD8), ETH_MII_RXD0 (PD9), ETH_MII_RXD1 (PD10),
313  //ETH_MII_RXD2 (PD11) and ETH_MII_RXD3 (PD12)
314  GPIO_InitStructure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
315  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
316  GPIO_InitStructure.Pull = GPIO_NOPULL;
317  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
318  HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
319 
320  //Remap Ethernet pins
321  __HAL_AFIO_REMAP_ETH_ENABLE();
322 
323 //STM32-P107 evaluation board?
324 #elif defined(USE_STM32_P107)
325  uint32_t temp;
326  GPIO_InitTypeDef GPIO_InitStructure;
327 
328  //Enable AFIO clock
329  __HAL_RCC_AFIO_CLK_ENABLE();
330 
331  //Enable GPIO clocks
332  __HAL_RCC_GPIOA_CLK_ENABLE();
333  __HAL_RCC_GPIOB_CLK_ENABLE();
334  __HAL_RCC_GPIOC_CLK_ENABLE();
335  __HAL_RCC_GPIOD_CLK_ENABLE();
336 
337  //Configure MCO (PA8) as an output
338  GPIO_InitStructure.Pin = GPIO_PIN_8;
339  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
340  GPIO_InitStructure.Pull = GPIO_NOPULL;
341  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
342  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
343 
344  //Configure PLL3 to output a 50MHz clock
345  temp = RCC->CFGR2 & ~RCC_CFGR2_PLL3MUL;
346  RCC->CFGR2 = temp | RCC_CFGR2_PLL3MUL10;
347 
348  //Enable PLL3
349  RCC->CR |= RCC_CR_PLL3ON;
350 
351  //Wait for the PLL3 to lock
352  while((RCC->CR & RCC_CR_PLL3RDY) == 0)
353  {
354  }
355 
356  //Configure MCO pin to output the PLL3 clock
357  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLL3CLK, 1);
358 
359  //Select RMII interface mode
360  __HAL_AFIO_ETH_RMII();
361 
362  //Configure MII_MDIO (PA2)
363  GPIO_InitStructure.Pin = GPIO_PIN_2;
364  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
365  GPIO_InitStructure.Pull = GPIO_NOPULL;
366  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
367  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
368 
369  //Configure ETH_RMII_TX_EN (PB11), ETH_RMII_TXD0 (PB12) and ETH_RMII_TXD1 (PB13)
370  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
371  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
372  GPIO_InitStructure.Pull = GPIO_NOPULL;
373  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
374  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
375 
376  //Configure ETH_MDC (PC1)
377  GPIO_InitStructure.Pin = GPIO_PIN_1;
378  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
379  GPIO_InitStructure.Pull = GPIO_NOPULL;
380  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
381  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
382 
383  //Configure ETH_RMII_REF_CLK (PA1) and ETH_RMII_CRS_DV (PA7)
384  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_7;
385  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
386  GPIO_InitStructure.Pull = GPIO_NOPULL;
387  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
388  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
389 
390  //Configure ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
391  GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5;
392  GPIO_InitStructure.Mode = GPIO_MODE_AF_INPUT;
393  GPIO_InitStructure.Pull = GPIO_NOPULL;
394  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
395  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
396 
397  //Do not remap Ethernet pins
398  __HAL_AFIO_REMAP_ETH_DISABLE();
399 #endif
400 }
401 
402 
403 /**
404  * @brief Initialize DMA descriptor lists
405  * @param[in] interface Underlying network interface
406  **/
407 
409 {
410  uint_t i;
411 
412  //Initialize TX DMA descriptor list
413  for(i = 0; i < STM32F1XX_ETH_TX_BUFFER_COUNT; i++)
414  {
415  //Use chain structure rather than ring structure
416  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
417  //Initialize transmit buffer size
418  txDmaDesc[i].tdes1 = 0;
419  //Transmit buffer address
420  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
421  //Next descriptor address
422  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
423  }
424 
425  //The last descriptor is chained to the first entry
426  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
427  //Point to the very first descriptor
428  txCurDmaDesc = &txDmaDesc[0];
429 
430  //Initialize RX DMA descriptor list
431  for(i = 0; i < STM32F1XX_ETH_RX_BUFFER_COUNT; i++)
432  {
433  //The descriptor is initially owned by the DMA
434  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
435  //Use chain structure rather than ring structure
437  //Receive buffer address
438  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
439  //Next descriptor address
440  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
441  }
442 
443  //The last descriptor is chained to the first entry
444  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
445  //Point to the very first descriptor
446  rxCurDmaDesc = &rxDmaDesc[0];
447 
448  //Start location of the TX descriptor list
449  ETH->DMATDLAR = (uint32_t) txDmaDesc;
450  //Start location of the RX descriptor list
451  ETH->DMARDLAR = (uint32_t) rxDmaDesc;
452 }
453 
454 
455 /**
456  * @brief STM32F1 Ethernet MAC timer handler
457  *
458  * This routine is periodically called by the TCP/IP stack to handle periodic
459  * operations such as polling the link state
460  *
461  * @param[in] interface Underlying network interface
462  **/
463 
465 {
466  //Valid Ethernet PHY or switch driver?
467  if(interface->phyDriver != NULL)
468  {
469  //Handle periodic operations
470  interface->phyDriver->tick(interface);
471  }
472  else if(interface->switchDriver != NULL)
473  {
474  //Handle periodic operations
475  interface->switchDriver->tick(interface);
476  }
477  else
478  {
479  //Just for sanity
480  }
481 }
482 
483 
484 /**
485  * @brief Enable interrupts
486  * @param[in] interface Underlying network interface
487  **/
488 
490 {
491  //Enable Ethernet MAC interrupts
492  NVIC_EnableIRQ(ETH_IRQn);
493 
494  //Valid Ethernet PHY or switch driver?
495  if(interface->phyDriver != NULL)
496  {
497  //Enable Ethernet PHY interrupts
498  interface->phyDriver->enableIrq(interface);
499  }
500  else if(interface->switchDriver != NULL)
501  {
502  //Enable Ethernet switch interrupts
503  interface->switchDriver->enableIrq(interface);
504  }
505  else
506  {
507  //Just for sanity
508  }
509 }
510 
511 
512 /**
513  * @brief Disable interrupts
514  * @param[in] interface Underlying network interface
515  **/
516 
518 {
519  //Disable Ethernet MAC interrupts
520  NVIC_DisableIRQ(ETH_IRQn);
521 
522  //Valid Ethernet PHY or switch driver?
523  if(interface->phyDriver != NULL)
524  {
525  //Disable Ethernet PHY interrupts
526  interface->phyDriver->disableIrq(interface);
527  }
528  else if(interface->switchDriver != NULL)
529  {
530  //Disable Ethernet switch interrupts
531  interface->switchDriver->disableIrq(interface);
532  }
533  else
534  {
535  //Just for sanity
536  }
537 }
538 
539 
540 /**
541  * @brief STM32F1 Ethernet MAC interrupt service routine
542  **/
543 
544 void ETH_IRQHandler(void)
545 {
546  bool_t flag;
547  uint32_t status;
548 
549  //Interrupt service routine prologue
550  osEnterIsr();
551 
552  //This flag will be set if a higher priority task must be woken
553  flag = FALSE;
554 
555  //Read DMA status register
556  status = ETH->DMASR;
557 
558  //Packet transmitted?
559  if((status & ETH_DMASR_TS) != 0)
560  {
561  //Clear TS interrupt flag
562  ETH->DMASR = ETH_DMASR_TS;
563 
564  //Check whether the TX buffer is available for writing
565  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
566  {
567  //Notify the TCP/IP stack that the transmitter is ready to send
568  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
569  }
570  }
571 
572  //Packet received?
573  if((status & ETH_DMASR_RS) != 0)
574  {
575  //Clear RS interrupt flag
576  ETH->DMASR = ETH_DMASR_RS;
577 
578  //Set event flag
579  nicDriverInterface->nicEvent = TRUE;
580  //Notify the TCP/IP stack of the event
581  flag |= osSetEventFromIsr(&netEvent);
582  }
583 
584  //Clear NIS interrupt flag
585  ETH->DMASR = ETH_DMASR_NIS;
586 
587  //Interrupt service routine epilogue
588  osExitIsr(flag);
589 }
590 
591 
592 /**
593  * @brief STM32F1 Ethernet MAC event handler
594  * @param[in] interface Underlying network interface
595  **/
596 
598 {
599  error_t error;
600 
601  //Process all pending packets
602  do
603  {
604  //Read incoming packet
605  error = stm32f1xxEthReceivePacket(interface);
606 
607  //No more data in the receive buffer?
608  } while(error != ERROR_BUFFER_EMPTY);
609 }
610 
611 
612 /**
613  * @brief Send a packet
614  * @param[in] interface Underlying network interface
615  * @param[in] buffer Multi-part buffer containing the data to send
616  * @param[in] offset Offset to the first data byte
617  * @param[in] ancillary Additional options passed to the stack along with
618  * the packet
619  * @return Error code
620  **/
621 
623  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
624 {
625  size_t length;
626 
627  //Retrieve the length of the packet
628  length = netBufferGetLength(buffer) - offset;
629 
630  //Check the frame length
632  {
633  //The transmitter can accept another packet
634  osSetEvent(&interface->nicTxEvent);
635  //Report an error
636  return ERROR_INVALID_LENGTH;
637  }
638 
639  //Make sure the current buffer is available for writing
640  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
641  {
642  return ERROR_FAILURE;
643  }
644 
645  //Copy user data to the transmit buffer
646  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
647 
648  //Write the number of bytes to send
649  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
650  //Set LS and FS flags as the data fits in a single buffer
651  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
652  //Give the ownership of the descriptor to the DMA
653  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
654 
655  //Clear TBUS flag to resume processing
656  ETH->DMASR = ETH_DMASR_TBUS;
657  //Instruct the DMA to poll the transmit descriptor list
658  ETH->DMATPDR = 0;
659 
660  //Point to the next descriptor in the list
661  txCurDmaDesc = (Stm32f1xxTxDmaDesc *) txCurDmaDesc->tdes3;
662 
663  //Check whether the next buffer is available for writing
664  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
665  {
666  //The transmitter can accept another packet
667  osSetEvent(&interface->nicTxEvent);
668  }
669 
670  //Data successfully written
671  return NO_ERROR;
672 }
673 
674 
675 /**
676  * @brief Receive a packet
677  * @param[in] interface Underlying network interface
678  * @return Error code
679  **/
680 
682 {
683  error_t error;
684  size_t n;
685  NetRxAncillary ancillary;
686 
687  //Current buffer available for reading?
688  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
689  {
690  //FS and LS flags should be set
691  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
692  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
693  {
694  //Make sure no error occurred
695  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
696  {
697  //Retrieve the length of the frame
698  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
699  //Limit the number of data to read
701 
702  //Additional options can be passed to the stack along with the packet
703  ancillary = NET_DEFAULT_RX_ANCILLARY;
704 
705  //Pass the packet to the upper layer
706  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
707  &ancillary);
708 
709  //Valid packet received
710  error = NO_ERROR;
711  }
712  else
713  {
714  //The received packet contains an error
715  error = ERROR_INVALID_PACKET;
716  }
717  }
718  else
719  {
720  //The packet is not valid
721  error = ERROR_INVALID_PACKET;
722  }
723 
724  //Give the ownership of the descriptor back to the DMA
725  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
726  //Point to the next descriptor in the list
727  rxCurDmaDesc = (Stm32f1xxRxDmaDesc *) rxCurDmaDesc->rdes3;
728  }
729  else
730  {
731  //No more data in the receive buffer
732  error = ERROR_BUFFER_EMPTY;
733  }
734 
735  //Clear RBUS flag to resume processing
736  ETH->DMASR = ETH_DMASR_RBUS;
737  //Instruct the DMA to poll the receive descriptor list
738  ETH->DMARPDR = 0;
739 
740  //Return status code
741  return error;
742 }
743 
744 
745 /**
746  * @brief Configure MAC address filtering
747  * @param[in] interface Underlying network interface
748  * @return Error code
749  **/
750 
752 {
753  uint_t i;
754  uint_t j;
755  uint_t k;
756  uint32_t crc;
757  uint32_t hashTable[2];
758  MacAddr unicastMacAddr[3];
759  MacFilterEntry *entry;
760 
761  //Debug message
762  TRACE_DEBUG("Updating MAC filter...\r\n");
763 
764  //Promiscuous mode?
765  if(interface->promiscuous)
766  {
767  //Pass all incoming frames regardless of their destination address
768  ETH->MACFFR = ETH_MACFFR_PM;
769  }
770  else
771  {
772  //Set the MAC address of the station
773  ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
774  ETH->MACA0HR = interface->macAddr.w[2];
775 
776  //The MAC supports 3 additional addresses for unicast perfect filtering
777  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
778  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
779  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
780 
781  //The hash table is used for multicast address filtering
782  hashTable[0] = 0;
783  hashTable[1] = 0;
784 
785  //The MAC address filter contains the list of MAC addresses to accept
786  //when receiving an Ethernet frame
787  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
788  {
789  //Point to the current entry
790  entry = &interface->macAddrFilter[i];
791 
792  //Valid entry?
793  if(entry->refCount > 0)
794  {
795  //Multicast address?
796  if(macIsMulticastAddr(&entry->addr))
797  {
798  //Compute CRC over the current MAC address
799  crc = stm32f1xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
800 
801  //The upper 6 bits in the CRC register are used to index the
802  //contents of the hash table
803  k = (crc >> 26) & 0x3F;
804 
805  //Update hash table contents
806  hashTable[k / 32] |= (1 << (k % 32));
807  }
808  else
809  {
810  //Up to 3 additional MAC addresses can be specified
811  if(j < 3)
812  {
813  //Save the unicast address
814  unicastMacAddr[j++] = entry->addr;
815  }
816  }
817  }
818  }
819 
820  //Configure the first unicast address filter
821  if(j >= 1)
822  {
823  //When the AE bit is set, the entry is used for perfect filtering
824  ETH->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
825  ETH->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACA1HR_AE;
826  }
827  else
828  {
829  //When the AE bit is cleared, the entry is ignored
830  ETH->MACA1LR = 0;
831  ETH->MACA1HR = 0;
832  }
833 
834  //Configure the second unicast address filter
835  if(j >= 2)
836  {
837  //When the AE bit is set, the entry is used for perfect filtering
838  ETH->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
839  ETH->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACA2HR_AE;
840  }
841  else
842  {
843  //When the AE bit is cleared, the entry is ignored
844  ETH->MACA2LR = 0;
845  ETH->MACA2HR = 0;
846  }
847 
848  //Configure the third unicast address filter
849  if(j >= 3)
850  {
851  //When the AE bit is set, the entry is used for perfect filtering
852  ETH->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
853  ETH->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACA3HR_AE;
854  }
855  else
856  {
857  //When the AE bit is cleared, the entry is ignored
858  ETH->MACA3LR = 0;
859  ETH->MACA3HR = 0;
860  }
861 
862  //Check whether frames with a multicast destination address should be
863  //accepted
864  if(interface->acceptAllMulticast)
865  {
866  //Configure the receive filter
867  ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_PAM;
868  }
869  else
870  {
871  //Configure the receive filter
872  ETH->MACFFR = ETH_MACFFR_HPF | ETH_MACFFR_HM;
873 
874  //Configure the multicast hash table
875  ETH->MACHTLR = hashTable[0];
876  ETH->MACHTHR = hashTable[1];
877 
878  //Debug message
879  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
880  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
881  }
882  }
883 
884  //Successful processing
885  return NO_ERROR;
886 }
887 
888 
889 /**
890  * @brief Adjust MAC configuration parameters for proper operation
891  * @param[in] interface Underlying network interface
892  * @return Error code
893  **/
894 
896 {
897  uint32_t config;
898 
899  //Read current MAC configuration
900  config = ETH->MACCR;
901 
902  //10BASE-T or 100BASE-TX operation mode?
903  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
904  {
905  config |= ETH_MACCR_FES;
906  }
907  else
908  {
909  config &= ~ETH_MACCR_FES;
910  }
911 
912  //Half-duplex or full-duplex mode?
913  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
914  {
915  config |= ETH_MACCR_DM;
916  }
917  else
918  {
919  config &= ~ETH_MACCR_DM;
920  }
921 
922  //Update MAC configuration register
923  ETH->MACCR = config;
924 
925  //Successful processing
926  return NO_ERROR;
927 }
928 
929 
930 /**
931  * @brief Write PHY register
932  * @param[in] opcode Access type (2 bits)
933  * @param[in] phyAddr PHY address (5 bits)
934  * @param[in] regAddr Register address (5 bits)
935  * @param[in] data Register value
936  **/
937 
938 void stm32f1xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
939  uint8_t regAddr, uint16_t data)
940 {
941  uint32_t temp;
942 
943  //Valid opcode?
944  if(opcode == SMI_OPCODE_WRITE)
945  {
946  //Take care not to alter MDC clock configuration
947  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
948  //Set up a write operation
949  temp |= ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
950  //PHY address
951  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
952  //Register address
953  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
954 
955  //Data to be written in the PHY register
956  ETH->MACMIIDR = data & ETH_MACMIIDR_MD;
957 
958  //Start a write operation
959  ETH->MACMIIAR = temp;
960  //Wait for the write to complete
961  while((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0)
962  {
963  }
964  }
965  else
966  {
967  //The MAC peripheral only supports standard Clause 22 opcodes
968  }
969 }
970 
971 
972 /**
973  * @brief Read PHY register
974  * @param[in] opcode Access type (2 bits)
975  * @param[in] phyAddr PHY address (5 bits)
976  * @param[in] regAddr Register address (5 bits)
977  * @return Register value
978  **/
979 
980 uint16_t stm32f1xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
981  uint8_t regAddr)
982 {
983  uint16_t data;
984  uint32_t temp;
985 
986  //Valid opcode?
987  if(opcode == SMI_OPCODE_READ)
988  {
989  //Take care not to alter MDC clock configuration
990  temp = ETH->MACMIIAR & ETH_MACMIIAR_CR;
991  //Set up a read operation
992  temp |= ETH_MACMIIAR_MB;
993  //PHY address
994  temp |= (phyAddr << 11) & ETH_MACMIIAR_PA;
995  //Register address
996  temp |= (regAddr << 6) & ETH_MACMIIAR_MR;
997 
998  //Start a read operation
999  ETH->MACMIIAR = temp;
1000  //Wait for the read to complete
1001  while((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0)
1002  {
1003  }
1004 
1005  //Get register value
1006  data = ETH->MACMIIDR & ETH_MACMIIDR_MD;
1007  }
1008  else
1009  {
1010  //The MAC peripheral only supports standard Clause 22 opcodes
1011  data = 0;
1012  }
1013 
1014  //Return the value of the PHY register
1015  return data;
1016 }
1017 
1018 
1019 /**
1020  * @brief CRC calculation
1021  * @param[in] data Pointer to the data over which to calculate the CRC
1022  * @param[in] length Number of bytes to process
1023  * @return Resulting CRC value
1024  **/
1025 
1026 uint32_t stm32f1xxEthCalcCrc(const void *data, size_t length)
1027 {
1028  uint_t i;
1029  uint_t j;
1030  uint32_t crc;
1031  const uint8_t *p;
1032 
1033  //Point to the data over which to calculate the CRC
1034  p = (uint8_t *) data;
1035  //CRC preset value
1036  crc = 0xFFFFFFFF;
1037 
1038  //Loop through data
1039  for(i = 0; i < length; i++)
1040  {
1041  //The message is processed bit by bit
1042  for(j = 0; j < 8; j++)
1043  {
1044  //Update CRC value
1045  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1046  {
1047  crc = (crc << 1) ^ 0x04C11DB7;
1048  }
1049  else
1050  {
1051  crc = crc << 1;
1052  }
1053  }
1054  }
1055 
1056  //Return CRC value
1057  return ~crc;
1058 }
#define txDmaDesc
#define rxBuffer
#define txBuffer
#define rxDmaDesc
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint8_t opcode
Definition: dns_common.h:188
error_t
Error codes.
Definition: error.h:43
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
MacAddr
Definition: ethernet.h:195
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define ETH_TDES0_OWN
#define ETH_RDES0_FS
#define ETH_TDES0_IC
#define ETH_RDES1_RCH
#define ETH_RDES0_OWN
#define ETH_RDES0_LS
#define ETH_RDES0_FL
#define ETH_RDES0_ES
#define ETH_TDES0_LS
#define ETH_RDES1_RBS1
#define ETH_TDES0_TCH
#define ETH_TDES0_FS
#define ETH_TDES1_TBS1
uint16_t regAddr
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
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:674
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
#define SMI_OPCODE_WRITE
Definition: nic.h:66
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define SMI_OPCODE_READ
Definition: nic.h:67
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define osEnterIsr()
#define osExitIsr(flag)
void stm32f1xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
void stm32f1xxEthEventHandler(NetInterface *interface)
STM32F1 Ethernet MAC event handler.
error_t stm32f1xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
error_t stm32f1xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void stm32f1xxEthTick(NetInterface *interface)
STM32F1 Ethernet MAC timer handler.
void stm32f1xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
error_t stm32f1xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
uint16_t stm32f1xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
void stm32f1xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
error_t stm32f1xxEthReceivePacket(NetInterface *interface)
Receive a packet.
void stm32f1xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
void ETH_IRQHandler(void)
STM32F1 Ethernet MAC interrupt service routine.
uint32_t stm32f1xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
__weak_func void stm32f1xxEthInitGpio(NetInterface *interface)
GPIO configuration.
error_t stm32f1xxEthInit(NetInterface *interface)
STM32F1 Ethernet MAC initialization.
const NicDriver stm32f1xxEthDriver
STM32F1 Ethernet MAC driver.
STM32F1 Ethernet MAC driver.
#define STM32F1XX_ETH_RX_BUFFER_SIZE
#define STM32F1XX_ETH_IRQ_GROUP_PRIORITY
#define STM32F1XX_ETH_IRQ_SUB_PRIORITY
#define STM32F1XX_ETH_TX_BUFFER_SIZE
#define ETH_MACCR_RESERVED15
#define STM32F1XX_ETH_RX_BUFFER_COUNT
#define STM32F1XX_ETH_IRQ_PRIORITY_GROUPING
#define STM32F1XX_ETH_TX_BUFFER_COUNT
MAC filter table entry.
Definition: ethernet.h:262
MacAddr addr
MAC address.
Definition: ethernet.h:263
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
NIC driver.
Definition: nic.h:283
Receive DMA descriptor.
Transmit DMA descriptor.
uint8_t length
Definition: tcp.h:368