gd32f307_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file gd32f307_eth_driver.c
3  * @brief GD32F307 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2022 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.1.8
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 Stm32f2xxTxDmaDesc *txCurDmaDesc;
79 //Pointer to the current RX DMA descriptor
80 static Stm32f2xxRxDmaDesc *rxCurDmaDesc;
81 
82 
83 /**
84  * @brief GD32F307 Ethernet MAC driver
85  **/
86 
88 {
90  ETH_MTU,
101  TRUE,
102  TRUE,
103  TRUE,
104  FALSE
105 };
106 
107 
108 /**
109  * @brief GD32F307 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 GD32F307 Ethernet MAC...\r\n");
120 
121  //Save underlying network interface
122  nicDriverInterface = interface;
123 
124  //GPIO configuration
125  gd32f307EthInitGpio(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_ADDR2H = 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_1BEAT |
197  ENET_ARBITRATION_RXTX_1_1 | ENET_PGBL_1BEAT | ENET_DMA_BCTL_DFM;
198 
199  //Initialize DMA descriptor lists
200  gd32f307EthInitDmaDesc(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(GD32F307_ETH_IRQ_PRIORITY_GROUPING);
219 
220  //Configure Ethernet interrupt priority
221  NVIC_SetPriority(ENET_IRQn, NVIC_EncodePriority(GD32F307_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 //GD32307C-EVAL-EVAL evaluation board?
238 #if defined(USE_GD32307C_EVAL)
239 
240 /**
241  * @brief GPIO configuration
242  * @param[in] interface Underlying network interface
243  **/
244 
245 void gd32f307EthInitGpio(NetInterface *interface)
246 {
247  //Enable SYSCFG clock
248  rcu_periph_clock_enable(RCU_AF);
249 
250  //Enable GPIO clocks
251  rcu_periph_clock_enable(RCU_GPIOA);
252  rcu_periph_clock_enable(RCU_GPIOB);
253  rcu_periph_clock_enable(RCU_GPIOC);
254 
255  //Configure CKOUT0 (PA8) as an output
256  gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);
257 
258  //Configure CKOUT0 pin to output the PLL2 clock (50MHz)
259  rcu_pll2_config(RCU_PLL2_MUL10);
260  rcu_osci_on(RCU_PLL2_CK);
261  rcu_osci_stab_wait(RCU_PLL2_CK);
262  rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2);
263 
264  //Select RMII interface mode
265  gpio_ethernet_phy_select(GPIO_ENET_PHY_RMII);
266 
267  //Configure ETH_RMII_REF_CLK (PA1)
268  gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
269  //Configure ETH_MDIO (PA2)
270  gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
271  //Configure ETH_RMII_CRS_DV (PA7)
272  gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
273 
274  //Configure ETH_RMII_TX_EN (PB11)
275  gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
276  //Configure ETH_RMII_TXD0 (PB12)
277  gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
278  //Configure ETH_RMII_TXD1 (PB13)
279  gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
280 
281  //Configure ETH_MDC (PC1)
282  gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
283  //Configure ETH_RMII_RXD0 (PC4)
284  gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
285  //Configure ETH_RMII_RXD1 (PC5)
286  gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_5);
287 }
288 
289 #endif
290 
291 
292 /**
293  * @brief Initialize DMA descriptor lists
294  * @param[in] interface Underlying network interface
295  **/
296 
298 {
299  uint_t i;
300 
301  //Initialize TX DMA descriptor list
302  for(i = 0; i < GD32F307_ETH_TX_BUFFER_COUNT; i++)
303  {
304  //Use chain structure rather than ring structure
305  txDmaDesc[i].tdes0 = ENET_TDES0_INTC | ENET_TDES0_TCHM;
306  //Initialize transmit buffer size
307  txDmaDesc[i].tdes1 = 0;
308  //Transmit buffer address
309  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
310  //Next descriptor address
311  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
312  //Reserved fields
313  txDmaDesc[i].tdes4 = 0;
314  txDmaDesc[i].tdes5 = 0;
315  //Transmit frame time stamp
316  txDmaDesc[i].tdes6 = 0;
317  txDmaDesc[i].tdes7 = 0;
318  }
319 
320  //The last descriptor is chained to the first entry
321  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
322  //Point to the very first descriptor
323  txCurDmaDesc = &txDmaDesc[0];
324 
325  //Initialize RX DMA descriptor list
326  for(i = 0; i < GD32F307_ETH_RX_BUFFER_COUNT; i++)
327  {
328  //The descriptor is initially owned by the DMA
329  rxDmaDesc[i].rdes0 = ENET_RDES0_DAV;
330  //Use chain structure rather than ring structure
331  rxDmaDesc[i].rdes1 = ENET_RDES1_RCHM | (GD32F307_ETH_RX_BUFFER_SIZE & ENET_RDES1_RB1S);
332  //Receive buffer address
333  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
334  //Next descriptor address
335  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
336  //Extended status
337  rxDmaDesc[i].rdes4 = 0;
338  //Reserved field
339  rxDmaDesc[i].rdes5 = 0;
340  //Receive frame time stamp
341  rxDmaDesc[i].rdes6 = 0;
342  rxDmaDesc[i].rdes7 = 0;
343  }
344 
345  //The last descriptor is chained to the first entry
346  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
347  //Point to the very first descriptor
348  rxCurDmaDesc = &rxDmaDesc[0];
349 
350  //Start location of the TX descriptor list
351  ENET_DMA_TDTADDR = (uint32_t) txDmaDesc;
352  //Start location of the RX descriptor list
353  ENET_DMA_RDTADDR = (uint32_t) rxDmaDesc;
354 }
355 
356 
357 /**
358  * @brief GD32F307 Ethernet MAC timer handler
359  *
360  * This routine is periodically called by the TCP/IP stack to handle periodic
361  * operations such as polling the link state
362  *
363  * @param[in] interface Underlying network interface
364  **/
365 
367 {
368  //Valid Ethernet PHY or switch driver?
369  if(interface->phyDriver != NULL)
370  {
371  //Handle periodic operations
372  interface->phyDriver->tick(interface);
373  }
374  else if(interface->switchDriver != NULL)
375  {
376  //Handle periodic operations
377  interface->switchDriver->tick(interface);
378  }
379  else
380  {
381  //Just for sanity
382  }
383 }
384 
385 
386 /**
387  * @brief Enable interrupts
388  * @param[in] interface Underlying network interface
389  **/
390 
392 {
393  //Enable Ethernet MAC interrupts
394  NVIC_EnableIRQ(ENET_IRQn);
395 
396  //Valid Ethernet PHY or switch driver?
397  if(interface->phyDriver != NULL)
398  {
399  //Enable Ethernet PHY interrupts
400  interface->phyDriver->enableIrq(interface);
401  }
402  else if(interface->switchDriver != NULL)
403  {
404  //Enable Ethernet switch interrupts
405  interface->switchDriver->enableIrq(interface);
406  }
407  else
408  {
409  //Just for sanity
410  }
411 }
412 
413 
414 /**
415  * @brief Disable interrupts
416  * @param[in] interface Underlying network interface
417  **/
418 
420 {
421  //Disable Ethernet MAC interrupts
422  NVIC_DisableIRQ(ENET_IRQn);
423 
424  //Valid Ethernet PHY or switch driver?
425  if(interface->phyDriver != NULL)
426  {
427  //Disable Ethernet PHY interrupts
428  interface->phyDriver->disableIrq(interface);
429  }
430  else if(interface->switchDriver != NULL)
431  {
432  //Disable Ethernet switch interrupts
433  interface->switchDriver->disableIrq(interface);
434  }
435  else
436  {
437  //Just for sanity
438  }
439 }
440 
441 
442 /**
443  * @brief GD32F307 Ethernet MAC interrupt service routine
444  **/
445 
446 void ENET_IRQHandler(void)
447 {
448  bool_t flag;
449  uint32_t status;
450 
451  //Interrupt service routine prologue
452  osEnterIsr();
453 
454  //This flag will be set if a higher priority task must be woken
455  flag = FALSE;
456 
457  //Read DMA status register
458  status = ENET_DMA_STAT;
459 
460  //Packet transmitted?
461  if((status & ENET_DMA_STAT_TS) != 0)
462  {
463  //Clear TS interrupt flag
464  ENET_DMA_STAT = ENET_DMA_STAT_TS;
465 
466  //Check whether the TX buffer is available for writing
467  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) == 0)
468  {
469  //Notify the TCP/IP stack that the transmitter is ready to send
470  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
471  }
472  }
473 
474  //Packet received?
475  if((status & ENET_DMA_STAT_RS) != 0)
476  {
477  //Clear RS interrupt flag
478  ENET_DMA_STAT = ENET_DMA_STAT_RS;
479 
480  //Set event flag
481  nicDriverInterface->nicEvent = TRUE;
482  //Notify the TCP/IP stack of the event
483  flag |= osSetEventFromIsr(&netEvent);
484  }
485 
486  //Clear NIS interrupt flag
487  ENET_DMA_STAT = ENET_DMA_STAT_NI;
488 
489  //Interrupt service routine epilogue
490  osExitIsr(flag);
491 }
492 
493 
494 /**
495  * @brief GD32F307 Ethernet MAC event handler
496  * @param[in] interface Underlying network interface
497  **/
498 
500 {
501  error_t error;
502 
503  //Process all pending packets
504  do
505  {
506  //Read incoming packet
507  error = gd32f307EthReceivePacket(interface);
508 
509  //No more data in the receive buffer?
510  } while(error != ERROR_BUFFER_EMPTY);
511 }
512 
513 
514 /**
515  * @brief Send a packet
516  * @param[in] interface Underlying network interface
517  * @param[in] buffer Multi-part buffer containing the data to send
518  * @param[in] offset Offset to the first data byte
519  * @param[in] ancillary Additional options passed to the stack along with
520  * the packet
521  * @return Error code
522  **/
523 
525  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
526 {
527  size_t length;
528 
529  //Retrieve the length of the packet
530  length = netBufferGetLength(buffer) - offset;
531 
532  //Check the frame length
534  {
535  //The transmitter can accept another packet
536  osSetEvent(&interface->nicTxEvent);
537  //Report an error
538  return ERROR_INVALID_LENGTH;
539  }
540 
541  //Make sure the current buffer is available for writing
542  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) != 0)
543  {
544  return ERROR_FAILURE;
545  }
546 
547  //Copy user data to the transmit buffer
548  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
549 
550  //Write the number of bytes to send
551  txCurDmaDesc->tdes1 = length & ENET_TDES1_TB1S;
552  //Set LS and FS flags as the data fits in a single buffer
553  txCurDmaDesc->tdes0 |= ENET_TDES0_LSG | ENET_TDES0_FSG;
554  //Give the ownership of the descriptor to the DMA
555  txCurDmaDesc->tdes0 |= ENET_TDES0_DAV;
556 
557  //Clear TBU flag to resume processing
558  ENET_DMA_STAT = ENET_DMA_STAT_TBU;
559  //Instruct the DMA to poll the transmit descriptor list
560  ENET_DMA_TPEN = 0;
561 
562  //Point to the next descriptor in the list
563  txCurDmaDesc = (Stm32f2xxTxDmaDesc *) txCurDmaDesc->tdes3;
564 
565  //Check whether the next buffer is available for writing
566  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) == 0)
567  {
568  //The transmitter can accept another packet
569  osSetEvent(&interface->nicTxEvent);
570  }
571 
572  //Data successfully written
573  return NO_ERROR;
574 }
575 
576 
577 /**
578  * @brief Receive a packet
579  * @param[in] interface Underlying network interface
580  * @return Error code
581  **/
582 
584 {
585  error_t error;
586  size_t n;
587  NetRxAncillary ancillary;
588 
589  //Current buffer available for reading?
590  if((rxCurDmaDesc->rdes0 & ENET_RDES0_DAV) == 0)
591  {
592  //FS and LS flags should be set
593  if((rxCurDmaDesc->rdes0 & ENET_RDES0_FDES) != 0 &&
594  (rxCurDmaDesc->rdes0 & ENET_RDES0_LDES) != 0)
595  {
596  //Make sure no error occurred
597  if((rxCurDmaDesc->rdes0 & ENET_RDES0_ERRS) == 0)
598  {
599  //Retrieve the length of the frame
600  n = (rxCurDmaDesc->rdes0 & ENET_RDES0_FRML) >> 16;
601  //Limit the number of data to read
603 
604  //Additional options can be passed to the stack along with the packet
605  ancillary = NET_DEFAULT_RX_ANCILLARY;
606 
607  //Pass the packet to the upper layer
608  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
609  &ancillary);
610 
611  //Valid packet received
612  error = NO_ERROR;
613  }
614  else
615  {
616  //The received packet contains an error
617  error = ERROR_INVALID_PACKET;
618  }
619  }
620  else
621  {
622  //The packet is not valid
623  error = ERROR_INVALID_PACKET;
624  }
625 
626  //Give the ownership of the descriptor back to the DMA
627  rxCurDmaDesc->rdes0 = ENET_RDES0_DAV;
628  //Point to the next descriptor in the list
629  rxCurDmaDesc = (Stm32f2xxRxDmaDesc *) rxCurDmaDesc->rdes3;
630  }
631  else
632  {
633  //No more data in the receive buffer
634  error = ERROR_BUFFER_EMPTY;
635  }
636 
637  //Clear RBU flag to resume processing
638  ENET_DMA_STAT = ENET_DMA_STAT_RBU;
639  //Instruct the DMA to poll the receive descriptor list
640  ENET_DMA_RPEN = 0;
641 
642  //Return status code
643  return error;
644 }
645 
646 
647 /**
648  * @brief Configure MAC address filtering
649  * @param[in] interface Underlying network interface
650  * @return Error code
651  **/
652 
654 {
655  uint_t i;
656  uint_t j;
657  uint_t k;
658  uint32_t crc;
659  uint32_t hashTable[2];
660  MacAddr unicastMacAddr[3];
661  MacFilterEntry *entry;
662 
663  //Debug message
664  TRACE_DEBUG("Updating MAC filter...\r\n");
665 
666  //Set the MAC address of the station
667  ENET_MAC_ADDR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
668  ENET_MAC_ADDR0H = interface->macAddr.w[2] | ENET_MAC_ADDR0H_MO;
669 
670  //The MAC supports 3 additional addresses for unicast perfect filtering
671  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
672  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
673  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
674 
675  //The hash table is used for multicast address filtering
676  hashTable[0] = 0;
677  hashTable[1] = 0;
678 
679  //The MAC address filter contains the list of MAC addresses to accept
680  //when receiving an Ethernet frame
681  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
682  {
683  //Point to the current entry
684  entry = &interface->macAddrFilter[i];
685 
686  //Valid entry?
687  if(entry->refCount > 0)
688  {
689  //Multicast address?
690  if(macIsMulticastAddr(&entry->addr))
691  {
692  //Compute CRC over the current MAC address
693  crc = gd32f307EthCalcCrc(&entry->addr, sizeof(MacAddr));
694 
695  //The upper 6 bits in the CRC register are used to index the
696  //contents of the hash table
697  k = (crc >> 26) & 0x3F;
698 
699  //Update hash table contents
700  hashTable[k / 32] |= (1 << (k % 32));
701  }
702  else
703  {
704  //Up to 3 additional MAC addresses can be specified
705  if(j < 3)
706  {
707  //Save the unicast address
708  unicastMacAddr[j++] = entry->addr;
709  }
710  }
711  }
712  }
713 
714  //Configure the first unicast address filter
715  if(j >= 1)
716  {
717  //When the AE bit is set, the entry is used for perfect filtering
718  ENET_MAC_ADDR1L = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
719  ENET_MAC_ADDR1H = unicastMacAddr[0].w[2] | ENET_MAC_ADDR1H_AFE;
720  }
721  else
722  {
723  //When the AE bit is cleared, the entry is ignored
724  ENET_MAC_ADDR1L = 0;
725  ENET_MAC_ADDR1H = 0;
726  }
727 
728  //Configure the second unicast address filter
729  if(j >= 2)
730  {
731  //When the AE bit is set, the entry is used for perfect filtering
732  ENET_MAC_ADDR2L = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
733  ENET_MAC_ADDR2H = unicastMacAddr[1].w[2] | ENET_MAC_ADDR2H_AFE;
734  }
735  else
736  {
737  //When the AE bit is cleared, the entry is ignored
738  ENET_MAC_ADDR2L = 0;
739  ENET_MAC_ADDR2H = 0;
740  }
741 
742  //Configure the third unicast address filter
743  if(j >= 3)
744  {
745  //When the AE bit is set, the entry is used for perfect filtering
746  ENET_MAC_ADDR3L = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
747  ENET_MAC_ADDR3H = unicastMacAddr[2].w[2] | ENET_MAC_ADDR3H_AFE;
748  }
749  else
750  {
751  //When the AE bit is cleared, the entry is ignored
752  ENET_MAC_ADDR3L = 0;
753  ENET_MAC_ADDR3H = 0;
754  }
755 
756  //Configure the multicast hash table
757  ENET_MAC_HLL = hashTable[0];
758  ENET_MAC_HLH = hashTable[1];
759 
760  //Debug message
761  TRACE_DEBUG(" ENET_MAC_HLL = %08" PRIX32 "\r\n", ENET_MAC_HLL);
762  TRACE_DEBUG(" ENET_MAC_HLH = %08" PRIX32 "\r\n", ENET_MAC_HLH);
763 
764  //Successful processing
765  return NO_ERROR;
766 }
767 
768 
769 /**
770  * @brief Adjust MAC configuration parameters for proper operation
771  * @param[in] interface Underlying network interface
772  * @return Error code
773  **/
774 
776 {
777  uint32_t config;
778 
779  //Read current MAC configuration
780  config = ENET_MAC_CFG;
781 
782  //10BASE-T or 100BASE-TX operation mode?
783  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
784  {
785  config |= ENET_MAC_CFG_SPD;
786  }
787  else
788  {
789  config &= ~ENET_MAC_CFG_SPD;
790  }
791 
792  //Half-duplex or full-duplex mode?
793  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
794  {
795  config |= ENET_MAC_CFG_DPM;
796  }
797  else
798  {
799  config &= ~ENET_MAC_CFG_DPM;
800  }
801 
802  //Update MAC configuration register
803  ENET_MAC_CFG = config;
804 
805  //Successful processing
806  return NO_ERROR;
807 }
808 
809 
810 /**
811  * @brief Write PHY register
812  * @param[in] opcode Access type (2 bits)
813  * @param[in] phyAddr PHY address (5 bits)
814  * @param[in] regAddr Register address (5 bits)
815  * @param[in] data Register value
816  **/
817 
818 void gd32f307EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
819  uint8_t regAddr, uint16_t data)
820 {
821  uint32_t temp;
822 
823  //Valid opcode?
824  if(opcode == SMI_OPCODE_WRITE)
825  {
826  //Take care not to alter MDC clock configuration
827  temp = ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_CLR;
828  //Set up a write operation
829  temp |= ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PB;
830  //PHY address
831  temp |= MAC_PHY_CTL_PA(phyAddr);
832  //Register address
833  temp |= MAC_PHY_CTL_PR(regAddr);
834 
835  //Data to be written in the PHY register
836  ENET_MAC_PHY_DATA = data & ENET_MAC_PHY_DATA_PD;
837 
838  //Start a write operation
839  ENET_MAC_PHY_CTL = temp;
840  //Wait for the write to complete
841  while((ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB) != 0)
842  {
843  }
844  }
845  else
846  {
847  //The MAC peripheral only supports standard Clause 22 opcodes
848  }
849 }
850 
851 
852 /**
853  * @brief Read PHY register
854  * @param[in] opcode Access type (2 bits)
855  * @param[in] phyAddr PHY address (5 bits)
856  * @param[in] regAddr Register address (5 bits)
857  * @return Register value
858  **/
859 
860 uint16_t gd32f307EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
861  uint8_t regAddr)
862 {
863  uint16_t data;
864  uint32_t temp;
865 
866  //Valid opcode?
867  if(opcode == SMI_OPCODE_READ)
868  {
869  //Take care not to alter MDC clock configuration
870  temp = ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_CLR;
871  //Set up a read operation
872  temp |= ENET_MAC_PHY_CTL_PB;
873  //PHY address
874  temp |= MAC_PHY_CTL_PA(phyAddr);
875  //Register address
876  temp |= MAC_PHY_CTL_PR(regAddr);
877 
878  //Start a read operation
879  ENET_MAC_PHY_CTL = temp;
880  //Wait for the read to complete
881  while((ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB) != 0)
882  {
883  }
884 
885  //Get register value
886  data = ENET_MAC_PHY_DATA & ENET_MAC_PHY_DATA_PD;
887  }
888  else
889  {
890  //The MAC peripheral only supports standard Clause 22 opcodes
891  data = 0;
892  }
893 
894  //Return the value of the PHY register
895  return data;
896 }
897 
898 
899 /**
900  * @brief CRC calculation
901  * @param[in] data Pointer to the data over which to calculate the CRC
902  * @param[in] length Number of bytes to process
903  * @return Resulting CRC value
904  **/
905 
906 uint32_t gd32f307EthCalcCrc(const void *data, size_t length)
907 {
908  uint_t i;
909  uint_t j;
910  uint32_t crc;
911  const uint8_t *p;
912 
913  //Point to the data over which to calculate the CRC
914  p = (uint8_t *) data;
915  //CRC preset value
916  crc = 0xFFFFFFFF;
917 
918  //Loop through data
919  for(i = 0; i < length; i++)
920  {
921  //The message is processed bit by bit
922  for(j = 0; j < 8; j++)
923  {
924  //Update CRC value
925  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
926  {
927  crc = (crc << 1) ^ 0x04C11DB7;
928  }
929  else
930  {
931  crc = crc << 1;
932  }
933  }
934  }
935 
936  //Return CRC value
937  return ~crc;
938 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
uint8_t length
Definition: coap_common.h:193
void gd32f307EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:48
#define netEvent
Definition: net_legacy.h:267
GD32F307 Ethernet MAC driver.
uint8_t data[]
Definition: ethernet.h:220
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:123
void gd32f307EthTick(NetInterface *interface)
GD32F307 Ethernet MAC timer handler.
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
void ENET_IRQHandler(void)
GD32F307 Ethernet MAC interrupt service routine.
uint8_t p
Definition: ndp.h:298
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
#define GD32F307_ETH_RX_BUFFER_COUNT
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:260
const NicDriver gd32f307EthDriver
GD32F307 Ethernet MAC driver.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
void gd32f307EthEventHandler(NetInterface *interface)
GD32F307 Ethernet MAC event handler.
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define FALSE
Definition: os_port.h:46
#define GD32F307_ETH_IRQ_GROUP_PRIORITY
__start_packed struct @0 MacAddr
MAC address.
error_t
Error codes.
Definition: error.h:43
void gd32f307EthEnableIrq(NetInterface *interface)
Enable interrupts.
void gd32f307EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:102
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:139
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:259
@ ERROR_INVALID_LENGTH
Definition: error.h:110
@ ERROR_BUFFER_EMPTY
Definition: error.h:140
uint32_t gd32f307EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define NetTxAncillary
Definition: net_misc.h:36
error_t gd32f307EthReceivePacket(NetInterface *interface)
Receive a packet.
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:95
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:62
error_t gd32f307EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define GD32F307_ETH_TX_BUFFER_COUNT
#define rxBuffer
error_t gd32f307EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define GD32F307_ETH_IRQ_PRIORITY_GROUPING
#define TRACE_DEBUG(...)
Definition: debug.h:107
void gd32f307EthDisableIrq(NetInterface *interface)
Disable interrupts.
Enhanced TX DMA descriptor.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:258
#define GD32F307_ETH_IRQ_SUB_PRIORITY
uint16_t gd32f307EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define osEnterIsr()
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define txDmaDesc
Enhanced RX DMA descriptor.
#define GD32F307_ETH_TX_BUFFER_SIZE
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:110
error_t gd32f307EthInit(NetInterface *interface)
GD32F307 Ethernet MAC initialization.
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
NIC driver.
Definition: nic.h:281
#define GD32F307_ETH_RX_BUFFER_SIZE
error_t gd32f307EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:55
@ 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
void gd32f307EthInitGpio(NetInterface *interface)