gd32h7xx_eth2_driver.c
Go to the documentation of this file.
1 /**
2  * @file gd32h7xx_eth2_driver.c
3  * @brief GigaDevice GD32H7 Ethernet MAC driver (ENET1 instance)
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.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "gd32h7xx.h"
36 #include "core/net.h"
38 #include "debug.h"
39 
40 //Underlying network interface
41 static NetInterface *nicDriverInterface;
42 
43 //IAR EWARM compiler?
44 #if defined(__ICCARM__)
45 
46 //Transmit buffer
47 #pragma data_alignment = 4
48 #pragma location = STM32H7XX_ETH2_RAM_SECTION
50 //Receive buffer
51 #pragma data_alignment = 4
52 #pragma location = STM32H7XX_ETH2_RAM_SECTION
54 //Transmit DMA descriptors
55 #pragma data_alignment = 4
56 #pragma location = STM32H7XX_ETH2_RAM_SECTION
58 //Receive DMA descriptors
59 #pragma data_alignment = 4
60 #pragma location = STM32H7XX_ETH2_RAM_SECTION
62 
63 //Keil MDK-ARM or GCC compiler?
64 #else
65 
66 //Transmit buffer
68  __attribute__((aligned(4), __section__(STM32H7XX_ETH2_RAM_SECTION)));
69 //Receive buffer
71  __attribute__((aligned(4), __section__(STM32H7XX_ETH2_RAM_SECTION)));
72 //Transmit DMA descriptors
74  __attribute__((aligned(4), __section__(STM32H7XX_ETH2_RAM_SECTION)));
75 //Receive DMA descriptors
77  __attribute__((aligned(4), __section__(STM32H7XX_ETH2_RAM_SECTION)));
78 
79 #endif
80 
81 //Pointer to the current TX DMA descriptor
82 static Gd32h7xxEth2TxDmaDesc *txCurDmaDesc;
83 //Pointer to the current RX DMA descriptor
84 static Gd32h7xxEth2RxDmaDesc *rxCurDmaDesc;
85 
86 
87 /**
88  * @brief GD32H7 Ethernet MAC driver (ENET1 instance)
89  **/
90 
92 {
94  ETH_MTU,
105  TRUE,
106  TRUE,
107  TRUE,
108  FALSE
109 };
110 
111 
112 /**
113  * @brief GD32H7 Ethernet MAC initialization
114  * @param[in] interface Underlying network interface
115  * @return Error code
116  **/
117 
119 {
120  error_t error;
121 
122  //Debug message
123  TRACE_INFO("Initializing GD32H7 Ethernet MAC (ENET1)...\r\n");
124 
125  //Save underlying network interface
126  nicDriverInterface = interface;
127 
128  //GPIO configuration
129  gd32h7xxEth2InitGpio(interface);
130 
131  //Enable Ethernet MAC clock
132  rcu_periph_clock_enable(RCU_ENET1);
133  rcu_periph_clock_enable(RCU_ENET1TX);
134  rcu_periph_clock_enable(RCU_ENET1RX);
135 
136  //Reset Ethernet MAC peripheral
137  rcu_periph_reset_enable(RCU_ENET1RST);
138  rcu_periph_reset_disable(RCU_ENET1RST);
139 
140  //Perform a software reset
141  ENET_DMA_BCTL(ENET1) |= ENET_DMA_BCTL_SWR;
142  //Wait for the reset to complete
143  while((ENET_DMA_BCTL(ENET1) & ENET_DMA_BCTL_SWR) != 0)
144  {
145  }
146 
147  //Adjust MDC clock range depending on HCLK frequency
148  ENET_MAC_PHY_CTL(ENET1) = ENET_MDC_HCLK_DIV62;
149 
150  //Valid Ethernet PHY or switch driver?
151  if(interface->phyDriver != NULL)
152  {
153  //Ethernet PHY initialization
154  error = interface->phyDriver->init(interface);
155  }
156  else if(interface->switchDriver != NULL)
157  {
158  //Ethernet switch initialization
159  error = interface->switchDriver->init(interface);
160  }
161  else
162  {
163  //The interface is not properly configured
164  error = ERROR_FAILURE;
165  }
166 
167  //Any error to report?
168  if(error)
169  {
170  return error;
171  }
172 
173  //Use default MAC configuration
174  ENET_MAC_CFG(ENET1) = ENET_MAC_CFG_ROD;
175 
176  //Set the MAC address of the station
177  ENET_MAC_ADDR0L(ENET1) = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
178  ENET_MAC_ADDR0H(ENET1) = interface->macAddr.w[2] | ENET_MAC_ADDR0H_MO;
179 
180  //The MAC supports 3 additional addresses for unicast perfect filtering
181  ENET_MAC_ADDR1L(ENET1) = 0;
182  ENET_MAC_ADDR1H(ENET1) = 0;
183  ENET_MAC_ADDR2L(ENET1) = 0;
184  ENET_MAC_ADDT2H(ENET1) = 0;
185  ENET_MAC_ADDR3L(ENET1) = 0;
186  ENET_MAC_ADDR3H(ENET1) = 0;
187 
188  //Initialize hash table
189  ENET_MAC_HLL(ENET1) = 0;
190  ENET_MAC_HLH(ENET1) = 0;
191 
192  //Configure the receive filter
193  ENET_MAC_FRMF(ENET1) = ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_HMF;
194  //Disable flow control
195  ENET_MAC_FCTL(ENET1) = 0;
196  //Enable store and forward mode
197  ENET_DMA_CTL(ENET1) = ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD;
198 
199  //Configure DMA bus mode
200  ENET_DMA_BCTL(ENET1) = ENET_DMA_BCTL_AA | ENET_DMA_BCTL_UIP | ENET_RXDP_32BEAT |
201  ENET_ARBITRATION_RXTX_1_1 | ENET_PGBL_32BEAT | ENET_DMA_BCTL_DFM;
202 
203  //Initialize DMA descriptor lists
204  gd32h7xxEth2InitDmaDesc(interface);
205 
206  //Prevent interrupts from being generated when the transmit statistic
207  //counters reach half their maximum value
208  ENET_MSC_TINTMSK(ENET1) = ENET_MSC_TINTMSK_TGFIM | ENET_MSC_TINTMSK_TGFMSCIM |
209  ENET_MSC_TINTMSK_TGFSCIM;
210 
211  //Prevent interrupts from being generated when the receive statistic
212  //counters reach half their maximum value
213  ENET_MSC_RINTMSK(ENET1) = ENET_MSC_RINTMSK_RGUFIM | ENET_MSC_RINTMSK_RFAEIM |
214  ENET_MSC_RINTMSK_RFCEIM;
215 
216  //Disable MAC interrupts
217  ENET_MAC_INTMSK(ENET1) = ENET_MAC_INTMSK_TMSTIM | ENET_MAC_INTMSK_WUMIM;
218  //Enable the desired DMA interrupts
219  ENET_DMA_INTEN(ENET1) = ENET_DMA_INTEN_NIE | ENET_DMA_INTEN_RIE | ENET_DMA_INTEN_TIE;
220 
221  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
222  NVIC_SetPriorityGrouping(GD32H7XX_ETH2_IRQ_PRIORITY_GROUPING);
223 
224  //Configure Ethernet interrupt priority
225  NVIC_SetPriority(ENET1_IRQn, NVIC_EncodePriority(GD32H7XX_ETH2_IRQ_PRIORITY_GROUPING,
227 
228  //Enable MAC transmission and reception
229  ENET_MAC_CFG(ENET1) |= ENET_MAC_CFG_TEN | ENET_MAC_CFG_REN;
230  //Enable DMA transmission and reception
231  ENET_DMA_CTL(ENET1) |= ENET_DMA_CTL_STE | ENET_DMA_CTL_SRE;
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 /**
242  * @brief GPIO configuration
243  * @param[in] interface Underlying network interface
244  **/
245 
246 __weak_func void gd32h7xxEth2InitGpio(NetInterface *interface)
247 {
248 }
249 
250 
251 /**
252  * @brief Initialize DMA descriptor lists
253  * @param[in] interface Underlying network interface
254  **/
255 
257 {
258  uint_t i;
259 
260  //Initialize TX DMA descriptor list
261  for(i = 0; i < GD32H7XX_ETH2_TX_BUFFER_COUNT; i++)
262  {
263  //Use chain structure rather than ring structure
264  txDmaDesc[i].tdes0 = ENET_TDES0_INTC | ENET_TDES0_TCHM;
265  //Initialize transmit buffer size
266  txDmaDesc[i].tdes1 = 0;
267  //Transmit buffer address
268  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
269  //Next descriptor address
270  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
271  //Reserved fields
272  txDmaDesc[i].tdes4 = 0;
273  txDmaDesc[i].tdes5 = 0;
274  //Transmit frame time stamp
275  txDmaDesc[i].tdes6 = 0;
276  txDmaDesc[i].tdes7 = 0;
277  }
278 
279  //The last descriptor is chained to the first entry
280  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
281  //Point to the very first descriptor
282  txCurDmaDesc = &txDmaDesc[0];
283 
284  //Initialize RX DMA descriptor list
285  for(i = 0; i < GD32H7XX_ETH2_RX_BUFFER_COUNT; i++)
286  {
287  //The descriptor is initially owned by the DMA
288  rxDmaDesc[i].rdes0 = ENET_RDES0_DAV;
289  //Use chain structure rather than ring structure
290  rxDmaDesc[i].rdes1 = ENET_RDES1_RCHM | (GD32H7XX_ETH2_RX_BUFFER_SIZE & ENET_RDES1_RB1S);
291  //Receive buffer address
292  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
293  //Next descriptor address
294  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
295  //Extended status
296  rxDmaDesc[i].rdes4 = 0;
297  //Reserved field
298  rxDmaDesc[i].rdes5 = 0;
299  //Receive frame time stamp
300  rxDmaDesc[i].rdes6 = 0;
301  rxDmaDesc[i].rdes7 = 0;
302  }
303 
304  //The last descriptor is chained to the first entry
305  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
306  //Point to the very first descriptor
307  rxCurDmaDesc = &rxDmaDesc[0];
308 
309  //Start location of the TX descriptor list
310  ENET_DMA_TDTADDR(ENET1) = (uint32_t) txDmaDesc;
311  //Start location of the RX descriptor list
312  ENET_DMA_RDTADDR(ENET1) = (uint32_t) rxDmaDesc;
313 }
314 
315 
316 /**
317  * @brief GD32H7 Ethernet MAC timer handler
318  *
319  * This routine is periodically called by the TCP/IP stack to handle periodic
320  * operations such as polling the link state
321  *
322  * @param[in] interface Underlying network interface
323  **/
324 
326 {
327  //Valid Ethernet PHY or switch driver?
328  if(interface->phyDriver != NULL)
329  {
330  //Handle periodic operations
331  interface->phyDriver->tick(interface);
332  }
333  else if(interface->switchDriver != NULL)
334  {
335  //Handle periodic operations
336  interface->switchDriver->tick(interface);
337  }
338  else
339  {
340  //Just for sanity
341  }
342 }
343 
344 
345 /**
346  * @brief Enable interrupts
347  * @param[in] interface Underlying network interface
348  **/
349 
351 {
352  //Enable Ethernet MAC interrupts
353  NVIC_EnableIRQ(ENET1_IRQn);
354 
355  //Valid Ethernet PHY or switch driver?
356  if(interface->phyDriver != NULL)
357  {
358  //Enable Ethernet PHY interrupts
359  interface->phyDriver->enableIrq(interface);
360  }
361  else if(interface->switchDriver != NULL)
362  {
363  //Enable Ethernet switch interrupts
364  interface->switchDriver->enableIrq(interface);
365  }
366  else
367  {
368  //Just for sanity
369  }
370 }
371 
372 
373 /**
374  * @brief Disable interrupts
375  * @param[in] interface Underlying network interface
376  **/
377 
379 {
380  //Disable Ethernet MAC interrupts
381  NVIC_DisableIRQ(ENET1_IRQn);
382 
383  //Valid Ethernet PHY or switch driver?
384  if(interface->phyDriver != NULL)
385  {
386  //Disable Ethernet PHY interrupts
387  interface->phyDriver->disableIrq(interface);
388  }
389  else if(interface->switchDriver != NULL)
390  {
391  //Disable Ethernet switch interrupts
392  interface->switchDriver->disableIrq(interface);
393  }
394  else
395  {
396  //Just for sanity
397  }
398 }
399 
400 
401 /**
402  * @brief GD32H7 Ethernet MAC interrupt service routine
403  **/
404 
406 {
407  bool_t flag;
408  uint32_t status;
409 
410  //Interrupt service routine prologue
411  osEnterIsr();
412 
413  //This flag will be set if a higher priority task must be woken
414  flag = FALSE;
415 
416  //Read DMA status register
417  status = ENET_DMA_STAT(ENET1);
418 
419  //Packet transmitted?
420  if((status & ENET_DMA_STAT_TS) != 0)
421  {
422  //Clear TS interrupt flag
423  ENET_DMA_STAT(ENET1) = ENET_DMA_STAT_TS;
424 
425  //Check whether the TX buffer is available for writing
426  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) == 0)
427  {
428  //Notify the TCP/IP stack that the transmitter is ready to send
429  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
430  }
431  }
432 
433  //Packet received?
434  if((status & ENET_DMA_STAT_RS) != 0)
435  {
436  //Clear RS interrupt flag
437  ENET_DMA_STAT(ENET1) = ENET_DMA_STAT_RS;
438 
439  //Set event flag
440  nicDriverInterface->nicEvent = TRUE;
441  //Notify the TCP/IP stack of the event
442  flag |= osSetEventFromIsr(&netEvent);
443  }
444 
445  //Clear NIS interrupt flag
446  ENET_DMA_STAT(ENET1) = ENET_DMA_STAT_NI;
447 
448  //Interrupt service routine epilogue
449  osExitIsr(flag);
450 }
451 
452 
453 /**
454  * @brief GD32H7 Ethernet MAC event handler
455  * @param[in] interface Underlying network interface
456  **/
457 
459 {
460  error_t error;
461 
462  //Process all pending packets
463  do
464  {
465  //Read incoming packet
466  error = gd32h7xxEth2ReceivePacket(interface);
467 
468  //No more data in the receive buffer?
469  } while(error != ERROR_BUFFER_EMPTY);
470 }
471 
472 
473 /**
474  * @brief Send a packet
475  * @param[in] interface Underlying network interface
476  * @param[in] buffer Multi-part buffer containing the data to send
477  * @param[in] offset Offset to the first data byte
478  * @param[in] ancillary Additional options passed to the stack along with
479  * the packet
480  * @return Error code
481  **/
482 
484  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
485 {
486  size_t length;
487 
488  //Retrieve the length of the packet
489  length = netBufferGetLength(buffer) - offset;
490 
491  //Check the frame length
493  {
494  //The transmitter can accept another packet
495  osSetEvent(&interface->nicTxEvent);
496  //Report an error
497  return ERROR_INVALID_LENGTH;
498  }
499 
500  //Make sure the current buffer is available for writing
501  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) != 0)
502  {
503  return ERROR_FAILURE;
504  }
505 
506  //Copy user data to the transmit buffer
507  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
508 
509  //Write the number of bytes to send
510  txCurDmaDesc->tdes1 = length & ENET_TDES1_TB1S;
511  //Set LS and FS flags as the data fits in a single buffer
512  txCurDmaDesc->tdes0 |= ENET_TDES0_LSG | ENET_TDES0_FSG;
513  //Give the ownership of the descriptor to the DMA
514  txCurDmaDesc->tdes0 |= ENET_TDES0_DAV;
515 
516  //Data synchronization barrier
517  __DSB();
518 
519  //Clear TBU flag to resume processing
520  ENET_DMA_STAT(ENET1) = ENET_DMA_STAT_TBU;
521  //Instruct the DMA to poll the transmit descriptor list
522  ENET_DMA_TPEN(ENET1) = 0;
523 
524  //Point to the next descriptor in the list
525  txCurDmaDesc = (Gd32h7xxEth2TxDmaDesc *) txCurDmaDesc->tdes3;
526 
527  //Check whether the next buffer is available for writing
528  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) == 0)
529  {
530  //The transmitter can accept another packet
531  osSetEvent(&interface->nicTxEvent);
532  }
533 
534  //Data successfully written
535  return NO_ERROR;
536 }
537 
538 
539 /**
540  * @brief Receive a packet
541  * @param[in] interface Underlying network interface
542  * @return Error code
543  **/
544 
546 {
547  error_t error;
548  size_t n;
549  NetRxAncillary ancillary;
550 
551  //Current buffer available for reading?
552  if((rxCurDmaDesc->rdes0 & ENET_RDES0_DAV) == 0)
553  {
554  //FS and LS flags should be set
555  if((rxCurDmaDesc->rdes0 & ENET_RDES0_FDES) != 0 &&
556  (rxCurDmaDesc->rdes0 & ENET_RDES0_LDES) != 0)
557  {
558  //Make sure no error occurred
559  if((rxCurDmaDesc->rdes0 & ENET_RDES0_ERRS) == 0)
560  {
561  //Retrieve the length of the frame
562  n = (rxCurDmaDesc->rdes0 & ENET_RDES0_FRML) >> 16;
563  //Limit the number of data to read
565 
566  //Additional options can be passed to the stack along with the packet
567  ancillary = NET_DEFAULT_RX_ANCILLARY;
568 
569  //Pass the packet to the upper layer
570  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
571  &ancillary);
572 
573  //Valid packet received
574  error = NO_ERROR;
575  }
576  else
577  {
578  //The received packet contains an error
579  error = ERROR_INVALID_PACKET;
580  }
581  }
582  else
583  {
584  //The packet is not valid
585  error = ERROR_INVALID_PACKET;
586  }
587 
588  //Give the ownership of the descriptor back to the DMA
589  rxCurDmaDesc->rdes0 = ENET_RDES0_DAV;
590  //Point to the next descriptor in the list
591  rxCurDmaDesc = (Gd32h7xxEth2RxDmaDesc *) rxCurDmaDesc->rdes3;
592  }
593  else
594  {
595  //No more data in the receive buffer
596  error = ERROR_BUFFER_EMPTY;
597  }
598 
599  //Clear RBU flag to resume processing
600  ENET_DMA_STAT(ENET1) = ENET_DMA_STAT_RBU;
601  //Instruct the DMA to poll the receive descriptor list
602  ENET_DMA_RPEN(ENET1) = 0;
603 
604  //Return status code
605  return error;
606 }
607 
608 
609 /**
610  * @brief Configure MAC address filtering
611  * @param[in] interface Underlying network interface
612  * @return Error code
613  **/
614 
616 {
617  uint_t i;
618  uint_t j;
619  uint_t k;
620  uint32_t crc;
621  uint32_t hashTable[2];
622  MacAddr unicastMacAddr[3];
623  MacFilterEntry *entry;
624 
625  //Debug message
626  TRACE_DEBUG("Updating MAC filter...\r\n");
627 
628  //Set the MAC address of the station
629  ENET_MAC_ADDR0L(ENET1) = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
630  ENET_MAC_ADDR0H(ENET1) = interface->macAddr.w[2] | ENET_MAC_ADDR0H_MO;
631 
632  //The MAC supports 3 additional addresses for unicast perfect filtering
633  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
634  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
635  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
636 
637  //The hash table is used for multicast address filtering
638  hashTable[0] = 0;
639  hashTable[1] = 0;
640 
641  //The MAC address filter contains the list of MAC addresses to accept
642  //when receiving an Ethernet frame
643  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
644  {
645  //Point to the current entry
646  entry = &interface->macAddrFilter[i];
647 
648  //Valid entry?
649  if(entry->refCount > 0)
650  {
651  //Multicast address?
652  if(macIsMulticastAddr(&entry->addr))
653  {
654  //Compute CRC over the current MAC address
655  crc = gd32h7xxEth2CalcCrc(&entry->addr, sizeof(MacAddr));
656 
657  //The upper 6 bits in the CRC register are used to index the
658  //contents of the hash table
659  k = (crc >> 26) & 0x3F;
660 
661  //Update hash table contents
662  hashTable[k / 32] |= (1 << (k % 32));
663  }
664  else
665  {
666  //Up to 3 additional MAC addresses can be specified
667  if(j < 3)
668  {
669  //Save the unicast address
670  unicastMacAddr[j++] = entry->addr;
671  }
672  }
673  }
674  }
675 
676  //Configure the first unicast address filter
677  if(j >= 1)
678  {
679  //When the AE bit is set, the entry is used for perfect filtering
680  ENET_MAC_ADDR1L(ENET1) = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
681  ENET_MAC_ADDR1H(ENET1) = unicastMacAddr[0].w[2] | ENET_MAC_ADDR1H_AFE;
682  }
683  else
684  {
685  //When the AE bit is cleared, the entry is ignored
686  ENET_MAC_ADDR1L(ENET1) = 0;
687  ENET_MAC_ADDR1H(ENET1) = 0;
688  }
689 
690  //Configure the second unicast address filter
691  if(j >= 2)
692  {
693  //When the AE bit is set, the entry is used for perfect filtering
694  ENET_MAC_ADDR2L(ENET1) = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
695  ENET_MAC_ADDT2H(ENET1) = unicastMacAddr[1].w[2] | ENET_MAC_ADDR2H_AFE;
696  }
697  else
698  {
699  //When the AE bit is cleared, the entry is ignored
700  ENET_MAC_ADDR2L(ENET1) = 0;
701  ENET_MAC_ADDT2H(ENET1) = 0;
702  }
703 
704  //Configure the third unicast address filter
705  if(j >= 3)
706  {
707  //When the AE bit is set, the entry is used for perfect filtering
708  ENET_MAC_ADDR3L(ENET1) = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
709  ENET_MAC_ADDR3H(ENET1) = unicastMacAddr[2].w[2] | ENET_MAC_ADDR3H_AFE;
710  }
711  else
712  {
713  //When the AE bit is cleared, the entry is ignored
714  ENET_MAC_ADDR3L(ENET1) = 0;
715  ENET_MAC_ADDR3H(ENET1) = 0;
716  }
717 
718  //Configure the multicast hash table
719  ENET_MAC_HLL(ENET1) = hashTable[0];
720  ENET_MAC_HLH(ENET1) = hashTable[1];
721 
722  //Debug message
723  TRACE_DEBUG(" ENET_MAC_HLL = %08" PRIX32 "\r\n", ENET_MAC_HLL(ENET1));
724  TRACE_DEBUG(" ENET_MAC_HLH = %08" PRIX32 "\r\n", ENET_MAC_HLH(ENET1));
725 
726  //Successful processing
727  return NO_ERROR;
728 }
729 
730 
731 /**
732  * @brief Adjust MAC configuration parameters for proper operation
733  * @param[in] interface Underlying network interface
734  * @return Error code
735  **/
736 
738 {
739  uint32_t config;
740 
741  //Read current MAC configuration
742  config = ENET_MAC_CFG(ENET1);
743 
744  //10BASE-T or 100BASE-TX operation mode?
745  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
746  {
747  config |= ENET_MAC_CFG_SPD;
748  }
749  else
750  {
751  config &= ~ENET_MAC_CFG_SPD;
752  }
753 
754  //Half-duplex or full-duplex mode?
755  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
756  {
757  config |= ENET_MAC_CFG_DPM;
758  }
759  else
760  {
761  config &= ~ENET_MAC_CFG_DPM;
762  }
763 
764  //Update MAC configuration register
765  ENET_MAC_CFG(ENET1) = config;
766 
767  //Successful processing
768  return NO_ERROR;
769 }
770 
771 
772 /**
773  * @brief Write PHY register
774  * @param[in] opcode Access type (2 bits)
775  * @param[in] phyAddr PHY address (5 bits)
776  * @param[in] regAddr Register address (5 bits)
777  * @param[in] data Register value
778  **/
779 
780 void gd32h7xxEth2WritePhyReg(uint8_t opcode, uint8_t phyAddr,
781  uint8_t regAddr, uint16_t data)
782 {
783  uint32_t temp;
784 
785  //Valid opcode?
786  if(opcode == SMI_OPCODE_WRITE)
787  {
788  //Take care not to alter MDC clock configuration
789  temp = ENET_MAC_PHY_CTL(ENET1) & ENET_MAC_PHY_CTL_CLR;
790  //Set up a write operation
791  temp |= ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PB;
792  //PHY address
793  temp |= MAC_PHY_CTL_PA(phyAddr);
794  //Register address
795  temp |= MAC_PHY_CTL_PR(regAddr);
796 
797  //Data to be written in the PHY register
798  ENET_MAC_PHY_DATA(ENET1) = data & ENET_MAC_PHY_DATA_PD;
799 
800  //Start a write operation
801  ENET_MAC_PHY_CTL(ENET1) = temp;
802  //Wait for the write to complete
803  while((ENET_MAC_PHY_CTL(ENET1) & ENET_MAC_PHY_CTL_PB) != 0)
804  {
805  }
806  }
807  else
808  {
809  //The MAC peripheral only supports standard Clause 22 opcodes
810  }
811 }
812 
813 
814 /**
815  * @brief Read PHY register
816  * @param[in] opcode Access type (2 bits)
817  * @param[in] phyAddr PHY address (5 bits)
818  * @param[in] regAddr Register address (5 bits)
819  * @return Register value
820  **/
821 
822 uint16_t gd32h7xxEth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr,
823  uint8_t regAddr)
824 {
825  uint16_t data;
826  uint32_t temp;
827 
828  //Valid opcode?
829  if(opcode == SMI_OPCODE_READ)
830  {
831  //Take care not to alter MDC clock configuration
832  temp = ENET_MAC_PHY_CTL(ENET1) & ENET_MAC_PHY_CTL_CLR;
833  //Set up a read operation
834  temp |= ENET_MAC_PHY_CTL_PB;
835  //PHY address
836  temp |= MAC_PHY_CTL_PA(phyAddr);
837  //Register address
838  temp |= MAC_PHY_CTL_PR(regAddr);
839 
840  //Start a read operation
841  ENET_MAC_PHY_CTL(ENET1) = temp;
842  //Wait for the read to complete
843  while((ENET_MAC_PHY_CTL(ENET1) & ENET_MAC_PHY_CTL_PB) != 0)
844  {
845  }
846 
847  //Get register value
848  data = ENET_MAC_PHY_DATA(ENET1) & ENET_MAC_PHY_DATA_PD;
849  }
850  else
851  {
852  //The MAC peripheral only supports standard Clause 22 opcodes
853  data = 0;
854  }
855 
856  //Return the value of the PHY register
857  return data;
858 }
859 
860 
861 /**
862  * @brief CRC calculation
863  * @param[in] data Pointer to the data over which to calculate the CRC
864  * @param[in] length Number of bytes to process
865  * @return Resulting CRC value
866  **/
867 
868 uint32_t gd32h7xxEth2CalcCrc(const void *data, size_t length)
869 {
870  uint_t i;
871  uint_t j;
872  uint32_t crc;
873  const uint8_t *p;
874 
875  //Point to the data over which to calculate the CRC
876  p = (uint8_t *) data;
877  //CRC preset value
878  crc = 0xFFFFFFFF;
879 
880  //Loop through data
881  for(i = 0; i < length; i++)
882  {
883  //The message is processed bit by bit
884  for(j = 0; j < 8; j++)
885  {
886  //Update CRC value
887  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
888  {
889  crc = (crc << 1) ^ 0x04C11DB7;
890  }
891  else
892  {
893  crc = crc << 1;
894  }
895  }
896  }
897 
898  //Return CRC value
899  return ~crc;
900 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
Enhanced RX DMA descriptor.
#define GD32H7XX_ETH2_TX_BUFFER_SIZE
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:61
#define GD32H7XX_ETH2_IRQ_GROUP_PRIORITY
#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
uint8_t p
Definition: ndp.h:300
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
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
Enhanced TX DMA descriptor.
#define GD32H7XX_ETH2_TX_BUFFER_COUNT
void gd32h7xxEth2EventHandler(NetInterface *interface)
GD32H7 Ethernet MAC event handler.
#define GD32H7XX_ETH2_IRQ_PRIORITY_GROUPING
#define STM32H7XX_ETH2_RAM_SECTION
__weak_func void gd32h7xxEth2InitGpio(NetInterface *interface)
GPIO configuration.
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
uint16_t gd32h7xxEth2ReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define FALSE
Definition: os_port.h:46
uint32_t gd32h7xxEth2CalcCrc(const void *data, size_t length)
CRC calculation.
error_t
Error codes.
Definition: error.h:43
void gd32h7xxEth2DisableIrq(NetInterface *interface)
Disable interrupts.
error_t gd32h7xxEth2ReceivePacket(NetInterface *interface)
Receive a packet.
error_t gd32h7xxEth2UpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:105
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define GD32H7XX_ETH2_RX_BUFFER_SIZE
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
void gd32h7xxEth2Tick(NetInterface *interface)
GD32H7 Ethernet MAC timer handler.
#define NetTxAncillary
Definition: net_misc.h:36
void ENET1_IRQHandler(void)
GD32H7 Ethernet MAC interrupt service routine.
#define SMI_OPCODE_READ
Definition: nic.h:67
void gd32h7xxEth2WritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define TRACE_INFO(...)
Definition: debug.h:105
error_t gd32h7xxEth2SendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
uint8_t length
Definition: tcp.h:375
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
#define rxBuffer
MacAddr
Definition: ethernet.h:195
GigaDevice GD32H7 Ethernet MAC driver (ENET1 instance)
const NicDriver gd32h7xxEth2Driver
GD32H7 Ethernet MAC driver (ENET1 instance)
#define TRACE_DEBUG(...)
Definition: debug.h:119
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:262
error_t gd32h7xxEth2Init(NetInterface *interface)
GD32H7 Ethernet MAC initialization.
#define osEnterIsr()
#define GD32H7XX_ETH2_RX_BUFFER_COUNT
#define GD32H7XX_ETH2_IRQ_SUB_PRIORITY
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void gd32h7xxEth2EnableIrq(NetInterface *interface)
Enable interrupts.
#define txDmaDesc
void gd32h7xxEth2InitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
error_t gd32h7xxEth2UpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
NIC driver.
Definition: nic.h:286
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.
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83