iLLD_TC27xD  1.0
IfxPsi5s_Psi5s.c
Go to the documentation of this file.
1 /**
2  * \file IfxPsi5s_Psi5s.c
3  * \brief PSI5S PSI5S details
4  *
5  * \version iLLD_1_0_0_11_0
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 "IfxPsi5s_Psi5s.h"
30 
31 /** \addtogroup IfxLld_Psi5s_Psi5s_Utility
32  * \{ */
33 
34 /******************************************************************************/
35 /*-----------------------Private Function Prototypes--------------------------*/
36 /******************************************************************************/
37 
38 /** \brief Enable PSI5S kernel
39  * \param psi5s pointer to the base of PSI5S register space
40  * \return None
41  */
42 static void IfxPsi5s_Psi5s_enableModule(Ifx_PSI5S *psi5s);
43 
44 /** \brief get the fracDiv clock frequency
45  * \param psi5s Pointer to the base of PSI5S register space
46  * \return Returns the configured fracDiv psi5s clock frequency in Hz.
47  */
48 static uint32 IfxPsi5s_Psi5s_getFracDivClock(Ifx_PSI5S *psi5s);
49 
50 /** \brief Configure the fracDiv clock.
51  * \param psi5s Pointer to the base of PSI5S register space
52  * \param clock Specifies the required clock frequency in Hz.
53  * \return Returns the configured clock frequency in Hz.
54  */
55 static uint32 IfxPsi5s_Psi5s_initializeClock(Ifx_PSI5S *psi5s, const IfxPsi5s_Psi5s_Clock *clock);
56 
57 /** \brief Reset PSI5S kernel
58  * \param psi5s pointer to the base of PSI5S registers
59  * \return None
60  */
61 static void IfxPsi5s_Psi5s_resetModule(Ifx_PSI5S *psi5s);
62 
63 /** \brief Configure the baudrate at the ASC interface.
64  * \param psi5s Pointer to the base of PSI5S register space
65  * \param baudrate Frequency Specifies the required baudrate frequency in Hz.
66  * \param ascConfig pointer to the configuration structure for ASC
67  * \return Returns the configured baudrate frequency in Hz.
68  */
69 static uint32 IfxPsi5s_Psi5s_setBaudrate(Ifx_PSI5S *psi5s, uint32 baudrate, IfxPsi5s_Psi5s_AscConfig *ascConfig);
70 
71 /** \} */
72 
73 /******************************************************************************/
74 /*-------------------------Function Implementations---------------------------*/
75 /******************************************************************************/
76 
78 {
79  Ifx_PSI5S *psi5sSFR = psi5s->psi5s;
80  IfxPsi5s_Psi5s_resetModule(psi5sSFR);
81 }
82 
83 
84 static void IfxPsi5s_Psi5s_enableModule(Ifx_PSI5S *psi5s)
85 {
86  psi5s->CLC.U = 0x00000000;
87 }
88 
89 
90 static uint32 IfxPsi5s_Psi5s_getFracDivClock(Ifx_PSI5S *psi5s)
91 {
92  uint32 result;
94 
95  switch (psi5s->FDR.B.DM)
96  {
98  result = fPsi5s;
99  break;
101  result = fPsi5s / (IFXPSI5S_STEP_RANGE - psi5s->FDR.B.STEP);
102  break;
104  result = (fPsi5s * IFXPSI5S_STEP_RANGE) / psi5s->FDR.B.STEP;
105  break;
107  result = 0;
108  break;
109  default:
110  result = 0;
111  }
112 
113  return result;
114 }
115 
116 
118 {
119  boolean status = TRUE;
120 
123 
124  Ifx_PSI5S *psi5s = config->module->psi5s;
125  channel->module = (IfxPsi5s_Psi5s *)config->module;
126  channel->channelId = config->channelId;
127 
128  Ifx_PSI5S_PGC tempPGC;
129  tempPGC.U = psi5s->PGC[config->channelId].U;
130  tempPGC.B.TXCMD = config->pulseGeneration.codeforZero;
131  tempPGC.B.ATXCMD = config->pulseGeneration.codeforOne;
132  tempPGC.B.TBS = config->pulseGeneration.timeBaseSelect;
133  tempPGC.B.ETB = config->pulseGeneration.externalTimeBaseSelect;
134  tempPGC.B.ETS = config->pulseGeneration.externalTriggerSelect;
135 
136  switch (config->pulseGeneration.periodicOrExternal)
137  {
139  tempPGC.B.PTE = TRUE;
140  tempPGC.B.ETE = FALSE;
141  break;
142 
144  tempPGC.B.PTE = FALSE;
145  tempPGC.B.ETE = TRUE;
146  break;
147  }
148 
149  psi5s->PGC[config->channelId].U = tempPGC.U;
150 
151  Ifx_PSI5S_CTV tempCTV;
152  tempCTV.U = psi5s->CTV[config->channelId].U;
153  tempCTV.B.CTV = config->channelTrigger.channelTriggerValue;
154  tempCTV.B.CTC = config->channelTrigger.channelTriggerCounter;
155  psi5s->CTV[config->channelId].U = tempCTV.U;
156 
157  psi5s->WDT[config->channelId].U = config->watchdogTimerLimit;
158 
159  Ifx_PSI5S_RCRA tempRCRA;
160  tempRCRA.U = psi5s->RCRA[config->channelId].U;
161  tempRCRA.B.CRC0 = config->receiveControl.crcOrParity[0];
162  tempRCRA.B.CRC1 = config->receiveControl.crcOrParity[1];
163  tempRCRA.B.CRC2 = config->receiveControl.crcOrParity[2];
164  tempRCRA.B.CRC3 = config->receiveControl.crcOrParity[3];
165  tempRCRA.B.CRC4 = config->receiveControl.crcOrParity[4];
166  tempRCRA.B.CRC5 = config->receiveControl.crcOrParity[5];
167  tempRCRA.B.TSEN = config->receiveControl.timestampEnabled;
168  tempRCRA.B.TSP = config->receiveControl.timestampSelect;
169  tempRCRA.B.TSTS = config->receiveControl.timestampTriggerSelect;
170  tempRCRA.B.FIDS = config->receiveControl.frameIdSelect;
171  tempRCRA.B.WDMS = config->receiveControl.watchdogTimerModeSelect;
172  tempRCRA.B.UFC0 = config->receiveControl.uartFrameCount[0];
173  tempRCRA.B.UFC1 = config->receiveControl.uartFrameCount[1];
174  tempRCRA.B.UFC2 = config->receiveControl.uartFrameCount[2];
175  tempRCRA.B.UFC3 = config->receiveControl.uartFrameCount[3];
176  tempRCRA.B.UFC4 = config->receiveControl.uartFrameCount[4];
177  tempRCRA.B.UFC5 = config->receiveControl.uartFrameCount[5];
178  psi5s->RCRA[config->channelId].U = tempRCRA.U;
179 
180  Ifx_PSI5S_RCRB tempRCRB;
181  tempRCRB.U = psi5s->RCRB[config->channelId].U;
182  tempRCRB.B.PDL0 = config->receiveControl.payloadLength[0];
183  tempRCRB.B.PDL1 = config->receiveControl.payloadLength[1];
184  tempRCRB.B.PDL2 = config->receiveControl.payloadLength[2];
185  tempRCRB.B.PDL3 = config->receiveControl.payloadLength[3];
186  tempRCRB.B.PDL4 = config->receiveControl.payloadLength[4];
187  tempRCRB.B.PDL5 = config->receiveControl.payloadLength[5];
188  psi5s->RCRB[config->channelId].U = tempRCRB.U;
189 
190  psi5s->NFC.U = (config->receiveControl.numberOfFramesExpected << (config->channelId * 3));
191 
192  Ifx_PSI5S_SCR tempSCR;
193  tempSCR.U = psi5s->SCR[config->channelId].U;
194  tempSCR.B.PLL = config->sendControl.payloadLength;
195  tempSCR.B.EPS = config->sendControl.enhancedProtocolSelection;
196  tempSCR.B.BSC = config->sendControl.bitStuffControl;
197  tempSCR.B.CRC = config->sendControl.crcGenerationControl;
198  tempSCR.B.STA = config->sendControl.startSequenceGenerationControl;
199  psi5s->SCR[config->channelId].U = tempSCR.U;
200 
201  IfxScuWdt_setCpuEndinit(passwd);
202 
203  return status;
204 }
205 
206 
208 {
209  IfxPsi5s_Psi5s_ChannelConfig IfxPsi5s_Psi5s_defaultChannelConfig = {
211  .module = NULL_PTR,
212  .pulseGeneration = {
213  .codeforZero = 0,
214  .codeforOne = 1,
215  .timeBaseSelect = IfxPsi5s_TimeBase_internal,
216  .externalTimeBaseSelect = IfxPsi5s_Trigger_0,
217  .periodicOrExternal = IfxPsi5s_TriggerType_periodic,
218  .externalTriggerSelect = IfxPsi5s_Trigger_0,
219  },
220  .channelTrigger = {
221  .channelTriggerValue = 0x20,
222  .channelTriggerCounter = 0x0
223  },
224  .watchdogTimerLimit = 0x0,
225  .receiveControl = {
226  .crcOrParity[0] = IfxPsi5s_CrcOrParity_parity,
227  .crcOrParity[1] = IfxPsi5s_CrcOrParity_parity,
228  .crcOrParity[2] = IfxPsi5s_CrcOrParity_parity,
229  .crcOrParity[3] = IfxPsi5s_CrcOrParity_parity,
230  .crcOrParity[4] = IfxPsi5s_CrcOrParity_parity,
231  .crcOrParity[5] = IfxPsi5s_CrcOrParity_parity,
232  .timestampEnabled = FALSE,
233  .timestampSelect = IfxPsi5s_TimestampRegister_a,
234  .timestampTriggerSelect = IfxPsi5s_TimestampTrigger_syncPulse,
235  .frameIdSelect = IfxPsi5s_FrameId_frameHeader,
236  .watchdogTimerModeSelect = IfxPsi5s_WatchdogTimerMode_frame,
237  .uartFrameCount[0] = IfxPsi5s_UartFrameCount_3,
238  .uartFrameCount[1] = IfxPsi5s_UartFrameCount_3,
239  .uartFrameCount[2] = IfxPsi5s_UartFrameCount_3,
240  .uartFrameCount[3] = IfxPsi5s_UartFrameCount_3,
241  .uartFrameCount[4] = IfxPsi5s_UartFrameCount_3,
242  .uartFrameCount[5] = IfxPsi5s_UartFrameCount_3,
243  .payloadLength[0] = 0,
244  .payloadLength[1] = 0,
245  .payloadLength[2] = 0,
246  .payloadLength[3] = 0,
247  .payloadLength[4] = 0,
248  .payloadLength[5] = 0,
249  .numberOfFramesExpected = IfxPsi5s_NumberExpectedFrames_1,
250  },
251  .sendControl = {
252  .payloadLength = 6,
253  .enhancedProtocolSelection = IfxPsi5s_EnhancedProtocol_toothGapMethod,
254  .bitStuffControl = FALSE,
255  .crcGenerationControl = FALSE,
256  .startSequenceGenerationControl = FALSE
257  }
258  };
259  *config = IfxPsi5s_Psi5s_defaultChannelConfig;
260  config->module = psi5s;
261 }
262 
263 
265 {
266  boolean status = TRUE;
267 
268  Ifx_PSI5S *psi5sSFR = config->module;
269  psi5s->psi5s = psi5sSFR;
270 
273  IfxPsi5s_Psi5s_enableModule(psi5sSFR);
274 
275  if (IfxPsi5s_Psi5s_initializeClock(psi5sSFR, &config->fracDiv) == 0)
276  {
277  status = FALSE;
278  return status;
279  }
280  else
281  {}
282 
283  if (IfxPsi5s_Psi5s_initializeClock(psi5sSFR, &config->timestampClock) == 0)
284  {
285  status = FALSE;
286  return status;
287  }
288  else
289  {}
290 
291  Ifx_PSI5S_CON tempCON;
292  tempCON.U = psi5sSFR->CON.U;
293  tempCON.B.M = config->ascConfig.receiveMode;
294  tempCON.B.STP = config->ascConfig.stopBits;
295  tempCON.B.PEN = config->ascConfig.parityCheckEnabled;
296  tempCON.B.FEN = config->ascConfig.framingCheckEnabled;
297  tempCON.B.OEN = config->ascConfig.overrunCheckEnabled;
298  tempCON.B.FDE = config->ascConfig.fractionalDividerEnabled;
299  tempCON.B.ODD = config->ascConfig.receiverOddParityEnabled;
300  tempCON.B.BRS = config->ascConfig.baudrateSelection;
301  tempCON.B.LB = config->ascConfig.loopbackEnabled;
302  tempCON.B.MTX = config->ascConfig.transmitMode;
303  tempCON.B.ODDTX = config->ascConfig.transmitterOddParityEnabled;
304  psi5sSFR->CON.U = tempCON.U;
305 
306  if (IfxPsi5s_Psi5s_setBaudrate(psi5sSFR, config->ascConfig.baudrateFrequency, (IfxPsi5s_Psi5s_AscConfig *)&(config->ascConfig))
307  == 0)
308  {
309  status = FALSE;
310  return status;
311  }
312  else
313  {}
314 
315  if (IfxPsi5s_Psi5s_initializeClock(psi5sSFR, &config->ascConfig.clockOutput) == 0)
316  {
317  status = FALSE;
318  return status;
319  }
320  else
321  {}
322 
323  Ifx_PSI5S_TSCNTA tempTSCNTA;
324  tempTSCNTA.U = psi5sSFR->TSCNTA.U;
325  tempTSCNTA.B.ETB = config->timestampCounterA.externalTimeBaseSelect;
326  tempTSCNTA.B.TBS = config->timestampCounterA.timeBaseSelect;
327  psi5sSFR->TSCNTA.U = tempTSCNTA.U;
328 
329  Ifx_PSI5S_TSCNTB tempTSCNTB;
330  tempTSCNTB.U = psi5sSFR->TSCNTB.U;
331  tempTSCNTB.B.ETB = config->timestampCounterB.externalTimeBaseSelect;
332  tempTSCNTB.B.TBS = config->timestampCounterB.timeBaseSelect;
333  psi5sSFR->TSCNTB.U = tempTSCNTB.U;
334 
335  Ifx_PSI5S_GCR tempGCR;
336  tempGCR.U = psi5sSFR->GCR.U;
337  tempGCR.B.CRCI = config->globalControlConfig.crcErrorConsideredForRSI;
338  tempGCR.B.XCRCI = config->globalControlConfig.xcrcErrorConsideredForRSI;
339  tempGCR.B.TEI = config->globalControlConfig.transmitErrorConsideredForRSI;
340  tempGCR.B.PE = config->globalControlConfig.parityErrorConsideredForRSI;
341  tempGCR.B.FE = config->globalControlConfig.framingErrorConsideredForRSI;
342  tempGCR.B.OE = config->globalControlConfig.overrunErrorConsideredForRSI;
344  tempGCR.B.HDI = config->globalControlConfig.headerErrorConsideredForRSI;
345  tempGCR.B.IDT = config->globalControlConfig.idleTime;
346  tempGCR.B.ASC = config->globalControlConfig.ascOnlyMode;
347  psi5sSFR->GCR.U = tempGCR.U;
348 
349  IfxScuWdt_setCpuEndinit(passwd);
350 
351  // Pin mapping //
352  const IfxPsi5s_Psi5s_Pins *pins = config->pins;
353 
354  if (pins != NULL_PTR)
355  {
356  const IfxPsi5s_Rx_In *rx = pins->rx;
357 
358  if (rx != NULL_PTR)
359  {
360  IfxPsi5s_initRxPin(rx, pins->rxMode);
361  }
362 
363  const IfxPsi5s_Tx_Out *tx = pins->tx;
364 
365  if (tx != NULL_PTR)
366  {
367  IfxPsi5s_initTxPin(tx, pins->txMode, pins->pinDriver);
368  }
369 
370  const IfxPsi5s_Clk_Out *clk = pins->clk;
371 
372  if (clk != NULL_PTR)
373  {
374  IfxPsi5s_initClkPin(clk, pins->clkMode, pins->pinDriver);
375  }
376  }
377 
378  return status;
379 }
380 
381 
383 {
384  uint32 spbFrequency = IfxScuCcu_getSpbFrequency();
385  config->module = psi5s;
386  config->fracDiv.frequency = spbFrequency;
389  config->timestampClock.frequency = spbFrequency;
397  config->ascConfig.clockOutput.frequency = spbFrequency;
408  config->ascConfig.loopbackEnabled = FALSE;
421  config->pins = NULL_PTR;
422 }
423 
424 
425 static uint32 IfxPsi5s_Psi5s_initializeClock(Ifx_PSI5S *psi5s, const IfxPsi5s_Psi5s_Clock *clock)
426 {
427  uint64 step = 0;
428  uint32 stepRange = IFXPSI5S_STEP_RANGE;
429  uint32 result = 0;
430  IfxPsi5s_DividerMode divMode = clock->mode;
431  IfxPsi5s_ClockType clockType = clock->type;
432  uint32 clockFrequency = clock->frequency;
433  uint32 fInput;
434  Ifx_PSI5S_FDR tempFDR;
435  Ifx_PSI5S_FDRT tempFDRT;
436  Ifx_PSI5S_FDO tempFDO;
437 
438  if (clockType == IfxPsi5s_ClockType_fracDiv)
439  {
440  fInput = IfxScuCcu_getSpbFrequency();
441  }
442  else if (clockType == IfxPsi5s_ClockType_ascOutput)
443  {
444  fInput = IfxScuCcu_getSpbFrequency(); // assumption here is that fBaud2 is equal to fSPB
445  stepRange = 2 * IFXPSI5S_STEP_RANGE;
446  }
447  else
448  {
449  fInput = IfxPsi5s_Psi5s_getFracDivClock(psi5s);
450 
451  if (fInput == 0)
452  {
453  result = 0;
454  return result;
455  }
456  else
457  {}
458  }
459 
460  switch (divMode)
461  {
463  step = stepRange - (fInput / clockFrequency);
464 
465  if (step > (stepRange - 1))
466  {
467  step = stepRange - 1;
468  }
469  else
470  {
471  /* do nothing */
472  }
473 
474  result = (uint32)(fInput / (stepRange - step));
475  break;
476 
478  step = (uint64)((uint64)clockFrequency * stepRange) / fInput;
479 
480  if (step > (stepRange - 1))
481  {
482  step = stepRange - 1;
483  }
484  else
485  {
486  /* do nothing */
487  }
488 
489  result = (uint32)((uint64)((uint64)fInput * step)) / stepRange;
490  break;
491 
493  default:
494  step = 0;
495  result = 0;
496  break;
497  }
498 
499  if (result != 0)
500  {
501  switch (clockType)
502  {
504  tempFDR.U = 0;
505  tempFDR.B.DM = divMode;
506  tempFDR.B.STEP = (uint32)step;
507  psi5s->FDR.U = tempFDR.U;
508  break;
509 
511  tempFDRT.U = 0;
512  tempFDRT.B.DM = divMode;
513  tempFDRT.B.STEP = (uint32)step;
514  psi5s->FDRT.U = tempFDRT.U;
515  break;
516 
518  tempFDO.U = 0;
519  tempFDO.B.DM = divMode;
520  tempFDO.B.STEP = (uint32)step;
521  psi5s->FDO.U = tempFDO.U;
522  break;
523  default:
524  break;
525  }
526  }
527 
528  return result;
529 }
530 
531 
533 {
534  frame->data.rdr = channel->module->psi5s->RDR.U;
535  frame->status.rds = channel->module->psi5s->RDS.U;
536  frame->timestamp.tsm = channel->module->psi5s->TSM.U;
537 
538  channel->module->psi5s->INTCLR[channel->channelId].U |= (IFX_PSI5S_INTCLR_RDI_MSK << IFX_PSI5S_INTCLR_RDI_OFF) | (IFX_PSI5S_INTCLR_RSI_MSK << IFX_PSI5S_INTCLR_RSI_OFF);
539 }
540 
541 
542 static void IfxPsi5s_Psi5s_resetModule(Ifx_PSI5S *psi5s)
543 {
546  psi5s->KRST1.B.RST = 1; /* Only if both Kernel reset bits are set a reset is executed */
547  psi5s->KRST0.B.RST = 1;
548 
549  while (psi5s->KRST0.B.RSTSTAT == 0)
550  {
551  /* Wait until reset is executed */
552  }
553 
554  psi5s->KRSTCLR.B.CLR = 1; /* Clear Kernel reset status bit */
556 }
557 
558 
560 {
561  channel->module->psi5s->SDR[channel->channelId].U = data & 0x00FFFFFF;
562 
563  if (channel->module->psi5s->INTSTAT[channel->channelId].B.TPOI)
564  {
565  return FALSE;
566  }
567  else
568  {
569  return TRUE;
570  }
571 }
572 
573 
574 static uint32 IfxPsi5s_Psi5s_setBaudrate(Ifx_PSI5S *psi5s, uint32 baudrate, IfxPsi5s_Psi5s_AscConfig *ascConfig)
575 {
576  uint32 bgValue = 0;
577  uint32 fdValue = 0;
578  uint32 result = 0;
579  uint32 fInput;
580 
581  if (ascConfig->receiveMode == IfxPsi5s_AscMode_sync)
582  {
583  if (ascConfig->transmitMode != IfxPsi5s_AscMode_sync)
584  {
585  // sync modes must be set for both receive and transmit
586  }
587 
588  fInput = IfxScuCcu_getBaud2Frequency();
589  bgValue = (uint32)(fInput / ((ascConfig->baudrateSelection + 2) * 4 * (uint64)baudrate) - 1);
590 
591  if (bgValue > (IFXPSI5S_BG_RANGE - 1))
592  {
593  bgValue = IFXPSI5S_BG_RANGE - 1;
594  }
595  else
596  {
597  /* do nothing */
598  }
599 
600  result = fInput / ((ascConfig->baudrateSelection + 2) * 4 * (bgValue + 1));
601  }
602  else if (ascConfig->fractionalDividerEnabled == FALSE)
603  {
604  fInput = IfxScuCcu_getBaud2Frequency();
605  bgValue = (uint32)(fInput / ((ascConfig->baudrateSelection + 2) * 16 * (uint64)baudrate) - 1);
606 
607  if (bgValue > (IFXPSI5S_BG_RANGE - 1))
608  {
609  bgValue = IFXPSI5S_BG_RANGE - 1;
610  }
611  else
612  {
613  /* do nothing */
614  }
615 
616  result = fInput / ((ascConfig->baudrateSelection + 2) * 16 * (bgValue + 1));
617  }
618  else
619  {
620  fInput = IfxScuCcu_getBaud2Frequency();
621  fdValue = (((uint64)baudrate * IFXPSI5S_FDV_RANGE * 16)) / (float)fInput;
622 
623  if (fdValue > (IFXPSI5S_FDV_RANGE - 1))
624  {
625  fdValue = IFXPSI5S_FDV_RANGE - 1;
626  bgValue = ((float)fdValue / IFXPSI5S_FDV_RANGE) * (fInput / (16 * baudrate)) - 1;
627 
628  if (bgValue > (IFXPSI5S_BG_RANGE - 1))
629  {
630  bgValue = IFXPSI5S_BG_RANGE - 1;
631  }
632  else
633  {
634  /* do nothing */
635  }
636  }
637  else
638  {
639  bgValue = 0;
640  }
641 
642  result = ((float)fdValue / IFXPSI5S_FDV_RANGE) * (fInput / (16 * (bgValue + 1)));
643  }
644 
645  psi5s->FDV.U = fdValue;
646  psi5s->BG.U = bgValue;
647 
648  return result;
649 }