xmc4800_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file xmc4800_eth_driver.c
3  * @brief Infineon XMC4800 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 "xmc4800.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 = XMC4800_ETH_RAM_SECTION
50 //Receive buffer
51 #pragma data_alignment = 4
52 #pragma location = XMC4800_ETH_RAM_SECTION
54 //Transmit DMA descriptors
55 #pragma data_alignment = 4
56 #pragma location = XMC4800_ETH_RAM_SECTION
58 //Receive DMA descriptors
59 #pragma data_alignment = 4
60 #pragma location = XMC4800_ETH_RAM_SECTION
62 
63 //Keil MDK-ARM or GCC compiler?
64 #else
65 
66 //Transmit buffer
68  __attribute__((aligned(4), __section__(XMC4800_ETH_RAM_SECTION)));
69 //Receive buffer
71  __attribute__((aligned(4), __section__(XMC4800_ETH_RAM_SECTION)));
72 //Transmit DMA descriptors
74  __attribute__((aligned(4), __section__(XMC4800_ETH_RAM_SECTION)));
75 //Receive DMA descriptors
77  __attribute__((aligned(4), __section__(XMC4800_ETH_RAM_SECTION)));
78 
79 #endif
80 
81 //Pointer to the current TX DMA descriptor
82 static Xmc4800TxDmaDesc *txCurDmaDesc;
83 //Pointer to the current RX DMA descriptor
84 static Xmc4800RxDmaDesc *rxCurDmaDesc;
85 
86 
87 /**
88  * @brief XMC4800 Ethernet MAC driver
89  **/
90 
92 {
94  ETH_MTU,
105  TRUE,
106  TRUE,
107  TRUE,
108  FALSE
109 };
110 
111 
112 /**
113  * @brief XMC4800 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 XMC4800 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  xmc4800EthInitGpio(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  //Set the MAC address of the station
181  ETH0->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
182  ETH0->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
183 
184  //The MAC supports 3 additional addresses for unicast perfect filtering
185  ETH0->MAC_ADDRESS1_LOW = 0;
186  ETH0->MAC_ADDRESS1_HIGH = 0;
187  ETH0->MAC_ADDRESS2_LOW = 0;
188  ETH0->MAC_ADDRESS2_HIGH = 0;
189  ETH0->MAC_ADDRESS3_LOW = 0;
190  ETH0->MAC_ADDRESS3_HIGH = 0;
191 
192  //Initialize hash table
193  ETH0->HASH_TABLE_LOW = 0;
194  ETH0->HASH_TABLE_HIGH = 0;
195 
196  //Configure the receive filter
197  ETH0->MAC_FRAME_FILTER = ETH_MAC_FRAME_FILTER_HPF_Msk | ETH_MAC_FRAME_FILTER_HMC_Msk;
198  //Disable flow control
199  ETH0->FLOW_CONTROL = 0;
200  //Enable store and forward mode
201  ETH0->OPERATION_MODE = ETH_OPERATION_MODE_RSF_Msk | ETH_OPERATION_MODE_TSF_Msk;
202 
203  //Configure DMA bus mode
204  ETH0->BUS_MODE = ETH_BUS_MODE_AAL_Msk | ETH_BUS_MODE_USP_Msk |
206 
207  //Initialize DMA descriptor lists
208  xmc4800EthInitDmaDesc(interface);
209 
210  //Prevent interrupts from being generated when statistic counters reach
211  //half their maximum value
212  ETH0->MMC_TRANSMIT_INTERRUPT_MASK = 0xFFFFFFFF;
213  ETH0->MMC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
214  ETH0->MMC_IPC_RECEIVE_INTERRUPT_MASK = 0xFFFFFFFF;
215 
216  //Disable MAC interrupts
217  ETH0->INTERRUPT_MASK = ETH_INTERRUPT_MASK_TSIM_Msk | ETH_INTERRUPT_MASK_PMTIM_Msk;
218 
219  //Enable the desired DMA interrupts
220  ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk |
221  ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk;
222 
223  //Set priority grouping (6 bits for pre-emption priority, no bits for subpriority)
224  NVIC_SetPriorityGrouping(XMC4800_ETH_IRQ_PRIORITY_GROUPING);
225 
226  //Configure Ethernet interrupt priority
227  NVIC_SetPriority(ETH0_0_IRQn, NVIC_EncodePriority(XMC4800_ETH_IRQ_PRIORITY_GROUPING,
229 
230  //Enable MAC transmission and reception
231  ETH0->MAC_CONFIGURATION |= ETH_MAC_CONFIGURATION_TE_Msk | ETH_MAC_CONFIGURATION_RE_Msk;
232  //Enable DMA transmission and reception
233  ETH0->OPERATION_MODE |= ETH_OPERATION_MODE_ST_Msk | ETH_OPERATION_MODE_SR_Msk;
234 
235  //Accept any packets from the upper layer
236  osSetEvent(&interface->nicTxEvent);
237 
238  //Successful initialization
239  return NO_ERROR;
240 }
241 
242 
243 //XMC4800 Relax EtherCAT Kit?
244 #if defined(USE_XMC4800_RELAX_ECAT_KIT)
245 
246 /**
247  * @brief GPIO configuration
248  * @param[in] interface Underlying network interface
249  **/
250 
251 void xmc4800EthInitGpio(NetInterface *interface)
252 {
253  uint32_t temp;
254 
255  //Configure ETH0.MDIO (P2.0), ETH0.RXD0A (P2.2) and ETH0.RXD1A (P2.3)
256  temp = PORT2->IOCR0;
257  temp &= ~(PORT2_IOCR0_PC0_Msk | PORT2_IOCR0_PC2_Msk | PORT2_IOCR0_PC3_Msk);
258  temp |= (0UL << PORT2_IOCR0_PC0_Pos) | (0UL << PORT2_IOCR0_PC2_Pos) | (0UL << PORT2_IOCR0_PC3_Pos);
259  PORT2->IOCR0 = temp;
260 
261  //Configure ETH0.RXERA (P2.4), ETH0.TX_EN (P2.5) and ETH0.MDC (P2.7)
262  temp = PORT2->IOCR4;
263  temp &= ~(PORT2_IOCR4_PC4_Msk | PORT2_IOCR4_PC5_Msk | PORT2_IOCR4_PC7_Msk);
264  temp |= (0UL << PORT2_IOCR4_PC4_Pos) | (17UL << PORT2_IOCR4_PC5_Pos) | (17UL << PORT2_IOCR4_PC7_Pos);
265  PORT2->IOCR4 = temp;
266 
267  //Configure ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9)
268  temp = PORT2->IOCR8;
269  temp &= ~(PORT2_IOCR8_PC8_Msk | PORT2_IOCR8_PC9_Msk);
270  temp |= (17UL << PORT2_IOCR8_PC8_Pos) | (17UL << PORT2_IOCR8_PC9_Pos);
271  PORT2->IOCR8 = temp;
272 
273  //Configure ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9)
274  temp = PORT15->IOCR8;
275  temp &= ~(PORT15_IOCR8_PC8_Msk | PORT15_IOCR8_PC9_Msk);
276  temp |= (0UL << PORT15_IOCR8_PC8_Pos) | (0UL << PORT15_IOCR8_PC9_Pos);
277  PORT15->IOCR8 = temp;
278 
279  //Assign ETH_MDIO (P2.0) to HW0
280  temp = PORT2->HWSEL & ~PORT2_HWSEL_HW0_Msk;
281  PORT2->HWSEL = temp | (1UL << PORT2_HWSEL_HW0_Pos);
282 
283  //Select output driver strength for ETH0.TX_EN (P2.5)
284  temp = PORT2->PDR0;
285  temp &= ~PORT2_PDR0_PD5_Msk;
286  temp |= (0UL << PORT2_PDR0_PD5_Pos);
287  PORT2->PDR0 = temp;
288 
289  //Select output driver strength for ETH0.TXD0 (P2.8) and ETH0.TXD1 (P2.9)
290  temp = PORT2->PDR1;
291  temp &= ~(PORT2_PDR1_PD8_Msk | PORT2_PDR1_PD9_Msk);
292  temp |= (0UL << PORT2_PDR1_PD8_Pos) | (0UL << PORT2_PDR1_PD9_Pos);
293  PORT2->PDR1 = temp;
294 
295  //Use ETH0.CLK_RMIIC (P15.8) and ETH0.CRS_DVC (P15.9) as digital inputs
296  PORT15->PDISC &= ~(PORT15_PDISC_PDIS8_Msk | PORT15_PDISC_PDIS9_Msk);
297 
298  //Select RMII operation mode
299  ETH0_CON->CON = ETH_CON_INFSEL_Msk | ETH_CON_MDIO_B | ETH_CON_RXER_A |
301 }
302 
303 #endif
304 
305 
306 /**
307  * @brief Initialize DMA descriptor lists
308  * @param[in] interface Underlying network interface
309  **/
310 
312 {
313  uint_t i;
314 
315  //Initialize TX DMA descriptor list
316  for(i = 0; i < XMC4800_ETH_TX_BUFFER_COUNT; i++)
317  {
318  //Use chain structure rather than ring structure
319  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
320  //Initialize transmit buffer size
321  txDmaDesc[i].tdes1 = 0;
322  //Transmit buffer address
323  txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i];
324  //Next descriptor address
325  txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1];
326  }
327 
328  //The last descriptor is chained to the first entry
329  txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0];
330  //Point to the very first descriptor
331  txCurDmaDesc = &txDmaDesc[0];
332 
333  //Initialize RX DMA descriptor list
334  for(i = 0; i < XMC4800_ETH_RX_BUFFER_COUNT; i++)
335  {
336  //The descriptor is initially owned by the DMA
337  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
338  //Use chain structure rather than ring structure
340  //Receive buffer address
341  rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i];
342  //Next descriptor address
343  rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1];
344  }
345 
346  //The last descriptor is chained to the first entry
347  rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0];
348  //Point to the very first descriptor
349  rxCurDmaDesc = &rxDmaDesc[0];
350 
351  //Start location of the TX descriptor list
352  ETH0->TRANSMIT_DESCRIPTOR_LIST_ADDRESS = (uint32_t) txDmaDesc;
353  //Start location of the RX descriptor list
354  ETH0->RECEIVE_DESCRIPTOR_LIST_ADDRESS = (uint32_t) rxDmaDesc;
355 }
356 
357 
358 /**
359  * @brief XMC4800 Ethernet MAC timer handler
360  *
361  * This routine is periodically called by the TCP/IP stack to handle periodic
362  * operations such as polling the link state
363  *
364  * @param[in] interface Underlying network interface
365  **/
366 
367 void xmc4800EthTick(NetInterface *interface)
368 {
369  //Valid Ethernet PHY or switch driver?
370  if(interface->phyDriver != NULL)
371  {
372  //Handle periodic operations
373  interface->phyDriver->tick(interface);
374  }
375  else if(interface->switchDriver != NULL)
376  {
377  //Handle periodic operations
378  interface->switchDriver->tick(interface);
379  }
380  else
381  {
382  //Just for sanity
383  }
384 }
385 
386 
387 /**
388  * @brief Enable interrupts
389  * @param[in] interface Underlying network interface
390  **/
391 
393 {
394  //Enable Ethernet MAC interrupts
395  NVIC_EnableIRQ(ETH0_0_IRQn);
396 
397  //Valid Ethernet PHY or switch driver?
398  if(interface->phyDriver != NULL)
399  {
400  //Enable Ethernet PHY interrupts
401  interface->phyDriver->enableIrq(interface);
402  }
403  else if(interface->switchDriver != NULL)
404  {
405  //Enable Ethernet switch interrupts
406  interface->switchDriver->enableIrq(interface);
407  }
408  else
409  {
410  //Just for sanity
411  }
412 }
413 
414 
415 /**
416  * @brief Disable interrupts
417  * @param[in] interface Underlying network interface
418  **/
419 
421 {
422  //Disable Ethernet MAC interrupts
423  NVIC_DisableIRQ(ETH0_0_IRQn);
424 
425  //Valid Ethernet PHY or switch driver?
426  if(interface->phyDriver != NULL)
427  {
428  //Disable Ethernet PHY interrupts
429  interface->phyDriver->disableIrq(interface);
430  }
431  else if(interface->switchDriver != NULL)
432  {
433  //Disable Ethernet switch interrupts
434  interface->switchDriver->disableIrq(interface);
435  }
436  else
437  {
438  //Just for sanity
439  }
440 }
441 
442 
443 /**
444  * @brief XMC4800 Ethernet MAC interrupt service routine
445  **/
446 
448 {
449  bool_t flag;
450  uint32_t status;
451 
452  //Interrupt service routine prologue
453  osEnterIsr();
454 
455  //This flag will be set if a higher priority task must be woken
456  flag = FALSE;
457 
458  //Read DMA status register
459  status = ETH0->STATUS;
460 
461  //Packet transmitted?
462  if((status & ETH_STATUS_TI_Msk) != 0)
463  {
464  //Clear TI interrupt flag
465  ETH0->STATUS = ETH_STATUS_TI_Msk;
466 
467  //Check whether the TX buffer is available for writing
468  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
469  {
470  //Notify the TCP/IP stack that the transmitter is ready to send
471  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
472  }
473  }
474 
475  //Packet received?
476  if((status & ETH_STATUS_RI_Msk) != 0)
477  {
478  //Disable RIE interrupt
479  ETH0->INTERRUPT_ENABLE &= ~ETH_INTERRUPT_ENABLE_RIE_Msk;
480 
481  //Set event flag
482  nicDriverInterface->nicEvent = TRUE;
483  //Notify the TCP/IP stack of the event
484  flag |= osSetEventFromIsr(&netEvent);
485  }
486 
487  //Clear NIS interrupt flag
488  ETH0->STATUS = ETH_STATUS_NIS_Msk;
489 
490  //Interrupt service routine epilogue
491  osExitIsr(flag);
492 }
493 
494 
495 /**
496  * @brief XMC4800 Ethernet MAC event handler
497  * @param[in] interface Underlying network interface
498  **/
499 
501 {
502  error_t error;
503 
504  //Packet received?
505  if((ETH0->STATUS & ETH_STATUS_RI_Msk) != 0)
506  {
507  //Clear interrupt flag
508  ETH0->STATUS = ETH_STATUS_RI_Msk;
509 
510  //Process all pending packets
511  do
512  {
513  //Read incoming packet
514  error = xmc4800EthReceivePacket(interface);
515 
516  //No more data in the receive buffer?
517  } while(error != ERROR_BUFFER_EMPTY);
518  }
519 
520  //Re-enable DMA interrupts
521  ETH0->INTERRUPT_ENABLE = ETH_INTERRUPT_ENABLE_NIE_Msk |
522  ETH_INTERRUPT_ENABLE_RIE_Msk | ETH_INTERRUPT_ENABLE_TIE_Msk;
523 }
524 
525 
526 /**
527  * @brief Send a packet
528  * @param[in] interface Underlying network interface
529  * @param[in] buffer Multi-part buffer containing the data to send
530  * @param[in] offset Offset to the first data byte
531  * @param[in] ancillary Additional options passed to the stack along with
532  * the packet
533  * @return Error code
534  **/
535 
537  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
538 {
539  size_t length;
540 
541  //Retrieve the length of the packet
542  length = netBufferGetLength(buffer) - offset;
543 
544  //Check the frame length
546  {
547  //The transmitter can accept another packet
548  osSetEvent(&interface->nicTxEvent);
549  //Report an error
550  return ERROR_INVALID_LENGTH;
551  }
552 
553  //Make sure the current buffer is available for writing
554  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) != 0)
555  {
556  return ERROR_FAILURE;
557  }
558 
559  //Copy user data to the transmit buffer
560  netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length);
561 
562  //Write the number of bytes to send
563  txCurDmaDesc->tdes1 = length & ETH_TDES1_TBS1;
564  //Set LS and FS flags as the data fits in a single buffer
565  txCurDmaDesc->tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
566  //Give the ownership of the descriptor to the DMA
567  txCurDmaDesc->tdes0 |= ETH_TDES0_OWN;
568 
569  //Clear TU flag to resume processing
570  ETH0->STATUS = ETH_STATUS_TU_Msk;
571  //Instruct the DMA to poll the transmit descriptor list
572  ETH0->TRANSMIT_POLL_DEMAND = 0;
573 
574  //Point to the next descriptor in the list
575  txCurDmaDesc = (Xmc4800TxDmaDesc *) txCurDmaDesc->tdes3;
576 
577  //Check whether the next buffer is available for writing
578  if((txCurDmaDesc->tdes0 & ETH_TDES0_OWN) == 0)
579  {
580  //The transmitter can accept another packet
581  osSetEvent(&interface->nicTxEvent);
582  }
583 
584  //Data successfully written
585  return NO_ERROR;
586 }
587 
588 
589 /**
590  * @brief Receive a packet
591  * @param[in] interface Underlying network interface
592  * @return Error code
593  **/
594 
596 {
597  error_t error;
598  size_t n;
599  NetRxAncillary ancillary;
600 
601  //The current buffer is available for reading?
602  if((rxCurDmaDesc->rdes0 & ETH_RDES0_OWN) == 0)
603  {
604  //FS and LS flags should be set
605  if((rxCurDmaDesc->rdes0 & ETH_RDES0_FS) != 0 &&
606  (rxCurDmaDesc->rdes0 & ETH_RDES0_LS) != 0)
607  {
608  //Make sure no error occurred
609  if((rxCurDmaDesc->rdes0 & ETH_RDES0_ES) == 0)
610  {
611  //Retrieve the length of the frame
612  n = (rxCurDmaDesc->rdes0 & ETH_RDES0_FL) >> 16;
613  //Limit the number of data to read
615 
616  //Additional options can be passed to the stack along with the packet
617  ancillary = NET_DEFAULT_RX_ANCILLARY;
618 
619  //Pass the packet to the upper layer
620  nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n,
621  &ancillary);
622 
623  //Valid packet received
624  error = NO_ERROR;
625  }
626  else
627  {
628  //The received packet contains an error
629  error = ERROR_INVALID_PACKET;
630  }
631  }
632  else
633  {
634  //The packet is not valid
635  error = ERROR_INVALID_PACKET;
636  }
637 
638  //Give the ownership of the descriptor back to the DMA
639  rxCurDmaDesc->rdes0 = ETH_RDES0_OWN;
640  //Point to the next descriptor in the list
641  rxCurDmaDesc = (Xmc4800RxDmaDesc *) rxCurDmaDesc->rdes3;
642  }
643  else
644  {
645  //No more data in the receive buffer
646  error = ERROR_BUFFER_EMPTY;
647  }
648 
649  //Clear RU flag to resume processing
650  ETH0->STATUS = ETH_STATUS_RU_Msk;
651  //Instruct the DMA to poll the receive descriptor list
652  ETH0->RECEIVE_POLL_DEMAND = 0;
653 
654  //Return status code
655  return error;
656 }
657 
658 
659 /**
660  * @brief Configure MAC address filtering
661  * @param[in] interface Underlying network interface
662  * @return Error code
663  **/
664 
666 {
667  uint_t i;
668  uint_t j;
669  uint_t k;
670  uint32_t crc;
671  uint32_t hashTable[2];
672  MacAddr unicastMacAddr[3];
673  MacFilterEntry *entry;
674 
675  //Debug message
676  TRACE_DEBUG("Updating MAC filter...\r\n");
677 
678  //Set the MAC address of the station
679  ETH0->MAC_ADDRESS0_LOW = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
680  ETH0->MAC_ADDRESS0_HIGH = interface->macAddr.w[2];
681 
682  //The MAC supports 3 additional addresses for unicast perfect filtering
683  unicastMacAddr[0] = MAC_UNSPECIFIED_ADDR;
684  unicastMacAddr[1] = MAC_UNSPECIFIED_ADDR;
685  unicastMacAddr[2] = MAC_UNSPECIFIED_ADDR;
686 
687  //The hash table is used for multicast address filtering
688  hashTable[0] = 0;
689  hashTable[1] = 0;
690 
691  //The MAC address filter contains the list of MAC addresses to accept
692  //when receiving an Ethernet frame
693  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
694  {
695  //Point to the current entry
696  entry = &interface->macAddrFilter[i];
697 
698  //Valid entry?
699  if(entry->refCount > 0)
700  {
701  //Multicast address?
702  if(macIsMulticastAddr(&entry->addr))
703  {
704  //Compute CRC over the current MAC address
705  crc = xmc4800EthCalcCrc(&entry->addr, sizeof(MacAddr));
706 
707  //The upper 6 bits in the CRC register are used to index the
708  //contents of the hash table
709  k = (crc >> 26) & 0x3F;
710 
711  //Update hash table contents
712  hashTable[k / 32] |= (1 << (k % 32));
713  }
714  else
715  {
716  //Up to 3 additional MAC addresses can be specified
717  if(j < 3)
718  {
719  //Save the unicast address
720  unicastMacAddr[j++] = entry->addr;
721  }
722  }
723  }
724  }
725 
726  //Configure the first unicast address filter
727  if(j >= 1)
728  {
729  //When the AE bit is set, the entry is used for perfect filtering
730  ETH0->MAC_ADDRESS1_LOW = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
731  ETH0->MAC_ADDRESS1_HIGH = unicastMacAddr[0].w[2] | ETH_MAC_ADDRESS1_HIGH_AE_Msk;
732  }
733  else
734  {
735  //When the AE bit is cleared, the entry is ignored
736  ETH0->MAC_ADDRESS1_LOW = 0;
737  ETH0->MAC_ADDRESS1_HIGH = 0;
738  }
739 
740  //Configure the second unicast address filter
741  if(j >= 2)
742  {
743  //When the AE bit is set, the entry is used for perfect filtering
744  ETH0->MAC_ADDRESS2_LOW = unicastMacAddr[1].w[0] | (unicastMacAddr[1].w[1] << 16);
745  ETH0->MAC_ADDRESS2_HIGH = unicastMacAddr[1].w[2] | ETH_MAC_ADDRESS2_HIGH_AE_Msk;
746  }
747  else
748  {
749  //When the AE bit is cleared, the entry is ignored
750  ETH0->MAC_ADDRESS2_LOW = 0;
751  ETH0->MAC_ADDRESS2_HIGH = 0;
752  }
753 
754  //Configure the third unicast address filter
755  if(j >= 3)
756  {
757  //When the AE bit is set, the entry is used for perfect filtering
758  ETH0->MAC_ADDRESS3_LOW = unicastMacAddr[2].w[0] | (unicastMacAddr[2].w[1] << 16);
759  ETH0->MAC_ADDRESS3_HIGH = unicastMacAddr[2].w[2] | ETH_MAC_ADDRESS3_HIGH_AE_Msk;
760  }
761  else
762  {
763  //When the AE bit is cleared, the entry is ignored
764  ETH0->MAC_ADDRESS3_LOW = 0;
765  ETH0->MAC_ADDRESS3_HIGH = 0;
766  }
767 
768  //Configure the multicast address filter
769  ETH0->HASH_TABLE_LOW = hashTable[0];
770  ETH0->HASH_TABLE_HIGH = hashTable[1];
771 
772  //Debug message
773  TRACE_DEBUG(" HASH_TABLE_LOW = %08" PRIX32 "\r\n", ETH0->HASH_TABLE_LOW);
774  TRACE_DEBUG(" HASH_TABLE_HIGH = %08" PRIX32 "\r\n", ETH0->HASH_TABLE_HIGH);
775 
776  //Successful processing
777  return NO_ERROR;
778 }
779 
780 
781 /**
782  * @brief Adjust MAC configuration parameters for proper operation
783  * @param[in] interface Underlying network interface
784  * @return Error code
785  **/
786 
788 {
789  uint32_t config;
790 
791  //Read current MAC configuration
792  config = ETH0->MAC_CONFIGURATION;
793 
794  //10BASE-T or 100BASE-TX operation mode?
795  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
796  {
797  config |= ETH_MAC_CONFIGURATION_FES_Msk;
798  }
799  else
800  {
801  config &= ~ETH_MAC_CONFIGURATION_FES_Msk;
802  }
803 
804  //Half-duplex or full-duplex mode?
805  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
806  {
807  config |= ETH_MAC_CONFIGURATION_DM_Msk;
808  }
809  else
810  {
811  config &= ~ETH_MAC_CONFIGURATION_DM_Msk;
812  }
813 
814  //Update MAC configuration register
815  ETH0->MAC_CONFIGURATION = config;
816 
817  //Successful processing
818  return NO_ERROR;
819 }
820 
821 
822 /**
823  * @brief Write PHY register
824  * @param[in] opcode Access type (2 bits)
825  * @param[in] phyAddr PHY address (5 bits)
826  * @param[in] regAddr Register address (5 bits)
827  * @param[in] data Register value
828  **/
829 
830 void xmc4800EthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
831  uint8_t regAddr, uint16_t data)
832 {
833  uint32_t temp;
834 
835  //Valid opcode?
836  if(opcode == SMI_OPCODE_WRITE)
837  {
838  //Take care not to alter MDC clock configuration
839  temp = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk;
840  //Set up a write operation
841  temp |= ETH_GMII_ADDRESS_MW_Msk | ETH_GMII_ADDRESS_MB_Msk;
842  //PHY address
843  temp |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk;
844  //Register address
845  temp |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk;
846 
847  //Data to be written in the PHY register
848  ETH0->GMII_DATA = data & ETH_GMII_DATA_MD_Msk;
849 
850  //Start a write operation
851  ETH0->GMII_ADDRESS = temp;
852  //Wait for the write to complete
853  while((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0)
854  {
855  }
856  }
857  else
858  {
859  //The MAC peripheral only supports standard Clause 22 opcodes
860  }
861 }
862 
863 
864 /**
865  * @brief Read PHY register
866  * @param[in] opcode Access type (2 bits)
867  * @param[in] phyAddr PHY address (5 bits)
868  * @param[in] regAddr Register address (5 bits)
869  * @return Register value
870  **/
871 
872 uint16_t xmc4800EthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
873  uint8_t regAddr)
874 {
875  uint16_t data;
876  uint32_t temp;
877 
878  //Valid opcode?
879  if(opcode == SMI_OPCODE_READ)
880  {
881  //Take care not to alter MDC clock configuration
882  temp = ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_CR_Msk;
883  //Set up a read operation
884  temp |= ETH_GMII_ADDRESS_MB_Msk;
885  //PHY address
886  temp |= (phyAddr << ETH_GMII_ADDRESS_PA_Pos) & ETH_GMII_ADDRESS_PA_Msk;
887  //Register address
888  temp |= (regAddr << ETH_GMII_ADDRESS_MR_Pos) & ETH_GMII_ADDRESS_MR_Msk;
889 
890  //Start a read operation
891  ETH0->GMII_ADDRESS = temp;
892  //Wait for the read to complete
893  while((ETH0->GMII_ADDRESS & ETH_GMII_ADDRESS_MB_Msk) != 0)
894  {
895  }
896 
897  //Get register value
898  data = ETH0->GMII_DATA & ETH_GMII_DATA_MD_Msk;
899  }
900  else
901  {
902  //The MAC peripheral only supports standard Clause 22 opcodes
903  data = 0;
904  }
905 
906  //Return the value of the PHY register
907  return data;
908 }
909 
910 
911 /**
912  * @brief CRC calculation
913  * @param[in] data Pointer to the data over which to calculate the CRC
914  * @param[in] length Number of bytes to process
915  * @return Resulting CRC value
916  **/
917 
918 uint32_t xmc4800EthCalcCrc(const void *data, size_t length)
919 {
920  uint_t i;
921  uint_t j;
922  uint32_t crc;
923  const uint8_t *p;
924 
925  //Point to the data over which to calculate the CRC
926  p = (uint8_t *) data;
927  //CRC preset value
928  crc = 0xFFFFFFFF;
929 
930  //Loop through data
931  for(i = 0; i < length; i++)
932  {
933  //The message is processed bit by bit
934  for(j = 0; j < 8; j++)
935  {
936  //Update CRC value
937  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
938  {
939  crc = (crc << 1) ^ 0x04C11DB7;
940  }
941  else
942  {
943  crc = crc << 1;
944  }
945  }
946  }
947 
948  //Return CRC value
949  return ~crc;
950 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define ETH_GMII_ADDRESS_CR_DIV62
uint8_t length
Definition: coap_common.h:190
error_t xmc4800EthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define ETH_CON_RXD0_A
uint8_t opcode
Definition: dns_common.h:172
int bool_t
Definition: compiler_port.h:49
#define ETH_TDES0_IC
#define netEvent
Definition: net_legacy.h:267
void xmc4800EthTick(NetInterface *interface)
XMC4800 Ethernet MAC timer handler.
uint8_t data[]
Definition: ethernet.h:209
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
#define ETH_TDES0_TCH
void xmc4800EthDisableIrq(NetInterface *interface)
Disable interrupts.
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
error_t xmc4800EthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void xmc4800EthEnableIrq(NetInterface *interface)
Enable interrupts.
const NicDriver xmc4800EthDriver
XMC4800 Ethernet MAC driver.
#define XMC4800_ETH_TX_BUFFER_SIZE
__start_packed struct @5 MacAddr
MAC address.
#define XMC4800_ETH_RX_BUFFER_COUNT
void xmc4800EthInitGpio(NetInterface *interface)
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:249
#define ETH_RDES0_OWN
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 XMC4800_ETH_RX_BUFFER_SIZE
#define osExitIsr(flag)
void xmc4800EthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t xmc4800EthInit(NetInterface *interface)
XMC4800 Ethernet MAC initialization.
#define SMI_OPCODE_WRITE
Definition: nic.h:65
#define XMC4800_ETH_RAM_SECTION
#define FALSE
Definition: os_port.h:46
#define ETH_RDES1_RBS1
#define ETH_CON_MDIO_B
error_t
Error codes.
Definition: error.h:42
#define ETH_RDES0_FL
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
void xmc4800EthEventHandler(NetInterface *interface)
XMC4800 Ethernet MAC event handler.
MacAddr addr
MAC address.
Definition: ethernet.h:248
#define ETH_RDES0_LS
#define NetTxAncillary
Definition: net_misc.h:36
#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
error_t xmc4800EthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
#define MIN(a, b)
Definition: os_port.h:62
error_t xmc4800EthReceivePacket(NetInterface *interface)
Receive a packet.
#define ETH_BUS_MODE_PBL_1
#define ETH_CON_CRS_DV_C
#define rxBuffer
#define ETH_RDES1_RCH
#define ETH_MAC_CONFIGURATION_RESERVED15_Msk
Receive DMA descriptor.
#define XMC4800_ETH_IRQ_PRIORITY_GROUPING
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define XMC4800_ETH_IRQ_SUB_PRIORITY
#define ETH_CON_RXER_A
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:105
uint8_t n
MAC filter table entry.
Definition: ethernet.h:246
uint32_t xmc4800EthCalcCrc(const void *data, size_t length)
CRC calculation.
#define XMC4800_ETH_TX_BUFFER_COUNT
#define ETH_TDES0_LS
#define osEnterIsr()
#define ETH_BUS_MODE_RPBL_1
#define ETH_CON_CLK_RMII_C
#define ETH_BUS_MODE_PR_1_1
Transmit DMA descriptor.
#define rxDmaDesc
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void ETH0_0_IRQHandler(void)
XMC4800 Ethernet MAC interrupt service routine.
#define XMC4800_ETH_IRQ_GROUP_PRIORITY
#define ETH_TDES0_FS
#define txDmaDesc
uint16_t xmc4800EthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
#define ETH_RDES0_ES
unsigned int uint_t
Definition: compiler_port.h:45
TCP/IP stack core.
NIC driver.
Definition: nic.h:257
void xmc4800EthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
#define ETH_TDES0_OWN
Infineon XMC4800 Ethernet MAC driver.
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:56
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define ETH_CON_RXD1_A
#define ETH_TDES1_TBS1
#define ETH_RDES0_FS
Ethernet interface.
Definition: nic.h:82