stm32mp1xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file stm32mp1xx_eth_driver.c
3  * @brief STM32MP1 Gigabit Ethernet MAC controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 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 1.9.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "stm32mp1xx.h"
36 #include "stm32mp1xx_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 STM32MP1 Ethernet MAC driver
86  **/
87 
89 {
91  ETH_MTU,
102  TRUE,
103  TRUE,
104  TRUE,
105  FALSE
106 };
107 
108 
109 /**
110  * @brief STM32MP1 Ethernet MAC initialization
111  * @param[in] interface Underlying network interface
112  * @return Error code
113  **/
114 
116 {
117  error_t error;
118 
119  //Debug message
120  TRACE_INFO("Initializing STM32MP1 Ethernet MAC...\r\n");
121 
122  //Save underlying network interface
123  nicDriverInterface = interface;
124 
125  //GPIO configuration
126  stm32mp1xxEthInitGpio(interface);
127 
128  //Enable Ethernet MAC clock
129  __HAL_RCC_ETH1MAC_CLK_ENABLE();
130  __HAL_RCC_ETH1TX_CLK_ENABLE();
131  __HAL_RCC_ETH1RX_CLK_ENABLE();
132 
133  //Reset Ethernet MAC peripheral
134  __HAL_RCC_ETH1MAC_FORCE_RESET();
135  __HAL_RCC_ETH1MAC_RELEASE_RESET();
136 
137  //Perform a software reset
138  ETH->DMAMR |= ETH_DMAMR_SWR;
139  //Wait for the reset to complete
140  while(ETH->DMAMR & ETH_DMAMR_SWR)
141  {
142  }
143 
144  //Adjust MDC clock range depending on HCLK frequency
145  ETH->MACMDIOAR = ETH_MACMDIOAR_CR_DIV124;
146 
147  //PHY transceiver initialization
148  error = interface->phyDriver->init(interface);
149  //Failed to initialize PHY transceiver?
150  if(error)
151  return error;
152 
153  //Use default MAC configuration
154  ETH->MACCR = ETH_MACCR_DO;
155 
156  //Set the MAC address of the station
157  ETH->MACA0LR = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
158  ETH->MACA0HR = interface->macAddr.w[2];
159 
160  //The MAC supports 3 additional addresses for unicast perfect filtering
161  ETH->MACA1LR = 0;
162  ETH->MACA1HR = 0;
163  ETH->MACA2LR = 0;
164  ETH->MACA2HR = 0;
165  ETH->MACA3LR = 0;
166  ETH->MACA3HR = 0;
167 
168  //Initialize hash table
169  ETH->MACHTHR = 0;
170  ETH->MACHTLR = 0;
171 
172  //Configure the receive filter
173  ETH->MACPFR = ETH_MACPFR_HPF | ETH_MACPFR_HMC;
174 
175  //Disable flow control
176  ETH->MACTFCR = 0;
177  ETH->MACRFCR = 0;
178 
179  //Enable the first RX queue
180  ETH->MACRC0R = ETH_MACRC0R_RXQ0EN_1;
181 
182  //Configure DMA operating mode
183  ETH->DMAMR = ETH_DMAMR_INTM_0 | ETH_DMAMR_PR_1_1;
184  //Configure system bus mode
185  ETH->DMASBMR |= ETH_DMASBMR_AAL;
186  //The DMA takes the descriptor table as contiguous
187  ETH->DMACCR = ETH_DMACCR_DSL_0BIT;
188 
189  //Configure TX features
190  ETH->DMACTCR = ETH_DMACTCR_TPBL_1PBL;
191 
192  //Configure RX features
193  ETH->DMACRCR = ETH_DMACRCR_RPBL_1PBL;
194  ETH->DMACRCR |= (STM32MP1XX_ETH_RX_BUFFER_SIZE << 1) & ETH_DMACRCR_RBSZ;
195 
196  //Enable store and forward mode for transmission
197  ETH->MTLTQOMR = ETH_MTLTQOMR_TQS_7 | ETH_MTLTQOMR_TXQEN_2 | ETH_MTLTQOMR_TSF;
198  //Enable store and forward mode for reception
199  ETH->MTLRQOMR = ETH_MTLRQOMR_RQS_7 | ETH_MTLRQOMR_RSF;
200 
201  //Initialize DMA descriptor lists
202  stm32mp1xxEthInitDmaDesc(interface);
203 
204  //Prevent interrupts from being generated when the transmit statistic
205  //counters reach half their maximum value
208 
209  //Prevent interrupts from being generated when the receive statistic
210  //counters reach half their maximum value
213 
214  //Disable MAC interrupts
215  ETH->MACIER = 0;
216  //Enable the desired DMA interrupts
217  ETH->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE;
218 
219  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
220  NVIC_SetPriorityGrouping(STM32MP1XX_ETH_IRQ_PRIORITY_GROUPING);
221 
222  //Configure Ethernet interrupt priority
223  NVIC_SetPriority(ETH1_IRQn, NVIC_EncodePriority(STM32MP1XX_ETH_IRQ_PRIORITY_GROUPING,
225 
226  //Enable MAC transmission and reception
227  ETH->MACCR |= ETH_MACCR_TE | ETH_MACCR_RE;
228 
229  //Enable DMA transmission and reception
230  ETH->DMACTCR |= ETH_DMACTCR_ST;
231  ETH->DMACRCR |= ETH_DMACRCR_SR;
232 
233  //Accept any packets from the upper layer
234  osSetEvent(&interface->nicTxEvent);
235 
236  //Successful initialization
237  return NO_ERROR;
238 }
239 
240 
241 //STM32MP157A-EV1 or STM32MP157C-DK2 evaluation board?
242 #if defined(USE_STM32MP15XX_EVAL) || defined(USE_STM32MP15XX_DISCO)
243 
244 /**
245  * @brief GPIO configuration
246  * @param[in] interface Underlying network interface
247  **/
248 
249 void stm32mp1xxEthInitGpio(NetInterface *interface)
250 {
251  GPIO_InitTypeDef GPIO_InitStructure;
252 
253 //STM32MP157A-EV1 evaluation board?
254 #if defined(USE_STM32MP15XX_EVAL)
255  //Enable SYSCFG clock
256  __HAL_RCC_SYSCFG_CLK_ENABLE();
257 
258  //Enable GPIO clocks
259  __HAL_RCC_GPIOA_CLK_ENABLE();
260  __HAL_RCC_GPIOB_CLK_ENABLE();
261  __HAL_RCC_GPIOC_CLK_ENABLE();
262  __HAL_RCC_GPIOE_CLK_ENABLE();
263  __HAL_RCC_GPIOG_CLK_ENABLE();
264 
265  //Select RGMII interface mode
266  HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_RGMII);
267 
268  //Configure RGMII pins
269  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
270  GPIO_InitStructure.Pull = GPIO_NOPULL;
271  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
272  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
273 
274  //Configure ETH1_RGMII_RX_CLK (PA1), ETH1_MDIO (PA2) and
275  //ETH1_RGMII_RX_CTL (PA7)
276  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
277  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
278 
279  //Configure ETH1_RGMII_RXD2 (PB0), ETH1_RGMII_RXD3 (PB1) and
280  //ETH1_RGMII_TX_CTL (PB11)
281  GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_11;
282  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
283 
284  //Configure ETH1_MDC (PC1), ETH1_RGMII_TXD2 (PC2), ETH1_RGMII_RXD0 (PC4) and
285  //ETH1_RGMII_RXD1 (PC5)
286  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5;
287  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
288 
289  //Configure ETH1_RGMII_TXD3 (PE2)
290  GPIO_InitStructure.Pin = GPIO_PIN_2;
291  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
292 
293  //Configure ETH1_RGMII_GTX_CLK (PG4), ETH1_RGMII_CLK125 (PG5),
294  //ETH1_RGMII_TXD0 (PG13) and ETH1_RMII_TXD1 (PG14)
295  GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_13 | GPIO_PIN_14;
296  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
297 
298 //STM32MP157C-DK2 evaluation board?
299 #elif defined(USE_STM32MP15XX_DISCO)
300  //Enable SYSCFG clock
301  __HAL_RCC_SYSCFG_CLK_ENABLE();
302 
303  //Enable GPIO clocks
304  __HAL_RCC_GPIOA_CLK_ENABLE();
305  __HAL_RCC_GPIOB_CLK_ENABLE();
306  __HAL_RCC_GPIOC_CLK_ENABLE();
307  __HAL_RCC_GPIOE_CLK_ENABLE();
308  __HAL_RCC_GPIOG_CLK_ENABLE();
309 
310  //Select RGMII interface mode
311  HAL_SYSCFG_ETHInterfaceSelect(SYSCFG_ETH_RGMII);
312 
313  //Configure RGMII pins
314  GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
315  GPIO_InitStructure.Pull = GPIO_NOPULL;
316  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
317  GPIO_InitStructure.Alternate = GPIO_AF11_ETH;
318 
319  //Configure ETH1_RGMII_RX_CLK (PA1), ETH1_MDIO (PA2) and
320  //ETH1_RGMII_RX_CTL (PA7)
321  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7;
322  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
323 
324  //Configure ETH1_RGMII_RXD2 (PB0), ETH1_RGMII_RXD3 (PB1) and
325  //ETH1_RGMII_TX_CTL (PB11)
326  GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_11;
327  HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
328 
329  //Configure ETH1_MDC (PC1), ETH1_RGMII_TXD2 (PC2), ETH1_RGMII_RXD0 (PC4) and
330  //ETH1_RGMII_RXD1 (PC5)
331  GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5;
332  HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
333 
334  //Configure ETH1_RGMII_TXD3 (PE2)
335  GPIO_InitStructure.Pin = GPIO_PIN_2;
336  HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
337 
338  //Configure ETH1_RGMII_GTX_CLK (PG4), ETH1_RGMII_CLK125 (PG5),
339  //ETH1_RGMII_TXD0 (PG13) and ETH1_RMII_TXD1 (PG14)
340  GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_13 | GPIO_PIN_14;
341  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
342 
343  //Configure PHY_RST (PG0)
344  GPIO_InitStructure.Pin = GPIO_PIN_0;
345  GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
346  GPIO_InitStructure.Pull = GPIO_NOPULL;
347  GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
348  HAL_GPIO_Init(GPIOG, &GPIO_InitStructure);
349 
350  //Reset PHY transceiver
351  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_RESET);
352  sleep(10);
353  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_SET);
354  sleep(10);
355 #endif
356 }
357 
358 #endif
359 
360 
361 /**
362  * @brief Initialize DMA descriptor lists
363  * @param[in] interface Underlying network interface
364  **/
365 
367 {
368  uint_t i;
369 
370  //Initialize TX DMA descriptor list
371  for(i = 0; i < STM32MP1XX_ETH_TX_BUFFER_COUNT; i++)
372  {
373  //The descriptor is initially owned by the application
374  txDmaDesc[i].tdes0 = 0;
375  txDmaDesc[i].tdes1 = 0;
376  txDmaDesc[i].tdes2 = 0;
377  txDmaDesc[i].tdes3 = 0;
378  }
379 
380  //Initialize TX descriptor index
381  txIndex = 0;
382 
383  //Initialize RX DMA descriptor list
384  for(i = 0; i < STM32MP1XX_ETH_RX_BUFFER_COUNT; i++)
385  {
386  //The descriptor is initially owned by the DMA
387  rxDmaDesc[i].rdes0 = (uint32_t) rxBuffer[i];
388  rxDmaDesc[i].rdes1 = 0;
389  rxDmaDesc[i].rdes2 = 0;
391  }
392 
393  //Initialize RX descriptor index
394  rxIndex = 0;
395 
396  //Start location of the TX descriptor list
397  ETH->DMACTDLAR = (uint32_t) &txDmaDesc[0];
398  //Length of the transmit descriptor ring
399  ETH->DMACTDRLR = STM32MP1XX_ETH_TX_BUFFER_COUNT - 1;
400 
401  //Start location of the RX descriptor list
402  ETH->DMACRDLAR = (uint32_t) &rxDmaDesc[0];
403  //Length of the receive descriptor ring
404  ETH->DMACRDRLR = STM32MP1XX_ETH_RX_BUFFER_COUNT - 1;
405 }
406 
407 
408 /**
409  * @brief STM32MP1 Ethernet MAC timer handler
410  *
411  * This routine is periodically called by the TCP/IP stack to
412  * handle periodic operations such as polling the link state
413  *
414  * @param[in] interface Underlying network interface
415  **/
416 
418 {
419  //Handle periodic operations
420  interface->phyDriver->tick(interface);
421 }
422 
423 
424 /**
425  * @brief Enable interrupts
426  * @param[in] interface Underlying network interface
427  **/
428 
430 {
431  //Enable Ethernet MAC interrupts
432  NVIC_EnableIRQ(ETH1_IRQn);
433  //Enable Ethernet PHY interrupts
434  interface->phyDriver->enableIrq(interface);
435 }
436 
437 
438 /**
439  * @brief Disable interrupts
440  * @param[in] interface Underlying network interface
441  **/
442 
444 {
445  //Disable Ethernet MAC interrupts
446  NVIC_DisableIRQ(ETH1_IRQn);
447  //Disable Ethernet PHY interrupts
448  interface->phyDriver->disableIrq(interface);
449 }
450 
451 
452 /**
453  * @brief STM32MP1 Ethernet MAC interrupt service routine
454  **/
455 
456 void ETH1_IRQHandler(void)
457 {
458  bool_t flag;
459  uint32_t status;
460 
461  //Interrupt service routine prologue
462  osEnterIsr();
463 
464  //This flag will be set if a higher priority task must be woken
465  flag = FALSE;
466 
467  //Read DMA status register
468  status = ETH->DMACSR;
469 
470  //A packet has been transmitted?
471  if(status & ETH_DMACSR_TI)
472  {
473  //Clear TI interrupt flag
474  ETH->DMACSR = ETH_DMACSR_TI;
475 
476  //Check whether the TX buffer is available for writing
477  if(!(txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN))
478  {
479  //Notify the TCP/IP stack that the transmitter is ready to send
480  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
481  }
482  }
483 
484  //A packet has been received?
485  if(status & ETH_DMACSR_RI)
486  {
487  //Disable RIE interrupt
488  ETH->DMACIER &= ~ETH_DMACIER_RIE;
489 
490  //Set event flag
491  nicDriverInterface->nicEvent = TRUE;
492  //Notify the TCP/IP stack of the event
493  flag |= osSetEventFromIsr(&netEvent);
494  }
495 
496  //Clear NIS interrupt flag
497  ETH->DMACSR = ETH_DMACSR_NIS;
498 
499  //Interrupt service routine epilogue
500  osExitIsr(flag);
501 }
502 
503 
504 /**
505  * @brief STM32MP1 Ethernet MAC event handler
506  * @param[in] interface Underlying network interface
507  **/
508 
510 {
511  error_t error;
512 
513  //Packet received?
514  if(ETH->DMACSR & ETH_DMACSR_RI)
515  {
516  //Clear interrupt flag
517  ETH->DMACSR = ETH_DMACSR_RI;
518 
519  //Process all pending packets
520  do
521  {
522  //Read incoming packet
523  error = stm32mp1xxEthReceivePacket(interface);
524 
525  //No more data in the receive buffer?
526  } while(error != ERROR_BUFFER_EMPTY);
527  }
528 
529  //Re-enable DMA interrupts
530  ETH->DMACIER = ETH_DMACIER_NIE | ETH_DMACIER_RIE | ETH_DMACIER_TIE;
531 }
532 
533 
534 /**
535  * @brief Send a packet
536  * @param[in] interface Underlying network interface
537  * @param[in] buffer Multi-part buffer containing the data to send
538  * @param[in] offset Offset to the first data byte
539  * @return Error code
540  **/
541 
543  const NetBuffer *buffer, size_t offset)
544 {
545  size_t length;
546 
547  //Retrieve the length of the packet
548  length = netBufferGetLength(buffer) - offset;
549 
550  //Check the frame length
552  {
553  //The transmitter can accept another packet
554  osSetEvent(&interface->nicTxEvent);
555  //Report an error
556  return ERROR_INVALID_LENGTH;
557  }
558 
559  //Make sure the current buffer is available for writing
560  if(txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN)
561  return ERROR_FAILURE;
562 
563  //Copy user data to the transmit buffer
564  netBufferRead(txBuffer[txIndex], buffer, offset, length);
565 
566  //Set the start address of the buffer
567  txDmaDesc[txIndex].tdes0 = (uint32_t) txBuffer[txIndex];
568  //Write the number of bytes to send
569  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
570  //Give the ownership of the descriptor to the DMA
571  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
572 
573  //Data synchronization barrier
574  __DSB();
575 
576  //Clear TBU flag to resume processing
577  ETH->DMACSR = ETH_DMACSR_TBU;
578  //Instruct the DMA to poll the transmit descriptor list
579  ETH->DMACTDTPR = 0;
580 
581  //Increment index and wrap around if necessary
582  if(++txIndex >= STM32MP1XX_ETH_TX_BUFFER_COUNT)
583  txIndex = 0;
584 
585  //Check whether the next buffer is available for writing
586  if(!(txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN))
587  {
588  //The transmitter can accept another packet
589  osSetEvent(&interface->nicTxEvent);
590  }
591 
592  //Data successfully written
593  return NO_ERROR;
594 }
595 
596 
597 /**
598  * @brief Receive a packet
599  * @param[in] interface Underlying network interface
600  * @return Error code
601  **/
602 
604 {
605  error_t error;
606  size_t n;
607 
608  //The current buffer is available for reading?
609  if(!(rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN))
610  {
611  //FD and LD flags should be set
612  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) &&
613  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD))
614  {
615  //Make sure no error occurred
616  if(!(rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_ES))
617  {
618  //Retrieve the length of the frame
619  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
620  //Limit the number of data to read
622 
623  //Pass the packet to the upper layer
624  nicProcessPacket(interface, rxBuffer[rxIndex], n);
625 
626  //Valid packet received
627  error = NO_ERROR;
628  }
629  else
630  {
631  //The received packet contains an error
632  error = ERROR_INVALID_PACKET;
633  }
634  }
635  else
636  {
637  //The packet is not valid
638  error = ERROR_INVALID_PACKET;
639  }
640 
641  //Set the start address of the buffer
642  rxDmaDesc[rxIndex].rdes0 = (uint32_t) rxBuffer[rxIndex];
643  //Give the ownership of the descriptor back to the DMA
645 
646  //Increment index and wrap around if necessary
647  if(++rxIndex >= STM32MP1XX_ETH_RX_BUFFER_COUNT)
648  rxIndex = 0;
649  }
650  else
651  {
652  //No more data in the receive buffer
653  error = ERROR_BUFFER_EMPTY;
654  }
655 
656  //Clear RBU flag to resume processing
657  ETH->DMACSR = ETH_DMACSR_RBU;
658  //Instruct the DMA to poll the receive descriptor list
659  ETH->DMACRDTPR = 0;
660 
661  //Return status code
662  return error;
663 }
664 
665 
666 /**
667  * @brief Configure MAC address filtering
668  * @param[in] interface Underlying network interface
669  * @return Error code
670  **/
671 
673 {
674  uint_t i;
675  uint_t j;
676  uint_t k;
677  uint32_t crc;
678  uint32_t hashTable[2];
679  MacAddr unicastMacAddr[3];
680  MacFilterEntry *entry;
681 
682  //Debug message
683  TRACE_DEBUG("Updating MAC filter...\r\n");
684 
685  //The MAC supports 3 additional addresses for unicast perfect filtering
686  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
687  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
688  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
689 
690  //The hash table is used for multicast address filtering
691  hashTable[0] = 0;
692  hashTable[1] = 0;
693 
694  //The MAC address filter contains the list of MAC addresses to accept
695  //when receiving an Ethernet frame
696  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
697  {
698  //Point to the current entry
699  entry = &interface->macAddrFilter[i];
700 
701  //Valid entry?
702  if(entry->refCount > 0)
703  {
704  //Multicast address?
705  if(macIsMulticastAddr(&entry->addr))
706  {
707  //Compute CRC over the current MAC address
708  crc = stm32mp1xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
709 
710  //The upper 6 bits in the CRC register are used to index the
711  //contents of the hash table
712  k = (crc >> 26) & 0x3F;
713 
714  //Update hash table contents
715  hashTable[k / 32] |= (1 << (k % 32));
716  }
717  else
718  {
719  //Up to 3 additional MAC addresses can be specified
720  if(j < 3)
721  {
722  //Save the unicast address
723  unicastMacAddr[j++] = entry->addr;
724  }
725  }
726  }
727  }
728 
729  //Configure the first unicast address filter
730  if(j >= 1)
731  {
732  //When the AE bit is set, the entry is used for perfect filtering
733  ETH->MACA1LR = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
734  ETH->MACA1HR = unicastMacAddr[0].w[2] | ETH_MACAHR_AE;
735  }
736  else
737  {
738  //When the AE bit is cleared, the entry is ignored
739  ETH->MACA1LR = 0;
740  ETH->MACA1HR = 0;
741  }
742 
743  //Configure the second unicast address filter
744  if(j >= 2)
745  {
746  //When the AE bit is set, the entry is used for perfect filtering
747  ETH->MACA2LR = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
748  ETH->MACA2HR = unicastMacAddr[1].w[2] | ETH_MACAHR_AE;
749  }
750  else
751  {
752  //When the AE bit is cleared, the entry is ignored
753  ETH->MACA2LR = 0;
754  ETH->MACA2HR = 0;
755  }
756 
757  //Configure the third unicast address filter
758  if(j >= 3)
759  {
760  //When the AE bit is set, the entry is used for perfect filtering
761  ETH->MACA3LR = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
762  ETH->MACA3HR = unicastMacAddr[2].w[2] | ETH_MACAHR_AE;
763  }
764  else
765  {
766  //When the AE bit is cleared, the entry is ignored
767  ETH->MACA3LR = 0;
768  ETH->MACA3HR = 0;
769  }
770 
771  //Configure the multicast address filter
772  ETH->MACHTHR = hashTable[0];
773  ETH->MACHTLR = hashTable[1];
774 
775  //Debug message
776  TRACE_DEBUG(" MACHTHR = %08" PRIX32 "\r\n", ETH->MACHTHR);
777  TRACE_DEBUG(" MACHTLR = %08" PRIX32 "\r\n", ETH->MACHTLR);
778 
779  //Successful processing
780  return NO_ERROR;
781 }
782 
783 
784 /**
785  * @brief Adjust MAC configuration parameters for proper operation
786  * @param[in] interface Underlying network interface
787  * @return Error code
788  **/
789 
791 {
792  uint32_t config;
793 
794  //Read current MAC configuration
795  config = ETH->MACCR;
796 
797  //1000BASE-T operation mode?
798  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
799  {
800  config &= ~ETH_MACCR_PS;
801  config &= ~ETH_MACCR_FES;
802  }
803  //100BASE-TX operation mode?
804  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
805  {
806  config |= ETH_MACCR_PS;
807  config |= ETH_MACCR_FES;
808  }
809  //10BASE-T operation mode?
810  else
811  {
812  config |= ETH_MACCR_PS;
813  config &= ~ETH_MACCR_FES;
814  }
815 
816  //Half-duplex or full-duplex mode?
817  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
818  config |= ETH_MACCR_DM;
819  else
820  config &= ~ETH_MACCR_DM;
821 
822  //Update MAC configuration register
823  ETH->MACCR = config;
824 
825  //Successful processing
826  return NO_ERROR;
827 }
828 
829 
830 /**
831  * @brief Write PHY register
832  * @param[in] opcode Access type (2 bits)
833  * @param[in] phyAddr PHY address (5 bits)
834  * @param[in] regAddr Register address (5 bits)
835  * @param[in] data Register value
836  **/
837 
838 void stm32mp1xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
839  uint8_t regAddr, uint16_t data)
840 {
841  uint32_t temp;
842 
843  //Valid opcode?
844  if(opcode == SMI_OPCODE_WRITE)
845  {
846  //Take care not to alter MDC clock configuration
847  temp = ETH->MACMDIOAR & ETH_MACMDIOAR_CR;
848  //Set up a write operation
849  temp |= ETH_MACMDIOAR_MOC_WR | ETH_MACMDIOAR_MB;
850  //PHY address
851  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
852  //Register address
853  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
854 
855  //Data to be written in the PHY register
856  ETH->MACMDIODR = data & ETH_MACMDIODR_MD;
857 
858  //Start a write operation
859  ETH->MACMDIOAR = temp;
860  //Wait for the write to complete
861  while(ETH->MACMDIOAR & ETH_MACMDIOAR_MB)
862  {
863  }
864  }
865  else
866  {
867  //The MAC peripheral only supports standard Clause 22 opcodes
868  }
869 }
870 
871 
872 /**
873  * @brief Read PHY register
874  * @param[in] opcode Access type (2 bits)
875  * @param[in] phyAddr PHY address (5 bits)
876  * @param[in] regAddr Register address (5 bits)
877  * @return Register value
878  **/
879 
880 uint16_t stm32mp1xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
881  uint8_t regAddr)
882 {
883  uint16_t data;
884  uint32_t temp;
885 
886  //Valid opcode?
887  if(opcode == SMI_OPCODE_READ)
888  {
889  //Take care not to alter MDC clock configuration
890  temp = ETH->MACMDIOAR & ETH_MACMDIOAR_CR;
891  //Set up a read operation
892  temp |= ETH_MACMDIOAR_MOC_RD | ETH_MACMDIOAR_MB;
893  //PHY address
894  temp |= (phyAddr << 21) & ETH_MACMDIOAR_PA;
895  //Register address
896  temp |= (regAddr << 16) & ETH_MACMDIOAR_RDA;
897 
898  //Start a read operation
899  ETH->MACMDIOAR = temp;
900  //Wait for the read to complete
901  while(ETH->MACMDIOAR & ETH_MACMDIOAR_MB)
902  {
903  }
904 
905  //Get register value
906  data = ETH->MACMDIODR & ETH_MACMDIODR_MD;
907  }
908  else
909  {
910  //The MAC peripheral only supports standard Clause 22 opcodes
911  data = 0;
912  }
913 
914  //Return the value of the PHY register
915  return data;
916 }
917 
918 
919 /**
920  * @brief CRC calculation
921  * @param[in] data Pointer to the data over which to calculate the CRC
922  * @param[in] length Number of bytes to process
923  * @return Resulting CRC value
924  **/
925 
926 uint32_t stm32mp1xxEthCalcCrc(const void *data, size_t length)
927 {
928  uint_t i;
929  uint_t j;
930 
931  //Point to the data over which to calculate the CRC
932  const uint8_t *p = (uint8_t *) data;
933  //CRC preset value
934  uint32_t crc = 0xFFFFFFFF;
935 
936  //Loop through data
937  for(i = 0; i < length; i++)
938  {
939  //The message is processed bit by bit
940  for(j = 0; j < 8; j++)
941  {
942  //Update CRC value
943  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
944  crc = (crc << 1) ^ 0x04C11DB7;
945  else
946  crc = crc << 1;
947  }
948  }
949 
950  //Return CRC value
951  return ~crc;
952 }
#define txDmaDesc
#define ETH_RDES3_LD
Receive descriptor.
MacAddr addr
MAC address.
Definition: ethernet.h:222
#define ETH_MMCTIMR_TXSCOLGPIM
void stm32mp1xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
TCP/IP stack core.
#define ETH_MACRC0R_RXQ0EN_1
#define ETH_RDES3_ES
error_t stm32mp1xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#define ETH_TDES2_IOC
#define STM32MP1XX_ETH_IRQ_SUB_PRIORITY
Debugging facilities.
uint8_t p
Definition: ndp.h:298
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define ETH_TDES2_B1L
Generic error code.
Definition: error.h:45
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:110
#define rxDmaDesc
#define ETH_RDES3_BUF1V
#define STM32MP1XX_ETH_TX_BUFFER_COUNT
#define ETH_MMCRIMR_RXLPIUSCIM
#define txBuffer
void stm32mp1xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define ETH_TDES3_FD
#define sleep(delay)
Definition: os_port.h:128
#define SMI_OPCODE_READ
Definition: nic.h:63
#define STM32MP1XX_ETH_RX_BUFFER_SIZE
#define ETH_MMCRIMR_RXALGNERPIM
error_t stm32mp1xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
__start_packed struct @108 MacAddr
MAC address.
#define ETH_RDES3_IOC
#define ETH_MMCRIMR_RXLPITRCIM
error_t stm32mp1xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
uint16_t stm32mp1xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
void stm32mp1xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define TRUE
Definition: os_port.h:50
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#define ETH_MTLTQOMR_TQS_7
#define SMI_OPCODE_WRITE
Definition: nic.h:62
uint8_t opcode
Definition: dns_common.h:172
void stm32mp1xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
void stm32mp1xxEthEventHandler(NetInterface *interface)
STM32MP1 Ethernet MAC event handler.
#define STM32MP1XX_ETH_IRQ_PRIORITY_GROUPING
#define ETH_MMCRIMR_RXCRCERPIM
uint32_t stm32mp1xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
void stm32mp1xxEthInitGpio(NetInterface *interface)
#define ETH_RDES3_PL
Transmit descriptor.
#define ETH_MTLTQOMR_TXQEN_2
error_t stm32mp1xxEthReceivePacket(NetInterface *interface)
Receive a packet.
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:672
NIC driver.
Definition: nic.h:179
#define STM32MP1XX_ETH_RX_BUFFER_COUNT
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define MIN(a, b)
Definition: os_port.h:62
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
#define ETH_MMCTIMR_TXMCOLGPIM
void stm32mp1xxEthTick(NetInterface *interface)
STM32MP1 Ethernet MAC timer handler.
#define TRACE_INFO(...)
Definition: debug.h:94
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
Ethernet interface.
Definition: nic.h:79
Success.
Definition: error.h:44
#define rxBuffer
#define ETH_RDES3_FD
OsEvent netEvent
Definition: net.c:74
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:223
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
error_t
Error codes.
Definition: error.h:42
unsigned int uint_t
Definition: compiler_port.h:45
STM32MP1 Gigabit Ethernet MAC controller.
#define ETH_MMCTIMR_TXLPIUSCIM
uint8_t data[]
Definition: dtls_misc.h:169
#define NetInterface
Definition: net.h:36
#define ETH_RDES3_OWN
#define STM32MP1XX_ETH_IRQ_GROUP_PRIORITY
void ETH1_IRQHandler(void)
STM32MP1 Ethernet MAC interrupt service routine.
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:395
#define ETH_MMCTIMR_TXGPKTIM
#define ETH_MMCTIMR_TXLPITRCIM
#define ETH_MTLRQOMR_RQS_7
#define ETH_MMCRIMR_RXUCGPIM
#define osExitIsr(flag)
#define ETH_TDES3_LD
#define ETH_TDES3_OWN
#define osEnterIsr()
uint8_t length
Definition: dtls_misc.h:142
uint8_t n
#define STM32MP1XX_ETH_TX_BUFFER_SIZE
#define FALSE
Definition: os_port.h:46
int bool_t
Definition: compiler_port.h:49
error_t stm32mp1xxEthInit(NetInterface *interface)
STM32MP1 Ethernet MAC initialization.
const NicDriver stm32mp1xxEthDriver
STM32MP1 Ethernet MAC driver.
MAC filter table entry.
Definition: ethernet.h:220
#define TRACE_DEBUG(...)
Definition: debug.h:106