tc3xx_eth_driver.c
Go to the documentation of this file.
1 /**
2  * @file tc3xx_eth_driver.c
3  * @brief Infineon AURIX TriCore TC3xx 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.4
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 TC3xx Ethernet MAC driver
90  **/
91 
93 {
95  ETH_MTU,
106  TRUE,
107  TRUE,
108  TRUE,
109  FALSE
110 };
111 
112 
113 /**
114  * @brief TC3xx Ethernet MAC initialization
115  * @param[in] interface Underlying network interface
116  * @return Error code
117  **/
118 
120 {
121  error_t error;
122  Ifx_SCU_CCUCON5 ccucon5;
123 
124  //Debug message
125  TRACE_INFO("Initializing TC3xx Ethernet MAC...\r\n");
126 
127  //Save underlying network interface
128  nicDriverInterface = interface;
129 
130  //The lock bit indicates if the CCUCON5 register can be updated with a new
131  //value
132  while(SCU_CCUCON5.B.LCK != 0)
133  {
134  }
135 
136  //Unlock sequence
137  unlock_safety_wdtcon();
138 
139  //Set GETH frequency divider
140  ccucon5.U = SCU_CCUCON5.U;
141  ccucon5.B.GETHDIV = 2;
142  ccucon5.B.UP = 1;
143  SCU_CCUCON5.U = ccucon5.U;
144 
145  //Lock sequence
146  lock_safety_wdtcon();
147 
148  //The lock bit is released when the update is complete
149  while(SCU_CCUCON5.B.LCK != 0)
150  {
151  }
152 
153  //Unlock sequence
154  unlock_wdtcon();
155  //Enable Ethernet module
156  MODULE_GETH.CLC.B.DISR = 0;
157  //Lock sequence
158  lock_wdtcon();
159 
160  //GPIO configuration
161  tc3xxEthInitGpio(interface);
162 
163  //Unlock sequence
164  unlock_wdtcon();
165  //Perform kernel reset
166  MODULE_GETH.KRST0.B.RST = 1;
167  MODULE_GETH.KRST1.B.RST = 1;
168  //Lock sequence
169  lock_wdtcon();
170 
171  //Wait for the reset to complete
172  while(MODULE_GETH.KRST0.B.RSTSTAT == 0)
173  {
174  }
175 
176  //Unlock sequence
177  unlock_wdtcon();
178  //Clear kernel reset status
179  MODULE_GETH.KRSTCLR.B.CLR = 1;
180  //Lock sequence
181  lock_wdtcon();
182 
183  //Perform a software reset
184  MODULE_GETH.DMA_MODE.B.SWR = 1;
185  //Wait for the reset to complete
186  while(MODULE_GETH.DMA_MODE.B.SWR)
187  {
188  }
189 
190  //Adjust MDC clock range depending on CSR clock frequency
191  MODULE_GETH.MAC_MDIO_ADDRESS.B.CR = 5;
192 
193  //Valid Ethernet PHY or switch driver?
194  if(interface->phyDriver != NULL)
195  {
196  //Ethernet PHY initialization
197  error = interface->phyDriver->init(interface);
198  }
199  else if(interface->switchDriver != NULL)
200  {
201  //Ethernet switch initialization
202  error = interface->switchDriver->init(interface);
203  }
204  else
205  {
206  //The interface is not properly configured
207  error = ERROR_FAILURE;
208  }
209 
210  //Any error to report?
211  if(error)
212  {
213  return error;
214  }
215 
216  //Use default MAC configuration
217  MODULE_GETH.MAC_CONFIGURATION.U = 0;
218  MODULE_GETH.MAC_CONFIGURATION.B.PS = 1;
219  MODULE_GETH.MAC_CONFIGURATION.B.DO = 1;
220 
221  //Configure the receive filter
222  MODULE_GETH.MAC_PACKET_FILTER.U = 0;
223 
224  //Configure MAC address filtering
225  tc3xxEthUpdateMacAddrFilter(interface);
226 
227  //Disable flow control
228  MODULE_GETH.MAC_Q0_TX_FLOW_CTRL.U = 0;
229  MODULE_GETH.MAC_RX_FLOW_CTRL.U = 0;
230 
231  //Enable the first RX queue
232  MODULE_GETH.MAC_RXQ_CTRL0.B.RXQ0EN = 2;
233 
234  //Configure DMA operating mode
235  MODULE_GETH.DMA_MODE.B.INTM = 0;
236  MODULE_GETH.DMA_MODE.B.PR = 0;
237 
238  //Configure system bus mode
239  MODULE_GETH.DMA_SYSBUS_MODE.B.AAL = 1;
240 
241  //The DMA takes the descriptor table as contiguous
242  MODULE_GETH.DMA_CH[0].CONTROL.B.DSL = 0;
243  //Configure TX features
244  MODULE_GETH.DMA_CH[0].TX_CONTROL.B.TXPBL = 32;
245 
246  //Configure RX features
247  MODULE_GETH.DMA_CH[0].RX_CONTROL.B.RXPBL = 32;
248  MODULE_GETH.DMA_CH[0].RX_CONTROL.B.RBSZ_13_Y = TC3XX_ETH_RX_BUFFER_SIZE / 4;
249 
250  //Enable store and forward mode for transmission
251  MODULE_GETH.MTL_TXQ0.OPERATION_MODE.B.TQS = 15;
252  MODULE_GETH.MTL_TXQ0.OPERATION_MODE.B.TXQEN = 2;
253  MODULE_GETH.MTL_TXQ0.OPERATION_MODE.B.TSF = 1;
254 
255  //Enable store and forward mode for reception
256  MODULE_GETH.MTL_RXQ0.OPERATION_MODE.B.RQS = 31;
257  MODULE_GETH.MTL_RXQ0.OPERATION_MODE.B.RSF = 1;
258 
259  //Initialize DMA descriptor lists
260  tc3xxEthInitDmaDesc(interface);
261 
262  //Disable all MMC counters
263  MODULE_GETH.MMC_CONTROL.B.CNTFREEZ = 1;
264 
265  //Disable MAC interrupts
266  MODULE_GETH.MAC_INTERRUPT_ENABLE.U = 0;
267 
268  //Enable the desired DMA interrupts
269  MODULE_GETH.DMA_CH[0].INTERRUPT_ENABLE.B.TIE = 1;
270  MODULE_GETH.DMA_CH[0].INTERRUPT_ENABLE.B.RIE = 1;
271  MODULE_GETH.DMA_CH[0].INTERRUPT_ENABLE.B.NIE = 1;
272 
273  //Register interrupt handler
274  InterruptInstall(SRC_ID_GETH0, tc3xxEthIrqHandler, TC3XX_ETH_IRQ_PRIORITY, 0);
275 
276  //Enable MAC transmission and reception
277  MODULE_GETH.MAC_CONFIGURATION.B.TE = 1;
278  MODULE_GETH.MAC_CONFIGURATION.B.RE = 1;
279 
280  //Enable DMA transmission and reception
281  MODULE_GETH.DMA_CH[0].TX_CONTROL.B.ST = 1;
282  MODULE_GETH.DMA_CH[0].RX_CONTROL.B.SR = 1;
283 
284  //Accept any packets from the upper layer
285  osSetEvent(&interface->nicTxEvent);
286 
287  //Successful initialization
288  return NO_ERROR;
289 }
290 
291 
292 /**
293  * @brief GPIO configuration
294  * @param[in] interface Underlying network interface
295  **/
296 
297 __weak_func void tc3xxEthInitGpio(NetInterface *interface)
298 {
299 //AURIX TC397 TFT Application Kit?
300 #if defined(USE_KIT_A2G_TC397_TFT)
301  //Configure GETH_TXD3 (P11.0)
302  MODULE_P11.IOCR0.B.PC0 = 22;
303 
304  //Configure GETH_TXD2 (P11.1)
305  MODULE_P11.IOCR0.B.PC1 = 22;
306 
307  //Configure GETH_TXD1 (P11.2)
308  MODULE_P11.IOCR0.B.PC2 = 22;
309 
310  //Configure GETH_TXD0 (P11.3)
311  MODULE_P11.IOCR0.B.PC3 = 22;
312 
313  //Configure GETH_TXCLK (P11.4)
314  MODULE_P11.IOCR4.B.PC4 = 23;
315 
316  //Configure GETH_GREFCLK (P11.5)
317  MODULE_P11.IOCR4.B.PC5 = 0;
318 
319  //Configure GETH_TCTL (P11.6)
320  MODULE_P11.IOCR4.B.PC6 = 22;
321 
322  //Configure GETH_RXD3A (P11.7)
323  MODULE_P11.IOCR4.B.PC7 = 0;
324  MODULE_GETH.GPCTL.B.ALTI9 = 0;
325 
326  //Configure GETH_RXD2A (P11.8)
327  MODULE_P11.IOCR8.B.PC8 = 0;
328  MODULE_GETH.GPCTL.B.ALTI8 = 0;
329 
330  //Configure GETH_RXD1A (P11.9)
331  MODULE_P11.IOCR8.B.PC9 = 0;
332  MODULE_GETH.GPCTL.B.ALTI7 = 0;
333 
334  //Configure GETH_RXD0A (P11.10)
335  MODULE_P11.IOCR8.B.PC10 = 0;
336  MODULE_GETH.GPCTL.B.ALTI6 = 0;
337 
338  //Configure GETH_RCTLA (P11.11)
339  MODULE_P11.IOCR8.B.PC11 = 0;
340  MODULE_GETH.GPCTL.B.ALTI4 = 0;
341 
342  //Configure GETH_RXCLKA (P11.12)
343  MODULE_P11.IOCR12.B.PC12 = 0;
344  MODULE_GETH.GPCTL.B.ALTI1 = 0;
345 
346  //Configure GETH_MDC (P12.0)
347  MODULE_P12.IOCR0.B.PC0 = 22;
348 
349  //Configure GETH_MDIOC (P12.1)
350  MODULE_P12.IOCR0.B.PC1 = 0;
351  MODULE_GETH.GPCTL.B.ALTI0 = 2;
352 
353  //Unlock sequence
354  unlock_safety_wdtcon();
355 
356  //Set bit SELx for TXD[3:0] TXCLK and TCTL signals
357  MODULE_P11.PCSR.B.SEL0 = 1;
358  MODULE_P11.PCSR.B.SEL1 = 1;
359  MODULE_P11.PCSR.B.SEL2 = 1;
360  MODULE_P11.PCSR.B.SEL3 = 1;
361  MODULE_P11.PCSR.B.SEL4 = 1;
362  MODULE_P11.PCSR.B.SEL6 = 1;
363 
364  //Lock sequence
365  lock_safety_wdtcon();
366 
367  //Unlock sequence
368  unlock_wdtcon();
369 
370  //Set speed grade
371  MODULE_P11.PDR0.B.PD0 = 3;
372  MODULE_P11.PDR0.B.PL0 = 0;
373  MODULE_P11.PDR0.B.PD1 = 3;
374  MODULE_P11.PDR0.B.PL1 = 0;
375  MODULE_P11.PDR0.B.PD2 = 3;
376  MODULE_P11.PDR0.B.PL2 = 0;
377  MODULE_P11.PDR0.B.PD3 = 3;
378  MODULE_P11.PDR0.B.PL3 = 0;
379  MODULE_P11.PDR0.B.PD4 = 3;
380  MODULE_P11.PDR0.B.PL4 = 0;
381  MODULE_P11.PDR0.B.PD5 = 3;
382  MODULE_P11.PDR0.B.PL5 = 0;
383  MODULE_P11.PDR0.B.PD6 = 3;
384  MODULE_P11.PDR0.B.PL6 = 0;
385  MODULE_P11.PDR0.B.PD7 = 3;
386  MODULE_P11.PDR0.B.PL7 = 0;
387  MODULE_P11.PDR1.B.PD8 = 3;
388  MODULE_P11.PDR1.B.PL8 = 0;
389  MODULE_P11.PDR1.B.PD9 = 3;
390  MODULE_P11.PDR1.B.PL9 = 0;
391  MODULE_P11.PDR1.B.PD10 = 3;
392  MODULE_P11.PDR1.B.PL10 = 0;
393  MODULE_P11.PDR1.B.PD11 = 3;
394  MODULE_P11.PDR1.B.PL11 = 0;
395  MODULE_P11.PDR1.B.PD12 = 3;
396  MODULE_P11.PDR1.B.PL12 = 0;
397 
398  MODULE_P12.PDR0.B.PD0 = 3;
399  MODULE_P12.PDR0.B.PL0 = 0;
400  MODULE_P12.PDR0.B.PD1 = 3;
401  MODULE_P12.PDR0.B.PL1 = 0;
402 
403  //Lock sequence
404  lock_wdtcon();
405 
406  //Select RGMII operation mode
407  MODULE_GETH.GPCTL.B.EPR = 1;
408 
409  //Set delay for RGMII TX and RX clocks
410  MODULE_GETH.SKEWCTL.B.TXCFG = 5;
411  MODULE_GETH.SKEWCTL.B.RXCFG = 5;
412 #endif
413 }
414 
415 
416 /**
417  * @brief Initialize DMA descriptor lists
418  * @param[in] interface Underlying network interface
419  **/
420 
422 {
423  uint_t i;
424 
425  //Initialize TX DMA descriptor list
426  for(i = 0; i < TC3XX_ETH_TX_BUFFER_COUNT; i++)
427  {
428  //The descriptor is initially owned by the application
429  txDmaDesc[i].tdes0 = 0;
430  txDmaDesc[i].tdes1 = 0;
431  txDmaDesc[i].tdes2 = 0;
432  txDmaDesc[i].tdes3 = 0;
433  }
434 
435  //Initialize TX descriptor index
436  txIndex = 0;
437 
438  //Initialize RX DMA descriptor list
439  for(i = 0; i < TC3XX_ETH_RX_BUFFER_COUNT; i++)
440  {
441  //The descriptor is initially owned by the DMA
442  rxDmaDesc[i].rdes0 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(rxBuffer[i]);
443  rxDmaDesc[i].rdes1 = 0;
444  rxDmaDesc[i].rdes2 = 0;
446  }
447 
448  //Initialize RX descriptor index
449  rxIndex = 0;
450 
451  //Start location of the TX descriptor list
452  MODULE_GETH.DMA_CH[0].TXDESC_LIST_ADDRESS.U = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&txDmaDesc[0]);
453  //Length of the transmit descriptor ring
454  MODULE_GETH.DMA_CH[0].TXDESC_RING_LENGTH.U = TC3XX_ETH_TX_BUFFER_COUNT - 1;
455 
456  //Start location of the RX descriptor list
457  MODULE_GETH.DMA_CH[0].RXDESC_LIST_ADDRESS.U = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&rxDmaDesc[0]);
458  //Length of the receive descriptor ring
459  MODULE_GETH.DMA_CH[0].RXDESC_RING_LENGTH.U = TC3XX_ETH_RX_BUFFER_COUNT - 1;
460 }
461 
462 
463 /**
464  * @brief TC3xx Ethernet MAC timer handler
465  *
466  * This routine is periodically called by the TCP/IP stack to handle periodic
467  * operations such as polling the link state
468  *
469  * @param[in] interface Underlying network interface
470  **/
471 
472 void tc3xxEthTick(NetInterface *interface)
473 {
474  //Valid Ethernet PHY or switch driver?
475  if(interface->phyDriver != NULL)
476  {
477  //Handle periodic operations
478  interface->phyDriver->tick(interface);
479  }
480  else if(interface->switchDriver != NULL)
481  {
482  //Handle periodic operations
483  interface->switchDriver->tick(interface);
484  }
485  else
486  {
487  //Just for sanity
488  }
489 }
490 
491 
492 /**
493  * @brief Enable interrupts
494  * @param[in] interface Underlying network interface
495  **/
496 
498 {
499  //Enable Ethernet MAC interrupts
500  InterruptEnable(SRC_ID_GETH0);
501 
502  //Valid Ethernet PHY or switch driver?
503  if(interface->phyDriver != NULL)
504  {
505  //Enable Ethernet PHY interrupts
506  interface->phyDriver->enableIrq(interface);
507  }
508  else if(interface->switchDriver != NULL)
509  {
510  //Enable Ethernet switch interrupts
511  interface->switchDriver->enableIrq(interface);
512  }
513  else
514  {
515  //Just for sanity
516  }
517 }
518 
519 
520 /**
521  * @brief Disable interrupts
522  * @param[in] interface Underlying network interface
523  **/
524 
526 {
527  //Enable Ethernet MAC interrupts
528  InterruptDisable(SRC_ID_GETH0);
529 
530  //Valid Ethernet PHY or switch driver?
531  if(interface->phyDriver != NULL)
532  {
533  //Disable Ethernet PHY interrupts
534  interface->phyDriver->disableIrq(interface);
535  }
536  else if(interface->switchDriver != NULL)
537  {
538  //Disable Ethernet switch interrupts
539  interface->switchDriver->disableIrq(interface);
540  }
541  else
542  {
543  //Just for sanity
544  }
545 }
546 
547 
548 /**
549  * @brief TC3xx Ethernet MAC interrupt service routine
550  * @param arg Unused parameter
551  **/
552 
554 {
555  bool_t flag;
556  uint32_t status;
557 
558  //Interrupt service routine prologue
559  osEnterIsr();
560 
561  //This flag will be set if a higher priority task must be woken
562  flag = FALSE;
563 
564  //Read DMA status register
565  status = MODULE_GETH.DMA_CH[0].STATUS.U;
566 
567  //Packet transmitted?
568  if((status & ETH_DMA_CH_STATUS_TI) != 0)
569  {
570  //Clear TI interrupt flag
571  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_TI;
572 
573  //Check whether the TX buffer is available for writing
574  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
575  {
576  //Notify the TCP/IP stack that the transmitter is ready to send
577  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
578  }
579  }
580 
581  //Packet received?
582  if((status & ETH_DMA_CH_STATUS_RI) != 0)
583  {
584  //Clear RI interrupt flag
585  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_RI;
586 
587  //Set event flag
588  nicDriverInterface->nicEvent = TRUE;
589  //Notify the TCP/IP stack of the event
590  flag |= osSetEventFromIsr(&netEvent);
591  }
592 
593  //Clear NIS interrupt flag
594  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_NIS;
595 
596  //Interrupt service routine epilogue
597  osExitIsr(flag);
598 }
599 
600 
601 /**
602  * @brief TC3xx Ethernet MAC event handler
603  * @param[in] interface Underlying network interface
604  **/
605 
607 {
608  error_t error;
609 
610  //Process all pending packets
611  do
612  {
613  //Read incoming packet
614  error = tc3xxEthReceivePacket(interface);
615 
616  //No more data in the receive buffer?
617  } while(error != ERROR_BUFFER_EMPTY);
618 }
619 
620 
621 /**
622  * @brief Send a packet
623  * @param[in] interface Underlying network interface
624  * @param[in] buffer Multi-part buffer containing the data to send
625  * @param[in] offset Offset to the first data byte
626  * @param[in] ancillary Additional options passed to the stack along with
627  * the packet
628  * @return Error code
629  **/
630 
632  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
633 {
634  size_t length;
635 
636  //Retrieve the length of the packet
637  length = netBufferGetLength(buffer) - offset;
638 
639  //Check the frame length
641  {
642  //The transmitter can accept another packet
643  osSetEvent(&interface->nicTxEvent);
644  //Report an error
645  return ERROR_INVALID_LENGTH;
646  }
647 
648  //Make sure the current buffer is available for writing
649  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) != 0)
650  {
651  return ERROR_FAILURE;
652  }
653 
654  //Copy user data to the transmit buffer
655  netBufferRead(txBuffer[txIndex], buffer, offset, length);
656 
657  //Set the start address of the buffer
658  txDmaDesc[txIndex].tdes0 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(txBuffer[txIndex]);
659  //Write the number of bytes to send
660  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
661  //Give the ownership of the descriptor to the DMA
662  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
663 
664  //Clear TBU flag to resume processing
665  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_TBU;
666  //Instruct the DMA to poll the transmit descriptor list
667  MODULE_GETH.DMA_CH[0].TXDESC_TAIL_POINTER.U = 0;
668 
669  //Increment index and wrap around if necessary
670  if(txIndex < (TC3XX_ETH_TX_BUFFER_COUNT - 1))
671  {
672  txIndex++;
673  }
674  else
675  {
676  txIndex = 0;
677  }
678 
679  //Check whether the next buffer is available for writing
680  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
681  {
682  //The transmitter can accept another packet
683  osSetEvent(&interface->nicTxEvent);
684  }
685 
686  //Data successfully written
687  return NO_ERROR;
688 }
689 
690 
691 /**
692  * @brief Receive a packet
693  * @param[in] interface Underlying network interface
694  * @return Error code
695  **/
696 
698 {
699  error_t error;
700  size_t n;
701  NetRxAncillary ancillary;
702 
703  //Current buffer available for reading?
704  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN) == 0)
705  {
706  //FD and LD flags should be set
707  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) != 0 &&
708  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD) != 0)
709  {
710  //Make sure no error occurred
711  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_ES) == 0)
712  {
713  //Retrieve the length of the frame
714  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
715  //Limit the number of data to read
717 
718  //Additional options can be passed to the stack along with the packet
719  ancillary = NET_DEFAULT_RX_ANCILLARY;
720 
721  //Pass the packet to the upper layer
722  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
723 
724  //Valid packet received
725  error = NO_ERROR;
726  }
727  else
728  {
729  //The received packet contains an error
730  error = ERROR_INVALID_PACKET;
731  }
732  }
733  else
734  {
735  //The packet is not valid
736  error = ERROR_INVALID_PACKET;
737  }
738 
739  //Set the start address of the buffer
740  rxDmaDesc[rxIndex].rdes0 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(rxBuffer[rxIndex]);
741  //Give the ownership of the descriptor back to the DMA
743 
744  //Increment index and wrap around if necessary
745  if(rxIndex < (TC3XX_ETH_RX_BUFFER_COUNT - 1))
746  {
747  rxIndex++;
748  }
749  else
750  {
751  rxIndex = 0;
752  }
753  }
754  else
755  {
756  //No more data in the receive buffer
757  error = ERROR_BUFFER_EMPTY;
758  }
759 
760  //Clear RBU flag to resume processing
761  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_RBU;
762  //Instruct the DMA to poll the receive descriptor list
763  MODULE_GETH.DMA_CH[0].RXDESC_TAIL_POINTER.U = 0;
764 
765  //Return status code
766  return error;
767 }
768 
769 
770 /**
771  * @brief Configure MAC address filtering
772  * @param[in] interface Underlying network interface
773  * @return Error code
774  **/
775 
777 {
778  uint_t i;
779  uint_t j;
780  MacFilterEntry *entry;
781  volatile Ifx_GETH_MAC_ADDRESS_LOW *macAddressLow;
782  volatile Ifx_GETH_MAC_ADDRESS_HIGH *macAddressHigh;
783 
784  //Debug message
785  TRACE_DEBUG("Updating MAC filter...\r\n");
786 
787  //Set the MAC address of the station
788  MODULE_GETH.MAC_ADDRESS_LOW0.U = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
789  MODULE_GETH.MAC_ADDRESS_HIGH0.U = interface->macAddr.w[2];
790 
791  //The MAC address filter contains the list of MAC addresses to accept
792  //when receiving an Ethernet frame
793  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE && j < 31; i++)
794  {
795  //Point to the current entry
796  entry = &interface->macAddrFilter[i];
797 
798  //Valid entry?
799  if(entry->refCount > 0)
800  {
801  //The MAC_ADDRESSi_LOW register holds the lower 32 bits of the MAC address
802  macAddressLow = &MODULE_GETH.MAC_ADDRESS_LOW1 + 2 * j;
803  //The MAC_ADDRESSi_HIGH register holds the upper 16 bits of the MAC address
804  macAddressHigh = &MODULE_GETH.MAC_ADDRESS_HIGH1 + 2 * j;
805 
806  //When the AE bit is set, the entry is used for perfect filtering
807  macAddressLow->U = entry->addr.w[0] | (entry->addr.w[1] << 16);
808  macAddressHigh->U = entry->addr.w[2] | ETH_MAC_ADDRESS_HIGH_AE;
809 
810  //Next entry
811  j++;
812  }
813  }
814 
815  //Clear unused entries
816  while(j < 31)
817  {
818  //The MAC_ADDRESSi_LOW register holds the lower 32 bits of the MAC address
819  macAddressLow = &MODULE_GETH.MAC_ADDRESS_LOW1 + 2 * j;
820  //The MAC_ADDRESSi_HIGH register holds the upper 16 bits of the MAC address
821  macAddressHigh = &MODULE_GETH.MAC_ADDRESS_HIGH1 + 2 * j;
822 
823  //When the AE bit is cleared, the entry is ignored
824  macAddressLow->U = 0;
825  macAddressHigh->U = 0;
826 
827  //Next entry
828  j++;
829  }
830 
831  //Successful processing
832  return NO_ERROR;
833 }
834 
835 
836 /**
837  * @brief Adjust MAC configuration parameters for proper operation
838  * @param[in] interface Underlying network interface
839  * @return Error code
840  **/
841 
843 {
844  Ifx_GETH_MAC_CONFIGURATION config;
845 
846  //Read current MAC configuration
847  config.U = MODULE_GETH.MAC_CONFIGURATION.U;
848 
849  //1000BASE-T operation mode?
850  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
851  {
852  config.B.PS = 0;
853  config.B.FES = 0;
854  }
855  //100BASE-TX operation mode?
856  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
857  {
858  config.B.PS = 1;
859  config.B.FES = 1;
860  }
861  //10BASE-T operation mode?
862  else
863  {
864  config.B.PS = 1;
865  config.B.FES = 0;
866  }
867 
868  //Half-duplex or full-duplex mode?
869  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
870  {
871  config.B.DM = 1;
872  }
873  else
874  {
875  config.B.DM = 0;
876  }
877 
878  //Update MAC configuration register
879  MODULE_GETH.MAC_CONFIGURATION.U = config.U;
880 
881  //Successful processing
882  return NO_ERROR;
883 }
884 
885 
886 /**
887  * @brief Write PHY register
888  * @param[in] opcode Access type (2 bits)
889  * @param[in] phyAddr PHY address (5 bits)
890  * @param[in] regAddr Register address (5 bits)
891  * @param[in] data Register value
892  **/
893 
894 void tc3xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
895  uint8_t regAddr, uint16_t data)
896 {
897  //Valid opcode?
898  if(opcode == SMI_OPCODE_WRITE)
899  {
900  //Set up a write operation
901  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_0 = 1;
902  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_1 = 0;
903 
904  //PHY address
905  MODULE_GETH.MAC_MDIO_ADDRESS.B.PA = phyAddr;
906  //Register address
907  MODULE_GETH.MAC_MDIO_ADDRESS.B.RDA = regAddr;
908 
909  //Data to be written in the PHY register
910  MODULE_GETH.MAC_MDIO_DATA.B.GD = data;
911 
912  //Start a write operation
913  MODULE_GETH.MAC_MDIO_ADDRESS.B.GB = 1;
914  //Wait for the write to complete
915  while(MODULE_GETH.MAC_MDIO_ADDRESS.B.GB)
916  {
917  }
918  }
919  else
920  {
921  //The MAC peripheral only supports standard Clause 22 opcodes
922  }
923 }
924 
925 
926 /**
927  * @brief Read PHY register
928  * @param[in] opcode Access type (2 bits)
929  * @param[in] phyAddr PHY address (5 bits)
930  * @param[in] regAddr Register address (5 bits)
931  * @return Register value
932  **/
933 
934 uint16_t tc3xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
935  uint8_t regAddr)
936 {
937  uint16_t data;
938 
939  //Valid opcode?
940  if(opcode == SMI_OPCODE_READ)
941  {
942  //Set up a read operation
943  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_0 = 1;
944  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_1 = 1;
945 
946  //PHY address
947  MODULE_GETH.MAC_MDIO_ADDRESS.B.PA = phyAddr;
948  //Register address
949  MODULE_GETH.MAC_MDIO_ADDRESS.B.RDA = regAddr;
950 
951  //Start a read operation
952  MODULE_GETH.MAC_MDIO_ADDRESS.B.GB = 1;
953  //Wait for the read to complete
954  while(MODULE_GETH.MAC_MDIO_ADDRESS.B.GB)
955  {
956  }
957 
958  //Get register value
959  data = MODULE_GETH.MAC_MDIO_DATA.B.GD;
960  }
961  else
962  {
963  //The MAC peripheral only supports standard Clause 22 opcodes
964  data = 0;
965  }
966 
967  //Return the value of the PHY register
968  return data;
969 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
@ NIC_LINK_SPEED_1GBPS
Definition: nic.h:113
Receive DMA descriptor.
uint8_t opcode
Definition: dns_common.h:188
int bool_t
Definition: compiler_port.h:53
#define netEvent
Definition: net_legacy.h:196
void tc3xxEthIrqHandler(int_t arg)
TC3xx Ethernet MAC interrupt service routine.
error_t tc3xxEthUpdateMacAddrFilter(NetInterface *interface)
Configure MAC address filtering.
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
signed int int_t
Definition: compiler_port.h:49
size_t netBufferRead(void *dest, const NetBuffer *src, size_t srcOffset, size_t length)
Read data from a multi-part buffer.
Definition: net_mem.c:690
const NicDriver tc3xxEthDriver
TC3xx Ethernet MAC driver.
#define ETH_RDES3_LD
error_t tc3xxEthSendPacket(NetInterface *interface, const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send a packet.
#define ETH_RDES3_ES
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
#define MAC_ADDR_FILTER_SIZE
Definition: ethernet.h:95
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
#define ETH_TDES3_LD
__weak_func void tc3xxEthInitGpio(NetInterface *interface)
GPIO configuration.
uint16_t tc3xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr)
Read PHY register.
uint_t refCount
Reference count for the current entry.
Definition: ethernet.h:264
Transmit DMA descriptor.
void nicProcessPacket(NetInterface *interface, uint8_t *packet, size_t length, NetRxAncillary *ancillary)
Handle a packet received by the network controller.
Definition: nic.c:392
#define osExitIsr(flag)
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define ETH_DMA_CH_STATUS_TI
#define TC3XX_ETH_RX_BUFFER_SIZE
#define TC3XX_ETH_TX_BUFFER_COUNT
#define FALSE
Definition: os_port.h:46
error_t tc3xxEthReceivePacket(NetInterface *interface)
Receive a packet.
void tc3xxEthEnableIrq(NetInterface *interface)
Enable interrupts.
#define ETH_GLOBAL_DSPR_ADDR(address)
error_t
Error codes.
Definition: error.h:43
#define ETH_DMA_CH_STATUS_NIS
#define ETH_TDES2_B1L
#define ETH_DMA_CH_STATUS_TBU
const NetRxAncillary NET_DEFAULT_RX_ANCILLARY
Definition: net_misc.c:104
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:140
#define NetInterface
Definition: net.h:36
MacAddr addr
MAC address.
Definition: ethernet.h:263
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:141
#define NetTxAncillary
Definition: net_misc.h:36
#define ETH_RDES3_BUF1V
#define SMI_OPCODE_READ
Definition: nic.h:67
#define ETH_TDES2_IOC
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
size_t netBufferGetLength(const NetBuffer *buffer)
Get the actual length of a multi-part buffer.
Definition: net_mem.c:297
#define MIN(a, b)
Definition: os_port.h:63
Infineon AURIX TriCore TC3xx Ethernet MAC driver.
#define ETH_RDES3_OWN
#define ETH_TDES3_OWN
#define rxBuffer
#define TRACE_DEBUG(...)
Definition: debug.h:107
error_t tc3xxEthUpdateMacConfig(NetInterface *interface)
Adjust MAC configuration parameters for proper operation.
uint16_t regAddr
#define ETH_MTU
Definition: ethernet.h:116
uint8_t n
MAC filter table entry.
Definition: ethernet.h:262
void tc3xxEthEventHandler(NetInterface *interface)
TC3xx Ethernet MAC event handler.
#define ETH_RDES3_FD
#define osEnterIsr()
#define ETH_DMA_CH_STATUS_RBU
#define TC3XX_ETH_RX_BUFFER_COUNT
#define TC3XX_ETH_TX_BUFFER_SIZE
#define rxDmaDesc
error_t tc3xxEthInit(NetInterface *interface)
TC3xx Ethernet MAC initialization.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define ETH_DMA_CH_STATUS_RI
void tc3xxEthDisableIrq(NetInterface *interface)
Disable interrupts.
#define ETH_TDES3_FD
#define TC3XX_ETH_IRQ_PRIORITY
#define txDmaDesc
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
void tc3xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr, uint8_t regAddr, uint16_t data)
Write PHY register.
unsigned int uint_t
Definition: compiler_port.h:50
TCP/IP stack core.
NIC driver.
Definition: nic.h:286
#define ETH_RDES3_IOC
void tc3xxEthTick(NetInterface *interface)
TC3xx Ethernet MAC timer handler.
#define ETH_MAC_ADDRESS_HIGH_AE
@ NO_ERROR
Success.
Definition: error.h:44
__attribute__((naked))
AVR32 Ethernet MAC interrupt wrapper.
Debugging facilities.
#define ETH_RDES3_PL
@ NIC_TYPE_ETHERNET
Ethernet interface.
Definition: nic.h:83
void tc3xxEthInitDmaDesc(NetInterface *interface)
Initialize DMA descriptor lists.