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