iLLD_TC27xC  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_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 "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 = 0x00000100;
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.B.TXCMD = config->pulseGeneration.codeforZero;
130  tempPGC.B.ATXCMD = config->pulseGeneration.codeforOne;
131  tempPGC.B.TBS = config->pulseGeneration.timeBaseSelect;
132  tempPGC.B.ETB = config->pulseGeneration.externalTimeBaseSelect;
133  tempPGC.B.ETS = config->pulseGeneration.externalTriggerSelect;
134 
135  switch (config->pulseGeneration.periodicOrExternal)
136  {
138  tempPGC.B.PTE = TRUE;
139  tempPGC.B.ETE = FALSE;
140  break;
141 
143  tempPGC.B.PTE = FALSE;
144  tempPGC.B.ETE = TRUE;
145  break;
146  }
147 
148  psi5s->PGC[config->channelId].U = tempPGC.U;
149 
150  Ifx_PSI5S_CTV tempCTV;
151  tempCTV.B.CTV = config->channelTrigger.channelTriggerValue;
152  tempCTV.B.CTC = config->channelTrigger.channelTriggerCounter;
153  psi5s->CTV[config->channelId].U = tempCTV.U;
154 
155  psi5s->WDT[config->channelId].U = config->watchdogTimerLimit;
156 
157  Ifx_PSI5S_RCRA tempRCRA;
158  tempRCRA.B.CRC0 = config->receiveControl.crcOrParity[0];
159  tempRCRA.B.CRC1 = config->receiveControl.crcOrParity[1];
160  tempRCRA.B.CRC2 = config->receiveControl.crcOrParity[2];
161  tempRCRA.B.CRC3 = config->receiveControl.crcOrParity[3];
162  tempRCRA.B.CRC4 = config->receiveControl.crcOrParity[4];
163  tempRCRA.B.CRC5 = config->receiveControl.crcOrParity[5];
164  tempRCRA.B.TSEN = config->receiveControl.timestampEnabled;
165  tempRCRA.B.TSP = config->receiveControl.timestampSelect;
166  tempRCRA.B.TSTS = config->receiveControl.timestampTriggerSelect;
167  tempRCRA.B.FIDS = config->receiveControl.frameIdSelect;
168  tempRCRA.B.WDMS = config->receiveControl.watchdogTimerModeSelect;
169  tempRCRA.B.UFC0 = config->receiveControl.uartFrameCount[0];
170  tempRCRA.B.UFC1 = config->receiveControl.uartFrameCount[1];
171  tempRCRA.B.UFC2 = config->receiveControl.uartFrameCount[2];
172  tempRCRA.B.UFC3 = config->receiveControl.uartFrameCount[3];
173  tempRCRA.B.UFC4 = config->receiveControl.uartFrameCount[4];
174  tempRCRA.B.UFC5 = config->receiveControl.uartFrameCount[5];
175  psi5s->RCRA[config->channelId].U = tempRCRA.U;
176 
177  Ifx_PSI5S_RCRB tempRCRB;
178  tempRCRB.B.PDL0 = config->receiveControl.payloadLength[0];
179  tempRCRB.B.PDL1 = config->receiveControl.payloadLength[1];
180  tempRCRB.B.PDL2 = config->receiveControl.payloadLength[2];
181  tempRCRB.B.PDL3 = config->receiveControl.payloadLength[3];
182  tempRCRB.B.PDL4 = config->receiveControl.payloadLength[4];
183  tempRCRB.B.PDL5 = config->receiveControl.payloadLength[5];
184  psi5s->RCRB[config->channelId].U = tempRCRB.U;
185 
186  psi5s->NFC.U |= (config->receiveControl.numberOfFramesExpected << (config->channelId * 3));
187 
188  Ifx_PSI5S_SCR tempSCR;
189  tempSCR.B.PLL = config->sendControl.payloadLength;
190  tempSCR.B.EPS = config->sendControl.enhancedProtocolSelection;
191  tempSCR.B.BSC = config->sendControl.bitStuffControl;
192  tempSCR.B.CRC = config->sendControl.crcGenerationControl;
193  tempSCR.B.STA = config->sendControl.startSequenceGenerationControl;
194  psi5s->SCR[config->channelId].U = tempSCR.U;
195 
196  IfxScuWdt_setCpuEndinit(passwd);
197 
198  return status;
199 }
200 
201 
203 {
204  IfxPsi5s_Psi5s_ChannelConfig IfxPsi5s_Psi5s_defaultChannelConfig = {
206  .module = NULL_PTR,
207  .pulseGeneration = {
208  .codeforZero = 0,
209  .codeforOne = 1,
210  .timeBaseSelect = IfxPsi5s_TimeBase_internal,
211  .externalTimeBaseSelect = IfxPsi5s_Trigger_0,
212  .periodicOrExternal = IfxPsi5s_TriggerType_periodic,
213  .externalTriggerSelect = IfxPsi5s_Trigger_0,
214  },
215  .channelTrigger = {
216  .channelTriggerValue = 0x20,
217  .channelTriggerCounter = 0x0
218  },
219  .watchdogTimerLimit = 0x0,
220  .receiveControl = {
221  .crcOrParity[0] = IfxPsi5s_CrcOrParity_parity,
222  .crcOrParity[1] = IfxPsi5s_CrcOrParity_parity,
223  .crcOrParity[2] = IfxPsi5s_CrcOrParity_parity,
224  .crcOrParity[3] = IfxPsi5s_CrcOrParity_parity,
225  .crcOrParity[4] = IfxPsi5s_CrcOrParity_parity,
226  .crcOrParity[5] = IfxPsi5s_CrcOrParity_parity,
227  .timestampEnabled = FALSE,
228  .timestampSelect = IfxPsi5s_TimestampRegister_a,
229  .timestampTriggerSelect = IfxPsi5s_TimestampTrigger_syncPulse,
230  .frameIdSelect = IfxPsi5s_FrameId_frameHeader,
231  .watchdogTimerModeSelect = IfxPsi5s_WatchdogTimerMode_frame,
232  .uartFrameCount[0] = IfxPsi5s_UartFrameCount_3,
233  .uartFrameCount[1] = IfxPsi5s_UartFrameCount_3,
234  .uartFrameCount[2] = IfxPsi5s_UartFrameCount_3,
235  .uartFrameCount[3] = IfxPsi5s_UartFrameCount_3,
236  .uartFrameCount[4] = IfxPsi5s_UartFrameCount_3,
237  .uartFrameCount[5] = IfxPsi5s_UartFrameCount_3,
238  .payloadLength[0] = 0,
239  .payloadLength[1] = 0,
240  .payloadLength[2] = 0,
241  .payloadLength[3] = 0,
242  .payloadLength[4] = 0,
243  .payloadLength[5] = 0,
244  .numberOfFramesExpected = IfxPsi5s_NumberExpectedFrames_1,
245  },
246  .sendControl = {
247  .payloadLength = 6,
248  .enhancedProtocolSelection = IfxPsi5s_EnhancedProtocol_toothGapMethod,
249  .bitStuffControl = FALSE,
250  .crcGenerationControl = FALSE,
251  .startSequenceGenerationControl = FALSE
252  }
253  };
254  *config = IfxPsi5s_Psi5s_defaultChannelConfig;
255  config->module = psi5s;
256 }
257 
258 
260 {
261  boolean status = TRUE;
262 
263  Ifx_PSI5S *psi5sSFR = config->module;
264  psi5s->psi5s = psi5sSFR;
265 
268  IfxPsi5s_Psi5s_enableModule(psi5sSFR);
269 
270  if (IfxPsi5s_Psi5s_initializeClock(psi5sSFR, &config->fracDiv) == 0)
271  {
272  status = FALSE;
273  return status;
274  }
275  else
276  {}
277 
278  if (IfxPsi5s_Psi5s_initializeClock(psi5sSFR, &config->timestampClock) == 0)
279  {
280  status = FALSE;
281  return status;
282  }
283  else
284  {}
285 
286  Ifx_PSI5S_CON tempCON;
287  tempCON.B.M = config->ascConfig.receiveMode;
288  tempCON.B.STP = config->ascConfig.stopBits;
289  tempCON.B.PEN = config->ascConfig.parityCheckEnabled;
290  tempCON.B.FEN = config->ascConfig.framingCheckEnabled;
291  tempCON.B.OEN = config->ascConfig.overrunCheckEnabled;
292  tempCON.B.FDE = config->ascConfig.fractionalDividerEnabled;
293  tempCON.B.ODD = config->ascConfig.receiverOddParityEnabled;
294  tempCON.B.BRS = config->ascConfig.baudrateSelection;
295  tempCON.B.LB = config->ascConfig.loopbackEnabled;
296  tempCON.B.MTX = config->ascConfig.transmitMode;
297  tempCON.B.ODDTX = config->ascConfig.transmitterOddParityEnabled;
298  psi5sSFR->CON.U = tempCON.U;
299 
300  if (IfxPsi5s_Psi5s_setBaudrate(psi5sSFR, config->ascConfig.baudrateFrequency, (IfxPsi5s_Psi5s_AscConfig *)&(config->ascConfig))
301  == 0)
302  {
303  status = FALSE;
304  return status;
305  }
306  else
307  {}
308 
309  if (IfxPsi5s_Psi5s_initializeClock(psi5sSFR, &config->ascConfig.clockOutput) == 0)
310  {
311  status = FALSE;
312  return status;
313  }
314  else
315  {}
316 
317  Ifx_PSI5S_TSCNTA tempTSCNTA;
318  tempTSCNTA.B.ETB = config->timestampCounterA.externalTimeBaseSelect;
319  tempTSCNTA.B.TBS = config->timestampCounterA.timeBaseSelect;
320  psi5sSFR->TSCNTA.U = tempTSCNTA.U;
321 
322  Ifx_PSI5S_TSCNTB tempTSCNTB;
323  tempTSCNTB.B.ETB = config->timestampCounterB.externalTimeBaseSelect;
324  tempTSCNTB.B.TBS = config->timestampCounterB.timeBaseSelect;
325  psi5sSFR->TSCNTB.U = tempTSCNTB.U;
326 
327  Ifx_PSI5S_GCR tempGCR;
328  tempGCR.B.CRCI = config->globalControlConfig.crcErrorConsideredForRSI;
329  tempGCR.B.XCRCI = config->globalControlConfig.xcrcErrorConsideredForRSI;
330  tempGCR.B.TEI = config->globalControlConfig.transmitErrorConsideredForRSI;
331  tempGCR.B.PE = config->globalControlConfig.parityErrorConsideredForRSI;
332  tempGCR.B.FE = config->globalControlConfig.framingErrorConsideredForRSI;
333  tempGCR.B.OE = config->globalControlConfig.overrunErrorConsideredForRSI;
335  tempGCR.B.HDI = config->globalControlConfig.headerErrorConsideredForRSI;
336  tempGCR.B.IDT = config->globalControlConfig.idleTime;
337  tempGCR.B.ASC = config->globalControlConfig.ascOnlyMode;
338  psi5sSFR->GCR.U = tempGCR.U;
339 
340  IfxScuWdt_setCpuEndinit(passwd);
341 
342  // Pin mapping //
343  const IfxPsi5s_Psi5s_Pins *pins = config->pins;
344 
345  if (pins != NULL_PTR)
346  {
347  const IfxPsi5s_Rx_In *rx = pins->rx;
348 
349  if (rx != NULL_PTR)
350  {
351  IfxPsi5s_initRxPin(rx, pins->rxMode);
352  }
353 
354  const IfxPsi5s_Tx_Out *tx = pins->tx;
355 
356  if (tx != NULL_PTR)
357  {
358  IfxPsi5s_initTxPin(tx, pins->txMode, pins->pinDriver);
359  }
360 
361  const IfxPsi5s_Sclk_Out *sclk = pins->sclk;
362 
363  if (sclk != NULL_PTR)
364  {
365  IfxPsi5s_initSclkPin(sclk, pins->sclkMode, pins->pinDriver);
366  }
367  }
368 
369  return status;
370 }
371 
372 
374 {
375  uint32 spbFrequency = IfxScuCcu_getSpbFrequency();
376  config->module = psi5s;
377  config->fracDiv.frequency = spbFrequency;
380  config->timestampClock.frequency = spbFrequency;
388  config->ascConfig.clockOutput.frequency = spbFrequency;
399  config->ascConfig.loopbackEnabled = FALSE;
412  config->pins = NULL_PTR;
413 }
414 
415 
416 static uint32 IfxPsi5s_Psi5s_initializeClock(Ifx_PSI5S *psi5s, const IfxPsi5s_Psi5s_Clock *clock)
417 {
418  uint32 step = 0;
419  uint32 stepRange = IFXPSI5S_STEP_RANGE;
420  uint32 result = 0;
421  IfxPsi5s_DividerMode divMode = clock->mode;
422  IfxPsi5s_ClockType clockType = clock->type;
423  uint32 clockFrequency = clock->frequency;
424  uint32 fInput;
425  Ifx_PSI5S_FDR tempFDR;
426  Ifx_PSI5S_FDRT tempFDRT;
427  Ifx_PSI5S_FDO tempFDO;
428 
429  if (clockType == IfxPsi5s_ClockType_fracDiv)
430  {
431  fInput = IfxScuCcu_getSpbFrequency();
432  }
433  else if (clockType == IfxPsi5s_ClockType_ascOutput)
434  {
435  fInput = IfxScuCcu_getSpbFrequency(); // assumption here is that fBaud2 is equal to fSPB
436  stepRange = 2 * IFXPSI5S_STEP_RANGE;
437  }
438  else
439  {
440  fInput = IfxPsi5s_Psi5s_getFracDivClock(psi5s);
441 
442  if (fInput == 0)
443  {
444  result = 0;
445  return result;
446  }
447  else
448  {}
449  }
450 
451  switch (divMode)
452  {
454  step = stepRange - (fInput / clockFrequency);
455 
456  if (step > (stepRange - 1))
457  {
458  step = stepRange - 1;
459  }
460  else
461  {
462  /* do nothing */
463  }
464 
465  result = fInput / (stepRange - step);
466  break;
467 
469  step = (clockFrequency * stepRange) / fInput;
470 
471  if (step > (stepRange - 1))
472  {
473  step = stepRange - 1;
474  }
475  else
476  {
477  /* do nothing */
478  }
479 
480  result = (fInput * step) / stepRange;
481  break;
482 
484  default:
485  step = 0;
486  result = 0;
487  break;
488  }
489 
490  if (result != 0)
491  {
492  switch (clockType)
493  {
495  tempFDR.B.DM = divMode;
496  tempFDR.B.STEP = step;
497  psi5s->FDR.U = tempFDR.U;
498  break;
499 
501  tempFDRT.B.DM = divMode;
502  tempFDRT.B.STEP = step;
503  psi5s->FDRT.U = tempFDRT.U;
504  break;
505 
507  tempFDO.B.DM = divMode;
508  tempFDO.B.STEP = step;
509  psi5s->FDO.U = tempFDO.U;
510  break;
511  }
512  }
513 
514  return result;
515 }
516 
517 
519 {
520  if (channel->module->psi5s->INTSTAT[channel->channelId].B.RDI == TRUE)
521  {
522  frame->data.rdr = channel->module->psi5s->RDR.U;
523  frame->status.rds = channel->module->psi5s->RDS.U;
524  frame->timestamp.tsm = channel->module->psi5s->TSM.U;
525 
526  channel->module->psi5s->INTCLR[channel->channelId].U = IFX_PSI5S_INTCLR_RDI_MSK << IFX_PSI5S_INTCLR_RDI_OFF;
527 
528  return TRUE;
529  }
530  else
531  {
532  return FALSE;
533  }
534 }
535 
536 
537 static void IfxPsi5s_Psi5s_resetModule(Ifx_PSI5S *psi5s)
538 {
541  psi5s->KRST1.B.RST = 1; /* Only if both Kernel reset bits are set a reset is executed */
542  psi5s->KRST0.B.RST = 1;
543 
544  while (psi5s->KRST0.B.RSTSTAT == 0)
545  {
546  /* Wait until reset is executed */
547  }
548 
549  psi5s->KRSTCLR.B.CLR = 1; /* Clear Kernel reset status bit */
551 }
552 
553 
555 {
556  channel->module->psi5s->SDR[channel->channelId].U = data & 0x00FFFFFF;
557 
558  if (channel->module->psi5s->INTSTAT[channel->channelId].B.TPOI)
559  {
560  return FALSE;
561  }
562  else
563  {
564  return TRUE;
565  }
566 }
567 
568 
569 static uint32 IfxPsi5s_Psi5s_setBaudrate(Ifx_PSI5S *psi5s, uint32 baudrate, IfxPsi5s_Psi5s_AscConfig *ascConfig)
570 {
571  uint32 bgValue = 0;
572  uint32 fdValue = 0;
573  uint32 result = 0;
574  uint32 fInput;
575 
576  if (ascConfig->receiveMode == IfxPsi5s_AscMode_sync)
577  {
578  if (ascConfig->transmitMode != IfxPsi5s_AscMode_sync)
579  {
580  // sync modes must be set for both receive and transmit
581  }
582 
583  fInput = IfxScuCcu_getSpbFrequency(); // assumption here is that fBaud2 is equal to fSPB
584  bgValue = fInput / ((ascConfig->baudrateSelection + 2) * 4 * baudrate) - 1;
585 
586  if (bgValue > (IFXPSI5S_BG_RANGE - 1))
587  {
588  bgValue = IFXPSI5S_BG_RANGE - 1;
589  }
590  else
591  {
592  /* do nothing */
593  }
594 
595  result = fInput / ((ascConfig->baudrateSelection + 2) * 4 * (bgValue + 1));
596  }
597  else if (ascConfig->fractionalDividerEnabled == FALSE)
598  {
599  fInput = IfxScuCcu_getSpbFrequency(); // assumption here is that fBaud2 is equal to fSPB
600  bgValue = fInput / ((ascConfig->baudrateSelection + 2) * 16 * baudrate) - 1;
601 
602  if (bgValue > (IFXPSI5S_BG_RANGE - 1))
603  {
604  bgValue = IFXPSI5S_BG_RANGE - 1;
605  }
606  else
607  {
608  /* do nothing */
609  }
610 
611  result = fInput / ((ascConfig->baudrateSelection + 2) * 16 * (bgValue + 1));
612  }
613  else
614  {
615  fInput = IfxScuCcu_getSpbFrequency(); // assumption here is that fBaud2 is equal to fSPB
616  fdValue = (baudrate * IFXPSI5S_FDV_RANGE) / fInput;
617 
618  if (fdValue > (IFXPSI5S_FDV_RANGE - 1))
619  {
620  fdValue = IFXPSI5S_STEP_RANGE - 1;
621  bgValue = (fdValue / IFXPSI5S_FDV_RANGE) * (fInput / (16 * baudrate)) - 1;
622 
623  if (bgValue > (IFXPSI5S_BG_RANGE - 1))
624  {
625  bgValue = IFXPSI5S_BG_RANGE - 1;
626  }
627  else
628  {
629  /* do nothing */
630  }
631  }
632  else
633  {
634  bgValue = 0;
635  }
636 
637  result = (fdValue / IFXPSI5S_FDV_RANGE) * (fInput / (16 * (bgValue + 1)));
638  }
639 
640  psi5s->FDV.U = fdValue;
641  psi5s->BG.U = bgValue;
642 
643  return result;
644 }