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-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include <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 TC375 Lite Kit?
300 #if defined(USE_KIT_A2G_TC375_LITE)
301  //Configure GETH_TXD1 (P11.2)
302  MODULE_P11.IOCR0.B.PC2 = 22;
303 
304  //Configure GETH_TXD0 (P11.3)
305  MODULE_P11.IOCR0.B.PC3 = 22;
306 
307  //Configure GETH_TXEN (P11.6)
308  MODULE_P11.IOCR4.B.PC6 = 22;
309 
310  //Configure GETH_RXD1A (P11.9)
311  MODULE_P11.IOCR8.B.PC9 = 0;
312  MODULE_GETH.GPCTL.B.ALTI7 = 0;
313 
314  //Configure GETH_RXD0A (P11.10)
315  MODULE_P11.IOCR8.B.PC10 = 0;
316  MODULE_GETH.GPCTL.B.ALTI6 = 0;
317 
318  //Configure GETH_CRSDVA (P11.11)
319  MODULE_P11.IOCR8.B.PC11 = 0;
320  MODULE_GETH.GPCTL.B.ALTI4 = 0;
321 
322  //Configure GETH_REFCLKA (P11.12)
323  MODULE_P11.IOCR12.B.PC12 = 0;
324  MODULE_GETH.GPCTL.B.ALTI1 = 0;
325 
326  //Configure GETH_MDC (P21.2)
327  MODULE_P21.IOCR0.B.PC2 = 21;
328 
329  //Configure GETH_MDIOD (P21.3)
330  MODULE_P21.IOCR0.B.PC3 = 0;
331  MODULE_GETH.GPCTL.B.ALTI0 = 3;
332 
333  //Unlock sequence
334  unlock_safety_wdtcon();
335 
336  //Set bit SELx for TXD[1:0] and TXEN signals
337  MODULE_P11.PCSR.B.SEL2 = 1;
338  MODULE_P11.PCSR.B.SEL3 = 1;
339  MODULE_P11.PCSR.B.SEL6 = 1;
340 
341  //Lock sequence
342  lock_safety_wdtcon();
343 
344  //Unlock sequence
345  unlock_wdtcon();
346 
347  //Set speed grade
348  MODULE_P11.PDR0.B.PD2 = 3;
349  MODULE_P11.PDR0.B.PL2 = 0;
350  MODULE_P11.PDR0.B.PD3 = 3;
351  MODULE_P11.PDR0.B.PL3 = 0;
352  MODULE_P11.PDR0.B.PD6 = 3;
353  MODULE_P11.PDR0.B.PL6 = 0;
354 
355  MODULE_P11.PDR1.B.PD9 = 3;
356  MODULE_P11.PDR1.B.PL9 = 0;
357  MODULE_P11.PDR1.B.PD10 = 3;
358  MODULE_P11.PDR1.B.PL10 = 0;
359  MODULE_P11.PDR1.B.PD11 = 3;
360  MODULE_P11.PDR1.B.PL11 = 0;
361  MODULE_P11.PDR1.B.PD12 = 3;
362  MODULE_P11.PDR1.B.PL12 = 0;
363 
364  MODULE_P21.PDR0.B.PD2 = 3;
365  MODULE_P21.PDR0.B.PL2 = 0;
366  MODULE_P21.PDR0.B.PD3 = 3;
367  MODULE_P21.PDR0.B.PL3 = 0;
368 
369  //Lock sequence
370  lock_wdtcon();
371 
372  //Select RMII operation mode
373  MODULE_GETH.GPCTL.B.EPR = 4;
374 
375 //AURIX TC387 TFT Application Kit or AURIX TC397 TFT Application Kit?
376 #elif defined(USE_KIT_A2G_TC387_TFT) || defined(USE_KIT_A2G_TC397_TFT)
377  //Configure GETH_TXD3 (P11.0)
378  MODULE_P11.IOCR0.B.PC0 = 22;
379 
380  //Configure GETH_TXD2 (P11.1)
381  MODULE_P11.IOCR0.B.PC1 = 22;
382 
383  //Configure GETH_TXD1 (P11.2)
384  MODULE_P11.IOCR0.B.PC2 = 22;
385 
386  //Configure GETH_TXD0 (P11.3)
387  MODULE_P11.IOCR0.B.PC3 = 22;
388 
389  //Configure GETH_TXCLK (P11.4)
390  MODULE_P11.IOCR4.B.PC4 = 23;
391 
392  //Configure GETH_GREFCLK (P11.5)
393  MODULE_P11.IOCR4.B.PC5 = 0;
394 
395  //Configure GETH_TCTL (P11.6)
396  MODULE_P11.IOCR4.B.PC6 = 22;
397 
398  //Configure GETH_RXD3A (P11.7)
399  MODULE_P11.IOCR4.B.PC7 = 0;
400  MODULE_GETH.GPCTL.B.ALTI9 = 0;
401 
402  //Configure GETH_RXD2A (P11.8)
403  MODULE_P11.IOCR8.B.PC8 = 0;
404  MODULE_GETH.GPCTL.B.ALTI8 = 0;
405 
406  //Configure GETH_RXD1A (P11.9)
407  MODULE_P11.IOCR8.B.PC9 = 0;
408  MODULE_GETH.GPCTL.B.ALTI7 = 0;
409 
410  //Configure GETH_RXD0A (P11.10)
411  MODULE_P11.IOCR8.B.PC10 = 0;
412  MODULE_GETH.GPCTL.B.ALTI6 = 0;
413 
414  //Configure GETH_RCTLA (P11.11)
415  MODULE_P11.IOCR8.B.PC11 = 0;
416  MODULE_GETH.GPCTL.B.ALTI4 = 0;
417 
418  //Configure GETH_RXCLKA (P11.12)
419  MODULE_P11.IOCR12.B.PC12 = 0;
420  MODULE_GETH.GPCTL.B.ALTI1 = 0;
421 
422  //Configure GETH_MDC (P12.0)
423  MODULE_P12.IOCR0.B.PC0 = 22;
424 
425  //Configure GETH_MDIOC (P12.1)
426  MODULE_P12.IOCR0.B.PC1 = 0;
427  MODULE_GETH.GPCTL.B.ALTI0 = 2;
428 
429  //Unlock sequence
430  unlock_safety_wdtcon();
431 
432  //Set bit SELx for TXD[3:0], TXCLK and TCTL signals
433  MODULE_P11.PCSR.B.SEL0 = 1;
434  MODULE_P11.PCSR.B.SEL1 = 1;
435  MODULE_P11.PCSR.B.SEL2 = 1;
436  MODULE_P11.PCSR.B.SEL3 = 1;
437  MODULE_P11.PCSR.B.SEL4 = 1;
438  MODULE_P11.PCSR.B.SEL6 = 1;
439 
440  //Lock sequence
441  lock_safety_wdtcon();
442 
443  //Unlock sequence
444  unlock_wdtcon();
445 
446  //Set speed grade
447  MODULE_P11.PDR0.B.PD0 = 3;
448  MODULE_P11.PDR0.B.PL0 = 0;
449  MODULE_P11.PDR0.B.PD1 = 3;
450  MODULE_P11.PDR0.B.PL1 = 0;
451  MODULE_P11.PDR0.B.PD2 = 3;
452  MODULE_P11.PDR0.B.PL2 = 0;
453  MODULE_P11.PDR0.B.PD3 = 3;
454  MODULE_P11.PDR0.B.PL3 = 0;
455  MODULE_P11.PDR0.B.PD4 = 3;
456  MODULE_P11.PDR0.B.PL4 = 0;
457  MODULE_P11.PDR0.B.PD5 = 3;
458  MODULE_P11.PDR0.B.PL5 = 0;
459  MODULE_P11.PDR0.B.PD6 = 3;
460  MODULE_P11.PDR0.B.PL6 = 0;
461  MODULE_P11.PDR0.B.PD7 = 3;
462  MODULE_P11.PDR0.B.PL7 = 0;
463 
464  MODULE_P11.PDR1.B.PD8 = 3;
465  MODULE_P11.PDR1.B.PL8 = 0;
466  MODULE_P11.PDR1.B.PD9 = 3;
467  MODULE_P11.PDR1.B.PL9 = 0;
468  MODULE_P11.PDR1.B.PD10 = 3;
469  MODULE_P11.PDR1.B.PL10 = 0;
470  MODULE_P11.PDR1.B.PD11 = 3;
471  MODULE_P11.PDR1.B.PL11 = 0;
472  MODULE_P11.PDR1.B.PD12 = 3;
473  MODULE_P11.PDR1.B.PL12 = 0;
474 
475  MODULE_P12.PDR0.B.PD0 = 3;
476  MODULE_P12.PDR0.B.PL0 = 0;
477  MODULE_P12.PDR0.B.PD1 = 3;
478  MODULE_P12.PDR0.B.PL1 = 0;
479 
480  //Lock sequence
481  lock_wdtcon();
482 
483  //Select RGMII operation mode
484  MODULE_GETH.GPCTL.B.EPR = 1;
485 
486  //Set delay for RGMII TX and RX clocks
487  MODULE_GETH.SKEWCTL.B.TXCFG = 5;
488  MODULE_GETH.SKEWCTL.B.RXCFG = 5;
489 #endif
490 }
491 
492 
493 /**
494  * @brief Initialize DMA descriptor lists
495  * @param[in] interface Underlying network interface
496  **/
497 
499 {
500  uint_t i;
501 
502  //Initialize TX DMA descriptor list
503  for(i = 0; i < TC3XX_ETH_TX_BUFFER_COUNT; i++)
504  {
505  //The descriptor is initially owned by the application
506  txDmaDesc[i].tdes0 = 0;
507  txDmaDesc[i].tdes1 = 0;
508  txDmaDesc[i].tdes2 = 0;
509  txDmaDesc[i].tdes3 = 0;
510  }
511 
512  //Initialize TX descriptor index
513  txIndex = 0;
514 
515  //Initialize RX DMA descriptor list
516  for(i = 0; i < TC3XX_ETH_RX_BUFFER_COUNT; i++)
517  {
518  //The descriptor is initially owned by the DMA
519  rxDmaDesc[i].rdes0 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(rxBuffer[i]);
520  rxDmaDesc[i].rdes1 = 0;
521  rxDmaDesc[i].rdes2 = 0;
523  }
524 
525  //Initialize RX descriptor index
526  rxIndex = 0;
527 
528  //Start location of the TX descriptor list
529  MODULE_GETH.DMA_CH[0].TXDESC_LIST_ADDRESS.U = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&txDmaDesc[0]);
530  //Length of the transmit descriptor ring
531  MODULE_GETH.DMA_CH[0].TXDESC_RING_LENGTH.U = TC3XX_ETH_TX_BUFFER_COUNT - 1;
532 
533  //Start location of the RX descriptor list
534  MODULE_GETH.DMA_CH[0].RXDESC_LIST_ADDRESS.U = (uint32_t) ETH_GLOBAL_DSPR_ADDR(&rxDmaDesc[0]);
535  //Length of the receive descriptor ring
536  MODULE_GETH.DMA_CH[0].RXDESC_RING_LENGTH.U = TC3XX_ETH_RX_BUFFER_COUNT - 1;
537 }
538 
539 
540 /**
541  * @brief TC3xx Ethernet MAC timer handler
542  *
543  * This routine is periodically called by the TCP/IP stack to handle periodic
544  * operations such as polling the link state
545  *
546  * @param[in] interface Underlying network interface
547  **/
548 
549 void tc3xxEthTick(NetInterface *interface)
550 {
551  //Valid Ethernet PHY or switch driver?
552  if(interface->phyDriver != NULL)
553  {
554  //Handle periodic operations
555  interface->phyDriver->tick(interface);
556  }
557  else if(interface->switchDriver != NULL)
558  {
559  //Handle periodic operations
560  interface->switchDriver->tick(interface);
561  }
562  else
563  {
564  //Just for sanity
565  }
566 }
567 
568 
569 /**
570  * @brief Enable interrupts
571  * @param[in] interface Underlying network interface
572  **/
573 
575 {
576  //Enable Ethernet MAC interrupts
577  InterruptEnable(SRC_ID_GETH0);
578 
579  //Valid Ethernet PHY or switch driver?
580  if(interface->phyDriver != NULL)
581  {
582  //Enable Ethernet PHY interrupts
583  interface->phyDriver->enableIrq(interface);
584  }
585  else if(interface->switchDriver != NULL)
586  {
587  //Enable Ethernet switch interrupts
588  interface->switchDriver->enableIrq(interface);
589  }
590  else
591  {
592  //Just for sanity
593  }
594 }
595 
596 
597 /**
598  * @brief Disable interrupts
599  * @param[in] interface Underlying network interface
600  **/
601 
603 {
604  //Enable Ethernet MAC interrupts
605  InterruptDisable(SRC_ID_GETH0);
606 
607  //Valid Ethernet PHY or switch driver?
608  if(interface->phyDriver != NULL)
609  {
610  //Disable Ethernet PHY interrupts
611  interface->phyDriver->disableIrq(interface);
612  }
613  else if(interface->switchDriver != NULL)
614  {
615  //Disable Ethernet switch interrupts
616  interface->switchDriver->disableIrq(interface);
617  }
618  else
619  {
620  //Just for sanity
621  }
622 }
623 
624 
625 /**
626  * @brief TC3xx Ethernet MAC interrupt service routine
627  * @param arg Unused parameter
628  **/
629 
631 {
632  bool_t flag;
633  uint32_t status;
634 
635  //Interrupt service routine prologue
636  osEnterIsr();
637 
638  //This flag will be set if a higher priority task must be woken
639  flag = FALSE;
640 
641  //Read DMA status register
642  status = MODULE_GETH.DMA_CH[0].STATUS.U;
643 
644  //Packet transmitted?
645  if((status & ETH_DMA_CH_STATUS_TI) != 0)
646  {
647  //Clear TI interrupt flag
648  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_TI;
649 
650  //Check whether the TX buffer is available for writing
651  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
652  {
653  //Notify the TCP/IP stack that the transmitter is ready to send
654  flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent);
655  }
656  }
657 
658  //Packet received?
659  if((status & ETH_DMA_CH_STATUS_RI) != 0)
660  {
661  //Clear RI interrupt flag
662  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_RI;
663 
664  //Set event flag
665  nicDriverInterface->nicEvent = TRUE;
666  //Notify the TCP/IP stack of the event
667  flag |= osSetEventFromIsr(&nicDriverInterface->netContext->event);
668  }
669 
670  //Clear NIS interrupt flag
671  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_NIS;
672 
673  //Interrupt service routine epilogue
674  osExitIsr(flag);
675 }
676 
677 
678 /**
679  * @brief TC3xx Ethernet MAC event handler
680  * @param[in] interface Underlying network interface
681  **/
682 
684 {
685  error_t error;
686 
687  //Process all pending packets
688  do
689  {
690  //Read incoming packet
691  error = tc3xxEthReceivePacket(interface);
692 
693  //No more data in the receive buffer?
694  } while(error != ERROR_BUFFER_EMPTY);
695 }
696 
697 
698 /**
699  * @brief Send a packet
700  * @param[in] interface Underlying network interface
701  * @param[in] buffer Multi-part buffer containing the data to send
702  * @param[in] offset Offset to the first data byte
703  * @param[in] ancillary Additional options passed to the stack along with
704  * the packet
705  * @return Error code
706  **/
707 
709  const NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
710 {
711  size_t length;
712 
713  //Retrieve the length of the packet
714  length = netBufferGetLength(buffer) - offset;
715 
716  //Check the frame length
718  {
719  //The transmitter can accept another packet
720  osSetEvent(&interface->nicTxEvent);
721  //Report an error
722  return ERROR_INVALID_LENGTH;
723  }
724 
725  //Make sure the current buffer is available for writing
726  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) != 0)
727  {
728  return ERROR_FAILURE;
729  }
730 
731  //Copy user data to the transmit buffer
732  netBufferRead(txBuffer[txIndex], buffer, offset, length);
733 
734  //Set the start address of the buffer
735  txDmaDesc[txIndex].tdes0 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(txBuffer[txIndex]);
736  //Write the number of bytes to send
737  txDmaDesc[txIndex].tdes2 = ETH_TDES2_IOC | (length & ETH_TDES2_B1L);
738  //Give the ownership of the descriptor to the DMA
739  txDmaDesc[txIndex].tdes3 = ETH_TDES3_OWN | ETH_TDES3_FD | ETH_TDES3_LD;
740 
741  //Clear TBU flag to resume processing
742  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_TBU;
743  //Instruct the DMA to poll the transmit descriptor list
744  MODULE_GETH.DMA_CH[0].TXDESC_TAIL_POINTER.U = 0;
745 
746  //Increment index and wrap around if necessary
747  if(txIndex < (TC3XX_ETH_TX_BUFFER_COUNT - 1))
748  {
749  txIndex++;
750  }
751  else
752  {
753  txIndex = 0;
754  }
755 
756  //Check whether the next buffer is available for writing
757  if((txDmaDesc[txIndex].tdes3 & ETH_TDES3_OWN) == 0)
758  {
759  //The transmitter can accept another packet
760  osSetEvent(&interface->nicTxEvent);
761  }
762 
763  //Data successfully written
764  return NO_ERROR;
765 }
766 
767 
768 /**
769  * @brief Receive a packet
770  * @param[in] interface Underlying network interface
771  * @return Error code
772  **/
773 
775 {
776  error_t error;
777  size_t n;
778  NetRxAncillary ancillary;
779 
780  //Current buffer available for reading?
781  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_OWN) == 0)
782  {
783  //FD and LD flags should be set
784  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_FD) != 0 &&
785  (rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_LD) != 0)
786  {
787  //Make sure no error occurred
788  if((rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_ES) == 0)
789  {
790  //Retrieve the length of the frame
791  n = rxDmaDesc[rxIndex].rdes3 & ETH_RDES3_PL;
792  //Limit the number of data to read
794 
795  //Additional options can be passed to the stack along with the packet
796  ancillary = NET_DEFAULT_RX_ANCILLARY;
797 
798  //Pass the packet to the upper layer
799  nicProcessPacket(interface, rxBuffer[rxIndex], n, &ancillary);
800 
801  //Valid packet received
802  error = NO_ERROR;
803  }
804  else
805  {
806  //The received packet contains an error
807  error = ERROR_INVALID_PACKET;
808  }
809  }
810  else
811  {
812  //The packet is not valid
813  error = ERROR_INVALID_PACKET;
814  }
815 
816  //Set the start address of the buffer
817  rxDmaDesc[rxIndex].rdes0 = (uint32_t) ETH_GLOBAL_DSPR_ADDR(rxBuffer[rxIndex]);
818  //Give the ownership of the descriptor back to the DMA
820 
821  //Increment index and wrap around if necessary
822  if(rxIndex < (TC3XX_ETH_RX_BUFFER_COUNT - 1))
823  {
824  rxIndex++;
825  }
826  else
827  {
828  rxIndex = 0;
829  }
830  }
831  else
832  {
833  //No more data in the receive buffer
834  error = ERROR_BUFFER_EMPTY;
835  }
836 
837  //Clear RBU flag to resume processing
838  MODULE_GETH.DMA_CH[0].STATUS.U = ETH_DMA_CH_STATUS_RBU;
839  //Instruct the DMA to poll the receive descriptor list
840  MODULE_GETH.DMA_CH[0].RXDESC_TAIL_POINTER.U = 0;
841 
842  //Return status code
843  return error;
844 }
845 
846 
847 /**
848  * @brief Configure MAC address filtering
849  * @param[in] interface Underlying network interface
850  * @return Error code
851  **/
852 
854 {
855  uint_t i;
856  uint_t j;
857  MacFilterEntry *entry;
858  volatile Ifx_GETH_MAC_ADDRESS_LOW *macAddressLow;
859  volatile Ifx_GETH_MAC_ADDRESS_HIGH *macAddressHigh;
860 
861  //Debug message
862  TRACE_DEBUG("Updating MAC filter...\r\n");
863 
864  //Set the MAC address of the station
865  MODULE_GETH.MAC_ADDRESS_LOW0.U = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16);
866  MODULE_GETH.MAC_ADDRESS_HIGH0.U = interface->macAddr.w[2];
867 
868  //The MAC address filter contains the list of MAC addresses to accept
869  //when receiving an Ethernet frame
870  for(i = 0, j = 0; i < MAC_ADDR_FILTER_SIZE && j < 31; i++)
871  {
872  //Point to the current entry
873  entry = &interface->macAddrFilter[i];
874 
875  //Valid entry?
876  if(entry->refCount > 0)
877  {
878  //The MAC_ADDRESSi_LOW register holds the lower 32 bits of the MAC address
879  macAddressLow = &MODULE_GETH.MAC_ADDRESS_LOW1 + 2 * j;
880  //The MAC_ADDRESSi_HIGH register holds the upper 16 bits of the MAC address
881  macAddressHigh = &MODULE_GETH.MAC_ADDRESS_HIGH1 + 2 * j;
882 
883  //When the AE bit is set, the entry is used for perfect filtering
884  macAddressLow->U = entry->addr.w[0] | (entry->addr.w[1] << 16);
885  macAddressHigh->U = entry->addr.w[2] | ETH_MAC_ADDRESS_HIGH_AE;
886 
887  //Next entry
888  j++;
889  }
890  }
891 
892  //Clear unused entries
893  while(j < 31)
894  {
895  //The MAC_ADDRESSi_LOW register holds the lower 32 bits of the MAC address
896  macAddressLow = &MODULE_GETH.MAC_ADDRESS_LOW1 + 2 * j;
897  //The MAC_ADDRESSi_HIGH register holds the upper 16 bits of the MAC address
898  macAddressHigh = &MODULE_GETH.MAC_ADDRESS_HIGH1 + 2 * j;
899 
900  //When the AE bit is cleared, the entry is ignored
901  macAddressLow->U = 0;
902  macAddressHigh->U = 0;
903 
904  //Next entry
905  j++;
906  }
907 
908  //Successful processing
909  return NO_ERROR;
910 }
911 
912 
913 /**
914  * @brief Adjust MAC configuration parameters for proper operation
915  * @param[in] interface Underlying network interface
916  * @return Error code
917  **/
918 
920 {
921  Ifx_GETH_MAC_CONFIGURATION config;
922 
923  //Read current MAC configuration
924  config.U = MODULE_GETH.MAC_CONFIGURATION.U;
925 
926  //1000BASE-T operation mode?
927  if(interface->linkSpeed == NIC_LINK_SPEED_1GBPS)
928  {
929  config.B.PS = 0;
930  config.B.FES = 0;
931  }
932  //100BASE-TX operation mode?
933  else if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS)
934  {
935  config.B.PS = 1;
936  config.B.FES = 1;
937  }
938  //10BASE-T operation mode?
939  else
940  {
941  config.B.PS = 1;
942  config.B.FES = 0;
943  }
944 
945  //Half-duplex or full-duplex mode?
946  if(interface->duplexMode == NIC_FULL_DUPLEX_MODE)
947  {
948  config.B.DM = 1;
949  }
950  else
951  {
952  config.B.DM = 0;
953  }
954 
955  //Update MAC configuration register
956  MODULE_GETH.MAC_CONFIGURATION.U = config.U;
957 
958  //Successful processing
959  return NO_ERROR;
960 }
961 
962 
963 /**
964  * @brief Write PHY register
965  * @param[in] opcode Access type (2 bits)
966  * @param[in] phyAddr PHY address (5 bits)
967  * @param[in] regAddr Register address (5 bits)
968  * @param[in] data Register value
969  **/
970 
971 void tc3xxEthWritePhyReg(uint8_t opcode, uint8_t phyAddr,
972  uint8_t regAddr, uint16_t data)
973 {
974  //Valid opcode?
975  if(opcode == SMI_OPCODE_WRITE)
976  {
977  //Set up a write operation
978  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_0 = 1;
979  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_1 = 0;
980 
981  //PHY address
982  MODULE_GETH.MAC_MDIO_ADDRESS.B.PA = phyAddr;
983  //Register address
984  MODULE_GETH.MAC_MDIO_ADDRESS.B.RDA = regAddr;
985 
986  //Data to be written in the PHY register
987  MODULE_GETH.MAC_MDIO_DATA.B.GD = data;
988 
989  //Start a write operation
990  MODULE_GETH.MAC_MDIO_ADDRESS.B.GB = 1;
991  //Wait for the write to complete
992  while(MODULE_GETH.MAC_MDIO_ADDRESS.B.GB)
993  {
994  }
995  }
996  else
997  {
998  //The MAC peripheral only supports standard Clause 22 opcodes
999  }
1000 }
1001 
1002 
1003 /**
1004  * @brief Read PHY register
1005  * @param[in] opcode Access type (2 bits)
1006  * @param[in] phyAddr PHY address (5 bits)
1007  * @param[in] regAddr Register address (5 bits)
1008  * @return Register value
1009  **/
1010 
1011 uint16_t tc3xxEthReadPhyReg(uint8_t opcode, uint8_t phyAddr,
1012  uint8_t regAddr)
1013 {
1014  uint16_t data;
1015 
1016  //Valid opcode?
1017  if(opcode == SMI_OPCODE_READ)
1018  {
1019  //Set up a read operation
1020  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_0 = 1;
1021  MODULE_GETH.MAC_MDIO_ADDRESS.B.GOC_1 = 1;
1022 
1023  //PHY address
1024  MODULE_GETH.MAC_MDIO_ADDRESS.B.PA = phyAddr;
1025  //Register address
1026  MODULE_GETH.MAC_MDIO_ADDRESS.B.RDA = regAddr;
1027 
1028  //Start a read operation
1029  MODULE_GETH.MAC_MDIO_ADDRESS.B.GB = 1;
1030  //Wait for the read to complete
1031  while(MODULE_GETH.MAC_MDIO_ADDRESS.B.GB)
1032  {
1033  }
1034 
1035  //Get register value
1036  data = MODULE_GETH.MAC_MDIO_DATA.B.GD;
1037  }
1038  else
1039  {
1040  //The MAC peripheral only supports standard Clause 22 opcodes
1041  data = 0;
1042  }
1043 
1044  //Return the value of the PHY register
1045  return data;
1046 }
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:191
int bool_t
Definition: compiler_port.h:63
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:56
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:224
#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:266
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:418
#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:103
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
#define txBuffer
#define NetRxAncillary
Definition: net_misc.h:40
@ ERROR_INVALID_PACKET
Definition: error.h:141
#define NetInterface
Definition: net.h:40
MacAddr addr
MAC address.
Definition: ethernet.h:265
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_BUFFER_EMPTY
Definition: error.h:142
#define 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:105
uint8_t length
Definition: tcp.h:375
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:119
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:264
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:57
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.