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