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