gd32f307_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file gd32f307_eth_driver.c
3  * @brief GD32F307 Ethernet MAC controller
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
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)
140  {
141  }
142 
143  //Adjust MDC clock range depending on HCLK frequency
144  ENET_MAC_PHY_CTL = ENET_MDC_HCLK_DIV62;
145 
146  //PHY transceiver initialization
147  error = interface->phyDriver->init(interface);
148  //Failed to initialize PHY transceiver?
149  if(error)
150  return error;
151 
152  //Use default MAC configuration
153  ENET_MAC_CFG = ENET_MAC_CFG_ROD;
154 
155  //Set the MAC address of the station
156  ENET_MAC_ADDR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
157  ENET_MAC_ADDR0H = interface->macAddr.w[2] | ENET_MAC_ADDR0H_MO;
158 
159  //The MAC supports 3 additional addresses for unicast perfect filtering
160  ENET_MAC_ADDR1L = 0;
161  ENET_MAC_ADDR1H = 0;
162  ENET_MAC_ADDR2L = 0;
163  ENET_MAC_ADDR2H = 0;
164  ENET_MAC_ADDR3L = 0;
165  ENET_MAC_ADDR3H = 0;
166 
167  //Initialize hash table
168  ENET_MAC_HLL = 0;
169  ENET_MAC_HLH = 0;
170 
171  //Configure the receive filter
172  ENET_MAC_FRMF = ENET_MAC_FRMF_HPFLT | ENET_MAC_FRMF_HMF;
173  //Disable flow control
174  ENET_MAC_FCTL = 0;
175  //Enable store and forward mode
176  ENET_DMA_CTL = ENET_DMA_CTL_RSFD | ENET_DMA_CTL_TSFD;
177 
178  //Configure DMA bus mode
179  ENET_DMA_BCTL = ENET_DMA_BCTL_AA | ENET_DMA_BCTL_UIP | ENET_RXDP_1BEAT |
180  ENET_ARBITRATION_RXTX_1_1 | ENET_PGBL_1BEAT | ENET_DMA_BCTL_DFM;
181 
182  //Initialize DMA descriptor lists
183  gd32f307EthInitDmaDesc(interface);
184 
185  //Prevent interrupts from being generated when the transmit statistic
186  //counters reach half their maximum value
187  ENET_MSC_TINTMSK = ENET_MSC_TINTMSK_TGFIM | ENET_MSC_TINTMSK_TGFMSCIM |
188  ENET_MSC_TINTMSK_TGFSCIM;
189 
190  //Prevent interrupts from being generated when the receive statistic
191  //counters reach half their maximum value
192  ENET_MSC_RINTMSK = ENET_MSC_RINTMSK_RGUFIM | ENET_MSC_RINTMSK_RFAEIM |
193  ENET_MSC_RINTMSK_RFCEIM;
194 
195  //Disable MAC interrupts
196  ENET_MAC_INTMSK = ENET_MAC_INTMSK_TMSTIM | ENET_MAC_INTMSK_WUMIM;
197  //Enable the desired DMA interrupts
198  ENET_DMA_INTEN = ENET_DMA_INTEN_NIE | ENET_DMA_INTEN_RIE | ENET_DMA_INTEN_TIE;
199 
200  //Set priority grouping (4 bits for pre-emption priority, no bits for subpriority)
201  NVIC_SetPriorityGrouping(GD32F307_ETH_IRQ_PRIORITY_GROUPING);
202 
203  //Configure Ethernet interrupt priority
204  NVIC_SetPriority(ENET_IRQn, NVIC_EncodePriority(GD32F307_ETH_IRQ_PRIORITY_GROUPING,
206 
207  //Enable MAC transmission and reception
208  ENET_MAC_CFG |= ENET_MAC_CFG_TEN | ENET_MAC_CFG_REN;
209  //Enable DMA transmission and reception
210  ENET_DMA_CTL |= ENET_DMA_CTL_STE | ENET_DMA_CTL_SRE;
211 
212  //Accept any packets from the upper layer
213  osSetEvent(&interface->nicTxEvent);
214 
215  //Successful initialization
216  return NO_ERROR;
217 }
218 
219 
220 //GD32307C-EVAL-EVAL evaluation board?
221 #if defined(USE_GD32307C_EVAL)
222 
223 /**
224  * @brief GPIO configuration
225  * @param[in] interface Underlying network interface
226  **/
227 
228 void gd32f307EthInitGpio(NetInterface *interface)
229 {
230  //Enable SYSCFG clock
231  rcu_periph_clock_enable(RCU_AF);
232 
233  //Enable GPIO clocks
234  rcu_periph_clock_enable(RCU_GPIOA);
235  rcu_periph_clock_enable(RCU_GPIOB);
236  rcu_periph_clock_enable(RCU_GPIOC);
237 
238  //Configure CKOUT0 (PA8) as an output
239  gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);
240 
241  //Configure CKOUT0 pin to output the PLL2 clock (50MHz)
242  rcu_pll2_config(RCU_PLL2_MUL10);
243  rcu_osci_on(RCU_PLL2_CK);
244  rcu_osci_stab_wait(RCU_PLL2_CK);
245  rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2);
246 
247  //Select RMII interface mode
248  gpio_ethernet_phy_select(GPIO_ENET_PHY_RMII);
249 
250  //Configure ETH_RMII_REF_CLK (PA1)
251  gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
252  //Configure ETH_MDIO (PA2)
253  gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
254  //Configure ETH_RMII_CRS_DV (PA7)
255  gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_7);
256 
257  //Configure ETH_RMII_TX_EN (PB11)
258  gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
259  //Configure ETH_RMII_TXD0 (PB12)
260  gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
261  //Configure ETH_RMII_TXD1 (PB13)
262  gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
263 
264  //Configure ETH_MDC (PC1)
265  gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
266  //Configure ETH_RMII_RXD0 (PC4)
267  gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
268  //Configure ETH_RMII_RXD1 (PC5)
269  gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_5);
270 }
271 
272 #endif
273 
274 
275 /**
276  * @brief Initialize DMA descriptor lists
277  * @param[in] interface Underlying network interface
278  **/
279 
281 {
282  uint_t i;
283 
284  //Initialize TX DMA descriptor list
285  for(i = 0; i < GD32F307_ETH_TX_BUFFER_COUNT; i++)
286  {
287  //Use chain structure rather than ring structure
288  txDmaDesc[i].tdes0 = ENET_TDES0_INTC | ENET_TDES0_TCHM;
289  //Initialize transmit buffer size
290  txDmaDesc[i].tdes1 = 0;
291  //Transmit buffer address
292  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
293  //Next descriptor address
294  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
295  //Reserved fields
296  txDmaDesc[i].tdes4 = 0;
297  txDmaDesc[i].tdes5 = 0;
298  //Transmit frame time stamp
299  txDmaDesc[i].tdes6 = 0;
300  txDmaDesc[i].tdes7 = 0;
301  }
302 
303  //The last descriptor is chained to the first entry
304  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
305  //Point to the very first descriptor
306  txCurDmaDesc = &txDmaDesc[0];
307 
308  //Initialize RX DMA descriptor list
309  for(i = 0; i < GD32F307_ETH_RX_BUFFER_COUNT; i++)
310  {
311  //The descriptor is initially owned by the DMA
312  rxDmaDesc[i].rdes0 = ENET_RDES0_DAV;
313  //Use chain structure rather than ring structure
314  rxDmaDesc[i].rdes1 = ENET_RDES1_RCHM | (GD32F307_ETH_RX_BUFFER_SIZE & ENET_RDES1_RB1S);
315  //Receive buffer address
316  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
317  //Next descriptor address
318  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
319  //Extended status
320  rxDmaDesc[i].rdes4 = 0;
321  //Reserved field
322  rxDmaDesc[i].rdes5 = 0;
323  //Receive frame time stamp
324  rxDmaDesc[i].rdes6 = 0;
325  rxDmaDesc[i].rdes7 = 0;
326  }
327 
328  //The last descriptor is chained to the first entry
329  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
330  //Point to the very first descriptor
331  rxCurDmaDesc = &rxDmaDesc[0];
332 
333  //Start location of the TX descriptor list
334  ENET_DMA_TDTADDR = (uint32_t) txDmaDesc;
335  //Start location of the RX descriptor list
336  ENET_DMA_RDTADDR = (uint32_t) rxDmaDesc;
337 }
338 
339 
340 /**
341  * @brief GD32F307 Ethernet MAC timer handler
342  *
343  * This routine is periodically called by the TCP/IP stack to
344  * handle periodic operations such as polling the link state
345  *
346  * @param[in] interface Underlying network interface
347  **/
348 
350 {
351  //Handle periodic operations
352  interface->phyDriver->tick(interface);
353 }
354 
355 
356 /**
357  * @brief Enable interrupts
358  * @param[in] interface Underlying network interface
359  **/
360 
362 {
363  //Enable Ethernet MAC interrupts
364  NVIC_EnableIRQ(ENET_IRQn);
365  //Enable Ethernet PHY interrupts
366  interface->phyDriver->enableIrq(interface);
367 }
368 
369 
370 /**
371  * @brief Disable interrupts
372  * @param[in] interface Underlying network interface
373  **/
374 
376 {
377  //Disable Ethernet MAC interrupts
378  NVIC_DisableIRQ(ENET_IRQn);
379  //Disable Ethernet PHY interrupts
380  interface->phyDriver->disableIrq(interface);
381 }
382 
383 
384 /**
385  * @brief GD32F307 Ethernet MAC interrupt service routine
386  **/
387 
388 void ENET_IRQHandler(void)
389 {
390  bool_t flag;
391  uint32_t status;
392 
393  //Interrupt service routine prologue
394  osEnterIsr();
395 
396  //This flag will be set if a higher priority task must be woken
397  flag = FALSE;
398 
399  //Read DMA status register
400  status = ENET_DMA_STAT;
401 
402  //A packet has been transmitted?
403  if(status & ENET_DMA_STAT_TS)
404  {
405  //Clear TS interrupt flag
406  ENET_DMA_STAT = ENET_DMA_STAT_TS;
407 
408  //Check whether the TX buffer is available for writing
409  if(!(txCurDmaDesc->tdes0 & ENET_TDES0_DAV))
410  {
411  //Notify the TCP/IP stack that the transmitter is ready to send
412  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
413  }
414  }
415 
416  //A packet has been received?
417  if(status & ENET_DMA_STAT_RS)
418  {
419  //Disable RIE interrupt
420  ENET_DMA_INTEN &= ~ENET_DMA_INTEN_RIE;
421 
422  //Set event flag
423  nicDriverInterface->nicEvent = TRUE;
424  //Notify the TCP/IP stack of the event
425  flag |= osSetEventFromIsr(&netEvent);
426  }
427 
428  //Clear NIS interrupt flag
429  ENET_DMA_STAT = ENET_DMA_STAT_NI;
430 
431  //Interrupt service routine epilogue
432  osExitIsr(flag);
433 }
434 
435 
436 /**
437  * @brief GD32F307 Ethernet MAC event handler
438  * @param[in] interface Underlying network interface
439  **/
440 
442 {
443  error_t error;
444 
445  //Packet received?
446  if(ENET_DMA_STAT & ENET_DMA_STAT_RS)
447  {
448  //Clear interrupt flag
449  ENET_DMA_STAT = ENET_DMA_STAT_RS;
450 
451  //Process all pending packets
452  do
453  {
454  //Read incoming packet
455  error = gd32f307EthReceivePacket(interface);
456 
457  //No more data in the receive buffer?
458  } while(error != ERROR_BUFFER_EMPTY);
459  }
460 
461  //Re-enable DMA interrupts
462  ENET_DMA_INTEN = ENET_DMA_INTEN_NIE | ENET_DMA_INTEN_RIE | ENET_DMA_INTEN_TIE;
463 }
464 
465 
466 /**
467  * @brief Send a packet
468  * @param[in] interface Underlying network interface
469  * @param[in] buffer Multi-part buffer containing the data to send
470  * @param[in] offset Offset to the first data byte
471  * @return Error code
472  **/
473 
475  const NetBuffer *buffer, size_t offset)
476 {
477  size_t length;
478 
479  //Retrieve the length of the packet
480  length = netBufferGetLength(buffer) - offset;
481 
482  //Check the frame length
484  {
485  //The transmitter can accept another packet
486  osSetEvent(&interface->nicTxEvent);
487  //Report an error
488  return ERROR_INVALID_LENGTH;
489  }
490 
491  //Make sure the current buffer is available for writing
492  if(txCurDmaDesc->tdes0 & ENET_TDES0_DAV)
493  return ERROR_FAILURE;
494 
495  //Copy user data to the transmit buffer
496  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
497 
498  //Write the number of bytes to send
499  txCurDmaDesc->tdes1 = length & ENET_TDES1_TB1S;
500  //Set LS and FS flags as the data fits in a single buffer
501  txCurDmaDesc->tdes0 |= ENET_TDES0_LSG | ENET_TDES0_FSG;
502  //Give the ownership of the descriptor to the DMA
503  txCurDmaDesc->tdes0 |= ENET_TDES0_DAV;
504 
505  //Clear TBU flag to resume processing
506  ENET_DMA_STAT = ENET_DMA_STAT_TBU;
507  //Instruct the DMA to poll the transmit descriptor list
508  ENET_DMA_TPEN = 0;
509 
510  //Point to the next descriptor in the list
511  txCurDmaDesc = (Stm32f2xxTxDmaDesc *) txCurDmaDesc->tdes3;
512 
513  //Check whether the next buffer is available for writing
514  if(!(txCurDmaDesc->tdes0 & ENET_TDES0_DAV))
515  {
516  //The transmitter can accept another packet
517  osSetEvent(&interface->nicTxEvent);
518  }
519 
520  //Data successfully written
521  return NO_ERROR;
522 }
523 
524 
525 /**
526  * @brief Receive a packet
527  * @param[in] interface Underlying network interface
528  * @return Error code
529  **/
530 
532 {
533  error_t error;
534  size_t n;
535 
536  //The current buffer is available for reading?
537  if(!(rxCurDmaDesc->rdes0 & ENET_RDES0_DAV))
538  {
539  //FS and LS flags should be set
540  if((rxCurDmaDesc->rdes0 & ENET_RDES0_FDES) && (rxCurDmaDesc->rdes0 & ENET_RDES0_LDES))
541  {
542  //Make sure no error occurred
543  if(!(rxCurDmaDesc->rdes0 & ENET_RDES0_ERRS))
544  {
545  //Retrieve the length of the frame
546  n = (rxCurDmaDesc->rdes0 & ENET_RDES0_FRML) >> 16;
547  //Limit the number of data to read
549 
550  //Pass the packet to the upper layer
551  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n);
552 
553  //Valid packet received
554  error = NO_ERROR;
555  }
556  else
557  {
558  //The received packet contains an error
559  error = ERROR_INVALID_PACKET;
560  }
561  }
562  else
563  {
564  //The packet is not valid
565  error = ERROR_INVALID_PACKET;
566  }
567 
568  //Give the ownership of the descriptor back to the DMA
569  rxCurDmaDesc->rdes0 = ENET_RDES0_DAV;
570  //Point to the next descriptor in the list
571  rxCurDmaDesc = (Stm32f2xxRxDmaDesc *) rxCurDmaDesc->rdes3;
572  }
573  else
574  {
575  //No more data in the receive buffer
576  error = ERROR_BUFFER_EMPTY;
577  }
578 
579  //Clear RBU flag to resume processing
580  ENET_DMA_STAT = ENET_DMA_STAT_RBU;
581  //Instruct the DMA to poll the receive descriptor list
582  ENET_DMA_RPEN = 0;
583 
584  //Return status code
585  return error;
586 }
587 
588 
589 /**
590  * @brief Configure MAC address filtering
591  * @param[in] interface Underlying network interface
592  * @return Error code
593  **/
594 
596 {
597  uint_t i;
598  uint_t j;
599  uint_t k;
600  uint32_t crc;
601  uint32_t hashTable[2];
602  MacAddr unicastMacAddr[3];
603  MacFilterEntry *entry;
604 
605  //Debug message
606  TRACE_DEBUG("Updating MAC filter...\r\n");
607 
608  //Set the MAC address of the station
609  ENET_MAC_ADDR0L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
610  ENET_MAC_ADDR0H = interface->macAddr.w[2] | ENET_MAC_ADDR0H_MO;
611 
612  //The MAC supports 3 additional addresses for unicast perfect filtering
613  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
614  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
615  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
616 
617  //The hash table is used for multicast address filtering
618  hashTable[0] = 0;
619  hashTable[1] = 0;
620 
621  //The MAC address filter contains the list of MAC addresses to accept
622  //when receiving an Ethernet frame
623  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
624  {
625  //Point to the current entry
626  entry = &interface->macAddrFilter[i];
627 
628  //Valid entry?
629  if(entry->refCount > 0)
630  {
631  //Multicast address?
632  if(macIsMulticastAddr(&entry->addr))
633  {
634  //Compute CRC over the current MAC address
635  crc = gd32f307EthCalcCrc(&entry->addr, sizeof(MacAddr));
636 
637  //The upper 6 bits in the CRC register are used to index the
638  //contents of the hash table
639  k = (crc >> 26) & 0x3F;
640 
641  //Update hash table contents
642  hashTable[k / 32] |= (1 << (k % 32));
643  }
644  else
645  {
646  //Up to 3 additional MAC addresses can be specified
647  if(j < 3)
648  {
649  //Save the unicast address
650  unicastMacAddr[j++] = entry->addr;
651  }
652  }
653  }
654  }
655 
656  //Configure the first unicast address filter
657  if(j >= 1)
658  {
659  //When the AE bit is set, the entry is used for perfect filtering
660  ENET_MAC_ADDR1L = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
661  ENET_MAC_ADDR1H = unicastMacAddr[0].w[2] | ENET_MAC_ADDR1H_AFE;
662  }
663  else
664  {
665  //When the AE bit is cleared, the entry is ignored
666  ENET_MAC_ADDR1L = 0;
667  ENET_MAC_ADDR1H = 0;
668  }
669 
670  //Configure the second unicast address filter
671  if(j >= 2)
672  {
673  //When the AE bit is set, the entry is used for perfect filtering
674  ENET_MAC_ADDR2L = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
675  ENET_MAC_ADDR2H = unicastMacAddr[1].w[2] | ENET_MAC_ADDR2H_AFE;
676  }
677  else
678  {
679  //When the AE bit is cleared, the entry is ignored
680  ENET_MAC_ADDR2L = 0;
681  ENET_MAC_ADDR2H = 0;
682  }
683 
684  //Configure the third unicast address filter
685  if(j >= 3)
686  {
687  //When the AE bit is set, the entry is used for perfect filtering
688  ENET_MAC_ADDR3L = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
689  ENET_MAC_ADDR3H = unicastMacAddr[2].w[2] | ENET_MAC_ADDR3H_AFE;
690  }
691  else
692  {
693  //When the AE bit is cleared, the entry is ignored
694  ENET_MAC_ADDR3L = 0;
695  ENET_MAC_ADDR3H = 0;
696  }
697 
698  //Configure the multicast address filter
699  ENET_MAC_HLL = hashTable[0];
700  ENET_MAC_HLH = hashTable[1];
701 
702  //Debug message
703  TRACE_DEBUG(" ENET_MAC_HLL = %08" PRIX32 "\r\n", ENET_MAC_HLL);
704  TRACE_DEBUG(" ENET_MAC_HLH = %08" PRIX32 "\r\n", ENET_MAC_HLH);
705 
706  //Successful processing
707  return NO_ERROR;
708 }
709 
710 
711 /**
712  * @brief Adjust MAC configuration parameters for proper operation
713  * @param[in] interface Underlying network interface
714  * @return Error code
715  **/
716 
718 {
719  uint32_t config;
720 
721  //Read current MAC configuration
722  config = ENET_MAC_CFG;
723 
724  //10BASE-T or 100BASE-TX operation mode?
725  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
726  config |= ENET_MAC_CFG_SPD;
727  else
728  config &= ~ENET_MAC_CFG_SPD;
729 
730  //Half-duplex or full-duplex mode?
731  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
732  config |= ENET_MAC_CFG_DPM;
733  else
734  config &= ~ENET_MAC_CFG_DPM;
735 
736  //Update MAC configuration register
737  ENET_MAC_CFG = config;
738 
739  //Successful processing
740  return NO_ERROR;
741 }
742 
743 
744 /**
745  * @brief Write PHY register
746  * @param[in] opcode Access type (2 bits)
747  * @param[in] phyAddr PHY address (5 bits)
748  * @param[in] regAddr Register address (5 bits)
749  * @param[in] data Register value
750  **/
751 
752 void gd32f307EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
753  uint8_t regAddr, uint16_t data)
754 {
755  uint32_t temp;
756 
757  //Valid opcode?
758  if(opcode == SMI_OPCODE_WRITE)
759  {
760  //Take care not to alter MDC clock configuration
761  temp = ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_CLR;
762  //Set up a write operation
763  temp |= ENET_MAC_PHY_CTL_PW | ENET_MAC_PHY_CTL_PB;
764  //PHY address
765  temp |= MAC_PHY_CTL_PA(phyAddr);
766  //Register address
767  temp |= MAC_PHY_CTL_PR(regAddr);
768 
769  //Data to be written in the PHY register
770  ENET_MAC_PHY_DATA = data & ENET_MAC_PHY_DATA_PD;
771 
772  //Start a write operation
773  ENET_MAC_PHY_CTL = temp;
774  //Wait for the write to complete
775  while(ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)
776  {
777  }
778  }
779  else
780  {
781  //The MAC peripheral only supports standard Clause 22 opcodes
782  }
783 }
784 
785 
786 /**
787  * @brief Read PHY register
788  * @param[in] opcode Access type (2 bits)
789  * @param[in] phyAddr PHY address (5 bits)
790  * @param[in] regAddr Register address (5 bits)
791  * @return Register value
792  **/
793 
794 uint16_t gd32f307EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
795  uint8_t regAddr)
796 {
797  uint16_t data;
798  uint32_t temp;
799 
800  //Valid opcode?
801  if(opcode == SMI_OPCODE_READ)
802  {
803  //Take care not to alter MDC clock configuration
804  temp = ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_CLR;
805  //Set up a read operation
806  temp |= ENET_MAC_PHY_CTL_PB;
807  //PHY address
808  temp |= MAC_PHY_CTL_PA(phyAddr);
809  //Register address
810  temp |= MAC_PHY_CTL_PR(regAddr);
811 
812  //Start a read operation
813  ENET_MAC_PHY_CTL = temp;
814  //Wait for the read to complete
815  while(ENET_MAC_PHY_CTL & ENET_MAC_PHY_CTL_PB)
816  {
817  }
818 
819  //Get register value
820  data = ENET_MAC_PHY_DATA & ENET_MAC_PHY_DATA_PD;
821  }
822  else
823  {
824  //The MAC peripheral only supports standard Clause 22 opcodes
825  data = 0;
826  }
827 
828  //Return the value of the PHY register
829  return data;
830 }
831 
832 
833 /**
834  * @brief CRC calculation
835  * @param[in] data Pointer to the data over which to calculate the CRC
836  * @param[in] length Number of bytes to process
837  * @return Resulting CRC value
838  **/
839 
840 uint32_t gd32f307EthCalcCrc(const void *data, size_t length)
841 {
842  uint_t i;
843  uint_t j;
844 
845  //Point to the data over which to calculate the CRC
846  const uint8_t *p = (uint8_t *) data;
847  //CRC preset value
848  uint32_t crc = 0xFFFFFFFF;
849 
850  //Loop through data
851  for(i = 0; i < length; i++)
852  {
853  //The message is processed bit by bit
854  for(j = 0; j < 8; j++)
855  {
856  //Update CRC value
857  if(((crc >> 31) ^ (p[i] >> j)) & 0x01)
858  crc = (crc << 1) ^ 0x04C11DB7;
859  else
860  crc = crc << 1;
861  }
862  }
863 
864  //Return CRC value
865  return ~crc;
866 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void gd32f307EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
uint8_t length
Definition: dtls_misc.h:149
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
GD32F307 Ethernet MAC controller.
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
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length)
Handle a packet received by the network controller.
Definition: nic.c:383
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:88
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:74
#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:223
const NicDriver gd32f307EthDriver
GD32F307 Ethernet MAC driver.
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:110
#define osExitIsr(flag)
void gd32f307EthEventHandler(NetInterface *interface)
GD32F307 Ethernet MAC event handler.
#define SMI_OPCODE_WRITE
Definition: nic.h:62
#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.
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:222
uint32_t gd32f307EthCalcCrc(const void *data, size_t length)
CRC calculation.
OsEvent netEvent
Definition: net.c:77
error_t gd32f307EthReceivePacket(NetInterface *interface)
Receive a packet.
#define SMI_OPCODE_READ
Definition: nic.h:63
#define TRACE_INFO(...)
Definition: debug.h:94
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:106
void gd32f307EthDisableIrq(NetInterface *interface)
Disable interrupts.
Enhanced TX DMA descriptor.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:91
uint8_t n
MAC filter table entry.
Definition: ethernet.h:220
#define GD32F307_ETH_IRQ_SUB_PRIORITY
uint16_t gd32f307EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define osEnterIsr()
error_t gd32f307EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset)
Send a packet.
#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.
uint8_t data[]
Definition: dtls_misc.h:176
NIC driver.
Definition: nic.h:179
#define GD32F307_ETH_RX_BUFFER_SIZE
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
__start_packed struct @108 MacAddr
MAC address.
Ethernet interface.
Definition: nic.h:79
void gd32f307EthInitGpio(NetInterface *interface)