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