stm32c5xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32c5xx_eth_driver.c
3  * @brief STM32C5 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "stm32_hal.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 //Current transmit descriptor
78 static uint_t txIndex;
79 //Current receive descriptor
80 static uint_t rxIndex;
81 
82 
83 /**
84  * @brief STM32C5 Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief STM32C5 Ethernet MAC initialization
110  * @param[in] interface Underlying network interface
111  * @return Error code
112  **/
113 
115 {
116  error_t error;
117  uint32_t temp;
118 
119  //Debug message
120  TRACE_INFO("Initializing STM32C5 Ethernet MAC...\r\n");
121 
122  //Save underlying network interface
123  nicDriverInterface = interface;
124 
125  //GPIO configuration
126  stm32c5xxEthInitGpio(interface);
127 
128  //Enable Ethernet MAC clock
129  HAL_RCC_ETH1_EnableClock();
130  HAL_RCC_ETH1TX_EnableClock();
131  HAL_RCC_ETH1RX_EnableClock();
132 
133  //Reset Ethernet MAC peripheral
134  HAL_RCC_ETH1_Reset();
135 
136  //Perform a software reset
137  ETH1->DMAMR |= ETH_DMAMR_SWR;
138  //Wait for the reset to complete
139  while((ETH1->DMAMR & ETH_DMAMR_SWR) != 0)
140  {
141  }
142 
143  //Adjust MDC clock range depending on HCLK frequency
144  ETH1->MACMDIOAR = ETH_MACMDIOAR_CR_Val(5);
145 
146  //Valid Ethernet PHY or switch driver?
147  if(interface->phyDriver != NULL)
148  {
149  //Ethernet PHY initialization
150  error = interface->phyDriver->init(interface);
151  }
152  else if(interface->switchDriver != NULL)
153  {
154  //Ethernet switch initialization
155  error = interface->switchDriver->init(interface);
156  }
157  else
158  {
159  //The interface is not properly configured
160  error = ERROR_FAILURE;
161  }
162 
163  //Any error to report?
164  if(error)
165  {
166  return error;
167  }
168 
169  //Use default MAC configuration
170  ETH1->MACCR = ETH_MACCR_GPSLCE | ETH_MACCR_RESERVED15 | ETH_MACCR_DO;
171 
172  //Set the maximum packet size that can be accepted
173  temp = ETH1->MACECR & ~ETH_MACECR_GPSL;
174  ETH1->MACECR = temp | STM32C5XX_ETH_RX_BUFFER_SIZE;
175 
176  //Configure MAC address filtering
178 
179  //Disable flow control
180  ETH1->MACQTXFCR = 0;
181  ETH1->MACRXFCR = 0;
182 
183  //Configure DMA operating mode
184  ETH1->DMAMR = ETH_DMAMR_INTM_Val(0) | ETH_DMAMR_TXPR_Val(0);
185  //Configure system bus mode
186  ETH1->DMASBMR |= ETH_DMASBMR_AAL;
187  //The DMA takes the descriptor table as contiguous
188  ETH1->DMACCR = ETH_DMACCR_DSL_Val(0);
189 
190  //Configure TX features
191  ETH1->DMACTXCR = ETH_DMACTXCR_TXPBL_Val(32);
192 
193  //Configure RX features
194  ETH1->DMACRXCR = ETH_DMACRXCR_RXPBL_Val(32) |
196 
197  //Enable store and forward mode
198  ETH1->MTLTXQOMR |= ETH_MTLTXQOMR_TSF;
199  ETH1->MTLRXQOMR |= ETH_MTLRXQOMR_RSF;
200 
201  //Initialize DMA descriptor lists
202  stm32c5xxEthInitDmaDesc(interface);
203 
204  //Prevent interrupts from being generated when the transmit statistic
205  //counters reach half their maximum value
206  ETH1->MMC_TX_INTERRUPT_MASK = ETH_MMC_TX_INTERRUPT_MASK_TXLPITRCIM |
207  ETH_MMC_TX_INTERRUPT_MASK_TXLPIUSCIM | ETH_MMC_TX_INTERRUPT_MASK_TXGPKTIM |
208  ETH_MMC_TX_INTERRUPT_MASK_TXMCOLGPIM | ETH_MMC_TX_INTERRUPT_MASK_TXSCOLGPIM;
209 
210  //Prevent interrupts from being generated when the receive statistic
211  //counters reach half their maximum value
212  ETH1->MMC_RX_INTERRUPT_MASK = ETH_MMC_RX_INTERRUPT_MASK_RXLPITRCIM |
213  ETH_MMC_RX_INTERRUPT_MASK_RXLPIUSCIM | ETH_MMC_RX_INTERRUPT_MASK_RXUCGPIM |
214  ETH_MMC_RX_INTERRUPT_MASK_RXALGNERPIM | ETH_MMC_RX_INTERRUPT_MASK_RXCRCERPIM;
215 
216  //Disable MAC interrupts
217  ETH1->MACIER = 0;
218  //Enable the desired DMA interrupts
219  ETH1->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE;
220 
221  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
222  NVIC_SetPriorityGrouping(STM32C5XX_ETH_IRQ_PRIORITY_GROUPING);
223 
224  //Configure Ethernet interrupt priority
225  NVIC_SetPriority(ETH1_IRQn, NVIC_EncodePriority(STM32C5XX_ETH_IRQ_PRIORITY_GROUPING,
227 
228  //Enable MAC transmission and reception
229  ETH1->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
230 
231  //Enable DMA transmission and reception
232  ETH1->DMACTXCR |= ETH_DMACTXCR_ST;
233  ETH1->DMACRXCR |= ETH_DMACRXCR_SR;
234 
235  //Accept any packets from the upper layer
236  osSetEvent(&interface->nicTxEvent);
237 
238  //Successful initialization
239  return NO_ERROR;
240 }
241 
242 
243 /**
244  * @brief GPIO configuration
245  * @param[in] interface Underlying network interface
246  **/
247 
248 __weak_func void stm32c5xxEthInitGpio(NetInterface *interface)
249 {
250 //Nucleo-C5A3ZG evaluation board?
251 #if defined(USE_NUCLEO_C5A3ZG)
252  hal_gpio_config_t gpio_config;
253 
254  //Enable SBS clock
255  HAL_RCC_SBS_EnableClock();
256 
257  //Enable GPIO clocks
258  HAL_RCC_GPIOA_EnableClock();
259  HAL_RCC_GPIOC_EnableClock();
260  HAL_RCC_GPIOD_EnableClock();
261  HAL_RCC_GPIOE_EnableClock();
262  HAL_RCC_GPIOG_EnableClock();
263 
264  //Select RMII interface mode
265  HAL_SBS_SetETHPHYInterface(ETH1, HAL_SBS_ETHPHY_ITF_GMII_MII);;
266 
267  //Configure RMII pins
268  gpio_config.mode = HAL_GPIO_MODE_ALTERNATE;
269  gpio_config.output_type = HAL_GPIO_OUTPUT_PUSHPULL;
270  gpio_config.pull = HAL_GPIO_PULL_NO;
271  gpio_config.speed = HAL_GPIO_SPEED_FREQ_VERY_HIGH;
272 
273  //Configure ETH1_RMII_REF_CLK (PA1)
274  gpio_config.alternate = HAL_GPIO_AF_10;
275  HAL_GPIO_Init(HAL_GPIOA, HAL_GPIO_PIN_1, &gpio_config);
276 
277  //Configure ETH1_MDC (PC1)
278  gpio_config.alternate = HAL_GPIO_AF_10;
279  HAL_GPIO_Init(HAL_GPIOC, HAL_GPIO_PIN_1, &gpio_config);
280 
281  //Configure ETH1_RMII_RXD0 (PC4)
282  gpio_config.alternate = HAL_GPIO_AF_12;
283  HAL_GPIO_Init(HAL_GPIOC, HAL_GPIO_PIN_4, &gpio_config);
284 
285  //Configure ETH1_RMII_RXD1 (PC5)
286  gpio_config.alternate = HAL_GPIO_AF_13;
287  HAL_GPIO_Init(HAL_GPIOC, HAL_GPIO_PIN_5, &gpio_config);
288 
289  //Configure ETH1_RMII_CRS_DV (PD1)
290  gpio_config.alternate = HAL_GPIO_AF_10;
291  HAL_GPIO_Init(HAL_GPIOD, HAL_GPIO_PIN_1, &gpio_config);
292 
293  //Configure ETH1_MDIO (PE12)
294  gpio_config.alternate = HAL_GPIO_AF_10;
295  HAL_GPIO_Init(HAL_GPIOE, HAL_GPIO_PIN_12, &gpio_config);
296 
297  //Configure RMII_TX_EN (PG11)
298  gpio_config.alternate = HAL_GPIO_AF_10;
299  HAL_GPIO_Init(HAL_GPIOG, HAL_GPIO_PIN_11, &gpio_config);
300 
301  //Configure ETH1_RMII_TXD1 (PG12)
302  gpio_config.alternate = HAL_GPIO_AF_10;
303  HAL_GPIO_Init(HAL_GPIOG, HAL_GPIO_PIN_12, &gpio_config);
304 
305  //Configure ETH1_RMII_TXD0 (PG13)
306  gpio_config.alternate = HAL_GPIO_AF_10;
307  HAL_GPIO_Init(HAL_GPIOG, HAL_GPIO_PIN_13, &gpio_config);
308 #endif
309 }
310 
311 
312 /**
313  * @brief Initialize DMA descriptor lists
314  * @param[in] interface Underlying network interface
315  **/
316 
318 {
319  uint_t i;
320 
321  //Initialize TX DMA descriptor list
322  for(i = 0; i < STM32C5XX_ETH_TX_BUFFER_COUNT; i++)
323  {
324  //The descriptor is initially owned by the application
325  txDmaDesc[i].tdes0 = 0;
326  txDmaDesc[i].tdes1 = 0;
327  txDmaDesc[i].tdes2 = 0;
328  txDmaDesc[i].tdes3 = 0;
329  }
330 
331  //Initialize TX descriptor index
332  txIndex = 0;
333 
334  //Initialize RX DMA descriptor list
335  for(i = 0; i < STM32C5XX_ETH_RX_BUFFER_COUNT; i++)
336  {
337  //The descriptor is initially owned by the DMA
338  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
339  rxDmaDesc[i].rdes1 = 0;
340  rxDmaDesc[i].rdes2 = 0;
342  }
343 
344  //Initialize RX descriptor index
345  rxIndex = 0;
346 
347  //Start location of the TX descriptor list
348  ETH1->DMACTXDLAR = (uint32_t) &txDmaDesc[0];
349  //Length of the transmit descriptor ring
350  ETH1->DMACTXRLR = STM32C5XX_ETH_TX_BUFFER_COUNT - 1;
351 
352  //Start location of the RX descriptor list
353  ETH1->DMACRXDLAR = (uint32_t) &rxDmaDesc[0];
354  //Length of the receive descriptor ring
355  ETH1->DMACRXRLR = STM32C5XX_ETH_RX_BUFFER_COUNT - 1;
356 }
357 
358 
359 /**
360  * @brief STM32C5 Ethernet MAC timer handler
361  *
362  * This routine is periodically called by the TCP/IP stack to handle periodic
363  * operations such as polling the link state
364  *
365  * @param[in] interface Underlying network interface
366  **/
367 
369 {
370  //Valid Ethernet PHY or switch driver?
371  if(interface->phyDriver != NULL)
372  {
373  //Handle periodic operations
374  interface->phyDriver->tick(interface);
375  }
376  else if(interface->switchDriver != NULL)
377  {
378  //Handle periodic operations
379  interface->switchDriver->tick(interface);
380  }
381  else
382  {
383  //Just for sanity
384  }
385 }
386 
387 
388 /**
389  * @brief Enable interrupts
390  * @param[in] interface Underlying network interface
391  **/
392 
394 {
395  //Enable Ethernet MAC interrupts
396  NVIC_EnableIRQ(ETH1_IRQn);
397 
398  //Valid Ethernet PHY or switch driver?
399  if(interface->phyDriver != NULL)
400  {
401  //Enable Ethernet PHY interrupts
402  interface->phyDriver->enableIrq(interface);
403  }
404  else if(interface->switchDriver != NULL)
405  {
406  //Enable Ethernet switch interrupts
407  interface->switchDriver->enableIrq(interface);
408  }
409  else
410  {
411  //Just for sanity
412  }
413 }
414 
415 
416 /**
417  * @brief Disable interrupts
418  * @param[in] interface Underlying network interface
419  **/
420 
422 {
423  //Disable Ethernet MAC interrupts
424  NVIC_DisableIRQ(ETH1_IRQn);
425 
426  //Valid Ethernet PHY or switch driver?
427  if(interface->phyDriver != NULL)
428  {
429  //Disable Ethernet PHY interrupts
430  interface->phyDriver->disableIrq(interface);
431  }
432  else if(interface->switchDriver != NULL)
433  {
434  //Disable Ethernet switch interrupts
435  interface->switchDriver->disableIrq(interface);
436  }
437  else
438  {
439  //Just for sanity
440  }
441 }
442 
443 
444 /**
445  * @brief STM32C5 Ethernet MAC interrupt service routine
446  **/
447 
448 void ETH_IRQHandler(void)
449 {
450  bool_t flag;
451  uint32_t status;
452 
453  //Interrupt service routine prologue
454  osEnterIsr();
455 
456  //This flag will be set if a higher priority task must be woken
457  flag = FALSE;
458 
459  //Read DMA status register
460  status = ETH1->DMACSR;
461 
462  //Packet transmitted?
463  if((status & ETH_DMACSR_TI) != 0)
464  {
465  //Clear TI interrupt flag
466  ETH1->DMACSR = ETH_DMACSR_TI;
467 
468  //Check whether the TX buffer is available for writing
469  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
470  {
471  //Notify the TCP/IP stack that the transmitter is ready to send
472  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
473  }
474  }
475 
476  //Packet received?
477  if((status & ETH_DMACSR_RI) != 0)
478  {
479  //Clear RI interrupt flag
480  ETH1->DMACSR = ETH_DMACSR_RI;
481 
482  //Set event flag
483  nicDriverInterface->nicEvent = TRUE;
484  //Notify the TCP/IP stack of the event
485  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
486  }
487 
488  //Clear NIS interrupt flag
489  ETH1->DMACSR = ETH_DMACSR_NIS;
490 
491  //Interrupt service routine epilogue
492  osExitIsr(flag);
493 }
494 
495 
496 /**
497  * @brief STM32C5 Ethernet MAC event handler
498  * @param[in] interface Underlying network interface
499  **/
500 
502 {
503  error_t error;
504 
505  //Process all pending packets
506  do
507  {
508  //Read incoming packet
509  error = stm32c5xxEthReceivePacket(interface);
510 
511  //No more data in the receive buffer?
512  } while(error != ERROR_BUFFER_EMPTY);
513 }
514 
515 
516 /**
517  * @brief Send a packet
518  * @param[in] interface Underlying network interface
519  * @param[in] buffer Multi-part buffer containing the data to send
520  * @param[in] offset Offset to the first data byte
521  * @param[in] ancillary Additional options passed to the stack along with
522  * the packet
523  * @return Error code
524  **/
525 
527  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
528 {
529  size_t length;
530 
531  //Retrieve the length of the packet
532  length = netBufferGetLength(buffer) - offset;
533 
534  //Check the frame length
536  {
537  //The transmitter can accept another packet
538  osSetEvent(&interface->nicTxEvent);
539  //Report an error
540  return ERROR_INVALID_LENGTH;
541  }
542 
543  //Make sure the current buffer is available for writing
544  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) != 0)
545  {
546  return ERROR_FAILURE;
547  }
548 
549  //Copy user data to the transmit buffer
550  netBufferRead(txBuffer[txIndex], buffer, offset, length);
551 
552  //Set the start address of the buffer
553  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
554  //Write the number of bytes to send
555  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
556  //Give the ownership of the descriptor to the DMA
557  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
558 
559  //Data synchronization barrier
560  __DSB();
561 
562  //Clear TBU flag to resume processing
563  ETH1->DMACSR = ETH_DMACSR_TBU;
564  //Instruct the DMA to poll the transmit descriptor list
565  ETH1->DMACTXDTPR = 0;
566 
567  //Increment index and wrap around if necessary
568  if(++txIndex >= STM32C5XX_ETH_TX_BUFFER_COUNT)
569  {
570  txIndex = 0;
571  }
572 
573  //Check whether the next buffer is available for writing
574  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
575  {
576  //The transmitter can accept another packet
577  osSetEvent(&interface->nicTxEvent);
578  }
579 
580  //Data successfully written
581  return NO_ERROR;
582 }
583 
584 
585 /**
586  * @brief Receive a packet
587  * @param[in] interface Underlying network interface
588  * @return Error code
589  **/
590 
592 {
593  error_t error;
594  size_t n;
595  uint32_t status;
596  NetRxAncillary ancillary;
597 
598  //Current buffer available for reading?
599  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN) == 0)
600  {
601  //FD and LD flags should be set
602  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) != 0 &&
603  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD) != 0)
604  {
605  //Check error bits
606  status = rxDmaDesc[rxIndex].rdes3 & (ETH_RDES3_CE | ETH_RDES3_GP |
608 
609  //The dribble bit error is valid only in the MII mode
610  if((SBS->PMCR & SBS_PMCR_ETH1_SEL_PHY) != HAL_SBS_ETHPHY_ITF_GMII_MII)
611  {
612  status &= ~ETH_RDES3_DE;
613  }
614 
615  //Make sure no error occurred
616  if(status == 0)
617  {
618  //Retrieve the length of the frame
619  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
620  //Limit the number of data to read
622 
623  //Additional options can be passed to the stack along with the packet
624  ancillary = NET_DEFAULT_RX_ANCILLARY;
625 
626  //Pass the packet to the upper layer
627  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
628 
629  //Valid packet received
630  error = NO_ERROR;
631  }
632  else
633  {
634  //The received packet contains an error
635  error = ERROR_INVALID_PACKET;
636  }
637  }
638  else
639  {
640  //The packet is not valid
641  error = ERROR_INVALID_PACKET;
642  }
643 
644  //Set the start address of the buffer
645  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
646  //Give the ownership of the descriptor back to the DMA
648 
649  //Increment index and wrap around if necessary
650  if(++rxIndex >= STM32C5XX_ETH_RX_BUFFER_COUNT)
651  {
652  rxIndex = 0;
653  }
654  }
655  else
656  {
657  //No more data in the receive buffer
658  error = ERROR_BUFFER_EMPTY;
659  }
660 
661  //Clear RBU flag to resume processing
662  ETH1->DMACSR = ETH_DMACSR_RBU;
663  //Instruct the DMA to poll the receive descriptor list
664  ETH1->DMACRXDTPR = 0;
665 
666  //Return status code
667  return error;
668 }
669 
670 
671 /**
672  * @brief Configure MAC address filtering
673  * @param[in] interface Underlying network interface
674  * @return Error code
675  **/
676 
678 {
679  uint_t i;
680  uint_t j;
681  uint_t k;
682  uint32_t crc;
683  uint32_t hashTable[2];
684  MacAddr unicastMacAddr[3];
685  MacFilterEntry *entry;
686 
687  //Debug message
688  TRACE_DEBUG("Updating MAC filter...\r\n");
689 
690  //Promiscuous mode?
691  if(interface->promiscuous)
692  {
693  //Pass all incoming frames regardless of their destination address
694  ETH1->MACPFR = ETH_MACPFR_PR;
695  }
696  else
697  {
698  //Set the MAC address of the station
699  ETH1->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
700  ETH1->MACA0HR = interface->macAddr.w[2];
701 
702  //The MAC supports 3 additional addresses for unicast perfect filtering
703  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
704  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
705  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
706 
707  //The hash table is used for multicast address filtering
708  hashTable[0] = 0;
709  hashTable[1] = 0;
710 
711  //The MAC address filter contains the list of MAC addresses to accept
712  //when receiving an Ethernet frame
713  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
714  {
715  //Point to the current entry
716  entry = &interface->macAddrFilter[i];
717 
718  //Valid entry?
719  if(entry->refCount > 0)
720  {
721  //Multicast address?
722  if(macIsMulticastAddr(&entry->addr))
723  {
724  //Compute CRC over the current MAC address
725  crc = stm32c5xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
726 
727  //The upper 6 bits in the CRC register are used to index the
728  //contents of the hash table
729  k = (crc >> 26) & 0x3F;
730 
731  //Update hash table contents
732  hashTable[k / 32] |= (1 << (k % 32));
733  }
734  else
735  {
736  //Up to 3 additional MAC addresses can be specified
737  if(j < 3)
738  {
739  //Save the unicast address
740  unicastMacAddr[j++] = entry->addr;
741  }
742  }
743  }
744  }
745 
746  //Configure the first unicast address filter
747  if(j >= 1)
748  {
749  //When the AE bit is set, the entry is used for perfect filtering
750  ETH1->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
751  ETH1->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACA1HR_AE;
752  }
753  else
754  {
755  //When the AE bit is cleared, the entry is ignored
756  ETH1->MACA1LR = 0;
757  ETH1->MACA1HR = 0;
758  }
759 
760  //Configure the second unicast address filter
761  if(j >= 2)
762  {
763  //When the AE bit is set, the entry is used for perfect filtering
764  ETH1->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
765  ETH1->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACA2HR_AE;
766  }
767  else
768  {
769  //When the AE bit is cleared, the entry is ignored
770  ETH1->MACA2LR = 0;
771  ETH1->MACA2HR = 0;
772  }
773 
774  //Configure the third unicast address filter
775  if(j >= 3)
776  {
777  //When the AE bit is set, the entry is used for perfect filtering
778  ETH1->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
779  ETH1->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACA3HR_AE;
780  }
781  else
782  {
783  //When the AE bit is cleared, the entry is ignored
784  ETH1->MACA3LR = 0;
785  ETH1->MACA3HR = 0;
786  }
787 
788  //Check whether frames with a multicast destination address should be
789  //accepted
790  if(interface->acceptAllMulticast)
791  {
792  //Configure the receive filter
793  ETH1->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_PM;
794  }
795  else
796  {
797  //Configure the receive filter
798  ETH1->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_HMC;
799 
800  //Configure the multicast hash table
801  ETH1->MACHT0R = hashTable[0];
802  ETH1->MACHT1R = hashTable[1];
803 
804  //Debug message
805  TRACE_DEBUG(" MACHT0R = 0x%08" PRIX32 "\r\n", ETH1->MACHT0R);
806  TRACE_DEBUG(" MACHT1R = 0x%08" PRIX32 "\r\n", ETH1->MACHT1R);
807  }
808  }
809 
810  //Successful processing
811  return NO_ERROR;
812 }
813 
814 
815 /**
816  * @brief Adjust MAC configuration parameters for proper operation
817  * @param[in] interface Underlying network interface
818  * @return Error code
819  **/
820 
822 {
823  uint32_t config;
824 
825  //Read current MAC configuration
826  config = ETH1->MACCR;
827 
828  //10BASE-T or 100BASE-TX operation mode?
829  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
830  {
831  config |= ETH_MACCR_FES;
832  }
833  else
834  {
835  config &= ~ETH_MACCR_FES;
836  }
837 
838  //Half-duplex or full-duplex mode?
839  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
840  {
841  config |= ETH_MACCR_DM;
842  }
843  else
844  {
845  config &= ~ETH_MACCR_DM;
846  }
847 
848  //Update MAC configuration register
849  ETH1->MACCR = config;
850 
851  //Successful processing
852  return NO_ERROR;
853 }
854 
855 
856 /**
857  * @brief Write PHY register
858  * @param[in] opcode Access type (2 bits)
859  * @param[in] phyAddr PHY address (5 bits)
860  * @param[in] regAddr Register address (5 bits)
861  * @param[in] data Register value
862  **/
863 
864 void stm32c5xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
865  uint8_t regAddr, uint16_t data)
866 {
867  uint32_t temp;
868 
869  //Valid opcode?
870  if(opcode == SMI_OPCODE_WRITE)
871  {
872  //Take care not to alter MDC clock configuration
873  temp = ETH1->MACMDIOAR & ETH_MACMDIOAR_CR;
874  //Set up a write operation
875  temp |= ETH_MACMDIOAR_GOC_Val(1) | ETH_MACMDIOAR_MB;
876  //PHY address
877  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
878  //Register address
879  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
880 
881  //Data to be written in the PHY register
882  ETH1->MACMDIODR = data & ETH_MACMDIODR_MD;
883 
884  //Start a write operation
885  ETH1->MACMDIOAR = temp;
886  //Wait for the write to complete
887  while((ETH1->MACMDIOAR & ETH_MACMDIOAR_MB) != 0)
888  {
889  }
890  }
891  else
892  {
893  //The MAC peripheral only supports standard Clause 22 opcodes
894  }
895 }
896 
897 
898 /**
899  * @brief Read PHY register
900  * @param[in] opcode Access type (2 bits)
901  * @param[in] phyAddr PHY address (5 bits)
902  * @param[in] regAddr Register address (5 bits)
903  * @return Register value
904  **/
905 
906 uint16_t stm32c5xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
907  uint8_t regAddr)
908 {
909  uint16_t data;
910  uint32_t temp;
911 
912  //Valid opcode?
913  if(opcode == SMI_OPCODE_READ)
914  {
915  //Take care not to alter MDC clock configuration
916  temp = ETH1->MACMDIOAR & ETH_MACMDIOAR_CR;
917  //Set up a read operation
918  temp |= ETH_MACMDIOAR_GOC_Val(3) | ETH_MACMDIOAR_MB;
919  //PHY address
920  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
921  //Register address
922  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
923 
924  //Start a read operation
925  ETH1->MACMDIOAR = temp;
926  //Wait for the read to complete
927  while((ETH1->MACMDIOAR & ETH_MACMDIOAR_MB) != 0)
928  {
929  }
930 
931  //Get register value
932  data = ETH1->MACMDIODR & ETH_MACMDIODR_MD;
933  }
934  else
935  {
936  //The MAC peripheral only supports standard Clause 22 opcodes
937  data = 0;
938  }
939 
940  //Return the value of the PHY register
941  return data;
942 }
943 
944 
945 /**
946  * @brief CRC calculation
947  * @param[in] data Pointer to the data over which to calculate the CRC
948  * @param[in] length Number of bytes to process
949  * @return Resulting CRC value
950  **/
951 
952 uint32_t stm32c5xxEthCalcCrc(const void *data, size_t length)
953 {
954  uint_t i;
955  uint_t j;
956  uint32_t crc;
957  const uint8_t *p;
958 
959  //Point to the data over which to calculate the CRC
960  p = (uint8_t *) data;
961  //CRC preset value
962  crc = 0xFFFFFFFF;
963 
964  //Loop through data
965  for(i = 0; i < length; i++)
966  {
967  //The message is processed bit by bit
968  for(j = 0; j < 8; j++)
969  {
970  //Update CRC value
971  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
972  {
973  crc = (crc << 1) ^ 0x04C11DB7;
974  }
975  else
976  {
977  crc = crc << 1;
978  }
979  }
980  }
981 
982  //Return CRC value
983  return ~crc;
984 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
error_t stm32c5xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define STM32C5XX_ETH_IRQ_SUB_PRIORITY
uint8_t opcode
Definition: dns_common.h:191
int bool_t
Definition: compiler_port.h:63
#define ETH_RDES3_DE
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
error_t stm32c5xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
const NicDriver stm32c5xxEthDriver
STM32C5 Ethernet MAC driver.
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:690
#define ETH_DMAMR_TXPR_Val(n)
#define ETH_RDES3_LD
#define ETH_DMACRXCR_RBSZ_Val(n)
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
#define ETH_TDES3_LD
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
error_t stm32c5xxEthReceivePacket(NetInterface *interface)
Receive a packet.
void stm32c5xxEthTick(NetInterface *interface)
STM32C5 Ethernet MAC timer handler.
#define ETH_RDES3_GP
#define ETH_RDES3_CE
#define ETH_MACCR_RESERVED15
void stm32c5xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:418
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define STM32C5XX_ETH_RX_BUFFER_COUNT
#define osExitIsr(flag)
#define ETH_DMAMR_INTM_Val(n)
#define ETH_MACMDIOAR_CR_Val(n)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define ETH_RDES3_RE
#define FALSE
Definition: os_port.h:46
#define STM32C5XX_ETH_IRQ_PRIORITY_GROUPING
#define ETH_MACMDIOAR_GOC_Val(n)
void stm32c5xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define ETH_RDES3_RWT
#define ETH_DMACCR_DSL_Val(n)
error_t stm32c5xxEthInit(NetInterface *interface)
STM32C5 Ethernet MAC initialization.
error_t
Error codes.
Definition: error.h:43
void stm32c5xxEthEventHandler(NetInterface *interface)
STM32C5 Ethernet MAC event handler.
#define ETH_TDES2_B1L
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void stm32c5xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define txBuffer
error_t stm32c5xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define NetRxAncillary
Definition: net_misc.h:40
STM32C5 Ethernet MAC driver.
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
MacAddr addr
MAC address.
Definition: ethernet.h:265
void stm32c5xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
@ ERROR_INVALID_LENGTH
Definition: error.h:111
void ETH_IRQHandler(void)
STM32C5 Ethernet MAC interrupt service routine.
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define STM32C5XX_ETH_TX_BUFFER_COUNT
#define NetTxAncillary
Definition: net_misc.h:36
#define ETH_RDES3_BUF1V
#define SMI_OPCODE_READ
Definition: nic.h:67
#define ETH_TDES2_IOC
#define STM32C5XX_ETH_TX_BUFFER_SIZE
uint16_t stm32c5xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define TRACE_INFO(...)
Definition: debug.h:105
__weak_func void stm32c5xxEthInitGpio(NetInterface *interface)
GPIO configuration.
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define STM32C5XX_ETH_IRQ_GROUP_PRIORITY
#define MIN(a, b)
Definition: os_port.h:63
#define ETH_RDES3_OWN
#define ETH_TDES3_OWN
#define rxBuffer
MacAddr
Definition: ethernet.h:197
#define TRACE_DEBUG(...)
Definition: debug.h:119
uint32_t stm32c5xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
Transmit descriptor.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
#define ETH_RDES3_FD
#define osEnterIsr()
#define STM32C5XX_ETH_RX_BUFFER_SIZE
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_TDES3_FD
#define ETH_RDES3_OE
Receive descriptor.
#define txDmaDesc
#define ETH_DMACRXCR_RXPBL_Val(n)
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define ETH_DMACTXCR_TXPBL_Val(n)
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define ETH_RDES3_IOC
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define ETH_RDES3_PL
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83