tc2xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file tc2xx_eth_driver.c
3  * @brief Infineon AURIX TriCore TC2xx Ethernet MAC driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 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.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <machine/intrinsics.h>
36 #include <machine/wdtcon.h>
37 #include "tc_inc_path.h"
38 #include TC_INCLUDE(TCPATH/Ifx_reg.h)
39 #include TC_INCLUDE(TCPATH/IfxCpu_bf.h)
40 #include "interrupts.h"
41 #include "core/net.h"
43 #include "debug.h"
44 
45 //Underlying network interface
46 static NetInterface *nicDriverInterface;
47 
48 //Tasking compiler?
49 #if defined(__TASKING__)
50 
51 //Transmit buffer
53  __align(4);
54 //Receive buffer
56  __align(4);
57 //Transmit DMA descriptors
59  __align(4);
60 //Receive DMA descriptors
62  __align(4);
63 
64 //GCC compiler?
65 #else
66 
67 //Transmit buffer
69  __attribute__((aligned(4)));
70 //Receive buffer
72  __attribute__((aligned(4)));
73 //Transmit DMA descriptors
75  __attribute__((aligned(4)));
76 //Receive DMA descriptors
78  __attribute__((aligned(4)));
79 
80 #endif
81 
82 //Current transmit descriptor
83 static uint_t txIndex;
84 //Current receive descriptor
85 static uint_t rxIndex;
86 
87 
88 /**
89  * @brief TC2xx Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief TC2xx Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122  uint_t i;
123 
124  //Debug message
125  TRACE_INFO("Initializing TC2xx Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //Unlock sequence
131  unlock_wdtcon();
132  //Enable Ethernet module
133  MODULE_ETH.CLC.U = 0;
134  //Lock sequence
135  lock_wdtcon();
136 
137  //GPIO configuration
138  tc2xxEthInitGpio(interface);
139 
140  //Unlock sequence
141  unlock_wdtcon();
142  //Perform kernel reset
143  MODULE_ETH.KRST0.B.RST = 1;
144  MODULE_ETH.KRST1.B.RST = 1;
145  //Lock sequence
146  lock_wdtcon();
147 
148  //Wait for the reset to complete
149  while(MODULE_ETH.KRST0.B.RSTSTAT == 0)
150  {
151  }
152 
153  //Unlock sequence
154  unlock_wdtcon();
155  //Clear kernel reset status
156  MODULE_ETH.KRSTCLR.B.CLR = 1;
157  //Lock sequence
158  lock_wdtcon();
159 
160  //Perform a software reset
161  MODULE_ETH.BUS_MODE.B.SWR = 1;
162  //Wait for the reset to complete
163  while(MODULE_ETH.BUS_MODE.B.SWR)
164  {
165  }
166 
167  //Adjust MDC clock range depending on CSR clock frequency
168  MODULE_ETH.GMII_ADDRESS.B.CR = 4;
169 
170  //Valid Ethernet PHY or switch driver?
171  if(interface->phyDriver != NULL)
172  {
173  //Ethernet PHY initialization
174  error = interface->phyDriver->init(interface);
175  }
176  else if(interface->switchDriver != NULL)
177  {
178  //Ethernet switch initialization
179  error = interface->switchDriver->init(interface);
180  }
181  else
182  {
183  //The interface is not properly configured
184  error = ERROR_FAILURE;
185  }
186 
187  //Any error to report?
188  if(error)
189  {
190  return error;
191  }
192 
193  //Use default MAC configuration
194  MODULE_ETH.MAC_CONFIGURATION.U = 0;
195  MODULE_ETH.MAC_CONFIGURATION.B.PS = 1;
196  MODULE_ETH.MAC_CONFIGURATION.B.DO = 1;
197 
198  //Set the MAC address of the station
199  MODULE_ETH.MAC_ADDRESS_G0[0].LOW.U = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
200  MODULE_ETH.MAC_ADDRESS_G0[0].HIGH.U = interface->macAddr.w[2];
201 
202  //The MAC supports 15 additional addresses for unicast perfect filtering
203  for(i = 1; i < 16; i++)
204  {
205  MODULE_ETH.MAC_ADDRESS_G0[i].LOW.U = 0;
206  MODULE_ETH.MAC_ADDRESS_G0[i].HIGH.U = 0;
207  }
208 
209  //Initialize hash table
210  MODULE_ETH.HASH_TABLE_LOW.U = 0;
211  MODULE_ETH.HASH_TABLE_HIGH.U = 0;
212 
213  //Configure the receive filter
214  MODULE_ETH.MAC_FRAME_FILTER.U = 0;
215  MODULE_ETH.MAC_FRAME_FILTER.B.HPF = 1;
216  MODULE_ETH.MAC_FRAME_FILTER.B.HMC = 1;
217 
218  //Disable flow control
219  MODULE_ETH.FLOW_CONTROL.U = 0;
220 
221  //Enable store and forward mode
222  MODULE_ETH.OPERATION_MODE.U = 0;
223  MODULE_ETH.OPERATION_MODE.B.RSF = 1;
224  MODULE_ETH.OPERATION_MODE.B.TSF = 1;
225 
226  //Configure DMA bus mode
227  MODULE_ETH.BUS_MODE.U = 0;
228  MODULE_ETH.BUS_MODE.B.PRWG = 0;
229  MODULE_ETH.BUS_MODE.B.TXPR = 0;
230  MODULE_ETH.BUS_MODE.B.MB = 0;
231  MODULE_ETH.BUS_MODE.B.AAL = 1;
232  MODULE_ETH.BUS_MODE.B.PBLx8 = 0;
233  MODULE_ETH.BUS_MODE.B.USP = 1;
234  MODULE_ETH.BUS_MODE.B.RPBL = 1;
235  MODULE_ETH.BUS_MODE.B.FB = 0;
236  MODULE_ETH.BUS_MODE.B.PR = 0;
237  MODULE_ETH.BUS_MODE.B.PBL = 1;
238  MODULE_ETH.BUS_MODE.B.ATDS = 1;
239  MODULE_ETH.BUS_MODE.B.DSL = 0;
240  MODULE_ETH.BUS_MODE.B.DA = 0;
241 
242  //Initialize DMA descriptor lists
243  tc2xxEthInitDmaDesc(interface);
244 
245  //Disable all MMC counters
246  MODULE_ETH.MMC_CONTROL.B.CNTFREEZ = 1;
247 
248  //Disable MAC interrupts
249  MODULE_ETH.INTERRUPT_MASK.B.LPIIM = 1;
250  MODULE_ETH.INTERRUPT_MASK.B.TSIM = 1;
251  MODULE_ETH.INTERRUPT_MASK.B.PMTIM = 1;
252  MODULE_ETH.INTERRUPT_MASK.B.PCSANCIM = 1;
253  MODULE_ETH.INTERRUPT_MASK.B.PCSLCHGIM = 1;
254  MODULE_ETH.INTERRUPT_MASK.B.RGSMIIIM = 1;
255 
256  //Enable the desired DMA interrupts
257  MODULE_ETH.INTERRUPT_ENABLE.B.TIE = 1;
258  MODULE_ETH.INTERRUPT_ENABLE.B.RIE = 1;
259  MODULE_ETH.INTERRUPT_ENABLE.B.NIE = 1;
260 
261  //Register interrupt handler
262  InterruptInstall(SRC_ID_ETH, tc2xxEthIrqHandler, TC2XX_ETH_IRQ_PRIORITY, 0);
263 
264  //Enable MAC transmission and reception
265  MODULE_ETH.MAC_CONFIGURATION.B.TE = 1;
266  MODULE_ETH.MAC_CONFIGURATION.B.RE = 1;
267 
268  //Enable DMA transmission and reception
269  MODULE_ETH.OPERATION_MODE.B.ST = 1;
270  MODULE_ETH.OPERATION_MODE.B.SR = 1;
271 
272  //Accept any packets from the upper layer
273  osSetEvent(&interface->nicTxEvent);
274 
275  //Successful initialization
276  return NO_ERROR;
277 }
278 
279 
280 /**
281  * @brief GPIO configuration
282  * @param[in] interface Underlying network interface
283  **/
284 
285 __weak_func void tc2xxEthInitGpio(NetInterface *interface)
286 {
287 //AURIX TC265 Starter Kit?
288 #if defined(USE_KIT_AURIX_TC265_TRB)
289  //Configure ETHTXD1 (P11.2)
290  MODULE_P11.IOCR0.B.PC2 = 22;
291 
292  //Configure ETHTXD0 (P11.3)
293  MODULE_P11.IOCR0.B.PC3 = 22;
294 
295  //Configure ETHTXEN (P11.6)
296  MODULE_P11.IOCR4.B.PC6 = 22;
297 
298  //Configure ETHRXD1 (P11.9)
299  MODULE_P11.IOCR8.B.PC9 = 0;
300  MODULE_ETH.GPCTL.B.ALTI7 = 0;
301 
302  //Configure ETHRXD0 (P11.10)
303  MODULE_P11.IOCR8.B.PC10 = 0;
304  MODULE_ETH.GPCTL.B.ALTI6 = 0;
305 
306  //Configure ETHCRSDVA (P11.11)
307  MODULE_P11.IOCR8.B.PC11 = 0;
308  MODULE_ETH.GPCTL.B.ALTI4 = 0;
309 
310  //Configure ETHRXCLKA (P11.12)
311  MODULE_P11.IOCR12.B.PC12 = 0;
312  MODULE_ETH.GPCTL.B.ALTI1 = 0;
313 
314  //Configure ETHMDC (P21.0)
315  MODULE_P21.IOCR0.B.PC0 = 22;
316 
317  //Configure ETHMDIOB (P21.1)
318  MODULE_P21.IOCR0.B.PC1 = 22;
319  MODULE_ETH.GPCTL.B.ALTI0 = 1;
320 
321  //Unlock sequence
322  unlock_safety_wdtcon();
323 
324  //Select Ethernet output signals through fast RMII mode
325  MODULE_P11.PCSR.B.SEL2 = 1;
326  MODULE_P11.PCSR.B.SEL3 = 1;
327  MODULE_P11.PCSR.B.SEL6 = 1;
328 
329  //Lock sequence
330  lock_safety_wdtcon();
331 
332  //Unlock sequence
333  unlock_wdtcon();
334 
335  //Set speed grade
336  MODULE_P11.PDR0.B.PD2 = 0;
337  MODULE_P11.PDR0.B.PL2 = 0;
338  MODULE_P11.PDR0.B.PD3 = 0;
339  MODULE_P11.PDR0.B.PL3 = 0;
340  MODULE_P11.PDR0.B.PD6 = 0;
341  MODULE_P11.PDR0.B.PL6 = 0;
342 
343  MODULE_P11.PDR1.B.PD9 = 0;
344  MODULE_P11.PDR1.B.PL9 = 0;
345  MODULE_P11.PDR1.B.PD10 = 0;
346  MODULE_P11.PDR1.B.PL10 = 0;
347  MODULE_P11.PDR1.B.PD11 = 0;
348  MODULE_P11.PDR1.B.PL11 = 0;
349  MODULE_P11.PDR1.B.PD12 = 0;
350  MODULE_P11.PDR1.B.PL12 = 0;
351 
352  MODULE_P21.PDR0.B.PD0 = 0;
353  MODULE_P21.PDR0.B.PL0 = 0;
354  MODULE_P21.PDR0.B.PD1 = 3;
355  MODULE_P21.PDR0.B.PL1 = 0;
356 
357  //Lock sequence
358  lock_wdtcon();
359 
360  //Select RMII operation mode
361  MODULE_ETH.GPCTL.B.EPR = 1;
362 
363 //AURIX TC277 TFT Application Kit or AURIX TC297 TFT Application Kit?
364 #elif defined(USE_KIT_AURIX_TC277_TFT) || defined(USE_KIT_AURIX_TC297_TFT)
365  //Configure ETHTXD1 (P11.2)
366  MODULE_P11.IOCR0.B.PC2 = 22;
367 
368  //Configure ETHTXD0 (P11.3)
369  MODULE_P11.IOCR0.B.PC3 = 22;
370 
371  //Configure ETHTXEN (P11.6)
372  MODULE_P11.IOCR4.B.PC6 = 22;
373 
374  //Configure ETHRXD1 (P11.9)
375  MODULE_P11.IOCR8.B.PC9 = 0;
376  MODULE_ETH.GPCTL.B.ALTI7 = 0;
377 
378  //Configure ETHRXD0 (P11.10)
379  MODULE_P11.IOCR8.B.PC10 = 0;
380  MODULE_ETH.GPCTL.B.ALTI6 = 0;
381 
382  //Configure ETHCRSDVA (P11.11)
383  MODULE_P11.IOCR8.B.PC11 = 0;
384  MODULE_ETH.GPCTL.B.ALTI4 = 0;
385 
386  //Configure ETHRXCLKA (P11.12)
387  MODULE_P11.IOCR12.B.PC12 = 0;
388  MODULE_ETH.GPCTL.B.ALTI1 = 0;
389 
390  //Configure ETHMDC (P21.2)
391  MODULE_P21.IOCR0.B.PC2 = 21;
392 
393  //Configure ETHMDIOD (P21.3)
394  MODULE_P21.IOCR0.B.PC3 = 0;
395  MODULE_ETH.GPCTL.B.ALTI0 = 3;
396 
397  //Unlock sequence
398  unlock_safety_wdtcon();
399 
400  //Select Ethernet output signals through fast RMII mode
401  MODULE_P11.PCSR.B.SEL2 = 1;
402  MODULE_P11.PCSR.B.SEL3 = 1;
403  MODULE_P11.PCSR.B.SEL6 = 1;
404 
405  //Lock sequence
406  lock_safety_wdtcon();
407 
408  //Unlock sequence
409  unlock_wdtcon();
410 
411  //Set speed grade
412  MODULE_P11.PDR0.B.PD2 = 0;
413  MODULE_P11.PDR0.B.PL2 = 0;
414  MODULE_P11.PDR0.B.PD3 = 0;
415  MODULE_P11.PDR0.B.PL3 = 0;
416  MODULE_P11.PDR0.B.PD6 = 0;
417  MODULE_P11.PDR0.B.PL6 = 0;
418 
419  MODULE_P11.PDR1.B.PD9 = 0;
420  MODULE_P11.PDR1.B.PL9 = 0;
421  MODULE_P11.PDR1.B.PD10 = 0;
422  MODULE_P11.PDR1.B.PL10 = 0;
423  MODULE_P11.PDR1.B.PD11 = 0;
424  MODULE_P11.PDR1.B.PL11 = 0;
425  MODULE_P11.PDR1.B.PD12 = 0;
426  MODULE_P11.PDR1.B.PL12 = 0;
427 
428  MODULE_P21.PDR0.B.PD2 = 0;
429  MODULE_P21.PDR0.B.PL2 = 0;
430  MODULE_P21.PDR0.B.PD3 = 0;
431  MODULE_P21.PDR0.B.PL3 = 0;
432 
433  //Lock sequence
434  lock_wdtcon();
435 
436  //Select RMII operation mode
437  MODULE_ETH.GPCTL.B.EPR = 1;
438 #endif
439 }
440 
441 
442 /**
443  * @brief Initialize DMA descriptor lists
444  * @param[in] interface Underlying network interface
445  **/
446 
448 {
449  uint_t i;
450 
451  //Initialize TX DMA descriptor list
452  for(i = 0; i < TC2XX_ETH_TX_BUFFER_COUNT; i++)
453  {
454  //Use chain structure rather than ring structure
455  txDmaDesc[i].tdes0 = ETH_TDES0_IC | ETH_TDES0_TCH;
456  //Initialize transmit buffer size
457  txDmaDesc[i].tdes1 = 0;
458  //Transmit buffer address
459  txDmaDesc[i].tdes2 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(txBuffer[i]);
460  //Next descriptor address
461  txDmaDesc[i].tdes3 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&txDmaDesc[i + 1]);
462  //Reserved fields
463  txDmaDesc[i].tdes4 = 0;
464  txDmaDesc[i].tdes5 = 0;
465  //Transmit frame time stamp
466  txDmaDesc[i].tdes6 = 0;
467  txDmaDesc[i].tdes7 = 0;
468  }
469 
470  //The last descriptor is chained to the first entry
471  txDmaDesc[i - 1].tdes3 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&txDmaDesc[0]);
472  //Point to the very first descriptor
473  txIndex = 0;
474 
475  //Initialize RX DMA descriptor list
476  for(i = 0; i < TC2XX_ETH_RX_BUFFER_COUNT; i++)
477  {
478  //The descriptor is initially owned by the DMA
479  rxDmaDesc[i].rdes0 = ETH_RDES0_OWN;
480  //Use chain structure rather than ring structure
482  //Receive buffer address
483  rxDmaDesc[i].rdes2 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(rxBuffer[i]);
484  //Next descriptor address
485  rxDmaDesc[i].rdes3 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&rxDmaDesc[i + 1]);
486  //Extended status
487  rxDmaDesc[i].rdes4 = 0;
488  //Reserved field
489  rxDmaDesc[i].rdes5 = 0;
490  //Receive frame time stamp
491  rxDmaDesc[i].rdes6 = 0;
492  rxDmaDesc[i].rdes7 = 0;
493  }
494 
495  //The last descriptor is chained to the first entry
496  rxDmaDesc[i - 1].rdes3 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&rxDmaDesc[0]);
497  //Point to the very first descriptor
498  rxIndex = 0;
499 
500  //Start location of the TX descriptor list
501  MODULE_ETH.TRANSMIT_DESCRIPTOR_LIST_ADDRESS.U = (uint32_t) ETH_GLOBAL_DSPR_ADDR(txDmaDesc);
502  //Start location of the RX descriptor list
503  MODULE_ETH.RECEIVE_DESCRIPTOR_LIST_ADDRESS.U = (uint32_t) ETH_GLOBAL_DSPR_ADDR(rxDmaDesc);
504 }
505 
506 
507 /**
508  * @brief TC2xx Ethernet MAC timer handler
509  *
510  * This routine is periodically called by the TCP/IP stack to handle periodic
511  * operations such as polling the link state
512  *
513  * @param[in] interface Underlying network interface
514  **/
515 
516 void tc2xxEthTick(NetInterface *interface)
517 {
518  //Valid Ethernet PHY or switch driver?
519  if(interface->phyDriver != NULL)
520  {
521  //Handle periodic operations
522  interface->phyDriver->tick(interface);
523  }
524  else if(interface->switchDriver != NULL)
525  {
526  //Handle periodic operations
527  interface->switchDriver->tick(interface);
528  }
529  else
530  {
531  //Just for sanity
532  }
533 }
534 
535 
536 /**
537  * @brief Enable interrupts
538  * @param[in] interface Underlying network interface
539  **/
540 
542 {
543  //Enable Ethernet MAC interrupts
544  InterruptEnable(SRC_ID_ETH);
545 
546  //Valid Ethernet PHY or switch driver?
547  if(interface->phyDriver != NULL)
548  {
549  //Enable Ethernet PHY interrupts
550  interface->phyDriver->enableIrq(interface);
551  }
552  else if(interface->switchDriver != NULL)
553  {
554  //Enable Ethernet switch interrupts
555  interface->switchDriver->enableIrq(interface);
556  }
557  else
558  {
559  //Just for sanity
560  }
561 }
562 
563 
564 /**
565  * @brief Disable interrupts
566  * @param[in] interface Underlying network interface
567  **/
568 
570 {
571  //Enable Ethernet MAC interrupts
572  InterruptDisable(SRC_ID_ETH);
573 
574  //Valid Ethernet PHY or switch driver?
575  if(interface->phyDriver != NULL)
576  {
577  //Disable Ethernet PHY interrupts
578  interface->phyDriver->disableIrq(interface);
579  }
580  else if(interface->switchDriver != NULL)
581  {
582  //Disable Ethernet switch interrupts
583  interface->switchDriver->disableIrq(interface);
584  }
585  else
586  {
587  //Just for sanity
588  }
589 }
590 
591 
592 /**
593  * @brief TC2xx Ethernet MAC interrupt service routine
594  * @param arg Unused parameter
595  **/
596 
598 {
599  bool_t flag;
600  uint32_t status;
601 
602  //Interrupt service routine prologue
603  osEnterIsr();
604 
605  //This flag will be set if a higher priority task must be woken
606  flag = FALSE;
607 
608  //Read DMA status register
609  status = MODULE_ETH.STATUS.U;
610 
611  //Packet transmitted?
612  if((status & ETH_STATUS_TI) != 0)
613  {
614  //Clear TI interrupt flag
615  MODULE_ETH.STATUS.U = ETH_STATUS_TI;
616 
617  //Check whether the TX buffer is available for writing
618  if((txDmaDesc[txIndex].tdes0 & ETH_TDES0_OWN) == 0)
619  {
620  //Notify the TCP/IP stack that the transmitter is ready to send
621  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
622  }
623  }
624 
625  //Packet received?
626  if((status & ETH_STATUS_RI) != 0)
627  {
628  //Clear RI interrupt flag
629  MODULE_ETH.STATUS.U = ETH_STATUS_RI;
630 
631  //Set event flag
632  nicDriverInterface->nicEvent = TRUE;
633  //Notify the TCP/IP stack of the event
634  flag |= osSetEventFromIsr(&netEvent);
635  }
636 
637  //Clear NIS interrupt flag
638  MODULE_ETH.STATUS.U = ETH_STATUS_NIS;
639 
640  //Interrupt service routine epilogue
641  osExitIsr(flag);
642 }
643 
644 
645 /**
646  * @brief TC2xx Ethernet MAC event handler
647  * @param[in] interface Underlying network interface
648  **/
649 
651 {
652  error_t error;
653 
654  //Process all pending packets
655  do
656  {
657  //Read incoming packet
658  error = tc2xxEthReceivePacket(interface);
659 
660  //No more data in the receive buffer?
661  } while(error != ERROR_BUFFER_EMPTY);
662 }
663 
664 
665 /**
666  * @brief Send a packet
667  * @param[in] interface Underlying network interface
668  * @param[in] buffer Multi-part buffer containing the data to send
669  * @param[in] offset Offset to the first data byte
670  * @param[in] ancillary Additional options passed to the stack along with
671  * the packet
672  * @return Error code
673  **/
674 
676  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
677 {
678  size_t length;
679 
680  //Retrieve the length of the packet
681  length = netBufferGetLength(buffer) - offset;
682 
683  //Check the frame length
685  {
686  //The transmitter can accept another packet
687  osSetEvent(&interface->nicTxEvent);
688  //Report an error
689  return ERROR_INVALID_LENGTH;
690  }
691 
692  //Make sure the current buffer is available for writing
693  if((txDmaDesc[txIndex].tdes0 & ETH_TDES0_OWN) != 0)
694  {
695  return ERROR_FAILURE;
696  }
697 
698  //Copy user data to the transmit buffer
699  netBufferRead(txBuffer[txIndex], buffer, offset, length);
700 
701  //Write the number of bytes to send
702  txDmaDesc[txIndex].tdes1 = length & ETH_TDES1_TBS1;
703  //Set LS and FS flags as the data fits in a single buffer
704  txDmaDesc[txIndex].tdes0 |= ETH_TDES0_LS | ETH_TDES0_FS;
705  //Give the ownership of the descriptor to the DMA
706  txDmaDesc[txIndex].tdes0 |= ETH_TDES0_OWN;
707 
708  //Clear TU flag to resume processing
709  MODULE_ETH.STATUS.U = ETH_STATUS_TU;
710  //Instruct the DMA to poll the transmit descriptor list
711  MODULE_ETH.TRANSMIT_POLL_DEMAND.U = 0;
712 
713  //Increment index and wrap around if necessary
714  if(txIndex < (TC2XX_ETH_TX_BUFFER_COUNT - 1))
715  {
716  txIndex++;
717  }
718  else
719  {
720  txIndex = 0;
721  }
722 
723  //Check whether the next buffer is available for writing
724  if((txDmaDesc[txIndex].tdes0 & ETH_TDES0_OWN) == 0)
725  {
726  //The transmitter can accept another packet
727  osSetEvent(&interface->nicTxEvent);
728  }
729 
730  //Data successfully written
731  return NO_ERROR;
732 }
733 
734 
735 /**
736  * @brief Receive a packet
737  * @param[in] interface Underlying network interface
738  * @return Error code
739  **/
740 
742 {
743  error_t error;
744  size_t n;
745  NetRxAncillary ancillary;
746 
747  //Current buffer available for reading?
748  if((rxDmaDesc[rxIndex].rdes0 & ETH_RDES0_OWN) == 0)
749  {
750  //FS and LS flags should be set
751  if((rxDmaDesc[rxIndex].rdes0 & ETH_RDES0_FS) != 0 &&
752  (rxDmaDesc[rxIndex].rdes0 & ETH_RDES0_LS) != 0)
753  {
754  //Make sure no error occurred
755  if((rxDmaDesc[rxIndex].rdes0 & ETH_RDES0_ES) == 0)
756  {
757  //Retrieve the length of the frame
758  n = (rxDmaDesc[rxIndex].rdes0 & ETH_RDES0_FL) >> 16;
759  //Limit the number of data to read
761 
762  //Additional options can be passed to the stack along with the packet
763  ancillary = NET_DEFAULT_RX_ANCILLARY;
764 
765  //Pass the packet to the upper layer
766  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
767 
768  //Valid packet received
769  error = NO_ERROR;
770  }
771  else
772  {
773  //The received packet contains an error
774  error = ERROR_INVALID_PACKET;
775  }
776  }
777  else
778  {
779  //The packet is not valid
780  error = ERROR_INVALID_PACKET;
781  }
782 
783  //Give the ownership of the descriptor back to the DMA
784  rxDmaDesc[rxIndex].rdes0 = ETH_RDES0_OWN;
785 
786  //Increment index and wrap around if necessary
787  if(rxIndex < (TC2XX_ETH_RX_BUFFER_COUNT - 1))
788  {
789  rxIndex++;
790  }
791  else
792  {
793  rxIndex = 0;
794  }
795  }
796  else
797  {
798  //No more data in the receive buffer
799  error = ERROR_BUFFER_EMPTY;
800  }
801 
802  //Clear RU flag to resume processing
803  MODULE_ETH.STATUS.U = ETH_STATUS_RU;
804  //Instruct the DMA to poll the receive descriptor list
805  MODULE_ETH.RECEIVE_POLL_DEMAND.U = 0;
806 
807  //Return status code
808  return error;
809 }
810 
811 
812 /**
813  * @brief Configure MAC address filtering
814  * @param[in] interface Underlying network interface
815  * @return Error code
816  **/
817 
819 {
820  uint_t i;
821  uint_t j;
822  uint_t k;
823  uint32_t crc;
824  uint32_t hashTable[2];
825  MacAddr unicastMacAddr[15];
826  MacFilterEntry *entry;
827 
828  //Debug message
829  TRACE_DEBUG("Updating MAC filter...\r\n");
830 
831  //Set the MAC address of the station
832  MODULE_ETH.MAC_ADDRESS_G0[0].LOW.U = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
833  MODULE_ETH.MAC_ADDRESS_G0[0].HIGH.U = interface->macAddr.w[2];
834 
835  //The MAC supports 15 additional addresses for unicast perfect filtering
836  for(i = 0; i < 15; i++)
837  {
838  unicastMacAddr[i] = MAC_UNSPECIFIED_ADDR;
839  }
840 
841  //The hash table is used for multicast address filtering
842  hashTable[0] = 0;
843  hashTable[1] = 0;
844 
845  //The MAC address filter contains the list of MAC addresses to accept
846  //when receiving an Ethernet frame
847  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE; i++)
848  {
849  //Point to the current entry
850  entry = &interface->macAddrFilter[i];
851 
852  //Valid entry?
853  if(entry->refCount > 0)
854  {
855  //Multicast address?
856  if(macIsMulticastAddr(&entry->addr))
857  {
858  //Compute CRC over the current MAC address
859  crc = tc2xxEthCalcCrc(&entry->addr, sizeof(MacAddr));
860 
861  //The upper 6 bits in the CRC register are used to index the
862  //contents of the hash table
863  k = (crc >> 26) & 0x3F;
864 
865  //Update hash table contents
866  hashTable[k / 32] |= (1 << (k % 32));
867  }
868  else
869  {
870  //Up to 15 additional MAC addresses can be specified
871  if(j < 15)
872  {
873  //Save the unicast address
874  unicastMacAddr[j++] = entry->addr;
875  }
876  }
877  }
878  }
879 
880  //Configure the unicast address filter
881  for(i = 0; i < 15; i++)
882  {
883  //Set current entry
884  MODULE_ETH.MAC_ADDRESS_G0[i + 1].LOW.U = unicastMacAddr[0].w[0] | (unicastMacAddr[0].w[1] << 16);
885  MODULE_ETH.MAC_ADDRESS_G0[i + 1].HIGH.U = unicastMacAddr[0].w[2];
886 
887  //When the AE bit is set, the entry is used for perfect filtering
888  if(i < j)
889  {
890  MODULE_ETH.MAC_ADDRESS_G0[i + 1].HIGH.B.AE = 1;
891  }
892  }
893 
894  //Configure the multicast hash table
895  MODULE_ETH.HASH_TABLE_LOW.U = hashTable[0];
896  MODULE_ETH.HASH_TABLE_HIGH.U = hashTable[1];
897 
898  //Debug message
899  TRACE_DEBUG(" HASH_TABLE_LOW = %08" PRIX32 "\r\n", MODULE_ETH.HASH_TABLE_LOW.U);
900  TRACE_DEBUG(" HASH_TABLE_HIGH = %08" PRIX32 "\r\n", MODULE_ETH.HASH_TABLE_HIGH.U);
901 
902  //Successful processing
903  return NO_ERROR;
904 }
905 
906 
907 /**
908  * @brief Adjust MAC configuration parameters for proper operation
909  * @param[in] interface Underlying network interface
910  * @return Error code
911  **/
912 
914 {
915  Ifx_ETH_MAC_CONFIGURATION config;
916 
917  //Read current MAC configuration
918  config.U = MODULE_ETH.MAC_CONFIGURATION.U;
919 
920  //10BASE-T or 100BASE-TX operation mode?
921  if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
922  {
923  config.B.FES = 1;
924  }
925  else
926  {
927  config.B.FES = 0;
928  }
929 
930  //Half-duplex or full-duplex mode?
931  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
932  {
933  config.B.DM = 1;
934  }
935  else
936  {
937  config.B.DM = 0;
938  }
939 
940  //Update MAC configuration register
941  MODULE_ETH.MAC_CONFIGURATION.U = config.U;
942 
943  //Successful processing
944  return NO_ERROR;
945 }
946 
947 
948 /**
949  * @brief Write PHY register
950  * @param[in] opcode Access type (2 bits)
951  * @param[in] phyAddr PHY address (5 bits)
952  * @param[in] regAddr Register address (5 bits)
953  * @param[in] data Register value
954  **/
955 
956 void tc2xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
957  uint8_t regAddr, uint16_t data)
958 {
959  //Valid opcode?
960  if(opcode == SMI_OPCODE_WRITE)
961  {
962  //Set up a write operation
963  MODULE_ETH.GMII_ADDRESS.B.GW = 1;
964  //PHY address
965  MODULE_ETH.GMII_ADDRESS.B.PA = phyAddr;
966  //Register address
967  MODULE_ETH.GMII_ADDRESS.B.GR = regAddr;
968 
969  //Data to be written in the PHY register
970  MODULE_ETH.GMII_DATA.B.GD = data;
971 
972  //Start a write operation
973  MODULE_ETH.GMII_ADDRESS.B.GB = 1;
974  //Wait for the write to complete
975  while(MODULE_ETH.GMII_ADDRESS.B.GB)
976  {
977  }
978  }
979  else
980  {
981  //The MAC peripheral only supports standard Clause 22 opcodes
982  }
983 }
984 
985 
986 /**
987  * @brief Read PHY register
988  * @param[in] opcode Access type (2 bits)
989  * @param[in] phyAddr PHY address (5 bits)
990  * @param[in] regAddr Register address (5 bits)
991  * @return Register value
992  **/
993 
994 uint16_t tc2xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
995  uint8_t regAddr)
996 {
997  uint16_t data;
998 
999  //Valid opcode?
1000  if(opcode == SMI_OPCODE_READ)
1001  {
1002  //Set up a read operation
1003  MODULE_ETH.GMII_ADDRESS.B.GW = 0;
1004  //PHY address
1005  MODULE_ETH.GMII_ADDRESS.B.PA = phyAddr;
1006  //Register address
1007  MODULE_ETH.GMII_ADDRESS.B.GR = regAddr;
1008 
1009  //Start a read operation
1010  MODULE_ETH.GMII_ADDRESS.B.GB = 1;
1011  //Wait for the read to complete
1012  while(MODULE_ETH.GMII_ADDRESS.B.GB)
1013  {
1014  }
1015 
1016  //Get register value
1017  data = MODULE_ETH.GMII_DATA.B.GD;
1018  }
1019  else
1020  {
1021  //The MAC peripheral only supports standard Clause 22 opcodes
1022  data = 0;
1023  }
1024 
1025  //Return the value of the PHY register
1026  return data;
1027 }
1028 
1029 
1030 /**
1031  * @brief CRC calculation
1032  * @param[in] data Pointer to the data over which to calculate the CRC
1033  * @param[in] length Number of bytes to process
1034  * @return Resulting CRC value
1035  **/
1036 
1037 uint32_t tc2xxEthCalcCrc(const void *data, size_t length)
1038 {
1039  uint_t i;
1040  uint_t j;
1041  uint32_t crc;
1042  const uint8_t *p;
1043 
1044  //Point to the data over which to calculate the CRC
1045  p = (uint8_t *) data;
1046  //CRC preset value
1047  crc = 0xFFFFFFFF;
1048 
1049  //Loop through data
1050  for(i = 0; i < length; i++)
1051  {
1052  //The message is processed bit by bit
1053  for(j = 0; j < 8; j++)
1054  {
1055  //Update CRC value
1056  if((((crc >> 31) ^ (p[i] >> j)) & 0x01) != 0)
1057  {
1058  crc = (crc << 1) ^ 0x04C11DB7;
1059  }
1060  else
1061  {
1062  crc = crc << 1;
1063  }
1064  }
1065  }
1066 
1067  //Return CRC value
1068  return ~crc;
1069 }
#define txDmaDesc
#define rxBuffer
#define txBuffer
#define rxDmaDesc
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
signed int int_t
Definition: compiler_port.h:49
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t n
uint8_t opcode
Definition: dns_common.h:188
error_t
Error codes.
Definition: error.h:43
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_PACKET
Definition: error.h:140
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
const MacAddr MAC_UNSPECIFIED_ADDR
Definition: ethernet.c:53
#define macIsMulticastAddr(macAddr)
Definition: ethernet.h:133
#define ETH_MTU
Definition: ethernet.h:116
uint8_t data[]
Definition: ethernet.h:222
MacAddr
Definition: ethernet.h:195
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define ETH_TDES0_OWN
#define ETH_RDES0_FS
#define ETH_TDES0_IC
#define ETH_RDES1_RCH
#define ETH_RDES0_OWN
#define ETH_RDES0_LS
#define ETH_RDES0_FL
#define ETH_RDES0_ES
#define ETH_TDES0_LS
#define ETH_RDES1_RBS1
#define ETH_TDES0_TCH
#define ETH_TDES0_FS
#define ETH_TDES1_TBS1
uint16_t regAddr
uint8_t p
Definition: ndp.h:300
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define netEvent
Definition: net_legacy.h:196
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
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:674
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:101
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:391
#define SMI_OPCODE_WRITE
Definition: nic.h:66
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
#define SMI_OPCODE_READ
Definition: nic.h:67
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
#define MIN(a, b)
Definition: os_port.h:63
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define osEnterIsr()
#define osExitIsr(flag)
MAC filter table entry.
Definition: ethernet.h:262
MacAddr addr
MAC address.
Definition: ethernet.h:263
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
NIC driver.
Definition: nic.h:283
Receive DMA descriptor.
Transmit DMA descriptor.
void tc2xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
error_t tc2xxEthReceivePacket(NetInterface *interface)
Receive a packet.
void tc2xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
error_t tc2xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
void tc2xxEthEventHandler(NetInterface *interface)
TC2xx Ethernet MAC event handler.
error_t tc2xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
error_t tc2xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
uint16_t tc2xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
void tc2xxEthTick(NetInterface *interface)
TC2xx Ethernet MAC timer handler.
error_t tc2xxEthInit(NetInterface *interface)
TC2xx Ethernet MAC initialization.
void tc2xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
void tc2xxEthIrqHandler(int_t arg)
TC2xx Ethernet MAC interrupt service routine.
void tc2xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.
const NicDriver tc2xxEthDriver
TC2xx Ethernet MAC driver.
uint32_t tc2xxEthCalcCrc(const void *data, size_t length)
CRC calculation.
__weak_func void tc2xxEthInitGpio(NetInterface *interface)
GPIO configuration.
Infineon AURIX TriCore TC2xx Ethernet MAC driver.
#define TC2XX_ETH_RX_BUFFER_COUNT
#define ETH_GLOBAL_DSPR_ADDR(address)
#define TC2XX_ETH_TX_BUFFER_SIZE
#define ETH_STATUS_TI
#define TC2XX_ETH_RX_BUFFER_SIZE
#define TC2XX_ETH_TX_BUFFER_COUNT
#define ETH_STATUS_RI
#define ETH_STATUS_TU
#define TC2XX_ETH_IRQ_PRIORITY
#define ETH_STATUS_NIS
#define ETH_STATUS_RU
uint8_t length
Definition: tcp.h:368