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