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