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