stm32mp13xx_eth2_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32mp13xx_eth2_driver.c
3  * @brief STM32MP13 Gigabit Ethernet MAC driver (ETH2 instance)
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.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "stm32mp13xx.h"
36 #include "stm32mp13xx_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 = STM32MP13XX_ETH2_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = STM32MP13XX_ETH2_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 8
57 #pragma location = STM32MP13XX_ETH2_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 8
61 #pragma location = STM32MP13XX_ETH2_RAM_SECTION
63 
64 //GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(STM32MP13XX_ETH2_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(STM32MP13XX_ETH2_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(8), __section__(STM32MP13XX_ETH2_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(8), __section__(STM32MP13XX_ETH2_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 STM32MP13 Ethernet MAC driver (ETH2 instance)
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief STM32MP13 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 STM32MP13 Ethernet MAC (ETH2)...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //GPIO configuration
131  stm32mp13xxEth2InitGpio(interface);
132 
133  //Enable Ethernet MAC clock
134  __HAL_RCC_ETH2CK_CLK_ENABLE();
135  __HAL_RCC_ETH2MAC_CLK_ENABLE();
136  __HAL_RCC_ETH2TX_CLK_ENABLE();
137  __HAL_RCC_ETH2RX_CLK_ENABLE();
138 
139  //Reset Ethernet MAC peripheral
140  __HAL_RCC_ETH2MAC_FORCE_RESET();
141  __HAL_RCC_ETH2MAC_RELEASE_RESET();
142 
143  //Perform a software reset
144  ETH2->DMAMR |= ETH_DMAMR_SWR;
145  //Wait for the reset to complete
146  while((ETH2->DMAMR & ETH_DMAMR_SWR) != 0)
147  {
148  }
149 
150  //Adjust MDC clock range depending on HCLK frequency
151  ETH2->MACMDIOAR = ETH_MACMDIOAR_CR_DIV124;
152 
153  //Valid Ethernet PHY or switch driver?
154  if(interface->phyDriver != NULL)
155  {
156  //Ethernet PHY initialization
157  error = interface->phyDriver->init(interface);
158  }
159  else if(interface->switchDriver != NULL)
160  {
161  //Ethernet switch initialization
162  error = interface->switchDriver->init(interface);
163  }
164  else
165  {
166  //The interface is not properly configured
167  error = ERROR_FAILURE;
168  }
169 
170  //Any error to report?
171  if(error)
172  {
173  return error;
174  }
175 
176  //Use default MAC configuration
177  ETH2->MACCR = ETH_MACCR_GPSLCE | ETH_MACCR_DO;
178 
179  //Set the maximum packet size that can be accepted
180  temp = ETH2->MACECR & ~ETH_MACECR_GPSL;
181  ETH2->MACECR = temp | STM32MP13XX_ETH2_RX_BUFFER_SIZE;
182 
183  //Configure MAC address filtering
185 
186  //Disable flow control
187  ETH2->MACQ0TXFCR = 0;
188  ETH2->MACRXFCR = 0;
189 
190  //Enable the first RX queue
191  ETH2->MACRXQC0R = ETH_MACRXQC0R_RXQ0EN_Val(2);
192 
193  //Configure DMA operating mode
194  ETH2->DMAMR = ETH_DMAMR_INTM_Val(0) | ETH_DMAMR_TXPR_Val(0);
195  //Configure system bus mode
196  ETH2->DMASBMR |= ETH_DMASBMR_AAL;
197 
198  //The DMA takes the descriptor table as contiguous
199  ETH2->DMAC0CR = ETH_DMAC0CR_DSL_Val(0);
200  //Configure TX features
201  ETH2->DMAC0TXCR = ETH_DMAC0TXCR_TXPBL_Val(32);
202 
203  //Configure RX features
204  ETH2->DMAC0RXCR = ETH_DMAC0RXCR_RXPBL_Val(32) |
206 
207  //Enable store and forward mode for transmission
208  ETH2->MTLTXQ0OMR = ETH_MTLTXQ0OMR_TQS_Val(7) | ETH_MTLTXQ0OMR_TXQEN_Val(2) |
209  ETH_MTLTXQ0OMR_TSF;
210 
211  //Enable store and forward mode for reception
212  ETH2->MTLRXQ0OMR = ETH_MTLRXQ0OMR_RQS_Val(7) | ETH_MTLRXQ0OMR_RSF;
213 
214  //Initialize DMA descriptor lists
215  stm32mp13xxEth2InitDmaDesc(interface);
216 
217  //Prevent interrupts from being generated when the transmit statistic
218  //counters reach half their maximum value
219  ETH2->MMCTXIMR = ETH_MMCTXIMR_TXLPITRCIM | ETH_MMCTXIMR_TXLPIUSCIM |
220  ETH_MMCTXIMR_TXGPKTIM | ETH_MMCTXIMR_TXMCOLGPIM | ETH_MMCTXIMR_TXSCOLGPIM;
221 
222  //Prevent interrupts from being generated when the receive statistic
223  //counters reach half their maximum value
224  ETH2->MMCRXIMR = ETH_MMCRXIMR_RXLPITRCIM | ETH_MMCRXIMR_RXLPIUSCIM |
225  ETH_MMCRXIMR_RXUCGPIM | ETH_MMCRXIMR_RXALGNERPIM | ETH_MMCRXIMR_RXCRCERPIM;
226 
227  //Disable MAC interrupts
228  ETH2->MACIER = 0;
229  //Enable the desired DMA interrupts
230  ETH2->DMAC0IER = ETH_DMAC0IER_NIE | ETH_DMAC0IER_RIE | ETH_DMAC0IER_TIE;
231 
232  //Configure Ethernet interrupt priority
233  IRQ_SetPriority(ETH2_IRQn, STM32MP13XX_ETH2_IRQ_PRIORITY);
234 
235  //Enable MAC transmission and reception
236  ETH2->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
237 
238  //Enable DMA transmission and reception
239  ETH2->DMAC0TXCR |= ETH_DMAC0TXCR_ST;
240  ETH2->DMAC0RXCR |= ETH_DMAC0RXCR_SR;
241 
242  //Accept any packets from the upper layer
243  osSetEvent(&interface->nicTxEvent);
244 
245  //Successful initialization
246  return NO_ERROR;
247 }
248 
249 
250 /**
251  * @brief GPIO configuration
252  * @param[in] interface Underlying network interface
253  **/
254 
255 __weak_func void stm32mp13xxEth2InitGpio(NetInterface *interface)
256 {
257 //STM32MP135F-DK evaluation board?
258 #if defined(USE_STM32MP13XX_DK)
259  GPIO_InitTypeDef GPIO_InitStructure;
260 
261  //Enable SYSCFG clock
262  __HAL_RCC_SYSCFG_CLK_ENABLE();
263 
264  //Enable GPIO clocks
265  __HAL_RCC_GPIOA_CLK_ENABLE();
266  __HAL_RCC_GPIOB_CLK_ENABLE();
267  __HAL_RCC_GPIOE_CLK_ENABLE();
268  __HAL_RCC_GPIOF_CLK_ENABLE();
269  __HAL_RCC_GPIOG_CLK_ENABLE();
270 
271  //Configure ETH2_CLK (PG8) as a 50MHz clock output
272  GPIO_InitStructure.Pin = GPIO_PIN_8;
273  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
274  GPIO_InitStructure.Pull = GPIO_NOPULL;
275  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
276  GPIO_InitStructure.Alternate = GPIO_AF13_ETH2;
277  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
278 
279  //Select RMII interface mode
280  HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH2_RMII);
281  //Select the source of the reference clock (RCC)
282  SYSCFG->PMCSETR = SYSCFG_PMCSETR_ETH2_REF_CLK_SEL;
283 
284  //Configure RMII pins
285  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
286  GPIO_InitStructure.Pull = GPIO_NOPULL;
287  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
288 
289  //Configure ETH2_RMII_CRS_DV (PA12)
290  GPIO_InitStructure.Pin = GPIO_PIN_12;
291  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
292  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
293 
294  //Configure ETH2_MDIO (PB2)
295  GPIO_InitStructure.Pin = GPIO_PIN_2;
296  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
297  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
298 
299  //Configure ETH2_RMII_RXD1 (PE2)
300  GPIO_InitStructure.Pin = GPIO_PIN_2;
301  GPIO_InitStructure.Alternate = GPIO_AF10_ETH;
302  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
303 
304  //Configure ETH2_RMII_RXD0 (PF4), ETH2_RMII_TX_EN (PF6) and ETH2_RMII_TXD0 (PF7)
305  GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_6 | GPIO_PIN_7;
306  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
307  HAL_GPIO_Init(GPIOF, &GPIO_InitStructure);
308 
309  //Configure ETH2_MDC (PG5) and ETH2_RMII_TXD1 (PG11)
310  GPIO_InitStructure.Pin = GPIO_PIN_5 | GPIO_PIN_11;
311  GPIO_InitStructure.Alternate = GPIO_AF10_ETH;
312  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
313 
314  //Reset PHY transceiver (hard reset)
315  stm32mp13xxEth2ResetPhy(interface);
316 #endif
317 }
318 
319 
320 /**
321  * @brief Reset PHY transceiver
322  * @param[in] interface Underlying network interface
323  **/
324 
325 __weak_func void stm32mp13xxEth2ResetPhy(NetInterface *interface)
326 {
327 }
328 
329 
330 /**
331  * @brief Initialize DMA descriptor lists
332  * @param[in] interface Underlying network interface
333  **/
334 
336 {
337  uint_t i;
338 
339  //Initialize TX DMA descriptor list
340  for(i = 0; i < STM32MP13XX_ETH2_TX_BUFFER_COUNT; i++)
341  {
342  //The descriptor is initially owned by the application
343  txDmaDesc[i].tdes0 = 0;
344  txDmaDesc[i].tdes1 = 0;
345  txDmaDesc[i].tdes2 = 0;
346  txDmaDesc[i].tdes3 = 0;
347  }
348 
349  //Initialize TX descriptor index
350  txIndex = 0;
351 
352  //Initialize RX DMA descriptor list
353  for(i = 0; i < STM32MP13XX_ETH2_RX_BUFFER_COUNT; i++)
354  {
355  //The descriptor is initially owned by the DMA
356  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
357  rxDmaDesc[i].rdes1 = 0;
358  rxDmaDesc[i].rdes2 = 0;
360  }
361 
362  //Initialize RX descriptor index
363  rxIndex = 0;
364 
365  //Start location of the TX descriptor list
366  ETH2->DMAC0TXDLAR = (uint32_t) &txDmaDesc[0];
367  //Length of the transmit descriptor ring
368  ETH2->DMAC0TXRLR = STM32MP13XX_ETH2_TX_BUFFER_COUNT - 1;
369 
370  //Start location of the RX descriptor list
371  ETH2->DMAC0RXDLAR = (uint32_t) &rxDmaDesc[0];
372  //Length of the receive descriptor ring
373  ETH2->DMAC0RXRLR = STM32MP13XX_ETH2_RX_BUFFER_COUNT - 1;
374 }
375 
376 
377 /**
378  * @brief STM32MP13 Ethernet MAC timer handler
379  *
380  * This routine is periodically called by the TCP/IP stack to handle periodic
381  * operations such as polling the link state
382  *
383  * @param[in] interface Underlying network interface
384  **/
385 
387 {
388  //Valid Ethernet PHY or switch driver?
389  if(interface->phyDriver != NULL)
390  {
391  //Handle periodic operations
392  interface->phyDriver->tick(interface);
393  }
394  else if(interface->switchDriver != NULL)
395  {
396  //Handle periodic operations
397  interface->switchDriver->tick(interface);
398  }
399  else
400  {
401  //Just for sanity
402  }
403 }
404 
405 
406 /**
407  * @brief Enable interrupts
408  * @param[in] interface Underlying network interface
409  **/
410 
412 {
413  //Enable Ethernet MAC interrupts
414  IRQ_Enable(ETH2_IRQn);
415 
416  //Valid Ethernet PHY or switch driver?
417  if(interface->phyDriver != NULL)
418  {
419  //Enable Ethernet PHY interrupts
420  interface->phyDriver->enableIrq(interface);
421  }
422  else if(interface->switchDriver != NULL)
423  {
424  //Enable Ethernet switch interrupts
425  interface->switchDriver->enableIrq(interface);
426  }
427  else
428  {
429  //Just for sanity
430  }
431 }
432 
433 
434 /**
435  * @brief Disable interrupts
436  * @param[in] interface Underlying network interface
437  **/
438 
440 {
441  //Disable Ethernet MAC interrupts
442  IRQ_Disable(ETH2_IRQn);
443 
444  //Valid Ethernet PHY or switch driver?
445  if(interface->phyDriver != NULL)
446  {
447  //Disable Ethernet PHY interrupts
448  interface->phyDriver->disableIrq(interface);
449  }
450  else if(interface->switchDriver != NULL)
451  {
452  //Disable Ethernet switch interrupts
453  interface->switchDriver->disableIrq(interface);
454  }
455  else
456  {
457  //Just for sanity
458  }
459 }
460 
461 
462 /**
463  * @brief STM32MP13 Ethernet MAC interrupt service routine
464  **/
465 
466 void ETH2_IRQHandler(void)
467 {
468  bool_t flag;
469  uint32_t status;
470 
471  //Interrupt service routine prologue
472  osEnterIsr();
473 
474  //This flag will be set if a higher priority task must be woken
475  flag = FALSE;
476 
477  //Read DMA status register
478  status = ETH2->DMAC0SR;
479 
480  //Packet transmitted?
481  if((status & ETH_DMAC0SR_TI) != 0)
482  {
483  //Clear TI interrupt flag
484  ETH2->DMAC0SR = ETH_DMAC0SR_TI;
485 
486  //Check whether the TX buffer is available for writing
487  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
488  {
489  //Notify the TCP/IP stack that the transmitter is ready to send
490  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
491  }
492  }
493 
494  //Packet received?
495  if((status & ETH_DMAC0SR_RI) != 0)
496  {
497  //Clear RI interrupt flag
498  ETH2->DMAC0SR = ETH_DMAC0SR_RI;
499 
500  //Set event flag
501  nicDriverInterface->nicEvent = TRUE;
502  //Notify the TCP/IP stack of the event
503  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
504  }
505 
506  //Clear NIS interrupt flag
507  ETH2->DMAC0SR = ETH_DMAC0SR_NIS;
508 
509  //Interrupt service routine epilogue
510  osExitIsr(flag);
511 }
512 
513 
514 /**
515  * @brief STM32MP13 Ethernet MAC event handler
516  * @param[in] interface Underlying network interface
517  **/
518 
520 {
521  error_t error;
522 
523  //Process all pending packets
524  do
525  {
526  //Read incoming packet
527  error = stm32mp13xxEth2ReceivePacket(interface);
528 
529  //No more data in the receive buffer?
530  } while(error != ERROR_BUFFER_EMPTY);
531 }
532 
533 
534 /**
535  * @brief Send a packet
536  * @param[in] interface Underlying network interface
537  * @param[in] buffer Multi-part buffer containing the data to send
538  * @param[in] offset Offset to the first data byte
539  * @param[in] ancillary Additional options passed to the stack along with
540  * the packet
541  * @return Error code
542  **/
543 
545  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
546 {
547  size_t length;
548 
549  //Retrieve the length of the packet
550  length = netBufferGetLength(buffer) - offset;
551 
552  //Check the frame length
554  {
555  //The transmitter can accept another packet
556  osSetEvent(&interface->nicTxEvent);
557  //Report an error
558  return ERROR_INVALID_LENGTH;
559  }
560 
561  //Make sure the current buffer is available for writing
562  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) != 0)
563  {
564  return ERROR_FAILURE;
565  }
566 
567  //Copy user data to the transmit buffer
568  netBufferRead(txBuffer[txIndex], buffer, offset, length);
569 
570  //Set the start address of the buffer
571  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
572  //Write the number of bytes to send
573  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
574  //Give the ownership of the descriptor to the DMA
575  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
576 
577  //Data synchronization barrier
578  __DSB();
579 
580  //Clear TBU flag to resume processing
581  ETH2->DMAC0SR = ETH_DMAC0SR_TBU;
582  //Instruct the DMA to poll the transmit descriptor list
583  ETH2->DMAC0TXDTPR = 0;
584 
585  //Increment index and wrap around if necessary
586  if(++txIndex >= STM32MP13XX_ETH2_TX_BUFFER_COUNT)
587  {
588  txIndex = 0;
589  }
590 
591  //Check whether the next buffer is available for writing
592  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
593  {
594  //The transmitter can accept another packet
595  osSetEvent(&interface->nicTxEvent);
596  }
597 
598  //Data successfully written
599  return NO_ERROR;
600 }
601 
602 
603 /**
604  * @brief Receive a packet
605  * @param[in] interface Underlying network interface
606  * @return Error code
607  **/
608 
610 {
611  error_t error;
612  size_t n;
613  NetRxAncillary ancillary;
614 
615  //Current buffer available for reading?
616  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN) == 0)
617  {
618  //FD and LD flags should be set
619  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) != 0 &&
620  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD) != 0)
621  {
622  //Make sure no error occurred
623  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_ES) == 0)
624  {
625  //Retrieve the length of the frame
626  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
627  //Limit the number of data to read
629 
630  //Additional options can be passed to the stack along with the packet
631  ancillary = NET_DEFAULT_RX_ANCILLARY;
632 
633  //Pass the packet to the upper layer
634  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
635 
636  //Valid packet received
637  error = NO_ERROR;
638  }
639  else
640  {
641  //The received packet contains an error
642  error = ERROR_INVALID_PACKET;
643  }
644  }
645  else
646  {
647  //The packet is not valid
648  error = ERROR_INVALID_PACKET;
649  }
650 
651  //Set the start address of the buffer
652  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
653  //Give the ownership of the descriptor back to the DMA
655 
656  //Increment index and wrap around if necessary
657  if(++rxIndex >= STM32MP13XX_ETH2_RX_BUFFER_COUNT)
658  {
659  rxIndex = 0;
660  }
661  }
662  else
663  {
664  //No more data in the receive buffer
665  error = ERROR_BUFFER_EMPTY;
666  }
667 
668  //Clear RBU flag to resume processing
669  ETH2->DMAC0SR = ETH_DMAC0SR_RBU;
670  //Instruct the DMA to poll the receive descriptor list
671  ETH2->DMAC0RXDTPR = 0;
672 
673  //Return status code
674  return error;
675 }
676 
677 
678 /**
679  * @brief Configure MAC address filtering
680  * @param[in] interface Underlying network interface
681  * @return Error code
682  **/
683 
685 {
686  uint_t i;
687  uint_t j;
688  uint_t k;
689  uint32_t crc;
690  uint32_t hashTable[2];
691  MacAddr unicastMacAddr[3];
692  MacFilterEntry *entry;
693 
694  //Debug message
695  TRACE_DEBUG("Updating MAC filter...\r\n");
696 
697  //Promiscuous mode?
698  if(interface->promiscuous)
699  {
700  //Pass all incoming frames regardless of their destination address
701  ETH2->MACPFR = ETH_MACPFR_PR;
702  }
703  else
704  {
705  //Set the MAC address of the station
706  ETH2->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
707  ETH2->MACA0HR = interface->macAddr.w[2];
708 
709  //The MAC supports 3 additional addresses for unicast perfect filtering
710  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
711  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
712  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
713 
714  //The hash table is used for multicast address filtering
715  hashTable[0] = 0;
716  hashTable[1] = 0;
717 
718  //The MAC address filter contains the list of MAC addresses to accept
719  //when receiving an Ethernet frame
720  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
721  {
722  //Point to the current entry
723  entry = &interface->macAddrFilter[i];
724 
725  //Valid entry?
726  if(entry->refCount > 0)
727  {
728  //Multicast address?
729  if(macIsMulticastAddr(&entry->addr))
730  {
731  //Compute CRC over the current MAC address
732  crc = stm32mp13xxEth2CalcCrc(&entry->addr, sizeof(MacAddr));
733 
734  //The upper 6 bits in the CRC register are used to index the
735  //contents of the hash table
736  k = (crc >> 26) & 0x3F;
737 
738  //Update hash table contents
739  hashTable[k / 32] |= (1 << (k % 32));
740  }
741  else
742  {
743  //Up to 3 additional MAC addresses can be specified
744  if(j < 3)
745  {
746  //Save the unicast address
747  unicastMacAddr[j++] = entry->addr;
748  }
749  }
750  }
751  }
752 
753  //Configure the first unicast address filter
754  if(j >= 1)
755  {
756  //When the AE bit is set, the entry is used for perfect filtering
757  ETH2->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
758  ETH2->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACA1HR_AE;
759  }
760  else
761  {
762  //When the AE bit is cleared, the entry is ignored
763  ETH2->MACA1LR = 0;
764  ETH2->MACA1HR = 0;
765  }
766 
767  //Configure the second unicast address filter
768  if(j >= 2)
769  {
770  //When the AE bit is set, the entry is used for perfect filtering
771  ETH2->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
772  ETH2->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACA2HR_AE;
773  }
774  else
775  {
776  //When the AE bit is cleared, the entry is ignored
777  ETH2->MACA2LR = 0;
778  ETH2->MACA2HR = 0;
779  }
780 
781  //Configure the third unicast address filter
782  if(j >= 3)
783  {
784  //When the AE bit is set, the entry is used for perfect filtering
785  ETH2->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
786  ETH2->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACA3HR_AE;
787  }
788  else
789  {
790  //When the AE bit is cleared, the entry is ignored
791  ETH2->MACA3LR = 0;
792  ETH2->MACA3HR = 0;
793  }
794 
795  //Check whether frames with a multicast destination address should be
796  //accepted
797  if(interface->acceptAllMulticast)
798  {
799  //Configure the receive filter
800  ETH2->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_PM;
801  }
802  else
803  {
804  //Configure the receive filter
805  ETH2->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_HMC;
806 
807  //Configure the multicast hash table
808  ETH2->MACHT0R = hashTable[0];
809  ETH2->MACHT1R = hashTable[1];
810 
811  //Debug message
812  TRACE_DEBUG(" MACHT0R = 0x%08" PRIX32 "\r\n", ETH2->MACHT0R);
813  TRACE_DEBUG(" MACHT1R = 0x%08" PRIX32 "\r\n", ETH2->MACHT1R);
814  }
815  }
816 
817  //Successful processing
818  return NO_ERROR;
819 }
820 
821 
822 /**
823  * @brief Adjust MAC configuration parameters for proper operation
824  * @param[in] interface Underlying network interface
825  * @return Error code
826  **/
827 
829 {
830  uint32_t config;
831 
832  //Read current MAC configuration
833  config = ETH2->MACCR;
834 
835  //1000BASE-T operation mode?
836  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
837  {
838  config &= ~ETH_MACCR_PS;
839  config &= ~ETH_MACCR_FES;
840  }
841  //100BASE-TX operation mode?
842  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
843  {
844  config |= ETH_MACCR_PS;
845  config |= ETH_MACCR_FES;
846  }
847  //10BASE-T operation mode?
848  else
849  {
850  config |= ETH_MACCR_PS;
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  ETH2->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 stm32mp13xxEth2WritePhyReg(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 = ETH2->MACMDIOAR & ETH_MACMDIOAR_CR;
890  //Set up a write operation
891  temp |= ETH_MACMDIOAR_GOC_Val(1) | ETH_MACMDIOAR_GB;
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  ETH2->MACMDIODR = data & ETH_MACMDIODR_GD;
899 
900  //Start a write operation
901  ETH2->MACMDIOAR = temp;
902  //Wait for the write to complete
903  while((ETH2->MACMDIOAR & ETH_MACMDIOAR_GB) != 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 stm32mp13xxEth2ReadPhyReg(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 = ETH2->MACMDIOAR & ETH_MACMDIOAR_CR;
933  //Set up a read operation
934  temp |= ETH_MACMDIOAR_GOC_Val(3) | ETH_MACMDIOAR_GB;
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  ETH2->MACMDIOAR = temp;
942  //Wait for the read to complete
943  while((ETH2->MACMDIOAR & ETH_MACMDIOAR_GB) != 0)
944  {
945  }
946 
947  //Get register value
948  data = ETH2->MACMDIODR & ETH_MACMDIODR_GD;
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 stm32mp13xxEth2CalcCrc(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 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
#define ETH_DMAC0TXCR_TXPBL_Val(n)
uint8_t opcode
Definition: dns_common.h:191
error_t stm32mp13xxEth2SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
int bool_t
Definition: compiler_port.h:63
void stm32mp13xxEth2Tick(NetInterface *interface)
STM32MP13 Ethernet MAC timer handler.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
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_RDES3_LD
uint8_t p
Definition: ndp.h:300
#define ETH_RDES3_ES
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
#define STM32MP13XX_ETH2_TX_BUFFER_SIZE
#define STM32MP13XX_ETH2_TX_BUFFER_COUNT
void stm32mp13xxEth2WritePhyReg(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 osExitIsr(flag)
error_t stm32mp13xxEth2ReceivePacket(NetInterface *interface)
Receive a packet.
#define SMI_OPCODE_WRITE
Definition: nic.h:66
void ETH2_IRQHandler(void)
STM32MP13 Ethernet MAC interrupt service routine.
#define FALSE
Definition: os_port.h:46
error_t stm32mp13xxEth2Init(NetInterface *interface)
STM32MP13 Ethernet MAC initialization.
error_t
Error codes.
Definition: error.h:43
#define STM32MP13XX_ETH2_RX_BUFFER_SIZE
#define ETH_TDES2_B1L
#define ETH_DMAMR_TXPR_Val(n)
void stm32mp13xxEth2EventHandler(NetInterface *interface)
STM32MP13 Ethernet MAC event handler.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
__weak_func void stm32mp13xxEth2ResetPhy(NetInterface *interface)
Reset PHY transceiver.
#define txBuffer
__weak_func void stm32mp13xxEth2InitGpio(NetInterface *interface)
GPIO configuration.
#define NetRxAncillary
Definition: net_misc.h:40
STM32MP13 Gigabit Ethernet MAC driver (ETH2 instance)
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
MacAddr addr
MAC address.
Definition: ethernet.h:265
#define ETH_DMAC0RXCR_RXPBL_Val(n)
void stm32mp13xxEth2EnableIrq(NetInterface *interface)
Enable interrupts.
#define ETH_MTLRXQ0OMR_RQS_Val(n)
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define NetTxAncillary
Definition: net_misc.h:36
#define ETH_MACRXQC0R_RXQ0EN_Val(n)
#define ETH_DMAC0RXCR_RBSZ_Val(n)
#define ETH_RDES3_BUF1V
#define SMI_OPCODE_READ
Definition: nic.h:67
#define ETH_TDES2_IOC
#define TRACE_INFO(...)
Definition: debug.h:105
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 STM32MP13XX_ETH2_IRQ_PRIORITY
#define MIN(a, b)
Definition: os_port.h:63
#define ETH_RDES3_OWN
#define ETH_TDES3_OWN
#define ETH_MTLTXQ0OMR_TXQEN_Val(n)
#define rxBuffer
#define ETH_MTLTXQ0OMR_TQS_Val(n)
#define STM32MP13XX_ETH2_RAM_SECTION
MacAddr
Definition: ethernet.h:197
uint32_t stm32mp13xxEth2CalcCrc(const void *data, size_t length)
CRC calculation.
void stm32mp13xxEth2DisableIrq(NetInterface *interface)
Disable interrupts.
#define TRACE_DEBUG(...)
Definition: debug.h:119
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()
const NicDriver stm32mp13xxEth2Driver
STM32MP13 Ethernet MAC driver (ETH2 instance)
#define ETH_DMAMR_INTM_Val(n)
uint16_t stm32mp13xxEth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_TDES3_FD
#define ETH_MACMDIOAR_GOC_Val(n)
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define STM32MP13XX_ETH2_RX_BUFFER_COUNT
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
#define ETH_DMAC0CR_DSL_Val(n)
NIC driver.
Definition: nic.h:286
error_t stm32mp13xxEth2UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define ETH_RDES3_IOC
error_t stm32mp13xxEth2UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
void stm32mp13xxEth2InitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
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