xmc4400_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file xmc4400_eth_driver.c
3  * @brief Infineon XMC4400 Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "xmc4400.h"
36 #include "core/net.h"
38 #include "debug.h"
39 
40 //Underlying network interface
41 static NetInterface *nicDriverInterface;
42 
43 //IAR EWARM compiler?
44 #if defined(__ICCARM__)
45 
46 //Transmit buffer
47 #pragma data_alignment = 4
48 #pragma location = XMC4400_ETH_RAM_SECTION
50 //Receive buffer
51 #pragma data_alignment = 4
52 #pragma location = XMC4400_ETH_RAM_SECTION
54 //Transmit DMA descriptors
55 #pragma data_alignment = 4
56 #pragma location = XMC4400_ETH_RAM_SECTION
58 //Receive DMA descriptors
59 #pragma data_alignment = 4
60 #pragma location = XMC4400_ETH_RAM_SECTION
62 
63 //Keil MDK-ARM or GCC compiler?
64 #else
65 
66 //Transmit buffer
68  __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));
69 //Receive buffer
71  __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));
72 //Transmit DMA descriptors
74  __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));
75 //Receive DMA descriptors
77  __attribute__((aligned(4), __section__(XMC4400_ETH_RAM_SECTION)));
78 
79 #endif
80 
81 //Pointer to the current TX DMA descriptor
82 static Xmc4400TxDmaDesc *txCurDmaDesc;
83 //Pointer to the current RX DMA descriptor
84 static Xmc4400RxDmaDesc *rxCurDmaDesc;
85 
86 
87 /**
88  * @brief XMC4400 Ethernet MAC driver
89  **/
90 
92 {
94  ETH_MTU,
105  TRUE,
106  TRUE,
107  TRUE,
108  FALSE
109 };
110 
111 
112 /**
113  * @brief XMC4400 Ethernet MAC initialization
114  * @param[in] interface Underlying network interface
115  * @return Error code
116  **/
117 
119 {
120  error_t error;
121 
122  //Debug message
123  TRACE_INFO("Initializing XMC4400 Ethernet MAC...\r\n");
124 
125  //Save underlying network interface
126  nicDriverInterface = interface;
127 
128  //Disable parity error trap
129  SCU_PARITY->PETE = 0;
130  //Disable unaligned access trap
131  PPB->CCR &= ~PPB_CCR_UNALIGN_TRP_Msk;
132 
133  //Enable ETH0 peripheral clock
134  SCU_CLK->CLKSET = SCU_CLK_CLKSET_ETH0CEN_Msk;
135 
136  //GPIO configuration
137  xmc4400EthInitGpio(interface);
138 
139  //Reset ETH0 peripheral
140  SCU_RESET->PRSET2 = SCU_RESET_PRSET2_ETH0RS_Msk;
141  SCU_RESET->PRCLR2 = SCU_RESET_PRCLR2_ETH0RS_Msk;
142 
143  //Reset DMA controller
144  ETH0->BUS_MODE |= ETH_BUS_MODE_SWR_Msk;
145  //Wait for the reset to complete
146  while((ETH0->BUS_MODE & ETH_BUS_MODE_SWR_Msk) != 0)
147  {
148  }
149 
150  //Adjust MDC clock range depending on ETH clock frequency
151  ETH0->GMII_ADDRESS = ETH_GMII_ADDRESS_CR_DIV62;
152 
153  //Valid Ethernet PHY or switch driver?
154  if(interface->phyDriver != NULL)
155  {
156  //Ethernet PHY initialization
157  error = interface->phyDriver->init(interface);
158  }
159  else if(interface->switchDriver != NULL)
160  {
161  //Ethernet switch initialization
162  error = interface->switchDriver->init(interface);
163  }
164  else
165  {
166  //The interface is not properly configured
167  error = ERROR_FAILURE;
168  }
169 
170  //Any error to report?
171  if(error)
172  {
173  return error;
174  }
175 
176  //Use default MAC configuration
177  ETH0->MAC_CONFIGURATION = ETH_MAC_CONFIGURATION_RESERVED15_Msk |
178  ETH_MAC_CONFIGURATION_DO_Msk;
179 
180  //Configure MAC address filtering
182 
183  //Disable flow control
184  ETH0->FLOW_CONTROL = 0;
185  //Enable store and forward mode
186  ETH0->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk;
187 
188  //Configure DMA bus mode
189  ETH0->BUS_MODE = ETH_BUS_MODE_AAL_Msk | ETH_BUS_MODE_USP_Msk |
191 
192  //Initialize DMA descriptor lists
193  xmc4400EthInitDmaDesc(interface);
194 
195  //Prevent interrupts from being generated when statistic counters reach
196  //half their maximum value
197  ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF;
198  ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
199  ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
200 
201  //Disable MAC interrupts
202  ETH0->INTERRUPT_MASK = ETH_INTERRUPT_MASK_TSIM_Msk | ETH_INTERRUPT_MASK_PMTIM_Msk;
203 
204  //Enable the desired DMA interrupts
205  ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk |
206  ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk;
207 
208  //Set priority grouping (6 bits for pre-emption priority, no bits for subpriority)
209  NVIC_SetPriorityGrouping(XMC4400_ETH_IRQ_PRIORITY_GROUPING);
210 
211  //Configure Ethernet interrupt priority
212  NVIC_SetPriority(ETH0_0_IRQn, NVIC_EncodePriority(XMC4400_ETH_IRQ_PRIORITY_GROUPING,
214 
215  //Enable MAC transmission and reception
216  ETH0->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk | ETH_MAC_CONFIGURATION_RE_Msk;
217  //Enable DMA transmission and reception
218  ETH0->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk | ETH_OPERATION_MODE_SR_Msk;
219 
220  //Accept any packets from the upper layer
221  osSetEvent(&interface->nicTxEvent);
222 
223  //Successful initialization
224  return NO_ERROR;
225 }
226 
227 
228 /**
229  * @brief GPIO configuration
230  * @param[in] interface Underlying network interface
231  **/
232 
233 __weak_func void xmc4400EthInitGpio(NetInterface *interface)
234 {
235 //XMC4400 Platform2GO Kit?
236 #if defined(USE_KIT_XMC4400_PLT2GO)
237  uint32_t temp;
238 
239  //Configure ETH0.TX_EN (P0.4)
240  temp = PORT0->IOCR4;
241  temp &= ~PORT0_IOCR4_PC4_Msk;
242  temp |= (17UL << PORT0_IOCR4_PC4_Pos);
243  PORT0->IOCR4 = temp;
244 
245  //Configure ETH0.MDIO (P2.0), ETH0.RXD0A (P2.2) and ETH0.RXD1A (P2.3)
246  temp = PORT2->IOCR0;
247  temp &= ~(PORT2_IOCR0_PC0_Msk | PORT2_IOCR0_PC2_Msk | PORT2_IOCR0_PC3_Msk);
248  temp |= (0UL << PORT2_IOCR0_PC0_Pos) | (0UL << PORT2_IOCR0_PC2_Pos) | (0UL << PORT2_IOCR0_PC3_Pos);
249  PORT2->IOCR0 = temp;
250 
251  //Configure ETH0.RXERA (P2.4)and ETH0.MDC (P2.7)
252  temp = PORT2->IOCR4;
253  temp &= ~(PORT2_IOCR4_PC4_Msk | PORT2_IOCR4_PC7_Msk);
254  temp |= (0UL << PORT2_IOCR4_PC4_Pos) | (17UL << PORT2_IOCR4_PC7_Pos);
255  PORT2->IOCR4 = temp;
256 
257  //Configure ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9)
258  temp = PORT2->IOCR8;
259  temp &= ~(PORT2_IOCR8_PC8_Msk | PORT2_IOCR8_PC9_Msk);
260  temp |= (17UL << PORT2_IOCR8_PC8_Pos) | (17UL << PORT2_IOCR8_PC9_Pos);
261  PORT2->IOCR8 = temp;
262 
263  //Configure ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9)
264  temp = PORT15->IOCR8;
265  temp &= ~(PORT15_IOCR8_PC8_Msk | PORT15_IOCR8_PC9_Msk);
266  temp |= (0UL << PORT15_IOCR8_PC8_Pos) | (0UL << PORT15_IOCR8_PC9_Pos);
267  PORT15->IOCR8 = temp;
268 
269  //Assign ETH_MDIO (P2.0) to HW0
270  temp = PORT2->HWSEL & ~PORT2_HWSEL_HW0_Msk;
271  PORT2->HWSEL = temp | (1UL << PORT2_HWSEL_HW0_Pos);
272 
273  //Select output driver strength for ETH0.TX_EN (P2.5)
274  temp = PORT2->PDR0;
275  temp &= ~PORT2_PDR0_PD5_Msk;
276  temp |= (0UL << PORT2_PDR0_PD5_Pos);
277  PORT2->PDR0 = temp;
278 
279  //Select output driver strength for ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9)
280  temp = PORT2->PDR1;
281  temp &= ~(PORT2_PDR1_PD8_Msk | PORT2_PDR1_PD9_Msk);
282  temp |= (0UL << PORT2_PDR1_PD8_Pos) | (0UL << PORT2_PDR1_PD9_Pos);
283  PORT2->PDR1 = temp;
284 
285  //Use ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9) as digital inputs
286  PORT15->PDISC &= ~(PORT15_PDISC_PDIS8_Msk | PORT15_PDISC_PDIS9_Msk);
287 
288  //Select RMII operation mode
289  ETH0_CON->CON = ETH_CON_INFSEL_Msk | ETH_CON_MDIO_B | ETH_CON_RXER_A |
291 #endif
292 }
293 
294 
295 /**
296  * @brief Initialize DMA descriptor lists
297  * @param[in] interface Underlying network interface
298  **/
299 
301 {
302  uint_t i;
303 
304  //Initialize TX DMA descriptor list
305  for(i = 0; i < XMC4400_ETH_TX_BUFFER_COUNT; i++)
306  {
307  //Use chain structure rather than ring structure
308  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
309  //Initialize transmit buffer size
310  txDmaDesc[i].tdes1 = 0;
311  //Transmit buffer address
312  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
313  //Next descriptor address
314  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
315  }
316 
317  //The last descriptor is chained to the first entry
318  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
319  //Point to the very first descriptor
320  txCurDmaDesc = &txDmaDesc[0];
321 
322  //Initialize RX DMA descriptor list
323  for(i = 0; i < XMC4400_ETH_RX_BUFFER_COUNT; i++)
324  {
325  //The descriptor is initially owned by the DMA
326  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
327  //Use chain structure rather than ring structure
329  //Receive buffer address
330  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
331  //Next descriptor address
332  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
333  }
334 
335  //The last descriptor is chained to the first entry
336  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
337  //Point to the very first descriptor
338  rxCurDmaDesc = &rxDmaDesc[0];
339 
340  //Start location of the TX descriptor list
341  ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) txDmaDesc;
342  //Start location of the RX descriptor list
343  ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) rxDmaDesc;
344 }
345 
346 
347 /**
348  * @brief XMC4400 Ethernet MAC timer handler
349  *
350  * This routine is periodically called by the TCP/IP stack to handle periodic
351  * operations such as polling the link state
352  *
353  * @param[in] interface Underlying network interface
354  **/
355 
356 void xmc4400EthTick(NetInterface *interface)
357 {
358  //Valid Ethernet PHY or switch driver?
359  if(interface->phyDriver != NULL)
360  {
361  //Handle periodic operations
362  interface->phyDriver->tick(interface);
363  }
364  else if(interface->switchDriver != NULL)
365  {
366  //Handle periodic operations
367  interface->switchDriver->tick(interface);
368  }
369  else
370  {
371  //Just for sanity
372  }
373 }
374 
375 
376 /**
377  * @brief Enable interrupts
378  * @param[in] interface Underlying network interface
379  **/
380 
382 {
383  //Enable Ethernet MAC interrupts
384  NVIC_EnableIRQ(ETH0_0_IRQn);
385 
386  //Valid Ethernet PHY or switch driver?
387  if(interface->phyDriver != NULL)
388  {
389  //Enable Ethernet PHY interrupts
390  interface->phyDriver->enableIrq(interface);
391  }
392  else if(interface->switchDriver != NULL)
393  {
394  //Enable Ethernet switch interrupts
395  interface->switchDriver->enableIrq(interface);
396  }
397  else
398  {
399  //Just for sanity
400  }
401 }
402 
403 
404 /**
405  * @brief Disable interrupts
406  * @param[in] interface Underlying network interface
407  **/
408 
410 {
411  //Disable Ethernet MAC interrupts
412  NVIC_DisableIRQ(ETH0_0_IRQn);
413 
414  //Valid Ethernet PHY or switch driver?
415  if(interface->phyDriver != NULL)
416  {
417  //Disable Ethernet PHY interrupts
418  interface->phyDriver->disableIrq(interface);
419  }
420  else if(interface->switchDriver != NULL)
421  {
422  //Disable Ethernet switch interrupts
423  interface->switchDriver->disableIrq(interface);
424  }
425  else
426  {
427  //Just for sanity
428  }
429 }
430 
431 
432 /**
433  * @brief XMC4400 Ethernet MAC interrupt service routine
434  **/
435 
437 {
438  bool_t flag;
439  uint32_t status;
440 
441  //Interrupt service routine prologue
442  osEnterIsr();
443 
444  //This flag will be set if a higher priority task must be woken
445  flag = FALSE;
446 
447  //Read DMA status register
448  status = ETH0->STATUS;
449 
450  //Packet transmitted?
451  if((status & ETH_STATUS_TI_Msk) != 0)
452  {
453  //Clear TI interrupt flag
454  ETH0->STATUS = ETH_STATUS_TI_Msk;
455 
456  //Check whether the TX buffer is available for writing
457  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
458  {
459  //Notify the TCP/IP stack that the transmitter is ready to send
460  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
461  }
462  }
463 
464  //Packet received?
465  if((status & ETH_STATUS_RI_Msk) != 0)
466  {
467  //Clear RI interrupt flag
468  ETH0->STATUS = ETH_STATUS_RI_Msk;
469 
470  //Set event flag
471  nicDriverInterface->nicEvent = TRUE;
472  //Notify the TCP/IP stack of the event
473  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
474  }
475 
476  //Clear NIS interrupt flag
477  ETH0->STATUS = ETH_STATUS_NIS_Msk;
478 
479  //Interrupt service routine epilogue
480  osExitIsr(flag);
481 }
482 
483 
484 /**
485  * @brief XMC4400 Ethernet MAC event handler
486  * @param[in] interface Underlying network interface
487  **/
488 
490 {
491  error_t error;
492 
493  //Process all pending packets
494  do
495  {
496  //Read incoming packet
497  error = xmc4400EthReceivePacket(interface);
498 
499  //No more data in the receive buffer?
500  } while(error != ERROR_BUFFER_EMPTY);
501 }
502 
503 
504 /**
505  * @brief Send a packet
506  * @param[in] interface Underlying network interface
507  * @param[in] buffer Multi-part buffer containing the data to send
508  * @param[in] offset Offset to the first data byte
509  * @param[in] ancillary Additional options passed to the stack along with
510  * the packet
511  * @return Error code
512  **/
513 
515  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
516 {
517  size_t length;
518 
519  //Retrieve the length of the packet
520  length = netBufferGetLength(buffer) - offset;
521 
522  //Check the frame length
524  {
525  //The transmitter can accept another packet
526  osSetEvent(&interface->nicTxEvent);
527  //Report an error
528  return ERROR_INVALID_LENGTH;
529  }
530 
531  //Make sure the current buffer is available for writing
532  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
533  {
534  return ERROR_FAILURE;
535  }
536 
537  //Copy user data to the transmit buffer
538  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
539 
540  //Write the number of bytes to send
541  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
542  //Set LS and FS flags as the data fits in a single buffer
543  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
544  //Give the ownership of the descriptor to the DMA
545  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
546 
547  //Clear TU flag to resume processing
548  ETH0->STATUS = ETH_STATUS_TU_Msk;
549  //Instruct the DMA to poll the transmit descriptor list
550  ETH0->TRANSMIT_POLL_DEMAND = 0;
551 
552  //Point to the next descriptor in the list
553  txCurDmaDesc = (Xmc4400TxDmaDesc *) txCurDmaDesc->tdes3;
554 
555  //Check whether the next buffer is available for writing
556  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
557  {
558  //The transmitter can accept another packet
559  osSetEvent(&interface->nicTxEvent);
560  }
561 
562  //Data successfully written
563  return NO_ERROR;
564 }
565 
566 
567 /**
568  * @brief Receive a packet
569  * @param[in] interface Underlying network interface
570  * @return Error code
571  **/
572 
574 {
575  error_t error;
576  size_t n;
577  NetRxAncillary ancillary;
578 
579  //Current buffer available for reading?
580  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
581  {
582  //FS and LS flags should be set
583  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
584  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
585  {
586  //Make sure no error occurred
587  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
588  {
589  //Retrieve the length of the frame
590  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
591  //Limit the number of data to read
593 
594  //Additional options can be passed to the stack along with the packet
595  ancillary = NET_DEFAULT_RX_ANCILLARY;
596 
597  //Pass the packet to the upper layer
598  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
599  &ancillary);
600 
601  //Valid packet received
602  error = NO_ERROR;
603  }
604  else
605  {
606  //The received packet contains an error
607  error = ERROR_INVALID_PACKET;
608  }
609  }
610  else
611  {
612  //The packet is not valid
613  error = ERROR_INVALID_PACKET;
614  }
615 
616  //Give the ownership of the descriptor back to the DMA
617  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
618  //Point to the next descriptor in the list
619  rxCurDmaDesc = (Xmc4400RxDmaDesc *) rxCurDmaDesc->rdes3;
620  }
621  else
622  {
623  //No more data in the receive buffer
624  error = ERROR_BUFFER_EMPTY;
625  }
626 
627  //Clear RU flag to resume processing
628  ETH0->STATUS = ETH_STATUS_RU_Msk;
629  //Instruct the DMA to poll the receive descriptor list
630  ETH0->RECEIVE_POLL_DEMAND = 0;
631 
632  //Return status code
633  return error;
634 }
635 
636 
637 /**
638  * @brief Configure MAC address filtering
639  * @param[in] interface Underlying network interface
640  * @return Error code
641  **/
642 
644 {
645  uint_t i;
646  uint_t j;
647  uint_t k;
648  uint32_t crc;
649  uint32_t hashTable[2];
650  MacAddr unicastMacAddr[3];
651  MacFilterEntry *entry;
652 
653  //Debug message
654  TRACE_DEBUG("Updating MAC filter...\r\n");
655 
656  //Promiscuous mode?
657  if(interface->promiscuous)
658  {
659  //Pass all incoming frames regardless of their destination address
660  ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_PR_Msk;
661  }
662  else
663  {
664  //Set the MAC address of the station
665  ETH0->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
666  ETH0->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
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 = xmc4400EthCalcCrc(&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  ETH0->MAC_ADDRESS1_LOW = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
717  ETH0->MAC_ADDRESS1_HIGH = unicastMacAddr[0].w[2] | ETH_MAC_ADDRESS1_HIGH_AE_Msk;
718  }
719  else
720  {
721  //When the AE bit is cleared, the entry is ignored
722  ETH0->MAC_ADDRESS1_LOW = 0;
723  ETH0->MAC_ADDRESS1_HIGH = 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  ETH0->MAC_ADDRESS2_LOW = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
731  ETH0->MAC_ADDRESS2_HIGH = unicastMacAddr[1].w[2] | ETH_MAC_ADDRESS2_HIGH_AE_Msk;
732  }
733  else
734  {
735  //When the AE bit is cleared, the entry is ignored
736  ETH0->MAC_ADDRESS2_LOW = 0;
737  ETH0->MAC_ADDRESS2_HIGH = 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  ETH0->MAC_ADDRESS3_LOW = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
745  ETH0->MAC_ADDRESS3_HIGH = unicastMacAddr[2].w[2] | ETH_MAC_ADDRESS3_HIGH_AE_Msk;
746  }
747  else
748  {
749  //When the AE bit is cleared, the entry is ignored
750  ETH0->MAC_ADDRESS3_LOW = 0;
751  ETH0->MAC_ADDRESS3_HIGH = 0;
752  }
753 
754  //Check whether frames with a multicast destination address should be
755  //accepted
756  if(interface->acceptAllMulticast)
757  {
758  //Configure the receive filter
759  ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk |
760  ETH_MAC_FRAME_FILTER_PM_Msk;
761  }
762  else
763  {
764  //Configure the receive filter
765  ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk |
766  ETH_MAC_FRAME_FILTER_HMC_Msk;
767 
768  //Configure the multicast hash table
769  ETH0->HASH_TABLE_LOW = hashTable[0];
770  ETH0->HASH_TABLE_HIGH = hashTable[1];
771 
772  //Debug message
773  TRACE_DEBUG(" HASH_TABLE_LOW = 0x%08" PRIX32 "\r\n", ETH0->HASH_TABLE_LOW);
774  TRACE_DEBUG(" HASH_TABLE_HIGH = 0x%08" PRIX32 "\r\n", ETH0->HASH_TABLE_HIGH);
775  }
776  }
777 
778  //Successful processing
779  return NO_ERROR;
780 }
781 
782 
783 /**
784  * @brief Adjust MAC configuration parameters for proper operation
785  * @param[in] interface Underlying network interface
786  * @return Error code
787  **/
788 
790 {
791  uint32_t config;
792 
793  //Read current MAC configuration
794  config = ETH0->MAC_CONFIGURATION;
795 
796  //10BASE-T or 100BASE-TX operation mode?
797  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
798  {
799  config |= ETH_MAC_CONFIGURATION_FES_Msk;
800  }
801  else
802  {
803  config &= ~ETH_MAC_CONFIGURATION_FES_Msk;
804  }
805 
806  //Half-duplex or full-duplex mode?
807  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
808  {
809  config |= ETH_MAC_CONFIGURATION_DM_Msk;
810  }
811  else
812  {
813  config &= ~ETH_MAC_CONFIGURATION_DM_Msk;
814  }
815 
816  //Update MAC configuration register
817  ETH0->MAC_CONFIGURATION = config;
818 
819  //Successful processing
820  return NO_ERROR;
821 }
822 
823 
824 /**
825  * @brief Write PHY register
826  * @param[in] opcode Access type (2 bits)
827  * @param[in] phyAddr PHY address (5 bits)
828  * @param[in] regAddr Register address (5 bits)
829  * @param[in] data Register value
830  **/
831 
832 void xmc4400EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
833  uint8_t regAddr, uint16_t data)
834 {
835  uint32_t temp;
836 
837  //Valid opcode?
838  if(opcode == SMI_OPCODE_WRITE)
839  {
840  //Take care not to alter MDC clock configuration
841  temp = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk;
842  //Set up a write operation
843  temp |= ETH_GMII_ADDRESS_MW_Msk | ETH_GMII_ADDRESS_MB_Msk;
844  //PHY address
845  temp |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk;
846  //Register address
847  temp |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk;
848 
849  //Data to be written in the PHY register
850  ETH0->GMII_DATA = data & ETH_GMII_DATA_MD_Msk;
851 
852  //Start a write operation
853  ETH0->GMII_ADDRESS = temp;
854  //Wait for the write to complete
855  while((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0)
856  {
857  }
858  }
859  else
860  {
861  //The MAC peripheral only supports standard Clause 22 opcodes
862  }
863 }
864 
865 
866 /**
867  * @brief Read PHY register
868  * @param[in] opcode Access type (2 bits)
869  * @param[in] phyAddr PHY address (5 bits)
870  * @param[in] regAddr Register address (5 bits)
871  * @return Register value
872  **/
873 
874 uint16_t xmc4400EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
875  uint8_t regAddr)
876 {
877  uint16_t data;
878  uint32_t temp;
879 
880  //Valid opcode?
881  if(opcode == SMI_OPCODE_READ)
882  {
883  //Take care not to alter MDC clock configuration
884  temp = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk;
885  //Set up a read operation
886  temp |= ETH_GMII_ADDRESS_MB_Msk;
887  //PHY address
888  temp |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk;
889  //Register address
890  temp |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk;
891 
892  //Start a read operation
893  ETH0->GMII_ADDRESS = temp;
894  //Wait for the read to complete
895  while((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0)
896  {
897  }
898 
899  //Get register value
900  data = ETH0->GMII_DATA & ETH_GMII_DATA_MD_Msk;
901  }
902  else
903  {
904  //The MAC peripheral only supports standard Clause 22 opcodes
905  data = 0;
906  }
907 
908  //Return the value of the PHY register
909  return data;
910 }
911 
912 
913 /**
914  * @brief CRC calculation
915  * @param[in] data Pointer to the data over which to calculate the CRC
916  * @param[in] length Number of bytes to process
917  * @return Resulting CRC value
918  **/
919 
920 uint32_t xmc4400EthCalcCrc(const void *data, size_t length)
921 {
922  uint_t i;
923  uint_t j;
924  uint32_t crc;
925  const uint8_t *p;
926 
927  //Point to the data over which to calculate the CRC
928  p = (uint8_t *) data;
929  //CRC preset value
930  crc = 0xFFFFFFFF;
931 
932  //Loop through data
933  for(i = 0; i < length; i++)
934  {
935  //The message is processed bit by bit
936  for(j = 0; j < 8; j++)
937  {
938  //Update CRC value
939  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
940  {
941  crc = (crc << 1) ^ 0x04C11DB7;
942  }
943  else
944  {
945  crc = crc << 1;
946  }
947  }
948  }
949 
950  //Return CRC value
951  return ~crc;
952 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define ETH_BUS_MODE_PR_1_1
error_t xmc4400EthReceivePacket(NetInterface *interface)
Receive a packet.
error_t xmc4400EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
const NicDriver xmc4400EthDriver
XMC4400 Ethernet MAC driver.
uint8_t opcode
Definition: dns_common.h:191
error_t xmc4400EthInit(NetInterface *interface)
XMC4400 Ethernet MAC initialization.
int bool_t
Definition: compiler_port.h:63
#define ETH_CON_MDIO_B
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:690
uint8_t p
Definition: ndp.h:300
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define ETH_TDES1_TBS1
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:224
#define ETH_CON_RXER_A
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:266
#define ETH_RDES0_LS
#define XMC4400_ETH_RAM_SECTION
#define ETH_BUS_MODE_RPBL_32
#define XMC4400_ETH_TX_BUFFER_COUNT
#define ETH_CON_CLK_RMII_C
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:418
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define osExitIsr(flag)
#define ETH_BUS_MODE_PBL_32
#define SMI_OPCODE_WRITE
Definition: nic.h:66
void xmc4400EthDisableIrq(NetInterface *interface)
Disable interrupts.
void xmc4400EthTick(NetInterface *interface)
XMC4400 Ethernet MAC timer handler.
#define ETH_CON_RXD0_A
#define FALSE
Definition: os_port.h:46
#define XMC4400_ETH_IRQ_PRIORITY_GROUPING
#define ETH_RDES0_FL
error_t
Error codes.
Definition: error.h:43
#define XMC4400_ETH_IRQ_GROUP_PRIORITY
void xmc4400EthEnableIrq(NetInterface *interface)
Enable interrupts.
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
error_t xmc4400EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
#define txBuffer
#define ETH_RDES0_OWN
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
MacAddr addr
MAC address.
Definition: ethernet.h:265
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define ETH_RDES0_FS
#define NetTxAncillary
Definition: net_misc.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
error_t xmc4400EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define TRACE_INFO(...)
Definition: debug.h:105
#define ETH_TDES0_OWN
uint8_t length
Definition: tcp.h:375
#define ETH_TDES0_TCH
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
void ETH0_0_IRQHandler(void)
XMC4400 Ethernet MAC interrupt service routine.
#define MIN(a, b)
Definition: os_port.h:63
uint16_t xmc4400EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define ETH_RDES0_ES
#define rxBuffer
MacAddr
Definition: ethernet.h:197
__weak_func void xmc4400EthInitGpio(NetInterface *interface)
GPIO configuration.
#define ETH_TDES0_IC
void xmc4400EthEventHandler(NetInterface *interface)
XMC4400 Ethernet MAC event handler.
#define TRACE_DEBUG(...)
Definition: debug.h:119
Receive DMA descriptor.
uint16_t regAddr
#define ETH_GMII_ADDRESS_CR_DIV62
#define ETH_MTU
Definition: ethernet.h:116
void xmc4400EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
uint8_t n
#define ETH_TDES0_FS
MAC filter table entry.
Definition: ethernet.h:264
#define ETH_RDES1_RCH
#define XMC4400_ETH_TX_BUFFER_SIZE
#define XMC4400_ETH_IRQ_SUB_PRIORITY
#define osEnterIsr()
#define rxDmaDesc
#define ETH_CON_CRS_DV_C
Infineon XMC4400 Ethernet MAC driver.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_TDES0_LS
Transmit DMA descriptor.
uint32_t xmc4400EthCalcCrc(const void *data, size_t length)
CRC calculation.
void xmc4400EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
#define ETH_MAC_CONFIGURATION_RESERVED15_Msk
#define txDmaDesc
#define ETH_RDES1_RBS1
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
unsigned int uint_t
Definition: compiler_port.h:57
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define ETH_CON_RXD1_A
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:51
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define XMC4400_ETH_RX_BUFFER_SIZE
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define XMC4400_ETH_RX_BUFFER_COUNT