stm32h5xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32h5xx_eth_driver.c
3  * @brief STM32H5 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 #include "stm32h5xx.h"
36 #include "stm32h5xx_hal.h"
37 #include "core/net.h"
39 #include "debug.h"
40 
41 //Underlying network interface
42 static NetInterface *nicDriverInterface;
43 
44 //IAR EWARM compiler?
45 #if defined(__ICCARM__)
46 
47 //Transmit buffer
48 #pragma data_alignment = 4
49 #pragma location = STM32H5XX_ETH_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = STM32H5XX_ETH_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 4
57 #pragma location = STM32H5XX_ETH_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 4
61 #pragma location = STM32H5XX_ETH_RAM_SECTION
63 
64 //Keil MDK-ARM or GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(STM32H5XX_ETH_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(STM32H5XX_ETH_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(4), __section__(STM32H5XX_ETH_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(4), __section__(STM32H5XX_ETH_RAM_SECTION)));
79 
80 #endif
81 
82 //Current transmit descriptor
83 static uint_t txIndex;
84 //Current receive descriptor
85 static uint_t rxIndex;
86 
87 
88 /**
89  * @brief STM32H5 Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief STM32H5 Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122  uint32_t temp;
123 
124  //Debug message
125  TRACE_INFO("Initializing STM32H5 Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //GPIO configuration
131  stm32h5xxEthInitGpio(interface);
132 
133  //Enable Ethernet MAC clock
134  __HAL_RCC_ETH_CLK_ENABLE();
135  __HAL_RCC_ETHTX_CLK_ENABLE();
136  __HAL_RCC_ETHRX_CLK_ENABLE();
137 
138  //Reset Ethernet MAC peripheral
139  __HAL_RCC_ETH_FORCE_RESET();
140  __HAL_RCC_ETH_RELEASE_RESET();
141 
142  //Perform a software reset
143  ETH->DMAMR |= ETH_DMAMR_SWR;
144  //Wait for the reset to complete
145  while((ETH->DMAMR & ETH_DMAMR_SWR) != 0)
146  {
147  }
148 
149  //Adjust MDC clock range depending on HCLK frequency
150  ETH->MACMDIOAR = ETH_MACMDIOAR_CR_DIV124;
151 
152  //Valid Ethernet PHY or switch driver?
153  if(interface->phyDriver != NULL)
154  {
155  //Ethernet PHY initialization
156  error = interface->phyDriver->init(interface);
157  }
158  else if(interface->switchDriver != NULL)
159  {
160  //Ethernet switch initialization
161  error = interface->switchDriver->init(interface);
162  }
163  else
164  {
165  //The interface is not properly configured
166  error = ERROR_FAILURE;
167  }
168 
169  //Any error to report?
170  if(error)
171  {
172  return error;
173  }
174 
175  //Use default MAC configuration
176  ETH->MACCR = ETH_MACCR_GPSLCE | ETH_MACCR_RESERVED15 | ETH_MACCR_DO;
177 
178  //Set the maximum packet size that can be accepted
179  temp = ETH->MACECR & ~ETH_MACECR_GPSL;
180  ETH->MACECR = temp | STM32H5XX_ETH_RX_BUFFER_SIZE;
181 
182  //Configure MAC address filtering
184 
185  //Disable flow control
186  ETH->MACTFCR = 0;
187  ETH->MACRFCR = 0;
188 
189  //Configure DMA operating mode
190  ETH->DMAMR = ETH_DMAMR_INTM_0 | ETH_DMAMR_PR_1_1;
191  //Configure system bus mode
192  ETH->DMASBMR |= ETH_DMASBMR_AAL;
193  //The DMA takes the descriptor table as contiguous
194  ETH->DMACCR = ETH_DMACCR_DSL_0BIT;
195 
196  //Configure TX features
197  ETH->DMACTCR = ETH_DMACTCR_TPBL_32PBL;
198 
199  //Configure RX features
200  ETH->DMACRCR = ETH_DMACRCR_RPBL_32PBL;
201  ETH->DMACRCR |= (STM32H5XX_ETH_RX_BUFFER_SIZE << 1) & ETH_DMACRCR_RBSZ;
202 
203  //Enable store and forward mode
204  ETH->MTLTQOMR |= ETH_MTLTQOMR_TSF;
205  ETH->MTLRQOMR |= ETH_MTLRQOMR_RSF;
206 
207  //Initialize DMA descriptor lists
208  stm32h5xxEthInitDmaDesc(interface);
209 
210  //Prevent interrupts from being generated when the transmit statistic
211  //counters reach half their maximum value
214 
215  //Prevent interrupts from being generated when the receive statistic
216  //counters reach half their maximum value
219 
220  //Disable MAC interrupts
221  ETH->MACIER = 0;
222  //Enable the desired DMA interrupts
223  ETH->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE;
224 
225  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
226  NVIC_SetPriorityGrouping(STM32H5XX_ETH_IRQ_PRIORITY_GROUPING);
227 
228  //Configure Ethernet interrupt priority
229  NVIC_SetPriority(ETH_IRQn, NVIC_EncodePriority(STM32H5XX_ETH_IRQ_PRIORITY_GROUPING,
231 
232  //Enable MAC transmission and reception
233  ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
234 
235  //Enable DMA transmission and reception
236  ETH->DMACTCR |= ETH_DMACTCR_ST;
237  ETH->DMACRCR |= ETH_DMACRCR_SR;
238 
239  //Accept any packets from the upper layer
240  osSetEvent(&interface->nicTxEvent);
241 
242  //Successful initialization
243  return NO_ERROR;
244 }
245 
246 
247 /**
248  * @brief GPIO configuration
249  * @param[in] interface Underlying network interface
250  **/
251 
252 __weak_func void stm32h5xxEthInitGpio(NetInterface *interface)
253 {
254 //STM32H573I-DK evaluation board?
255 #if defined(USE_STM32H573I_DK)
256  GPIO_InitTypeDef GPIO_InitStructure;
257 
258  //Enable SBS clock
259  __HAL_RCC_SBS_CLK_ENABLE();
260 
261  //Enable GPIO clocks
262  __HAL_RCC_GPIOA_CLK_ENABLE();
263  __HAL_RCC_GPIOC_CLK_ENABLE();
264  __HAL_RCC_GPIOG_CLK_ENABLE();
265 
266  //Select RMII interface mode
267  HAL_SBS_ETHInterfaceSelect(SBS_ETH_RMII);
268 
269  //Configure RMII pins
270  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
271  GPIO_InitStructure.Pull = GPIO_NOPULL;
272  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
273  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
274 
275  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
276  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
277  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
278 
279  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
280  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
281  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
282 
283  //Configure RMII_TX_EN (PG11), ETH_RMII_TXD1 (PG12) and ETH_RMII_TXD0 (PG13)
284  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
285  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
286 
287 //Nucleo-H563ZI evaluation board?
288 #elif defined(USE_STM32H5XX_NUCLEO)
289  GPIO_InitTypeDef GPIO_InitStructure;
290 
291  //Enable SBS clock
292  __HAL_RCC_SBS_CLK_ENABLE();
293 
294  //Enable GPIO clocks
295  __HAL_RCC_GPIOA_CLK_ENABLE();
296  __HAL_RCC_GPIOB_CLK_ENABLE();
297  __HAL_RCC_GPIOC_CLK_ENABLE();
298  __HAL_RCC_GPIOG_CLK_ENABLE();
299 
300  //Select RMII interface mode
301  HAL_SBS_ETHInterfaceSelect(SBS_ETH_RMII);
302 
303  //Configure RMII pins
304  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
305  GPIO_InitStructure.Pull = GPIO_NOPULL;
306  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
307  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
308 
309  //Configure ETH_RMII_REF_CLK (PA1), ETH_MDIO (PA2) and ETH_RMII_CRS_DV (PA7)
310  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
311  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
312 
313  //Configure ETH_RMII_TXD1 (PB15)
314  GPIO_InitStructure.Pin = GPIO_PIN_15;
315  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
316 
317  //Configure ETH_MDC (PC1), ETH_RMII_RXD0 (PC4) and ETH_RMII_RXD1 (PC5)
318  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
319  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
320 
321  //Configure RMII_TX_EN (PG11) and ETH_RMII_TXD0 (PG13)
322  GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13;
323  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
324 #endif
325 }
326 
327 
328 /**
329  * @brief Initialize DMA descriptor lists
330  * @param[in] interface Underlying network interface
331  **/
332 
334 {
335  uint_t i;
336 
337  //Initialize TX DMA descriptor list
338  for(i = 0; i < STM32H5XX_ETH_TX_BUFFER_COUNT; i++)
339  {
340  //The descriptor is initially owned by the application
341  txDmaDesc[i].tdes0 = 0;
342  txDmaDesc[i].tdes1 = 0;
343  txDmaDesc[i].tdes2 = 0;
344  txDmaDesc[i].tdes3 = 0;
345  }
346 
347  //Initialize TX descriptor index
348  txIndex = 0;
349 
350  //Initialize RX DMA descriptor list
351  for(i = 0; i < STM32H5XX_ETH_RX_BUFFER_COUNT; i++)
352  {
353  //The descriptor is initially owned by the DMA
354  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
355  rxDmaDesc[i].rdes1 = 0;
356  rxDmaDesc[i].rdes2 = 0;
358  }
359 
360  //Initialize RX descriptor index
361  rxIndex = 0;
362 
363  //Start location of the TX descriptor list
364  ETH->DMACTDLAR = (uint32_t) &txDmaDesc[0];
365  //Length of the transmit descriptor ring
366  ETH->DMACTDRLR = STM32H5XX_ETH_TX_BUFFER_COUNT - 1;
367 
368  //Start location of the RX descriptor list
369  ETH->DMACRDLAR = (uint32_t) &rxDmaDesc[0];
370  //Length of the receive descriptor ring
371  ETH->DMACRDRLR = STM32H5XX_ETH_RX_BUFFER_COUNT - 1;
372 }
373 
374 
375 /**
376  * @brief STM32H5 Ethernet MAC timer handler
377  *
378  * This routine is periodically called by the TCP/IP stack to handle periodic
379  * operations such as polling the link state
380  *
381  * @param[in] interface Underlying network interface
382  **/
383 
385 {
386  //Valid Ethernet PHY or switch driver?
387  if(interface->phyDriver != NULL)
388  {
389  //Handle periodic operations
390  interface->phyDriver->tick(interface);
391  }
392  else if(interface->switchDriver != NULL)
393  {
394  //Handle periodic operations
395  interface->switchDriver->tick(interface);
396  }
397  else
398  {
399  //Just for sanity
400  }
401 }
402 
403 
404 /**
405  * @brief Enable interrupts
406  * @param[in] interface Underlying network interface
407  **/
408 
410 {
411  //Enable Ethernet MAC interrupts
412  NVIC_EnableIRQ(ETH_IRQn);
413 
414  //Valid Ethernet PHY or switch driver?
415  if(interface->phyDriver != NULL)
416  {
417  //Enable Ethernet PHY interrupts
418  interface->phyDriver->enableIrq(interface);
419  }
420  else if(interface->switchDriver != NULL)
421  {
422  //Enable Ethernet switch interrupts
423  interface->switchDriver->enableIrq(interface);
424  }
425  else
426  {
427  //Just for sanity
428  }
429 }
430 
431 
432 /**
433  * @brief Disable interrupts
434  * @param[in] interface Underlying network interface
435  **/
436 
438 {
439  //Disable Ethernet MAC interrupts
440  NVIC_DisableIRQ(ETH_IRQn);
441 
442  //Valid Ethernet PHY or switch driver?
443  if(interface->phyDriver != NULL)
444  {
445  //Disable Ethernet PHY interrupts
446  interface->phyDriver->disableIrq(interface);
447  }
448  else if(interface->switchDriver != NULL)
449  {
450  //Disable Ethernet switch interrupts
451  interface->switchDriver->disableIrq(interface);
452  }
453  else
454  {
455  //Just for sanity
456  }
457 }
458 
459 
460 /**
461  * @brief STM32H5 Ethernet MAC interrupt service routine
462  **/
463 
464 void ETH_IRQHandler(void)
465 {
466  bool_t flag;
467  uint32_t status;
468 
469  //Interrupt service routine prologue
470  osEnterIsr();
471 
472  //This flag will be set if a higher priority task must be woken
473  flag = FALSE;
474 
475  //Read DMA status register
476  status = ETH->DMACSR;
477 
478  //Packet transmitted?
479  if((status & ETH_DMACSR_TI) != 0)
480  {
481  //Clear TI interrupt flag
482  ETH->DMACSR = ETH_DMACSR_TI;
483 
484  //Check whether the TX buffer is available for writing
485  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
486  {
487  //Notify the TCP/IP stack that the transmitter is ready to send
488  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
489  }
490  }
491 
492  //Packet received?
493  if((status & ETH_DMACSR_RI) != 0)
494  {
495  //Clear RI interrupt flag
496  ETH->DMACSR = ETH_DMACSR_RI;
497 
498  //Set event flag
499  nicDriverInterface->nicEvent = TRUE;
500  //Notify the TCP/IP stack of the event
501  flag |= osSetEventFromIsr(&netEvent);
502  }
503 
504  //Clear NIS interrupt flag
505  ETH->DMACSR = ETH_DMACSR_NIS;
506 
507  //Interrupt service routine epilogue
508  osExitIsr(flag);
509 }
510 
511 
512 /**
513  * @brief STM32H5 Ethernet MAC event handler
514  * @param[in] interface Underlying network interface
515  **/
516 
518 {
519  error_t error;
520 
521  //Process all pending packets
522  do
523  {
524  //Read incoming packet
525  error = stm32h5xxEthReceivePacket(interface);
526 
527  //No more data in the receive buffer?
528  } while(error != ERROR_BUFFER_EMPTY);
529 }
530 
531 
532 /**
533  * @brief Send a packet
534  * @param[in] interface Underlying network interface
535  * @param[in] buffer Multi-part buffer containing the data to send
536  * @param[in] offset Offset to the first data byte
537  * @param[in] ancillary Additional options passed to the stack along with
538  * the packet
539  * @return Error code
540  **/
541 
543  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
544 {
545  size_t length;
546 
547  //Retrieve the length of the packet
548  length = netBufferGetLength(buffer) - offset;
549 
550  //Check the frame length
552  {
553  //The transmitter can accept another packet
554  osSetEvent(&interface->nicTxEvent);
555  //Report an error
556  return ERROR_INVALID_LENGTH;
557  }
558 
559  //Make sure the current buffer is available for writing
560  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) != 0)
561  {
562  return ERROR_FAILURE;
563  }
564 
565  //Copy user data to the transmit buffer
566  netBufferRead(txBuffer[txIndex], buffer, offset, length);
567 
568  //Set the start address of the buffer
569  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
570  //Write the number of bytes to send
571  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
572  //Give the ownership of the descriptor to the DMA
573  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
574 
575  //Data synchronization barrier
576  __DSB();
577 
578  //Clear TBU flag to resume processing
579  ETH->DMACSR = ETH_DMACSR_TBU;
580  //Instruct the DMA to poll the transmit descriptor list
581  ETH->DMACTDTPR = 0;
582 
583  //Increment index and wrap around if necessary
584  if(++txIndex >= STM32H5XX_ETH_TX_BUFFER_COUNT)
585  {
586  txIndex = 0;
587  }
588 
589  //Check whether the next buffer is available for writing
590  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
591  {
592  //The transmitter can accept another packet
593  osSetEvent(&interface->nicTxEvent);
594  }
595 
596  //Data successfully written
597  return NO_ERROR;
598 }
599 
600 
601 /**
602  * @brief Receive a packet
603  * @param[in] interface Underlying network interface
604  * @return Error code
605  **/
606 
608 {
609  error_t error;
610  size_t n;
611  uint32_t status;
612  NetRxAncillary ancillary;
613 
614  //Current buffer available for reading?
615  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN) == 0)
616  {
617  //FD and LD flags should be set
618  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) != 0 &&
619  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD) != 0)
620  {
621  //Check error bits
622  status = rxDmaDesc[rxIndex].rdes3 & (ETH_RDES3_CE | ETH_RDES3_GP |
624 
625  //The dribble bit error is valid only in the MII mode
626  if((SBS->PMCR & SBS_PMCR_ETH_SEL_PHY) != SBS_ETH_MII)
627  {
628  status &= ~ETH_RDES3_DE;
629  }
630 
631  //Make sure no error occurred
632  if(status == 0)
633  {
634  //Retrieve the length of the frame
635  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
636  //Limit the number of data to read
638 
639  //Additional options can be passed to the stack along with the packet
640  ancillary = NET_DEFAULT_RX_ANCILLARY;
641 
642  //Pass the packet to the upper layer
643  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
644 
645  //Valid packet received
646  error = NO_ERROR;
647  }
648  else
649  {
650  //The received packet contains an error
651  error = ERROR_INVALID_PACKET;
652  }
653  }
654  else
655  {
656  //The packet is not valid
657  error = ERROR_INVALID_PACKET;
658  }
659 
660  //Set the start address of the buffer
661  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
662  //Give the ownership of the descriptor back to the DMA
664 
665  //Increment index and wrap around if necessary
666  if(++rxIndex >= STM32H5XX_ETH_RX_BUFFER_COUNT)
667  {
668  rxIndex = 0;
669  }
670  }
671  else
672  {
673  //No more data in the receive buffer
674  error = ERROR_BUFFER_EMPTY;
675  }
676 
677  //Clear RBU flag to resume processing
678  ETH->DMACSR = ETH_DMACSR_RBU;
679  //Instruct the DMA to poll the receive descriptor list
680  ETH->DMACRDTPR = 0;
681 
682  //Return status code
683  return error;
684 }
685 
686 
687 /**
688  * @brief Configure MAC address filtering
689  * @param[in] interface Underlying network interface
690  * @return Error code
691  **/
692 
694 {
695  uint_t i;
696  uint_t j;
697  uint_t k;
698  uint32_t crc;
699  uint32_t hashTable[2];
700  MacAddr unicastMacAddr[3];
701  MacFilterEntry *entry;
702 
703  //Debug message
704  TRACE_DEBUG("Updating MAC filter...\r\n");
705 
706  //Promiscuous mode?
707  if(interface->promiscuous)
708  {
709  //Pass all incoming frames regardless of their destination address
710  ETH->MACPFR = ETH_MACPFR_PR;
711  }
712  else
713  {
714  //Set the MAC address of the station
715  ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
716  ETH->MACA0HR = interface->macAddr.w[2];
717 
718  //The MAC supports 3 additional addresses for unicast perfect filtering
719  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
720  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
721  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
722 
723  //The hash table is used for multicast address filtering
724  hashTable[0] = 0;
725  hashTable[1] = 0;
726 
727  //The MAC address filter contains the list of MAC addresses to accept
728  //when receiving an Ethernet frame
729  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
730  {
731  //Point to the current entry
732  entry = &interface->macAddrFilter[i];
733 
734  //Valid entry?
735  if(entry->refCount > 0)
736  {
737  //Multicast address?
738  if(macIsMulticastAddr(&entry->addr))
739  {
740  //Compute CRC over the current MAC address
741  crc = stm32h5xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
742 
743  //The upper 6 bits in the CRC register are used to index the
744  //contents of the hash table
745  k = (crc >> 26) & 0x3F;
746 
747  //Update hash table contents
748  hashTable[k / 32] |= (1 << (k % 32));
749  }
750  else
751  {
752  //Up to 3 additional MAC addresses can be specified
753  if(j < 3)
754  {
755  //Save the unicast address
756  unicastMacAddr[j++] = entry->addr;
757  }
758  }
759  }
760  }
761 
762  //Configure the first unicast address filter
763  if(j >= 1)
764  {
765  //When the AE bit is set, the entry is used for perfect filtering
766  ETH->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
767  ETH->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACAHR_AE;
768  }
769  else
770  {
771  //When the AE bit is cleared, the entry is ignored
772  ETH->MACA1LR = 0;
773  ETH->MACA1HR = 0;
774  }
775 
776  //Configure the second unicast address filter
777  if(j >= 2)
778  {
779  //When the AE bit is set, the entry is used for perfect filtering
780  ETH->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
781  ETH->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACAHR_AE;
782  }
783  else
784  {
785  //When the AE bit is cleared, the entry is ignored
786  ETH->MACA2LR = 0;
787  ETH->MACA2HR = 0;
788  }
789 
790  //Configure the third unicast address filter
791  if(j >= 3)
792  {
793  //When the AE bit is set, the entry is used for perfect filtering
794  ETH->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
795  ETH->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACAHR_AE;
796  }
797  else
798  {
799  //When the AE bit is cleared, the entry is ignored
800  ETH->MACA3LR = 0;
801  ETH->MACA3HR = 0;
802  }
803 
804  //Check whether frames with a multicast destination address should be
805  //accepted
806  if(interface->acceptAllMulticast)
807  {
808  //Configure the receive filter
809  ETH->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_PM;
810  }
811  else
812  {
813  //Configure the receive filter
814  ETH->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_HMC;
815 
816  //Configure the multicast hash table
817  ETH->MACHT0R = hashTable[0];
818  ETH->MACHT1R = hashTable[1];
819 
820  //Debug message
821  TRACE_DEBUG(" MACHT0R = %08" PRIX32 "\r\n", ETH->MACHT0R);
822  TRACE_DEBUG(" MACHT1R = %08" PRIX32 "\r\n", ETH->MACHT1R);
823  }
824  }
825 
826  //Successful processing
827  return NO_ERROR;
828 }
829 
830 
831 /**
832  * @brief Adjust MAC configuration parameters for proper operation
833  * @param[in] interface Underlying network interface
834  * @return Error code
835  **/
836 
838 {
839  uint32_t config;
840 
841  //Read current MAC configuration
842  config = ETH->MACCR;
843 
844  //10BASE-T or 100BASE-TX operation mode?
845  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
846  {
847  config |= ETH_MACCR_FES;
848  }
849  else
850  {
851  config &= ~ETH_MACCR_FES;
852  }
853 
854  //Half-duplex or full-duplex mode?
855  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
856  {
857  config |= ETH_MACCR_DM;
858  }
859  else
860  {
861  config &= ~ETH_MACCR_DM;
862  }
863 
864  //Update MAC configuration register
865  ETH->MACCR = config;
866 
867  //Successful processing
868  return NO_ERROR;
869 }
870 
871 
872 /**
873  * @brief Write PHY register
874  * @param[in] opcode Access type (2 bits)
875  * @param[in] phyAddr PHY address (5 bits)
876  * @param[in] regAddr Register address (5 bits)
877  * @param[in] data Register value
878  **/
879 
880 void stm32h5xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
881  uint8_t regAddr, uint16_t data)
882 {
883  uint32_t temp;
884 
885  //Valid opcode?
886  if(opcode == SMI_OPCODE_WRITE)
887  {
888  //Take care not to alter MDC clock configuration
889  temp = ETH->MACMDIOAR & ETH_MACMDIOAR_CR;
890  //Set up a write operation
891  temp |= ETH_MACMDIOAR_MOC_WR | ETH_MACMDIOAR_MB;
892  //PHY address
893  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
894  //Register address
895  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
896 
897  //Data to be written in the PHY register
898  ETH->MACMDIODR = data & ETH_MACMDIODR_MD;
899 
900  //Start a write operation
901  ETH->MACMDIOAR = temp;
902  //Wait for the write to complete
903  while((ETH->MACMDIOAR & ETH_MACMDIOAR_MB) != 0)
904  {
905  }
906  }
907  else
908  {
909  //The MAC peripheral only supports standard Clause 22 opcodes
910  }
911 }
912 
913 
914 /**
915  * @brief Read PHY register
916  * @param[in] opcode Access type (2 bits)
917  * @param[in] phyAddr PHY address (5 bits)
918  * @param[in] regAddr Register address (5 bits)
919  * @return Register value
920  **/
921 
922 uint16_t stm32h5xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
923  uint8_t regAddr)
924 {
925  uint16_t data;
926  uint32_t temp;
927 
928  //Valid opcode?
929  if(opcode == SMI_OPCODE_READ)
930  {
931  //Take care not to alter MDC clock configuration
932  temp = ETH->MACMDIOAR & ETH_MACMDIOAR_CR;
933  //Set up a read operation
934  temp |= ETH_MACMDIOAR_MOC_RD | ETH_MACMDIOAR_MB;
935  //PHY address
936  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
937  //Register address
938  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
939 
940  //Start a read operation
941  ETH->MACMDIOAR = temp;
942  //Wait for the read to complete
943  while((ETH->MACMDIOAR & ETH_MACMDIOAR_MB) != 0)
944  {
945  }
946 
947  //Get register value
948  data = ETH->MACMDIODR & ETH_MACMDIODR_MD;
949  }
950  else
951  {
952  //The MAC peripheral only supports standard Clause 22 opcodes
953  data = 0;
954  }
955 
956  //Return the value of the PHY register
957  return data;
958 }
959 
960 
961 /**
962  * @brief CRC calculation
963  * @param[in] data Pointer to the data over which to calculate the CRC
964  * @param[in] length Number of bytes to process
965  * @return Resulting CRC value
966  **/
967 
968 uint32_t stm32h5xxEthCalcCrc(const void *data, size_t length)
969 {
970  uint_t i;
971  uint_t j;
972  uint32_t crc;
973  const uint8_t *p;
974 
975  //Point to the data over which to calculate the CRC
976  p = (uint8_t *) data;
977  //CRC preset value
978  crc = 0xFFFFFFFF;
979 
980  //Loop through data
981  for(i = 0; i < length; i++)
982  {
983  //The message is processed bit by bit
984  for(j = 0; j < 8; j++)
985  {
986  //Update CRC value
987  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
988  {
989  crc = (crc << 1) ^ 0x04C11DB7;
990  }
991  else
992  {
993  crc = crc << 1;
994  }
995  }
996  }
997 
998  //Return CRC value
999  return ~crc;
1000 }
#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
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)
#define ETH_MACCR_RESERVED15
error_t stm32h5xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void stm32h5xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
void stm32h5xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
const NicDriver stm32h5xxEthDriver
STM32H5 Ethernet MAC driver.
error_t stm32h5xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t stm32h5xxEthInit(NetInterface *interface)
STM32H5 Ethernet MAC initialization.
void stm32h5xxEthEventHandler(NetInterface *interface)
STM32H5 Ethernet MAC event handler.
uint16_t stm32h5xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
error_t stm32h5xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
__weak_func void stm32h5xxEthInitGpio(NetInterface *interface)
GPIO configuration.
void ETH_IRQHandler(void)
STM32H5 Ethernet MAC interrupt service routine.
uint32_t stm32h5xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
void stm32h5xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
void stm32h5xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
error_t stm32h5xxEthReceivePacket(NetInterface *interface)
Receive a packet.
void stm32h5xxEthTick(NetInterface *interface)
STM32H5 Ethernet MAC timer handler.
STM32H5 Ethernet MAC driver.
#define ETH_TDES3_LD
#define ETH_RDES3_DE
#define STM32H5XX_ETH_RX_BUFFER_COUNT
#define ETH_RDES3_RWT
#define ETH_RDES3_OWN
#define ETH_MMCTIMR_TXLPIUSCIM
#define STM32H5XX_ETH_IRQ_PRIORITY_GROUPING
#define ETH_MMCTIMR_TXSCOLGPIM
#define ETH_RDES3_GP
#define STM32H5XX_ETH_TX_BUFFER_COUNT
#define ETH_MMCTIMR_TXLPITRCIM
#define STM32H5XX_ETH_RX_BUFFER_SIZE
#define ETH_RDES3_RE
#define ETH_MMCTIMR_TXMCOLGPIM
#define STM32H5XX_ETH_TX_BUFFER_SIZE
#define ETH_RDES3_FD
#define ETH_MMCRIMR_RXUCGPIM
#define ETH_MMCTIMR_TXGPKTIM
#define ETH_RDES3_IOC
#define ETH_RDES3_BUF1V
#define ETH_TDES2_B1L
#define ETH_MMCRIMR_RXALGNERPIM
#define STM32H5XX_ETH_RAM_SECTION
#define STM32H5XX_ETH_IRQ_SUB_PRIORITY
#define ETH_TDES3_FD
#define ETH_RDES3_CE
#define ETH_RDES3_OE
#define STM32H5XX_ETH_IRQ_GROUP_PRIORITY
#define ETH_RDES3_PL
#define ETH_MMCRIMR_RXLPIUSCIM
#define ETH_TDES3_OWN
#define ETH_MMCRIMR_RXLPITRCIM
#define ETH_RDES3_LD
#define ETH_TDES2_IOC
#define ETH_MMCRIMR_RXCRCERPIM
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 descriptor.
Transmit descriptor.
uint8_t length
Definition: tcp.h:368