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-2020 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.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  //Disable RIE interrupt
478  ENET_DMA_INTEN &= ~ENET_DMA_INTEN_RIE;
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  //Packet received?
504  if((ENET_DMA_STAT & ENET_DMA_STAT_RS) != 0)
505  {
506  //Clear interrupt flag
507  ENET_DMA_STAT = ENET_DMA_STAT_RS;
508 
509  //Process all pending packets
510  do
511  {
512  //Read incoming packet
513  error = gd32f307EthReceivePacket(interface);
514 
515  //No more data in the receive buffer?
516  } while(error != ERROR_BUFFER_EMPTY);
517  }
518 
519  //Re-enable DMA interrupts
520  ENET_DMA_INTEN = ENET_DMA_INTEN_NIE | ENET_DMA_INTEN_RIE | ENET_DMA_INTEN_TIE;
521 }
522 
523 
524 /**
525  * @brief Send a packet
526  * @param[in] interface Underlying network interface
527  * @param[in] buffer Multi-part buffer containing the data to send
528  * @param[in] offset Offset to the first data byte
529  * @param[in] ancillary Additional options passed to the stack along with
530  * the packet
531  * @return Error code
532  **/
533 
535  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
536 {
537  size_t length;
538 
539  //Retrieve the length of the packet
540  length = netBufferGetLength(buffer) - offset;
541 
542  //Check the frame length
544  {
545  //The transmitter can accept another packet
546  osSetEvent(&interface->nicTxEvent);
547  //Report an error
548  return ERROR_INVALID_LENGTH;
549  }
550 
551  //Make sure the current buffer is available for writing
552  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) != 0)
553  {
554  return ERROR_FAILURE;
555  }
556 
557  //Copy user data to the transmit buffer
558  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
559 
560  //Write the number of bytes to send
561  txCurDmaDesc->tdes1 = length & ENET_TDES1_TB1S;
562  //Set LS and FS flags as the data fits in a single buffer
563  txCurDmaDesc->tdes0 |= ENET_TDES0_LSG | ENET_TDES0_FSG;
564  //Give the ownership of the descriptor to the DMA
565  txCurDmaDesc->tdes0 |= ENET_TDES0_DAV;
566 
567  //Clear TBU flag to resume processing
568  ENET_DMA_STAT = ENET_DMA_STAT_TBU;
569  //Instruct the DMA to poll the transmit descriptor list
570  ENET_DMA_TPEN = 0;
571 
572  //Point to the next descriptor in the list
573  txCurDmaDesc = (Stm32f2xxTxDmaDesc *) txCurDmaDesc->tdes3;
574 
575  //Check whether the next buffer is available for writing
576  if((txCurDmaDesc->tdes0 & ENET_TDES0_DAV) == 0)
577  {
578  //The transmitter can accept another packet
579  osSetEvent(&interface->nicTxEvent);
580  }
581 
582  //Data successfully written
583  return NO_ERROR;
584 }
585 
586 
587 /**
588  * @brief Receive a packet
589  * @param[in] interface Underlying network interface
590  * @return Error code
591  **/
592 
594 {
595  error_t error;
596  size_t n;
597  NetRxAncillary ancillary;
598 
599  //The current buffer is available for reading?
600  if((rxCurDmaDesc->rdes0 & ENET_RDES0_DAV) == 0)
601  {
602  //FS and LS flags should be set
603  if((rxCurDmaDesc->rdes0 & ENET_RDES0_FDES) != 0 &&
604  (rxCurDmaDesc->rdes0 & ENET_RDES0_LDES) != 0)
605  {
606  //Make sure no error occurred
607  if((rxCurDmaDesc->rdes0 & ENET_RDES0_ERRS) == 0)
608  {
609  //Retrieve the length of the frame
610  n = (rxCurDmaDesc->rdes0 & ENET_RDES0_FRML) >> 16;
611  //Limit the number of data to read
613 
614  //Additional options can be passed to the stack along with the packet
615  ancillary = NET_DEFAULT_RX_ANCILLARY;
616 
617  //Pass the packet to the upper layer
618  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
619  &ancillary);
620 
621  //Valid packet received
622  error = NO_ERROR;
623  }
624  else
625  {
626  //The received packet contains an error
627  error = ERROR_INVALID_PACKET;
628  }
629  }
630  else
631  {
632  //The packet is not valid
633  error = ERROR_INVALID_PACKET;
634  }
635 
636  //Give the ownership of the descriptor back to the DMA
637  rxCurDmaDesc->rdes0 = ENET_RDES0_DAV;
638  //Point to the next descriptor in the list
639  rxCurDmaDesc = (Stm32f2xxRxDmaDesc *) rxCurDmaDesc->rdes3;
640  }
641  else
642  {
643  //No more data in the receive buffer
644  error = ERROR_BUFFER_EMPTY;
645  }
646 
647  //Clear RBU flag to resume processing
648  ENET_DMA_STAT = ENET_DMA_STAT_RBU;
649  //Instruct the DMA to poll the receive descriptor list
650  ENET_DMA_RPEN = 0;
651 
652  //Return status code
653  return error;
654 }
655 
656 
657 /**
658  * @brief Configure MAC address filtering
659  * @param[in] interface Underlying network interface
660  * @return Error code
661  **/
662 
664 {
665  uint_t i;
666  uint_t j;
667  uint_t k;
668  uint32_t crc;
669  uint32_t hashTable[2];
670  MacAddr unicastMacAddr[3];
671  MacFilterEntry *entry;
672 
673  //Debug message
674  TRACE_DEBUG("Updating MAC filter...\r\n");
675 
676  //Set the MAC address of the station
677  ENET_MAC_ADDR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
678  ENET_MAC_ADDR0H = interface->macAddr.w[2] | ENET_MAC_ADDR0H_MO;
679 
680  //The MAC supports 3 additional addresses for unicast perfect filtering
681  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
682  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
683  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
684 
685  //The hash table is used for multicast address filtering
686  hashTable[0] = 0;
687  hashTable[1] = 0;
688 
689  //The MAC address filter contains the list of MAC addresses to accept
690  //when receiving an Ethernet frame
691  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
692  {
693  //Point to the current entry
694  entry = &interface->macAddrFilter[i];
695 
696  //Valid entry?
697  if(entry->refCount > 0)
698  {
699  //Multicast address?
700  if(macIsMulticastAddr(&entry->addr))
701  {
702  //Compute CRC over the current MAC address
703  crc = gd32f307EthCalcCrc(&entry->addr, sizeof(MacAddr));
704 
705  //The upper 6 bits in the CRC register are used to index the
706  //contents of the hash table
707  k = (crc >> 26) & 0x3F;
708 
709  //Update hash table contents
710  hashTable[k / 32] |= (1 << (k % 32));
711  }
712  else
713  {
714  //Up to 3 additional MAC addresses can be specified
715  if(j < 3)
716  {
717  //Save the unicast address
718  unicastMacAddr[j++] = entry->addr;
719  }
720  }
721  }
722  }
723 
724  //Configure the first unicast address filter
725  if(j >= 1)
726  {
727  //When the AE bit is set, the entry is used for perfect filtering
728  ENET_MAC_ADDR1L = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
729  ENET_MAC_ADDR1H = unicastMacAddr[0].w[2] | ENET_MAC_ADDR1H_AFE;
730  }
731  else
732  {
733  //When the AE bit is cleared, the entry is ignored
734  ENET_MAC_ADDR1L = 0;
735  ENET_MAC_ADDR1H = 0;
736  }
737 
738  //Configure the second unicast address filter
739  if(j >= 2)
740  {
741  //When the AE bit is set, the entry is used for perfect filtering
742  ENET_MAC_ADDR2L = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
743  ENET_MAC_ADDR2H = unicastMacAddr[1].w[2] | ENET_MAC_ADDR2H_AFE;
744  }
745  else
746  {
747  //When the AE bit is cleared, the entry is ignored
748  ENET_MAC_ADDR2L = 0;
749  ENET_MAC_ADDR2H = 0;
750  }
751 
752  //Configure the third unicast address filter
753  if(j >= 3)
754  {
755  //When the AE bit is set, the entry is used for perfect filtering
756  ENET_MAC_ADDR3L = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
757  ENET_MAC_ADDR3H = unicastMacAddr[2].w[2] | ENET_MAC_ADDR3H_AFE;
758  }
759  else
760  {
761  //When the AE bit is cleared, the entry is ignored
762  ENET_MAC_ADDR3L = 0;
763  ENET_MAC_ADDR3H = 0;
764  }
765 
766  //Configure the multicast address filter
767  ENET_MAC_HLL = hashTable[0];
768  ENET_MAC_HLH = hashTable[1];
769 
770  //Debug message
771  TRACE_DEBUG(" ENET_MAC_HLL = %08" PRIX32 "\r\n", ENET_MAC_HLL);
772  TRACE_DEBUG(" ENET_MAC_HLH = %08" PRIX32 "\r\n", ENET_MAC_HLH);
773 
774  //Successful processing
775  return NO_ERROR;
776 }
777 
778 
779 /**
780  * @brief Adjust MAC configuration parameters for proper operation
781  * @param[in] interface Underlying network interface
782  * @return Error code
783  **/
784 
786 {
787  uint32_t config;
788 
789  //Read current MAC configuration
790  config = ENET_MAC_CFG;
791 
792  //10BASE-T or 100BASE-TX operation mode?
793  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
794  {
795  config |= ENET_MAC_CFG_SPD;
796  }
797  else
798  {
799  config &= ~ENET_MAC_CFG_SPD;
800  }
801 
802  //Half-duplex or full-duplex mode?
803  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
804  {
805  config |= ENET_MAC_CFG_DPM;
806  }
807  else
808  {
809  config &= ~ENET_MAC_CFG_DPM;
810  }
811 
812  //Update MAC configuration register
813  ENET_MAC_CFG = config;
814 
815  //Successful processing
816  return NO_ERROR;
817 }
818 
819 
820 /**
821  * @brief Write PHY register
822  * @param[in] opcode Access type (2 bits)
823  * @param[in] phyAddr PHY address (5 bits)
824  * @param[in] regAddr Register address (5 bits)
825  * @param[in] data Register value
826  **/
827 
828 void gd32f307EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
829  uint8_t regAddr, uint16_t data)
830 {
831  uint32_t temp;
832 
833  //Valid opcode?
834  if(opcode == SMI_OPCODE_WRITE)
835  {
836  //Take care not to alter MDC clock configuration
837  temp = ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_CLR;
838  //Set up a write operation
839  temp |= ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PB;
840  //PHY address
841  temp |= MAC_PHY_CTL_PA(phyAddr);
842  //Register address
843  temp |= MAC_PHY_CTL_PR(regAddr);
844 
845  //Data to be written in the PHY register
846  ENET_MAC_PHY_DATA = data & ENET_MAC_PHY_DATA_PD;
847 
848  //Start a write operation
849  ENET_MAC_PHY_CTL = temp;
850  //Wait for the write to complete
851  while((ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB) != 0)
852  {
853  }
854  }
855  else
856  {
857  //The MAC peripheral only supports standard Clause 22 opcodes
858  }
859 }
860 
861 
862 /**
863  * @brief Read PHY register
864  * @param[in] opcode Access type (2 bits)
865  * @param[in] phyAddr PHY address (5 bits)
866  * @param[in] regAddr Register address (5 bits)
867  * @return Register value
868  **/
869 
870 uint16_t gd32f307EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
871  uint8_t regAddr)
872 {
873  uint16_t data;
874  uint32_t temp;
875 
876  //Valid opcode?
877  if(opcode == SMI_OPCODE_READ)
878  {
879  //Take care not to alter MDC clock configuration
880  temp = ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_CLR;
881  //Set up a read operation
882  temp |= ENET_MAC_PHY_CTL_PB;
883  //PHY address
884  temp |= MAC_PHY_CTL_PA(phyAddr);
885  //Register address
886  temp |= MAC_PHY_CTL_PR(regAddr);
887 
888  //Start a read operation
889  ENET_MAC_PHY_CTL = temp;
890  //Wait for the read to complete
891  while((ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB) != 0)
892  {
893  }
894 
895  //Get register value
896  data = ENET_MAC_PHY_DATA & ENET_MAC_PHY_DATA_PD;
897  }
898  else
899  {
900  //The MAC peripheral only supports standard Clause 22 opcodes
901  data = 0;
902  }
903 
904  //Return the value of the PHY register
905  return data;
906 }
907 
908 
909 /**
910  * @brief CRC calculation
911  * @param[in] data Pointer to the data over which to calculate the CRC
912  * @param[in] length Number of bytes to process
913  * @return Resulting CRC value
914  **/
915 
916 uint32_t gd32f307EthCalcCrc(const void *data, size_t length)
917 {
918  uint_t i;
919  uint_t j;
920  uint32_t crc;
921  const uint8_t *p;
922 
923  //Point to the data over which to calculate the CRC
924  p = (uint8_t *) data;
925  //CRC preset value
926  crc = 0xFFFFFFFF;
927 
928  //Loop through data
929  for(i = 0; i < length; i++)
930  {
931  //The message is processed bit by bit
932  for(j = 0; j < 8; j++)
933  {
934  //Update CRC value
935  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
936  {
937  crc = (crc << 1) ^ 0x04C11DB7;
938  }
939  else
940  {
941  crc = crc << 1;
942  }
943  }
944  }
945 
946  //Return CRC value
947  return ~crc;
948 }
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:190
void gd32f307EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
#define netEvent
Definition: net_legacy.h:267
GD32F307 Ethernet MAC driver.
uint8_t data[]
Definition: ethernet.h:209
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:88
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:88
#define TRUE
Definition: os_port.h:50
#define GD32F307_ETH_RX_BUFFER_COUNT
__start_packed struct @5 MacAddr
MAC address.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:249
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:388
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:124
#define osExitIsr(flag)
void gd32f307EthEventHandler(NetInterface *interface)
GD32F307 Ethernet MAC event handler.
#define SMI_OPCODE_WRITE
Definition: nic.h:65
#define FALSE
Definition: os_port.h:46
#define GD32F307_ETH_IRQ_GROUP_PRIORITY
error_t
Error codes.
Definition: error.h:42
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:96
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:248
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:66
#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:105
uint8_t n
MAC filter table entry.
Definition: ethernet.h:246
#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
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:257
#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:56
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
Ethernet interface.
Definition: nic.h:82
void gd32f307EthInitGpio(NetInterface *interface)