iLLD_TC27xC  1.0
IfxEth.c
Go to the documentation of this file.
1 /**
2  * \file IfxEth.c
3  * \brief ETH basic functionality
4  *
5  * \version iLLD_0_1_0_10
6  * \copyright Copyright (c) 2013 Infineon Technologies AG. All rights reserved.
7  *
8  *
9  * IMPORTANT NOTICE
10  *
11  *
12  * Infineon Technologies AG (Infineon) is supplying this file for use
13  * exclusively with Infineon's microcontroller products. This file can be freely
14  * distributed within development tools that are supporting such microcontroller
15  * products.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
18  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
20  * INFINEON SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
21  * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
22  *
23  */
24 
25 /******************************************************************************/
26 /*----------------------------------Includes----------------------------------*/
27 /******************************************************************************/
28 
29 #include "IfxEth.h"
30 #include "Src/Std/IfxSrc.h"
31 #include "Scu/Std/IfxScuWdt.h"
32 #include "IfxPort_reg.h"
33 #include "IfxEth_bf.h"
34 #include "IfxEth.h"
35 #include "IfxPort_reg.h"
36 
37 /** \addtogroup IfxLld_Eth_Std_Configuration
38  * \{ */
39 
40 /******************************************************************************/
41 /*-----------------------Private Function Prototypes--------------------------*/
42 /******************************************************************************/
43 
44 /** \brief Sets transmit descriptor address
45  * \param eth pointer to the ethernet module
46  * \param address Address
47  * \return None
48  */
49 static void IfxEth_setTransmitDescriptorAddress(Ifx_ETH *eth, void *address);
50 
51 /** \brief Sets receive descriptor address
52  * \param eth pointer to the ethernet module
53  * \param address Address
54  * \return None
55  */
56 static void IfxEth_setReceiveDescriptorAddress(Ifx_ETH *eth, void *address);
57 
58 /** \} */
59 
60 /** \addtogroup IfxLld_Eth_Std_Initialisation
61  * \{ */
62 
63 /******************************************************************************/
64 /*-----------------------Private Function Prototypes--------------------------*/
65 /******************************************************************************/
66 
67 /** \brief Initialises transmit descriptors
68  * \param eth pointer to ETH driver structure
69  * \return None
70  */
71 static void IfxEth_initTransmitDescriptors(IfxEth *eth);
72 
73 /** \brief Initialises the receive descriptors
74  * \param eth ETH driver structure
75  * \return None
76  */
77 static void IfxEth_initReceiveDescriptors(IfxEth *eth);
78 
79 /** \} */
80 
81 /******************************************************************************/
82 /*-----------------------Exported Variables/Constants-------------------------*/
83 /******************************************************************************/
84 
86 
88 
90 
92 
93 /******************************************************************************/
94 /*-------------------------Function Implementations---------------------------*/
95 /******************************************************************************/
96 
98 {
99  eth->status.U = ETH_STATUS.U;
100 
101  // check if suspended
102  if (eth->status.U & 0x00600000)
103  {
104  if (eth->status.B.TU)
105  {
106  // clear transmit unavailable and underflow flags
107  ETH_STATUS.U = (IFX_ETH_STATUS_TU_MSK << IFX_ETH_STATUS_TU_OFF) |
108  (IFX_ETH_STATUS_UNF_MSK << IFX_ETH_STATUS_UNF_OFF);
109  }
110 
112  }
113 }
114 
115 
117 {
118  eth->status.U = ETH_STATUS.U;
119 
120  // check if receiver suspended
121  if (eth->status.U & (4U << IFX_ETH_STATUS_RS_OFF))
122  {
123  if (eth->status.B.RU)
124  {
125  ETH_STATUS.U = (IFX_ETH_STATUS_RU_MSK << IFX_ETH_STATUS_RU_OFF);
126  }
127 
129  }
130 }
131 
132 
134 {
135  (void)eth;
136 
137  ETH_TRANSMIT_POLL_DEMAND.U = 0;
138  ETH_OPERATION_MODE.B.ST = 0;
139  ETH_MAC_CONFIGURATION.B.TE = 0;
140 }
141 
142 
144 {
145  (void)eth;
146 
147  ETH_MAC_CONFIGURATION.B.TE = 1;
148  ETH_OPERATION_MODE.B.ST = 1;
149  ETH_TRANSMIT_POLL_DEMAND.U = 1;
150 }
151 
152 
154 {
155  (void)eth;
156 
157  // enable receiver and RX DMA
158  ETH_OPERATION_MODE.B.SR = 1;
159  ETH_MAC_CONFIGURATION.B.RE = 1;
160  ETH_RECEIVE_POLL_DEMAND.U = 1;
161 }
162 
163 
164 void IfxEth_setupOutputPins(IfxEth *eth, const IfxEth_PortPins *portPins)
165 {
168 
169  IfxEth_Mdc_Out *mdc = portPins->mdc;
170  IfxEth_Mdio_InOut *mdio = portPins->mdio;
171  IfxEth_Txen_Out *txen = portPins->txEn;
172  IfxEth_Txd_Out *txd0 = portPins->txd0;
173  IfxEth_Txd_Out *txd1 = portPins->txd1;
174 
175  (void)eth;
176 
177 #if 0
178  IfxPort_setPinPadDriver(mdc->pin.port, mdc->pin.pinIndex, speedGrade);
179  IfxPort_setPinPadDriver(mdio->pin.port, mdio->pin.pinIndex, speedGrade);
180 #endif
181  IfxPort_setPinPadDriver(txen->pin.port, txen->pin.pinIndex, speedGrade);
182  IfxPort_setPinPadDriver(txd0->pin.port, txd0->pin.pinIndex, speedGrade);
183  IfxPort_setPinPadDriver(txd1->pin.port, txd1->pin.pinIndex, speedGrade);
184 
185  IfxPort_setPinModeOutput(mdc->pin.port, mdc->pin.pinIndex, mode, mdc->select);
186  IfxPort_setPinModeOutput(txen->pin.port, txen->pin.pinIndex, mode, txen->select);
187  IfxPort_setPinModeOutput(txd0->pin.port, txd0->pin.pinIndex, mode, txd0->select);
188  IfxPort_setPinModeOutput(txd1->pin.port, txd1->pin.pinIndex, mode, txd1->select);
189 
190  // For MDIO, when P21.1 is used it should be configured as output
191  if ((mdio->pin.port == (&MODULE_P21)) && (mdio->pin.pinIndex == 1))
192  {
193  IfxPort_setPinModeOutput(mdio->pin.port, mdio->pin.pinIndex, mode, mdio->outSelect);
194  }
195 }
196 
197 
198 void IfxEth_setupInputPins(IfxEth *eth, const IfxEth_PortPins *portPins)
199 {
200  (void)eth;
201 
202  ETH_GPCTL.B.ALTI0 = portPins->mdio->inSelect;
203  ETH_GPCTL.B.ALTI1 = portPins->refClk->select;
204  ETH_GPCTL.B.ALTI4 = portPins->crsDiv->select;
205  ETH_GPCTL.B.ALTI6 = portPins->rxd0->select;
206  ETH_GPCTL.B.ALTI7 = portPins->rxd1->select;
207 
208  {
211 
212  IfxEth_Crsdv_In *crsDiv = portPins->crsDiv;
213  IfxEth_Refclk_In *refClk = portPins->refClk;
214  IfxEth_Rxd_In *rxd0 = portPins->rxd0;
215  IfxEth_Rxd_In *rxd1 = portPins->rxd1;
216 
217  IfxPort_setPinModeInput(crsDiv->pin.port, crsDiv->pin.pinIndex, mode);
218  IfxPort_setPinModeInput(refClk->pin.port, refClk->pin.pinIndex, mode);
219  IfxPort_setPinModeInput(rxd0->pin.port, rxd0->pin.pinIndex, mode);
220  IfxPort_setPinModeInput(rxd1->pin.port, rxd1->pin.pinIndex, mode);
221 
222  IfxPort_setPinPadDriver(crsDiv->pin.port, crsDiv->pin.pinIndex, speedGrade);
223  IfxPort_setPinPadDriver(refClk->pin.port, refClk->pin.pinIndex, speedGrade);
224  IfxPort_setPinPadDriver(rxd0->pin.port, rxd0->pin.pinIndex, speedGrade);
225  IfxPort_setPinPadDriver(rxd1->pin.port, rxd1->pin.pinIndex, speedGrade);
226  }
227 }
228 
229 
231 {
232  int i;
233 
234  if (mode != IfxEth_ChecksumMode_bypass)
235  {
236  ETH_OPERATION_MODE.B.TSF = 1U;
237  ETH_OPERATION_MODE.B.DT = 0U; /* 0 = drop TCP/IP frame with checksum error */
238  ETH_MAC_CONFIGURATION.B.IPC = 1U; /* 1 = enable received IP frame checksum engine */
239 
241 
242  for (i = 0; i < IFXETH_MAX_TX_BUFFERS; i++)
243  {
244  descr->TDES0.A.CIC = mode;
245  descr = IfxEth_TxDescr_getNext(descr);
246  }
247  }
248 }
249 
250 
251 static void IfxEth_setTransmitDescriptorAddress(Ifx_ETH *eth, void *address)
252 {
253  eth->TRANSMIT_DESCRIPTOR_LIST_ADDRESS.U = (uint32)address;
254 }
255 
256 
257 static void IfxEth_setReceiveDescriptorAddress(Ifx_ETH *eth, void *address)
258 {
259  eth->RECEIVE_DESCRIPTOR_LIST_ADDRESS.U = (uint32)address;
260 }
261 
262 
263 void IfxEth_setMacAddress(IfxEth *eth, const uint8 *macAddress)
264 {
265  (void)eth;
266  ETH_MAC_ADDRESS_G00_HIGH.U = 0
267  | ((uint32)macAddress[4] << 0U)
268  | ((uint32)macAddress[5] << 8U)
269  | 0x80000000U;
270 
271  ETH_MAC_ADDRESS_G00_LOW.U = 0
272  | ((uint32)macAddress[0] << 0U)
273  | ((uint32)macAddress[1] << 8U)
274  | ((uint32)macAddress[2] << 16U)
275  | ((uint32)macAddress[3] << 24U)
276  ;
277 }
278 
279 
280 void IfxEth_setAndSendTransmitBuffer(IfxEth *eth, void *buffer, uint16 len)
281 {
283  IfxEth_sendTransmitBuffer(eth, len);
284 }
285 
286 
288 {
290 
291  descr->TDES1.U = len; /* with TCH set, TBS1 is used for buffer size */
292  descr->TDES0.A.OWN = 1U; /* release to DMA */
293 
296 
297  eth->txCount++;
298 }
299 
300 
301 void IfxEth_readMacAddress(IfxEth *eth, uint8 *macAddress)
302 {
303  (void)eth;
304  *((uint32 *)macAddress) = ETH_MAC_ADDRESS_G00_LOW.U;
305  *((uint16 *)(&macAddress[4])) = (uint16)(ETH_MAC_ADDRESS_G00_HIGH.U & 0xFFFFU);
306 }
307 
308 
309 static void IfxEth_initTransmitDescriptors(IfxEth *eth)
310 {
311  int i;
312  IfxEth_TxDescr *descr = IfxEth_txDescr.items;
313  eth->txDescr = &IfxEth_txDescr;
314 
315  eth->pTxDescr = descr;
316 
317  /* Initialize chained descriptor mode */
318  for (i = 0; i < IFXETH_MAX_TX_BUFFERS; i++)
319  {
320  descr->TDES0.U = 0;
321  descr->TDES0.A.IC = 1U;
322  descr->TDES0.A.FS = 1U;
323  descr->TDES0.A.LS = 1U;
324  descr->TDES0.A.TCH = 1U;
325 
326 #if !IFXETH_TX_BUFFER_BY_USER
327  IfxEth_TxDescr_setBuffer(descr, &(IfxEth_txBuffer[i][0]));
328 #endif
329 
330  /* with TCH set, TDES3 points to next descriptor */
331  descr->TDES3.U = (uint32)&descr[1];
332  descr = &descr[1];
333  }
334 
335  /* correction for last descriptor */
336  {
337  descr = &descr[-1];
338 
339  /* indicate end of ring */
340  descr->TDES0.A.TER = 1U;
341 
342  /* with TCH set, TDES3 points to the first descriptor */
344  descr->TDES3.U = (uint32)eth->pTxDescr;
345  }
346 
347  eth->txCount = 0;
348 
349  /* write descriptor list base address */
350  IfxEth_setTransmitDescriptorAddress(&MODULE_ETH, IfxEth_getBaseTxDescriptor(eth));
351 }
352 
353 
354 static void IfxEth_initReceiveDescriptors(IfxEth *eth)
355 {
356  // Use enhanced descriptors, because ETH is generally configured to precision time protocol.
357  int i;
358  IfxEth_RxDescr *descr = IfxEth_rxDescr.items;
359  eth->rxDescr = &IfxEth_rxDescr;
360 
361  eth->pRxDescr = descr;
362 
363  /* init descriptor chained mode */
364  for (i = 0; i < IFXETH_MAX_RX_BUFFERS; i++)
365  {
366  descr->RDES0.U = 0;
367  descr->RDES0.A.OWN = 1U;
368 
369  descr->RDES1.U = 0;
370  descr->RDES1.A.RCH = 1U;
371  descr->RDES1.A.RBS1 = (IFXETH_RTX_BUFFER_SIZE);
372 
373 #if !IFXETH_RX_BUFFER_BY_USER
374  IfxEth_RxDescr_setBuffer(descr, &(IfxEth_rxBuffer[i][0]));
375 #endif
376 
377  /* with RCH set, link to next descriptor address */
378  descr->RDES3.U = (uint32)&(descr[1]);
379  descr = &descr[1];
380  }
381 
382  /* correction for last descriptor */
383  {
384  descr = &descr[-1];
385 
386  /* indicate end of ring */
387  descr->RDES1.A.RER = 1U;
388 
389  /* with RCH set, link to first descriptor address */
391  descr->RDES3.U = (uint32)eth->pRxDescr;
392  }
393 
394  eth->rxCount = 0;
395 
396  /* write descriptor list base address */
397  IfxEth_setReceiveDescriptorAddress(&MODULE_ETH, IfxEth_getBaseRxDescriptor(eth));
398 }
399 
400 
401 void IfxEth_init(IfxEth *eth, const IfxEth_Config *config)
402 {
403 #ifndef _WIN32
405  IfxEth_setupOutputPins(eth, config->portPins);
406  IfxEth_setupInputPins(eth, config->portPins);
407 #endif
408 
409  ETH_GPCTL.B.EPR = 1; /* select RMII (needs module reset) */
410  ETH_BUS_MODE.B.SWR = 1; /* reset module */
411 
412  {
413  uint32 timeout = 0;
414 
415  // FIXME the timeout value may be defined in IfxEth_cfg.h
416  while ((ETH_BUS_MODE.B.SWR == 1) && (timeout < 1000))
417  {
418  /* wait reset is finished or timeout. */
419  timeout++;
420  }
421  }
422 
423  /* configure bus mode */
424  {
425  Ifx_ETH_BUS_MODE busMode;
426  busMode.U = ETH_BUS_MODE.U;
427  busMode.B.DSL = 0; /* descriptor skip length in ring mode */
428  busMode.B.ATDS = 0; /* alternate descriptor size: 0 => 4 DWORDS, 1 => 8 DWORDS */
429  busMode.B.DA = 0; /* 0 = weighted round-robin, 1 = fixed priority */
430 
431  ETH_BUS_MODE.U = busMode.U;
432  }
433 
434  /* configure ETH MAC */
435  {
436  Ifx_ETH_MAC_CONFIGURATION ethMacCfg;
437  ethMacCfg.U = ETH_MAC_CONFIGURATION.U;
438 
439  ethMacCfg.B.PRELEN = 0; /* 7 bytes preamble */
440  // ethMacCfg.B.RE = 0; /* disable receiver */
441  // ethMacCfg.B.TE = 0; /* disable transmitter */
442  ethMacCfg.B.DC = 0; /* Deferral Check */
443  // ethMacCfg.B.BL = 0; /* Backoff Limit */
444  ethMacCfg.B.ACS = 1; /* Automatic Pad/CRC stripping--less than 1536 bytes */
445  // ethMacCfg.B.DR = 0; /* Disable Retry */
446  ethMacCfg.B.IPC = 0; /* checksum offload */
447  ethMacCfg.B.DM = 1; /* Duplex Mode: 0=Half Duplex, 1=Full duplex */
448  ethMacCfg.B.LM = 0; /* Loopback Mode */
449  // ethMacCfg.B.DO = 0; /* Disable Receive Own */
450  ethMacCfg.B.FES = 1; /* Speed 0->10mbps 1->100mbps */
451  ethMacCfg.B.PS = 1; /* port select 10/100mbps */
452  ethMacCfg.B.IFG = 0; /* Inter Frame Gap - gap between frames = 96 bit times */
453  ethMacCfg.B.JE = 0; /* Jumbo Frame Enable - no jumbo frames */
454  ethMacCfg.B.JD = 0; /* Jabber Disable - cut of transmission after 2,048 data bytes. */
455  ethMacCfg.B.WD = 0; /* Watchdog Disable - cut off frame after 2,048 bytes. */
456  ethMacCfg.B.CST = 1; /* CRC stripping - last four bytes are stripped and dropped to application. */
457  ethMacCfg.B.TWOKPE = 0; /* 2K Packets Enable - with JE=0 - all received frames of size > 1,518bytes are Giant frames.*/
458 
459  ETH_MAC_CONFIGURATION.U = ethMacCfg.U;
460  }
461 
462  IfxEth_setMacAddress(eth, config->macAddress);
463 
464  // setup MMC
465  ETH_MMC_CONTROL.B.CNTFREEZ = 1; // disable MMC counters - counters reset
466 
467  // setup GMAC
468  ETH_STATUS.U = 0x0001e7ff; // reset all interrupt flag(s)
469  ETH_MAC_FRAME_FILTER.U = 0x00000010; // Hash Unicast
470 
471  ETH_INTERRUPT_ENABLE.U = 0x00010041; // enable tx & rx interrupts
472 
473 #ifndef _WIN32
474 
475  if (config->isrPriority)
476  {
477  IfxSrc_init(&SRC_ETH, config->isrProvider, config->isrPriority);
478  IfxSrc_enable(&SRC_ETH);
479  }
480 
481  if (config->phyInit != NULL_PTR)
482  {
483  config->phyInit(); // init PHY (100Mbit, full duplex with RMII)
484  }
485 
486 #endif
487 
488  //eth->module = &MODULE_ETH;
489  eth->config = *config;
490  eth->error = 0;
491  eth->status.U = 0;
492  eth->rxCount = 0;
493  eth->txCount = 0;
494 
496 
499 
500  IfxEth_initReceiveDescriptors(eth);
501  IfxEth_initTransmitDescriptors(eth);
502 
503  //IfxEth_startTransmitter(eth);
504 }
505 
506 
508 {
509  void *buffer = NULL_PTR;
511 
512  // check descriptor / buffer is free.
513  if (descr->TDES0.A.OWN == 0)
514  {
515  buffer = ((void *)descr->TDES2.U);
516  }
517 
518  return buffer;
519 }
520 
521 
523 {
524  void *result = 0;
525  IfxEth_RxDescr *descr;
526 
527  if (IfxEth_isRxDataAvailable(eth))
528  {
529  eth->rxCount++;
530  descr = IfxEth_getActualRxDescriptor(eth);
531  result = (void *)(descr->RDES2.U);
532  }
533 
535 
536  return result;
537 }
538 
539 
541 {
543  IfxEth_RxDescr_release(descr);
545 }
546 
547 
549 {
550  {
552  IfxScuWdt_clearCpuEndinit(l_TempVar);
553  ETH_CLC.U = 0;
554  IfxScuWdt_setCpuEndinit(l_TempVar);
555  }
556 }