stm32n6xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32n6xx_eth_driver.c
3  * @brief STM32N6 Gigabit Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "stm32n6xx.h"
36 #include "stm32n6xx_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 = STM32N6XX_ETH_RAM_SECTION
51 //Receive buffer
52 #pragma data_alignment = 4
53 #pragma location = STM32N6XX_ETH_RAM_SECTION
55 //Transmit DMA descriptors
56 #pragma data_alignment = 8
57 #pragma location = STM32N6XX_ETH_RAM_SECTION
59 //Receive DMA descriptors
60 #pragma data_alignment = 8
61 #pragma location = STM32N6XX_ETH_RAM_SECTION
63 
64 //Keil MDK-ARM or GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4), __section__(STM32N6XX_ETH_RAM_SECTION)));
70 //Receive buffer
72  __attribute__((aligned(4), __section__(STM32N6XX_ETH_RAM_SECTION)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(8), __section__(STM32N6XX_ETH_RAM_SECTION)));
76 //Receive DMA descriptors
78  __attribute__((aligned(8), __section__(STM32N6XX_ETH_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 STM32N6 Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief STM32N6 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 STM32N6 Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //GPIO configuration
131  stm32n6xxEthInitGpio(interface);
132 
133  //Enable Ethernet MAC clock
134  __HAL_RCC_ETH1_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_ETH1_FORCE_RESET();
141  __HAL_RCC_ETH1_RELEASE_RESET();
142 
143  //Perform a software reset
144  ETH1->DMAMR |= ETH_DMAMR_SWR;
145  //Wait for the reset to complete
146  while((ETH1->DMAMR & ETH_DMAMR_SWR) != 0)
147  {
148  }
149 
150  //Adjust MDC clock range depending on HCLK frequency
151  ETH1->MACMDIOAR = ETH_MACMDIOAR_CR_Val(5);
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  ETH1->MACCR = ETH_MACCR_GPSLCE | ETH_MACCR_DO;
178 
179  //Set the maximum packet size that can be accepted
180  temp = ETH1->MACECR & ~ETH_MACECR_GPSL;
181  ETH1->MACECR = temp | STM32N6XX_ETH_RX_BUFFER_SIZE;
182 
183  //Configure MAC address filtering
185 
186  //Disable flow control
187  ETH1->MACQ0TXFCR = 0;
188  ETH1->MACRXFCR = 0;
189 
190  //Enable the first RX queue
191  ETH1->MACRXQC0R = ETH_MACRXQC0R_RXQ0EN_Val(2);
192 
193  //Configure DMA operating mode
194  ETH1->DMAMR = ETH_DMAMR_INTM_Val(0) | ETH_DMAMR_TXPR_Val(0);
195  //Configure system bus mode
196  ETH1->DMASBMR |= ETH_DMASBMR_AAL;
197 
198  //The DMA takes the descriptor table as contiguous
199  ETH1->DMA_CH[0].DMACCR = ETH_DMACxCR_DSL_Val(0);
200  //Configure TX features
201  ETH1->DMA_CH[0].DMACTXCR = ETH_DMACxTXCR_TXPBL_Val(32);
202 
203  //Configure RX features
204  ETH1->DMA_CH[0].DMACRXCR = ETH_DMACxRXCR_RXPBL_Val(32) |
206 
207  //Enable store and forward mode for transmission
208  ETH1->MTL_QUEUE[0].MTLTXQOMR = ETH_MTLTXQxOMR_TQS_Val(7) | ETH_MTLTXQxOMR_TXQEN_Val(2) |
209  ETH_MTLTXQxOMR_TSF;
210 
211  //Enable store and forward mode for reception
212  ETH1->MTL_QUEUE[0].MTLRXQOMR = ETH_MTLRXQxOMR_RQS_Val(7) | ETH_MTLRXQxOMR_RSF;
213 
214  //Initialize DMA descriptor lists
215  stm32n6xxEthInitDmaDesc(interface);
216 
217  //Prevent interrupts from being generated when the transmit statistic
218  //counters reach half their maximum value
219  ETH1->MMCTIMR = ETH_MMCTIMR_TXLPITRCIM | ETH_MMCTIMR_TXLPIUSCIM |
220  ETH_MMCTIMR_TXGPKTIM | ETH_MMCTIMR_TXMCOLGPIM | ETH_MMCTIMR_TXSCOLGPIM;
221 
222  //Prevent interrupts from being generated when the receive statistic
223  //counters reach half their maximum value
224  ETH1->MMCRIMR = ETH_MMCRIMR_RXLPITRCIM | ETH_MMCRIMR_RXLPIUSCIM |
225  ETH_MMCRIMR_RXUCGPIM | ETH_MMCRIMR_RXALGNERPIM | ETH_MMCRIMR_RXCRCERPIM;
226 
227  //Disable MAC interrupts
228  ETH1->MACIER = 0;
229  //Enable the desired DMA interrupts
230  ETH1->DMA_CH[0].DMACIER = ETH_DMACxIER_NIE | ETH_DMACxIER_RIE | ETH_DMACxIER_TIE;
231 
232  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
233  NVIC_SetPriorityGrouping(STM32N6XX_ETH_IRQ_PRIORITY_GROUPING);
234 
235  //Configure Ethernet interrupt priority
236  NVIC_SetPriority(ETH1_IRQn, NVIC_EncodePriority(STM32N6XX_ETH_IRQ_PRIORITY_GROUPING,
238 
239  //Enable MAC transmission and reception
240  ETH1->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
241 
242  //Enable DMA transmission and reception
243  ETH1->DMA_CH[0].DMACTXCR |= ETH_DMACxTXCR_ST;
244  ETH1->DMA_CH[0].DMACRXCR |= ETH_DMACxRXCR_SR;
245 
246  //Accept any packets from the upper layer
247  osSetEvent(&interface->nicTxEvent);
248 
249  //Successful initialization
250  return NO_ERROR;
251 }
252 
253 
254 /**
255  * @brief GPIO configuration
256  * @param[in] interface Underlying network interface
257  **/
258 
259 __weak_func void stm32n6xxEthInitGpio(NetInterface *interface)
260 {
261 //Nucleo-N657X0-Q evaluation board?
262 #if defined(USE_STM32N6xx_NUCLEO)
263  GPIO_InitTypeDef GPIO_InitStructure;
264 
265  //Enable GPIO clocks
266  __HAL_RCC_GPIOF_CLK_ENABLE();
267  __HAL_RCC_GPIOG_CLK_ENABLE();
268 
269  //Select RMII interface mode
270  SET_BIT(RCC->CCIPR2, RCC_ETH1PHYIF_RMII);
271 
272  //Configure RMII pins
273  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
274  GPIO_InitStructure.Pull = GPIO_NOPULL;
275  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
276  GPIO_InitStructure.Alternate = GPIO_AF11_ETH1;
277 
278  //Configure ETH1_MDIO (PF4), ETH1_RMII_REF_CLK (PF7),
279  //ETH1_RMII_CRS_DV (PF10), ETH1_RMII_TX_EN (PF11), ETH1_RMII_TXD0 (PF12),
280  //ETH1_RMII_TXD1 (PF13), ETH1_RMII_RXD0 (PF14) and ETH1_RMII_RXD1 (PF15)
281  GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_7 | GPIO_PIN_10 |
282  GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
283  HAL_GPIO_Init(GPIOF, &GPIO_InitStructure);
284 
285  //Configure ETH1_MDC (PG11),
286  GPIO_InitStructure.Pin = GPIO_PIN_11;
287  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
288 
289 //STM32N6570-DK evaluation board?
290 #elif defined(USE_STM32N6570_DK)
291  GPIO_InitTypeDef GPIO_InitStructure;
292  GPIO_DelayTypeDef GPIO_DelayStructure;
293 
294  //Enable GPIO clocks
295  __HAL_RCC_GPIOD_CLK_ENABLE();
296  __HAL_RCC_GPIOF_CLK_ENABLE();
297  __HAL_RCC_GPIOG_CLK_ENABLE();
298 
299  //Select RGMII interface mode
300  SET_BIT(RCC->CCIPR2, RCC_ETH1PHYIF_RGMII);
301 
302  //Configure RGMII pins
303  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
304  GPIO_InitStructure.Pull = GPIO_NOPULL;
305  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
306  GPIO_InitStructure.Alternate = GPIO_AF11_ETH1;
307 
308  //Configure ETH1_MDC (PD1) and ETH1_MDIO (PD12)
309  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_12;
310  HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
311 
312  //Configure ETH1_RGMII_CLK125 (PF2), ETH1_RGMII_RX_CLK (PF7),
313  //ETH1_RGMII_RXD2 (PF8), ETH1_RGMII_RXD3 (PF9), ETH1_RGMII_RX_CTL (PF10),
314  //ETH1_RGMII_TX_CTL (PF11), ETH1_RGMII_TXD0 (PF12), ETH1_RMII_TXD1 (PF13),
315  //ETH1_RGMII_RXD0 (PF14) and ETH1_RGMII_RXD1 (PF15)
316  GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
317  GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |
318  GPIO_PIN_15;
319  HAL_GPIO_Init(GPIOF, &GPIO_InitStructure);
320 
321  //Configure ETH1_RGMII_TXD2 (PG3) and ETH1_RGMII_TXD3 (PG4)
322  GPIO_InitStructure.Pin = GPIO_PIN_3 | GPIO_PIN_4;
323  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
324 
325  //Configure ETH1_RGMII_GTX_CLK (PF0)
326  GPIO_InitStructure.Pin = GPIO_PIN_0;
327  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_MEDIUM;
328  GPIO_InitStructure.Alternate = GPIO_AF12_ETH1;
329  HAL_GPIO_Init(GPIOF, &GPIO_InitStructure);
330 
331  //Configure GPIO delay on ETH1_RGMII_RX_CLK (PF7)
332  GPIO_DelayStructure.Delay = GPIO_DELAY_PS_500;
333  GPIO_DelayStructure.Path = GPIO_PATH_IN;
334  HAL_GPIO_SetDelay(GPIOF, GPIO_PIN_7, &GPIO_DelayStructure);
335 #endif
336 }
337 
338 
339 /**
340  * @brief Initialize DMA descriptor lists
341  * @param[in] interface Underlying network interface
342  **/
343 
345 {
346  uint_t i;
347 
348  //Initialize TX DMA descriptor list
349  for(i = 0; i < STM32N6XX_ETH_TX_BUFFER_COUNT; i++)
350  {
351  //The descriptor is initially owned by the application
352  txDmaDesc[i].tdes0 = 0;
353  txDmaDesc[i].tdes1 = 0;
354  txDmaDesc[i].tdes2 = 0;
355  txDmaDesc[i].tdes3 = 0;
356  }
357 
358  //Initialize TX descriptor index
359  txIndex = 0;
360 
361  //Initialize RX DMA descriptor list
362  for(i = 0; i < STM32N6XX_ETH_RX_BUFFER_COUNT; i++)
363  {
364  //The descriptor is initially owned by the DMA
365  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
366  rxDmaDesc[i].rdes1 = 0;
367  rxDmaDesc[i].rdes2 = 0;
369  }
370 
371  //Initialize RX descriptor index
372  rxIndex = 0;
373 
374  //Start location of the TX descriptor list
375  ETH1->DMA_CH[0].DMACTXDLAR = (uint32_t) &txDmaDesc[0];
376  //Length of the transmit descriptor ring
377  ETH1->DMA_CH[0].DMACTXRLR = STM32N6XX_ETH_TX_BUFFER_COUNT - 1;
378 
379  //Start location of the RX descriptor list
380  ETH1->DMA_CH[0].DMACRXDLAR = (uint32_t) &rxDmaDesc[0];
381  //Length of the receive descriptor ring
382  ETH1->DMA_CH[0].DMACRXRLR = STM32N6XX_ETH_RX_BUFFER_COUNT - 1;
383 }
384 
385 
386 /**
387  * @brief STM32N6 Ethernet MAC timer handler
388  *
389  * This routine is periodically called by the TCP/IP stack to handle periodic
390  * operations such as polling the link state
391  *
392  * @param[in] interface Underlying network interface
393  **/
394 
396 {
397  //Valid Ethernet PHY or switch driver?
398  if(interface->phyDriver != NULL)
399  {
400  //Handle periodic operations
401  interface->phyDriver->tick(interface);
402  }
403  else if(interface->switchDriver != NULL)
404  {
405  //Handle periodic operations
406  interface->switchDriver->tick(interface);
407  }
408  else
409  {
410  //Just for sanity
411  }
412 }
413 
414 
415 /**
416  * @brief Enable interrupts
417  * @param[in] interface Underlying network interface
418  **/
419 
421 {
422  //Enable Ethernet MAC interrupts
423  NVIC_EnableIRQ(ETH1_IRQn);
424 
425  //Valid Ethernet PHY or switch driver?
426  if(interface->phyDriver != NULL)
427  {
428  //Enable Ethernet PHY interrupts
429  interface->phyDriver->enableIrq(interface);
430  }
431  else if(interface->switchDriver != NULL)
432  {
433  //Enable Ethernet switch interrupts
434  interface->switchDriver->enableIrq(interface);
435  }
436  else
437  {
438  //Just for sanity
439  }
440 }
441 
442 
443 /**
444  * @brief Disable interrupts
445  * @param[in] interface Underlying network interface
446  **/
447 
449 {
450  //Disable Ethernet MAC interrupts
451  NVIC_DisableIRQ(ETH1_IRQn);
452 
453  //Valid Ethernet PHY or switch driver?
454  if(interface->phyDriver != NULL)
455  {
456  //Disable Ethernet PHY interrupts
457  interface->phyDriver->disableIrq(interface);
458  }
459  else if(interface->switchDriver != NULL)
460  {
461  //Disable Ethernet switch interrupts
462  interface->switchDriver->disableIrq(interface);
463  }
464  else
465  {
466  //Just for sanity
467  }
468 }
469 
470 
471 /**
472  * @brief STM32N6 Ethernet MAC interrupt service routine
473  **/
474 
475 void ETH1_IRQHandler(void)
476 {
477  bool_t flag;
478  uint32_t status;
479 
480  //Interrupt service routine prologue
481  osEnterIsr();
482 
483  //This flag will be set if a higher priority task must be woken
484  flag = FALSE;
485 
486  //Read DMA status register
487  status = ETH1->DMA_CH[0].DMACSR;
488 
489  //Packet transmitted?
490  if((status & ETH_DMACxSR_TI) != 0)
491  {
492  //Clear TI interrupt flag
493  ETH1->DMA_CH[0].DMACSR = ETH_DMACxSR_TI;
494 
495  //Check whether the TX buffer is available for writing
496  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
497  {
498  //Notify the TCP/IP stack that the transmitter is ready to send
499  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
500  }
501  }
502 
503  //Packet received?
504  if((status & ETH_DMACxSR_RI) != 0)
505  {
506  //Clear RI interrupt flag
507  ETH1->DMA_CH[0].DMACSR = ETH_DMACxSR_RI;
508 
509  //Set event flag
510  nicDriverInterface->nicEvent = TRUE;
511  //Notify the TCP/IP stack of the event
512  flag |= osSetEventFromIsr(&netEvent);
513  }
514 
515  //Clear NIS interrupt flag
516  ETH1->DMA_CH[0].DMACSR = ETH_DMACxSR_NIS;
517 
518  //Interrupt service routine epilogue
519  osExitIsr(flag);
520 }
521 
522 
523 /**
524  * @brief STM32N6 Ethernet MAC event handler
525  * @param[in] interface Underlying network interface
526  **/
527 
529 {
530  error_t error;
531 
532  //Process all pending packets
533  do
534  {
535  //Read incoming packet
536  error = stm32n6xxEthReceivePacket(interface);
537 
538  //No more data in the receive buffer?
539  } while(error != ERROR_BUFFER_EMPTY);
540 }
541 
542 
543 /**
544  * @brief Send a packet
545  * @param[in] interface Underlying network interface
546  * @param[in] buffer Multi-part buffer containing the data to send
547  * @param[in] offset Offset to the first data byte
548  * @param[in] ancillary Additional options passed to the stack along with
549  * the packet
550  * @return Error code
551  **/
552 
554  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
555 {
556  size_t length;
557 
558  //Retrieve the length of the packet
559  length = netBufferGetLength(buffer) - offset;
560 
561  //Check the frame length
563  {
564  //The transmitter can accept another packet
565  osSetEvent(&interface->nicTxEvent);
566  //Report an error
567  return ERROR_INVALID_LENGTH;
568  }
569 
570  //Make sure the current buffer is available for writing
571  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) != 0)
572  {
573  return ERROR_FAILURE;
574  }
575 
576  //Copy user data to the transmit buffer
577  netBufferRead(txBuffer[txIndex], buffer, offset, length);
578 
579  //Set the start address of the buffer
580  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
581  //Write the number of bytes to send
582  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
583  //Give the ownership of the descriptor to the DMA
584  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
585 
586  //Data synchronization barrier
587  __DSB();
588 
589  //Clear TBU flag to resume processing
590  ETH1->DMA_CH[0].DMACSR = ETH_DMACxSR_TBU;
591  //Instruct the DMA to poll the transmit descriptor list
592  ETH1->DMA_CH[0].DMACTXDTPR = 0;
593 
594  //Increment index and wrap around if necessary
595  if(++txIndex >= STM32N6XX_ETH_TX_BUFFER_COUNT)
596  {
597  txIndex = 0;
598  }
599 
600  //Check whether the next buffer is available for writing
601  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
602  {
603  //The transmitter can accept another packet
604  osSetEvent(&interface->nicTxEvent);
605  }
606 
607  //Data successfully written
608  return NO_ERROR;
609 }
610 
611 
612 /**
613  * @brief Receive a packet
614  * @param[in] interface Underlying network interface
615  * @return Error code
616  **/
617 
619 {
620  error_t error;
621  size_t n;
622  NetRxAncillary ancillary;
623 
624  //Current buffer available for reading?
625  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN) == 0)
626  {
627  //FD and LD flags should be set
628  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) != 0 &&
629  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD) != 0)
630  {
631  //Make sure no error occurred
632  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_ES) == 0)
633  {
634  //Retrieve the length of the frame
635  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
636  //Limit the number of data to read
638 
639  //Additional options can be passed to the stack along with the packet
640  ancillary = NET_DEFAULT_RX_ANCILLARY;
641 
642  //Pass the packet to the upper layer
643  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
644 
645  //Valid packet received
646  error = NO_ERROR;
647  }
648  else
649  {
650  //The received packet contains an error
651  error = ERROR_INVALID_PACKET;
652  }
653  }
654  else
655  {
656  //The packet is not valid
657  error = ERROR_INVALID_PACKET;
658  }
659 
660  //Set the start address of the buffer
661  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
662  //Give the ownership of the descriptor back to the DMA
664 
665  //Increment index and wrap around if necessary
666  if(++rxIndex >= STM32N6XX_ETH_RX_BUFFER_COUNT)
667  {
668  rxIndex = 0;
669  }
670  }
671  else
672  {
673  //No more data in the receive buffer
674  error = ERROR_BUFFER_EMPTY;
675  }
676 
677  //Clear RBU flag to resume processing
678  ETH1->DMA_CH[0].DMACSR = ETH_DMACxSR_RBU;
679  //Instruct the DMA to poll the receive descriptor list
680  ETH1->DMA_CH[0].DMACRXDTPR = 0;
681 
682  //Return status code
683  return error;
684 }
685 
686 
687 /**
688  * @brief Configure MAC address filtering
689  * @param[in] interface Underlying network interface
690  * @return Error code
691  **/
692 
694 {
695  uint_t i;
696  uint_t j;
697  uint_t k;
698  uint32_t crc;
699  uint32_t hashTable[2];
700  MacAddr unicastMacAddr[3];
701  MacFilterEntry *entry;
702 
703  //Debug message
704  TRACE_DEBUG("Updating MAC filter...\r\n");
705 
706  //Promiscuous mode?
707  if(interface->promiscuous)
708  {
709  //Pass all incoming frames regardless of their destination address
710  ETH1->MACPFR = ETH_MACPFR_PR;
711  }
712  else
713  {
714  //Set the MAC address of the station
715  ETH1->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
716  ETH1->MACA0HR = interface->macAddr.w[2];
717 
718  //The MAC supports 3 additional addresses for unicast perfect filtering
719  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
720  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
721  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
722 
723  //The hash table is used for multicast address filtering
724  hashTable[0] = 0;
725  hashTable[1] = 0;
726 
727  //The MAC address filter contains the list of MAC addresses to accept
728  //when receiving an Ethernet frame
729  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
730  {
731  //Point to the current entry
732  entry = &interface->macAddrFilter[i];
733 
734  //Valid entry?
735  if(entry->refCount > 0)
736  {
737  //Multicast address?
738  if(macIsMulticastAddr(&entry->addr))
739  {
740  //Compute CRC over the current MAC address
741  crc = stm32n6xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
742 
743  //The upper 6 bits in the CRC register are used to index the
744  //contents of the hash table
745  k = (crc >> 26) & 0x3F;
746 
747  //Update hash table contents
748  hashTable[k / 32] |= (1 << (k % 32));
749  }
750  else
751  {
752  //Up to 3 additional MAC addresses can be specified
753  if(j < 3)
754  {
755  //Save the unicast address
756  unicastMacAddr[j++] = entry->addr;
757  }
758  }
759  }
760  }
761 
762  //Configure the first unicast address filter
763  if(j >= 1)
764  {
765  //When the AE bit is set, the entry is used for perfect filtering
766  ETH1->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
767  ETH1->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACAxHR_AE;
768  }
769  else
770  {
771  //When the AE bit is cleared, the entry is ignored
772  ETH1->MACA1LR = 0;
773  ETH1->MACA1HR = 0;
774  }
775 
776  //Configure the second unicast address filter
777  if(j >= 2)
778  {
779  //When the AE bit is set, the entry is used for perfect filtering
780  ETH1->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
781  ETH1->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACAxHR_AE;
782  }
783  else
784  {
785  //When the AE bit is cleared, the entry is ignored
786  ETH1->MACA2LR = 0;
787  ETH1->MACA2HR = 0;
788  }
789 
790  //Configure the third unicast address filter
791  if(j >= 3)
792  {
793  //When the AE bit is set, the entry is used for perfect filtering
794  ETH1->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
795  ETH1->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACAxHR_AE;
796  }
797  else
798  {
799  //When the AE bit is cleared, the entry is ignored
800  ETH1->MACA3LR = 0;
801  ETH1->MACA3HR = 0;
802  }
803 
804  //Check whether frames with a multicast destination address should be
805  //accepted
806  if(interface->acceptAllMulticast)
807  {
808  //Configure the receive filter
809  ETH1->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_PM;
810  }
811  else
812  {
813  //Configure the receive filter
814  ETH1->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_HMC;
815 
816  //Configure the multicast hash table
817  ETH1->MACHT0R = hashTable[0];
818  ETH1->MACHT1R = hashTable[1];
819 
820  //Debug message
821  TRACE_DEBUG(" MACHT0R = %08" PRIX32 "\r\n", ETH1->MACHT0R);
822  TRACE_DEBUG(" MACHT1R = %08" PRIX32 "\r\n", ETH1->MACHT1R);
823  }
824  }
825 
826  //Successful processing
827  return NO_ERROR;
828 }
829 
830 
831 /**
832  * @brief Adjust MAC configuration parameters for proper operation
833  * @param[in] interface Underlying network interface
834  * @return Error code
835  **/
836 
838 {
839  uint32_t config;
840 
841  //Read current MAC configuration
842  config = ETH1->MACCR;
843 
844  //1000BASE-T operation mode?
845  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
846  {
847  config &= ~ETH_MACCR_PS;
848  config &= ~ETH_MACCR_FES;
849  }
850  //100BASE-TX operation mode?
851  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
852  {
853  config |= ETH_MACCR_PS;
854  config |= ETH_MACCR_FES;
855  }
856  //10BASE-T operation mode?
857  else
858  {
859  config |= ETH_MACCR_PS;
860  config &= ~ETH_MACCR_FES;
861  }
862 
863  //Half-duplex or full-duplex mode?
864  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
865  {
866  config |= ETH_MACCR_DM;
867  }
868  else
869  {
870  config &= ~ETH_MACCR_DM;
871  }
872 
873  //Update MAC configuration register
874  ETH1->MACCR = config;
875 
876  //Successful processing
877  return NO_ERROR;
878 }
879 
880 
881 /**
882  * @brief Write PHY register
883  * @param[in] opcode Access type (2 bits)
884  * @param[in] phyAddr PHY address (5 bits)
885  * @param[in] regAddr Register address (5 bits)
886  * @param[in] data Register value
887  **/
888 
889 void stm32n6xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
890  uint8_t regAddr, uint16_t data)
891 {
892  uint32_t temp;
893 
894  //Valid opcode?
895  if(opcode == SMI_OPCODE_WRITE)
896  {
897  //Take care not to alter MDC clock configuration
898  temp = ETH1->MACMDIOAR & ETH_MACMDIOAR_CR;
899  //Set up a write operation
900  temp |= ETH_MACMDIOAR_GOC_Val(1) | ETH_MACMDIOAR_GB;
901  //PHY address
902  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
903  //Register address
904  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
905 
906  //Data to be written in the PHY register
907  ETH1->MACMDIODR = data & ETH_MACMDIODR_GD;
908 
909  //Start a write operation
910  ETH1->MACMDIOAR = temp;
911  //Wait for the write to complete
912  while((ETH1->MACMDIOAR & ETH_MACMDIOAR_GB) != 0)
913  {
914  }
915  }
916  else
917  {
918  //The MAC peripheral only supports standard Clause 22 opcodes
919  }
920 }
921 
922 
923 /**
924  * @brief Read PHY register
925  * @param[in] opcode Access type (2 bits)
926  * @param[in] phyAddr PHY address (5 bits)
927  * @param[in] regAddr Register address (5 bits)
928  * @return Register value
929  **/
930 
931 uint16_t stm32n6xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
932  uint8_t regAddr)
933 {
934  uint16_t data;
935  uint32_t temp;
936 
937  //Valid opcode?
938  if(opcode == SMI_OPCODE_READ)
939  {
940  //Take care not to alter MDC clock configuration
941  temp = ETH1->MACMDIOAR & ETH_MACMDIOAR_CR;
942  //Set up a read operation
943  temp |= ETH_MACMDIOAR_GOC_Val(3) | ETH_MACMDIOAR_GB;
944  //PHY address
945  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
946  //Register address
947  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
948 
949  //Start a read operation
950  ETH1->MACMDIOAR = temp;
951  //Wait for the read to complete
952  while((ETH1->MACMDIOAR & ETH_MACMDIOAR_GB) != 0)
953  {
954  }
955 
956  //Get register value
957  data = ETH1->MACMDIODR & ETH_MACMDIODR_GD;
958  }
959  else
960  {
961  //The MAC peripheral only supports standard Clause 22 opcodes
962  data = 0;
963  }
964 
965  //Return the value of the PHY register
966  return data;
967 }
968 
969 
970 /**
971  * @brief CRC calculation
972  * @param[in] data Pointer to the data over which to calculate the CRC
973  * @param[in] length Number of bytes to process
974  * @return Resulting CRC value
975  **/
976 
977 uint32_t stm32n6xxEthCalcCrc(const void *data, size_t length)
978 {
979  uint_t i;
980  uint_t j;
981  uint32_t crc;
982  const uint8_t *p;
983 
984  //Point to the data over which to calculate the CRC
985  p = (uint8_t *) data;
986  //CRC preset value
987  crc = 0xFFFFFFFF;
988 
989  //Loop through data
990  for(i = 0; i < length; i++)
991  {
992  //The message is processed bit by bit
993  for(j = 0; j < 8; j++)
994  {
995  //Update CRC value
996  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
997  {
998  crc = (crc << 1) ^ 0x04C11DB7;
999  }
1000  else
1001  {
1002  crc = crc << 1;
1003  }
1004  }
1005  }
1006 
1007  //Return CRC value
1008  return ~crc;
1009 }
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 STM32N6XX_ETH_IRQ_GROUP_PRIORITY
#define STM32N6XX_ETH_RX_BUFFER_SIZE
uint8_t opcode
Definition: dns_common.h:190
int bool_t
Definition: compiler_port.h:61
error_t stm32n6xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define netEvent
Definition: net_legacy.h:196
Transmit descriptor.
#define ETH_MTLTXQxOMR_TXQEN_Val(n)
@ 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_MTLTXQxOMR_TQS_Val(n)
#define ETH_RDES3_LD
#define ETH_MACMDIOAR_CR_Val(n)
#define ETH_DMACxRXCR_RBSZ_Val(n)
void stm32n6xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
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 ETH_MTLRXQxOMR_RQS_Val(n)
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
#define ETH_TDES3_LD
void stm32n6xxEthTick(NetInterface *interface)
STM32N6 Ethernet MAC timer handler.
#define STM32N6XX_ETH_RX_BUFFER_COUNT
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
#define STM32N6XX_ETH_TX_BUFFER_SIZE
uint32_t stm32n6xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
Receive descriptor.
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 ETH_DMACxCR_DSL_Val(n)
#define FALSE
Definition: os_port.h:46
#define STM32N6XX_ETH_IRQ_PRIORITY_GROUPING
error_t
Error codes.
Definition: error.h:43
error_t stm32n6xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define ETH_TDES2_B1L
#define ETH_DMAMR_TXPR_Val(n)
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
void stm32n6xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:265
uint16_t stm32n6xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
@ 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_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
const NicDriver stm32n6xxEthDriver
STM32N6 Ethernet MAC driver.
void stm32n6xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define MIN(a, b)
Definition: os_port.h:63
#define ETH_RDES3_OWN
#define ETH_TDES3_OWN
#define rxBuffer
MacAddr
Definition: ethernet.h:197
#define TRACE_DEBUG(...)
Definition: debug.h:119
void stm32n6xxEthEventHandler(NetInterface *interface)
STM32N6 Ethernet MAC event handler.
error_t stm32n6xxEthInit(NetInterface *interface)
STM32N6 Ethernet MAC initialization.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:264
#define ETH_RDES3_FD
__weak_func void stm32n6xxEthInitGpio(NetInterface *interface)
GPIO configuration.
#define osEnterIsr()
#define STM32N6XX_ETH_IRQ_SUB_PRIORITY
#define ETH_DMAMR_INTM_Val(n)
#define STM32N6XX_ETH_TX_BUFFER_COUNT
#define rxDmaDesc
void stm32n6xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
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 STM32N6XX_ETH_RAM_SECTION
#define ETH_DMACxTXCR_TXPBL_Val(n)
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define ETH_DMACxRXCR_RXPBL_Val(n)
#define ETH_RDES3_IOC
STM32N6 Gigabit Ethernet MAC driver.
error_t stm32n6xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
error_t stm32n6xxEthReceivePacket(NetInterface *interface)
Receive a packet.
void ETH1_IRQHandler(void)
STM32N6 Ethernet MAC interrupt service routine.
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