iLLD_TC27xD  1.0
IfxMultican.c
Go to the documentation of this file.
1 /**
2  * \file IfxMultican.c
3  * \brief MULTICAN basic functionality
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 "IfxMultican.h"
30 
31 /******************************************************************************/
32 /*-----------------------Private Function Prototypes--------------------------*/
33 /******************************************************************************/
34 
35 /** \brief Do actual long frame reading from the message object
36  * \param mcan Specifies the CAN module
37  * \param msgObjId Specifies the message object index. Range = [0, \ref IFXMULTICAN_NUM_MESSAGE_OBJECTS - 1]
38  * \param msg This parameter is filled in by the function with the received message. Also when reading is not successful.
39  * \param data Pointer to data (in words)
40  * \return None
41  */
42 static void IfxMultican_MsgObj_doReadLongFrame(Ifx_CAN *mcan, IfxMultican_MsgObjId msgObjId, IfxMultican_Message *msg, uint32 *data);
43 
44 /** \brief Do actual message reading from the message object
45  * \param hwObj Pointer to CAN message object registers
46  * \param msg This parameter is filled in by the function with the received message. Also when reading is not successful.
47  * \return None
48  */
49 static void IfxMultican_MsgObj_doReadMessage(Ifx_CAN_MO *hwObj, IfxMultican_Message *msg);
50 
51 /******************************************************************************/
52 /*-------------------------Function Implementations---------------------------*/
53 /******************************************************************************/
54 
55 boolean IfxMultican_MsgObj_cancelSend(Ifx_CAN_MO *hwObj)
56 {
57  boolean result = FALSE;
58  Ifx_CAN_MO_CTR ctr;
59  Ifx_CAN_MO_STAT stat;
60 
61  stat.U = hwObj->STAT.U;
62 
63  if ((stat.B.TXRQ != 0) && (stat.B.NEWDAT != 0))
64  {
65  ctr.U = 0;
66  ctr.B.RESRTSEL = 1; /* take out from transmission */
67  hwObj->CTR.U = ctr.U;
68  result = TRUE;
69  }
70 
71  return result;
72 }
73 
74 
76 {
77  Ifx_CAN_MO_CTR ctr;
78  ctr.U = 0;
79  ctr.U = 1U << flag;
80 
81  hwObj->CTR.U = ctr.U;
82 }
83 
84 
85 void IfxMultican_MsgObj_deinit(Ifx_CAN *mcan, IfxMultican_MsgObjId msgObjId)
86 {
87  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
88  /* Remove the message object from any node */
89  /* Append message object to the end of the list */
90  IfxMultican_setListCommand(mcan, 0x2, 0, msgObjId);
91 
92  hwObj->CTR.U = 0x0000FFFFUL; /* to be written first */
93 
94  hwObj->FCR.U = 0x00000000UL;
95  hwObj->FGPR.U = 0x00000000UL;
96  hwObj->IPR.U = 0x00000000UL;
97  hwObj->AMR.U = 0x3FFFFFFFUL;
98  hwObj->DATAL.U = 0x00000000UL;
99  hwObj->DATAH.U = 0x00000000UL;
100  hwObj->AR.U = 0x00000000UL;
101 }
102 
103 
104 static void IfxMultican_MsgObj_doReadLongFrame(Ifx_CAN *mcan, IfxMultican_MsgObjId msgObjId, IfxMultican_Message *msg, uint32 *data)
105 {
106  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
107 
108  IfxMultican_MsgObjId botMsgObjId = hwObj->FGPR.B.BOT;
109  Ifx_CAN_MO *hwBotObj = IfxMultican_MsgObj_getPointer(mcan, botMsgObjId);
110 
111  IfxMultican_MsgObjId topMsgObjId = hwObj->FGPR.B.TOP;
112  Ifx_CAN_MO *hwTopObj = IfxMultican_MsgObj_getPointer(mcan, topMsgObjId);
113 
114  /* for standard message object and FIFO message objects*/
116 
117  /* copy the length code from hardware */
119 
120  /* read the data from the data registers */
121  if (lengthCode > IfxMultican_DataLengthCode_0) /* no.of bytes 0 to 8 */
122  {
123  *data++ = hwObj->DATAL.U;
124  *data++ = hwObj->DATAH.U;
125  }
126 
127  /* read from bottom message object extended data registers */
128  if (lengthCode > IfxMultican_DataLengthCode_8)
129  {
130  *data++ = hwBotObj->EDATA0.U;
131  }
132 
133  if (lengthCode > IfxMultican_DataLengthCode_12)
134  {
135  *data++ = hwBotObj->EDATA1.U;
136  }
137 
138  if (lengthCode > IfxMultican_DataLengthCode_16)
139  {
140  *data++ = hwBotObj->EDATA2.U;
141  }
142 
143  if (lengthCode > IfxMultican_DataLengthCode_20)
144  {
145  *data++ = hwBotObj->EDATA3.U;
146  }
147 
148  if (lengthCode > IfxMultican_DataLengthCode_24)
149  {
150  *data++ = hwBotObj->EDATA4.U;
151  *data++ = hwBotObj->EDATA5.U;
152  }
153 
154  if (lengthCode > IfxMultican_DataLengthCode_32)
155  {
156  *data++ = hwBotObj->EDATA6.U;
157  /* read from top message object extended data registers */
158  *data++ = hwTopObj->EDATA0.U;
159  *data++ = hwTopObj->EDATA1.U;
160  *data++ = hwTopObj->EDATA2.U;
161  }
162 
163  if (lengthCode > IfxMultican_DataLengthCode_48)
164  {
165  *data++ = hwTopObj->EDATA3.U;
166  *data++ = hwTopObj->EDATA4.U;
167  *data++ = hwTopObj->EDATA5.U;
168  *data = hwTopObj->EDATA6.U;
169  }
170 
171  msg->fastBitRate = hwObj->FCR.B.BRS;
172 
173  msg->lengthCode = lengthCode;
174 
175  /* copy the ID from the hardware */
176  msg->id = IfxMultican_MsgObj_getMessageId(hwObj);
177 }
178 
179 
180 static void IfxMultican_MsgObj_doReadMessage(Ifx_CAN_MO *hwObj, IfxMultican_Message *msg)
181 {
182  /* for standard message object and FIFO message objects*/
184 
185  /* read the data from the data registers */
186  msg->data[0] = hwObj->DATAL.U;
187  msg->data[1] = hwObj->DATAH.U;
188 
189  /* copy the length code from hardware */
191 
192  /* copy the ID from the hardware */
193  msg->id = IfxMultican_MsgObj_getMessageId(hwObj);
194 }
195 
196 
198 {
199  uint32 index = mcan->MSID[msgObjGroup].U;
200  IfxMultican_MsgObjId msgObjId = -1;
201 
202  if (index != 0x20U)
203  {
204  mcan->MSPND[msgObjGroup].U = ~(1UL << index);
205  msgObjId = index + (msgObjGroup << 5);
206  }
207 
208  return msgObjId;
209 }
210 
211 
213 {
214  IfxMultican_MsgObjStat status;
215 
216  status.U = hwObj->STAT.U;
217 
218  return status;
219 }
220 
221 
223 {
224  uint32 shift = (1U << flag);
225 
226  return (hwObj->STAT.U & shift) ? TRUE : FALSE;
227 }
228 
229 
231 {
232  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
234 
235  boolean longFrame = (hwObj->FCR.B.FDF != 0) ? TRUE : FALSE;
236 
237  if (longFrame)
238  {
239  /* if new data available in the message object */
240  if (hwObj->STAT.B.NEWDAT != 0)
241  {
242  Ifx_CAN_MO_STAT stat;
243  IfxMultican_MsgObj_doReadLongFrame(mcan, msgObjId, msg, data);
244  stat = hwObj->STAT; /* Cache the status after reading to reduce message lost propability */
245 
246  if (stat.B.RXUPD != 0)
247  { /* Data might be inconsistent (update while reading), declare as message lost, data will be read next time the API is called */
249  }
250  else if (stat.B.NEWDAT != 0)
251  { /* Data might be inconsistent (update while reading), force massage lost flag, read new incoming data */
252  Ifx_CAN_MO_STAT stat2;
254  /* perform read from the hardware */
255  IfxMultican_MsgObj_doReadLongFrame(mcan, msgObjId, msg, data);
256 
257  stat2 = hwObj->STAT; /* Cache the status after reading */
258 
259  if ((stat2.B.NEWDAT == 0) && (stat2.B.RXUPD == 0))
260  {
261  status |= IfxMultican_Status_newData;
262  }
263  else
264  { /* Return message lost at 2nd read attempt, data will be read next time the API is called*/
265  }
266  }
267  else
268  {
270  }
271 
272  if (stat.B.MSGLST != 0)
273  { /* At least on message has been lost */
276  }
277  }
278  else
279  {
281  }
282  }
283  else
284  {
285  /* use normal read message API */
286  }
287 
288  return status;
289 }
290 
291 
293 {
295 
296  /* if new data available in the message object */
297  if (hwObj->STAT.B.NEWDAT != 0)
298  {
299  Ifx_CAN_MO_STAT stat;
300  IfxMultican_MsgObj_doReadMessage(hwObj, msg);
301  stat = hwObj->STAT; /* Cache the status after reading to reduce message lost propability */
302 
303  if (stat.B.RXUPD != 0)
304  { /* Data might be inconsistent (update while reading), declare as message lost, data will be read next time the API is called */
306  }
307  else if (stat.B.NEWDAT != 0)
308  { /* Data might be inconsistent (update while reading), force massage lost flag, read new incoming data */
309  Ifx_CAN_MO_STAT stat2;
311  /* perform read from the hardware */
312  IfxMultican_MsgObj_doReadMessage(hwObj, msg);
313 
314  stat2 = hwObj->STAT; /* Cache the status after reading */
315 
316  if ((stat2.B.NEWDAT == 0) && (stat2.B.RXUPD == 0))
317  {
318  status |= IfxMultican_Status_newData;
319  }
320  else
321  { /* Return message lost at 2nd read attempt, data will be read next time the API is called*/
322  }
323  }
324  else
325  {
327  }
328 
329  if (stat.B.MSGLST != 0)
330  { /* At least on message has been lost */
333  }
334  }
335  else
336  {
338  }
339 
340  return status;
341 }
342 
343 
345 {
346  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
348 
349  /* get the base address of top and bottom message objects */
350  IfxMultican_MsgObjId botMsgObjId = hwObj->FGPR.B.BOT;
351  Ifx_CAN_MO *hwBotObj = IfxMultican_MsgObj_getPointer(mcan, botMsgObjId);
352 
353  IfxMultican_MsgObjId topMsgObjId = hwObj->FGPR.B.TOP;
354  Ifx_CAN_MO *hwTopObj = IfxMultican_MsgObj_getPointer(mcan, topMsgObjId);
355 
356  boolean longFrame = (hwObj->FCR.B.FDF != 0) ? TRUE : FALSE;
357 
358  /* in either of the below cases, the two conditions FDEN = 0, EDl = 1 and BRS = 0/1 will not reach */
359  /* long frame CAN FD */
360  /* FDEN = 1, EDL = 1 and BRS = 0/1 */
361  if (longFrame)
362  {
363  if (hwObj->STAT.B.TXRQ)
364  { /* previous message was not transferred, e.g. due to busy bus, BUS-OFF or others */
366  }
367  else
368  {
369  /* MSGVAL: Set message as not valid */
371 
372  if (msg->lengthCode > IfxMultican_DataLengthCode_0) /* no.of bytes 0 to 8 */
373  {
374  hwObj->DATAL.U = *data++;
375  hwObj->DATAH.U = *data++;
376  }
377 
378  /* load bottom message object extended data registers */
380  {
381  hwBotObj->EDATA0.U = *data++;
382  }
383 
385  {
386  hwBotObj->EDATA1.U = *data++;
387  }
388 
390  {
391  hwBotObj->EDATA2.U = *data++;
392  }
393 
395  {
396  hwBotObj->EDATA3.U = *data++;
397  }
398 
400  {
401  hwBotObj->EDATA4.U = *data++;
402  hwBotObj->EDATA5.U = *data++;
403  }
404 
406  {
407  hwBotObj->EDATA6.U = *data++;
408  /* load bottom message object extended data registers */
409  hwTopObj->EDATA0.U = *data++;
410  hwTopObj->EDATA1.U = *data++;
411  hwTopObj->EDATA2.U = *data++;
412  }
413 
415  {
416  hwTopObj->EDATA3.U = *data++;
417  hwTopObj->EDATA4.U = *data++;
418  hwTopObj->EDATA5.U = *data++;
419  hwTopObj->EDATA6.U = *data;
420  }
421 
422  /* for long message */
423  {
424  /* set ID */
425  boolean extendedFrame = IfxMultican_MsgObj_isExtendedFrame(hwObj);
426  IfxMultican_MsgObj_setMessageId(hwObj, msg->id, extendedFrame);
427 
428  /* set data length code */
430 
431  /* set bit rate switch (fast bit rate enable/disable) */
433  }
434 
435  /* --- flags configuration --- */
436  {
437  /* set new data flag */
439 
440  /* set message as valid */
442 
443  /* set RTSEL */
445 
446  /* set TXRQ */
448  }
449  }
450  }
451 
452  /* standard frame */
453  /* FDEN = 0/1, EDL = 0 and BRS = 0 (BRS = 1 also has no effect here) */
454  else
455  {
456  /* use normal send message API */
458  }
459 
460  return status;
461 }
462 
463 
465 {
467 
468  if (hwObj->STAT.B.TXRQ)
469  { /* previous message was not transferred, e.g. due to busy bus, BUS-OFF or others */
471  }
472  else
473  {
474  /* MSGVAL: Set message as not valid */
476 
477  /* for standard and FIFO message object */
478  hwObj->DATAL.U = msg->data[0]; /* Set the new data */
479  hwObj->DATAH.U = msg->data[1]; /* Set the new data */
480 
481  /* for standard and FIFO message object */
482  {
483  /* set ID */
484  boolean extendedFrame = IfxMultican_MsgObj_isExtendedFrame(hwObj);
485  IfxMultican_MsgObj_setMessageId(hwObj, msg->id, extendedFrame);
486 
487  /* standard frame */
488  /* in case of FD standard frame, FDEN = 0/1, EDL = 0 and BRS = 0 (BRS = 1 also has no effect here) */
489  /* set data length code */
491  }
492 
493  /* --- flags configuration --- */
494 
495  /* for standard and FIFO message object */
496  {
497  /* set new data flag */
499 
500  /* set message as valid, in case of FIFO mSGVAL has to be set before setting it to each slave object */
502 
503  /* set TXRQ, should not be set for FIFO base object */
505  }
506  }
507 
508  return status;
509 }
510 
511 
512 void IfxMultican_MsgObj_setFilter(Ifx_CAN_MO *hwObj, boolean extend, uint32 id, uint32 accMask)
513 {
514  Ifx_CAN_MO_CTR ctr;
515 
516  ctr.U = 0;
517  ctr.B.RESMSGVAL = 1; /* MSGVAL: Set message as not valid */
518  hwObj->CTR.U = ctr.U;
519 
520  hwObj->AMR.B.AM = accMask << ((extend != 0) ? 0 : 18);
521  hwObj->AR.B.IDE = (id << ((extend != 0) ? 0 : 18)) | (extend << 29);
522 
523  ctr.U = 0;
524  ctr.B.SETMSGVAL = 1; /* MSGVAL: Set message as valid */
525  hwObj->CTR.U = ctr.U;
526 }
527 
528 
530 {
531  Ifx_CAN_MO_CTR ctr;
532  ctr.U = 0;
533 
534  ctr.U = 1U << (flag + 16);
535 
536  hwObj->CTR.U = ctr.U;
537 }
538 
539 
540 void IfxMultican_Node_deinit(Ifx_CAN_N *hwNode)
541 {
542  hwNode->CR.U = 0x00000001;
543  hwNode->SR.U = 0x00000000;
544  hwNode->IPR.U = 0x00000000;
545  hwNode->PCR.U = 0x00000000;
546  hwNode->BTEVR.U = 0x00000000;
547  hwNode->ECNT.U = 0x00600000;
548  hwNode->FCR.U = 0x00000000;
549 }
550 
551 
553 {
554  IfxPort_setPinModeInput(rxd->pin.port, rxd->pin.pinIndex, mode);
555  hwNode->PCR.B.RXSEL = rxd->select;
556 
557  return TRUE;
558 }
559 
560 
562 {
563  IfxPort_setPinModeOutput(txd->pin.port, txd->pin.pinIndex, mode, txd->select);
565 
566  return TRUE;
567 }
568 
569 
571 {
573 
574  boolean busOffState = hwNode->SR.B.BOFF;
575  boolean errorWarningStatus = hwNode->SR.B.EWRN;
576 
577  /* if the node is in bus off state, initiaite the recovery process */
578  if ((busOffState != 0) && (hwNode->ECNT.B.TEC > 254))
579  {
580  status = IfxMultican_Status_busOff;
581 
582  /* reset error counters */
583  hwNode->ECNT.B.TEC = 0x01;
584  hwNode->ECNT.B.REC = 0x01;
585 
586  /* clear error warning status */
587  hwNode->SR.B.EWRN = 0;
588 
589  /* clear ALERT status */
590  hwNode->SR.B.ALERT = 0;
591 
592  /* disable node INIT = 1 */
594  }
595 
596  /* during recovery process, if REC counter reaches 0x60 */
597  else if ((busOffState != 0) && (errorWarningStatus != 0))
598  {
600  }
601 
602  /* if the recovery process is been finished or not in Bus off mode */
603  else if ((busOffState == 0) && (errorWarningStatus == 0))
604  {
605  /* enable node INIT = 0 */
607 
608  status = IfxMultican_Status_ok;
609  }
610 
611  return status;
612 }
613 
614 
615 void IfxMultican_Node_setBitTiming(Ifx_CAN_N *hwNode, float32 moduleFreq, uint32 baudrate, uint16 samplePoint, uint16 synchJumpWidth)
616 {
617  sint32 tempBRP, tempSJW, tempTSEG1 = 12;
618  sint32 bestBRP = 0, bestSJW = 0, bestTBAUD = 0, bestTSEG1 = 1, bestTSEG2;
619  sint32 bestError = 10000;
620 
621  /*
622  * Bit timing & sampling
623  * Tq = (BRP+1)/Fcan if DIV8 = 0
624  * Tq = 8*(BRP+1)/Fcan if DIV8 = 1
625  * TSync = 1.Tq
626  * TSeg1 = (TSEG1+1)*Tq >= 3Tq
627  * TSeg2 = (TSEG2+1)*Tq >= 2Tq
628  * Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
629  *
630  * Resynchronization:
631  *
632  * Tsjw = (SJW + 1)*Tq
633  * TSeg1 >= Tsjw + Tprop
634  * TSeg2 >= Tsjw
635  */
636 
637  /* search for best baudrate */
638  bestError = 10000;
639 
640  for (tempBRP = 1; tempBRP <= (0x3F + 1); tempBRP++)
641  {
642  float32 Fquanta = moduleFreq / tempBRP;
643  sint32 tempTBAUD = Fquanta / baudrate;
644  float32 tempBaudrate = Fquanta / tempTBAUD;
645  float32 error = __absf(tempBaudrate - baudrate);
646 
647  if ((tempTBAUD <= 20) && (bestError > error))
648  {
649  bestBRP = tempBRP;
650  bestTBAUD = tempTBAUD;
651  bestError = error;
652 
653  if (error < 0.1)
654  {
655  break;
656  }
657  }
658  }
659 
660  /* search for best sample point */
661  bestError = 10000;
662 
663  for (tempTSEG1 = 16; tempTSEG1 >= 3; tempTSEG1--)
664  {
665  sint32 tempSamplePoint = ((tempTSEG1 + 1) * 10000) / bestTBAUD;
666  sint32 error = __abs(tempSamplePoint - samplePoint);
667 
668  if (bestError > error)
669  {
670  bestTSEG1 = tempTSEG1;
671  bestError = error;
672  }
673 
674  if (tempSamplePoint < samplePoint)
675  {
676  break;
677  }
678  }
679 
680  bestTSEG2 = bestTBAUD - bestTSEG1 - 1;
681 
682  /* search for best SJW */
683  bestError = 10000;
684 
685  for (tempSJW = 1; tempSJW <= 4; tempSJW++)
686  {
687  sint32 tempSynchJumpWidth = (tempSJW * 10000) / bestTBAUD;
688  sint32 error = __abs(tempSynchJumpWidth - synchJumpWidth);
689 
690  if (bestError > error)
691  {
692  bestSJW = tempSJW;
693  bestError = error;
694  }
695  }
696 
697  {
698  Ifx_CAN_N_BTR nbtr;
699  nbtr.U = 0;
700  nbtr.B.BRP = bestBRP - 1;
701  nbtr.B.SJW = bestSJW - 1;
702  nbtr.B.TSEG1 = bestTSEG1 - 1;
703  nbtr.B.TSEG2 = bestTSEG2 - 1;
704  nbtr.B.DIV8 = 0;
705  //nbtr.B.FTX = 0; /* TTCAN only */
706 
707  hwNode->BTR.U = nbtr.U;
708  }
709 }
710 
711 
712 void IfxMultican_Node_setFastBitTiming(Ifx_CAN_N *hwNode, float32 moduleFreq, uint32 baudrate, uint16 samplePoint, uint16 synchJumpWidth)
713 {
714  sint32 tempFBRP, tempFSJW, tempFTSEG1 = 12;
715  sint32 bestFBRP = 0, bestFSJW = 0, bestFTBAUD = 0, bestFTSEG1 = 1, bestFTSEG2;
716  sint32 bestError = 10000;
717 
718  /*
719  * Bit timing & sampling
720  * Tq = (BRP+1)/Fcan if DIV8 = 0
721  * Tq = 8*(BRP+1)/Fcan if DIV8 = 1
722  * TSync = 1.Tq
723  * TSeg1 = (TSEG1+1)*Tq >= 3Tq
724  * TSeg2 = (TSEG2+1)*Tq >= 2Tq
725  * Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
726  *
727  * Resynchronization:
728  *
729  * Tsjw = (SJW + 1)*Tq
730  * TSeg1 >= Tsjw + Tprop
731  * TSeg2 >= Tsjw
732  */
733 
734  /* search for best baudrate */
735  bestError = 10000;
736 
737  for (tempFBRP = 1; tempFBRP <= (0x3F + 1); tempFBRP++)
738  {
739  float32 Fquanta = moduleFreq / tempFBRP;
740  sint32 tempTBAUD = Fquanta / baudrate;
741  float32 tempBaudrate = Fquanta / tempTBAUD;
742  float32 error = __absf(tempBaudrate - baudrate);
743 
744  if ((tempTBAUD <= 20) && (bestError > error))
745  {
746  bestFBRP = tempFBRP;
747  bestFTBAUD = tempTBAUD;
748  bestError = error;
749 
750  if (error < 0.1)
751  {
752  break;
753  }
754  }
755  }
756 
757  /* search for best sample point */
758  bestError = 10000;
759 
760  for (tempFTSEG1 = 16; tempFTSEG1 >= 3; tempFTSEG1--)
761  {
762  sint32 tempSamplePoint = ((tempFTSEG1 + 1) * 10000) / bestFTBAUD;
763  sint32 error = __abs(tempSamplePoint - samplePoint);
764 
765  if (bestError > error)
766  {
767  bestFTSEG1 = tempFTSEG1;
768  bestError = error;
769  }
770 
771  if (tempSamplePoint < samplePoint)
772  {
773  break;
774  }
775  }
776 
777  bestFTSEG2 = bestFTBAUD - bestFTSEG1 - 1;
778 
779  /* search for best SJW */
780  bestError = 10000;
781 
782  for (tempFSJW = 1; tempFSJW <= 4; tempFSJW++)
783  {
784  sint32 tempSynchJumpWidth = (tempFSJW * 10000) / bestFTBAUD;
785  sint32 error = __abs(tempSynchJumpWidth - synchJumpWidth);
786 
787  if (bestError > error)
788  {
789  bestFSJW = tempFSJW;
790  bestError = error;
791  }
792  }
793 
794  {
795  Ifx_CAN_N_FBTR nfbtr;
796  nfbtr.U = 0;
797  nfbtr.B.FBRP = bestFBRP - 1;
798  nfbtr.B.FSJW = bestFSJW - 1;
799  nfbtr.B.FTSEG1 = bestFTSEG1 - 1;
800  nfbtr.B.FTSEG2 = bestFTSEG2 - 1;
801 
802  hwNode->FBTR.U = nfbtr.U;
803  }
804 }
805 
806 
807 void IfxMultican_Node_setNominalBitTiming(Ifx_CAN_N *hwNode, float32 moduleFreq, uint32 baudrate, uint16 samplePoint, uint16 synchJumpWidth)
808 {
809  sint32 tempBRP, tempSJW, tempTSEG1 = 12;
810  sint32 bestBRP = 0, bestSJW = 0, bestTBAUD = 0, bestTSEG1 = 1, bestTSEG2;
811  sint32 bestError = 10000;
812 
813  /*
814  * Bit timing & sampling
815  * Tq = (BRP+1)/Fcan if DIV8 = 0
816  * Tq = 8*(BRP+1)/Fcan if DIV8 = 1
817  * TSync = 1.Tq
818  * TSeg1 = (TSEG1+1)*Tq >= 3Tq
819  * TSeg2 = (TSEG2+1)*Tq >= 2Tq
820  * Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
821  *
822  * Resynchronization:
823  *
824  * Tsjw = (SJW + 1)*Tq
825  * TSeg1 >= Tsjw + Tprop
826  * TSeg2 >= Tsjw
827  */
828 
829  /* search for best baudrate */
830  bestError = 10000;
831 
832  for (tempBRP = 1; tempBRP <= (0x3F + 1); tempBRP++)
833  {
834  float32 Fquanta = moduleFreq / tempBRP;
835  sint32 tempTBAUD = Fquanta / baudrate;
836  float32 tempBaudrate = Fquanta / tempTBAUD;
837  float32 error = __absf(tempBaudrate - baudrate);
838 
839  if ((tempTBAUD <= 20) && (bestError > error))
840  {
841  bestBRP = tempBRP;
842  bestTBAUD = tempTBAUD;
843  bestError = error;
844 
845  if (error < 0.1)
846  {
847  break;
848  }
849  }
850  }
851 
852  /* search for best sample point */
853  bestError = 10000;
854 
855  for (tempTSEG1 = 64; tempTSEG1 >= 3; tempTSEG1--)
856  {
857  sint32 tempSamplePoint = ((tempTSEG1 + 1) * 10000) / bestTBAUD;
858  sint32 error = __abs(tempSamplePoint - samplePoint);
859 
860  if (bestError > error)
861  {
862  bestTSEG1 = tempTSEG1;
863  bestError = error;
864  }
865 
866  if (tempSamplePoint < samplePoint)
867  {
868  break;
869  }
870  }
871 
872  bestTSEG2 = bestTBAUD - bestTSEG1 - 1;
873 
874  /* search for best SJW */
875  bestError = 10000;
876 
877  for (tempSJW = 1; tempSJW <= 16; tempSJW++)
878  {
879  sint32 tempSynchJumpWidth = (tempSJW * 10000) / bestTBAUD;
880  sint32 error = __abs(tempSynchJumpWidth - synchJumpWidth);
881 
882  if (bestError > error)
883  {
884  bestSJW = tempSJW;
885  bestError = error;
886  }
887  }
888 
889  {
890  Ifx_CAN_N_BTEVR nbtevr;
891  nbtevr.U = 0;
892  nbtevr.B.BRP = bestBRP - 1;
893  nbtevr.B.SJW = bestSJW - 1;
894  nbtevr.B.TSEG1 = bestTSEG1 - 1;
895  nbtevr.B.TSEG2 = bestTSEG2 - 1;
896  nbtevr.B.DIV8 = 0;
897  //nbtr.B.FTX = 0; /* TTCAN only */
898 
899  hwNode->BTEVR.U = nbtevr.U;
900  }
901 }
902 
903 
904 void IfxMultican_calcTimingFromBTR(float32 moduleFreq, uint32 btr, uint32 *baudrate, uint16 *samplePoint, uint16 *synchJumpWidth)
905 {
906  Ifx_CAN_N_BTR nbtr = {.U = btr};
907  uint32 tempBRP = 1U + nbtr.B.BRP;
908  uint32 tempSJW = 1U + nbtr.B.SJW;
909  uint32 tempTSEG1 = 1U + nbtr.B.TSEG1;
910  uint32 tempTSEG2 = 1U + nbtr.B.TSEG2;
911  uint32 tempDIV8 = (nbtr.B.DIV8 != 0) ? 8U : 1U;
912 
913  uint32 tempTSEG = 1 + tempTSEG1 + tempTSEG2;
914 
915  *baudrate = (uint32)(moduleFreq / (float32)(tempDIV8 * tempBRP * tempTSEG));
916  *samplePoint = (uint16)(((float32)tempTSEG1) * 10000 / ((float32)(tempTSEG)));
917  *synchJumpWidth = (uint16)(((float32)tempSJW) * 10000 / ((float32)(tempTSEG)));
918 }
919 
920 
921 void IfxMultican_deinit(Ifx_CAN *mcan)
922 {
923  // should use kernel reset functionality!
924  uint16 i;
925 
926  /* Ifx_CAN.CLC is reset last */
927  for (i = 0; i < IFXMULTICAN_NUM_MESSAGE_OBJECTS; i++)
928  {
929  IfxMultican_MsgObj_deinit(mcan, i);
930  }
931 
932  for (i = 0; i < IFXMULTICAN_NUM_NODES; i++)
933  {
934  Ifx_CAN_N *hwNode = IfxMultican_Node_getPointer(mcan, IfxMultican_NodeId_0 + i);
935 
936  IfxMultican_Node_deinit(hwNode);
937  }
938 
939  for (i = 0; i < IFXMULTICAN_NUM_SRC; i++)
940  {
941  MODULE_SRC.CAN.CAN[0].INT[i].U = 0x00000000;
942  }
943 
944  for (i = 0; i < 8; i++)
945  {
946  mcan->MSPND[i].U = 0x00000000;
947  }
948 
949  mcan->MSIMASK.U = 0x00000000;
950  mcan->MCR.U = 0x00000000;
951  {
954  mcan->FDR.U = 0x00000000;
955  IfxScuWdt_setCpuEndinit(passwd);
957  mcan->CLC.U = 0x00000001;
958  IfxScuWdt_setCpuEndinit(passwd);
959  }
960 }
961 
962 
963 volatile Ifx_SRC_SRCR *IfxMultican_getSrcPointer(Ifx_CAN *mcan, IfxMultican_SrcId srcId)
964 {
965  return &(MODULE_SRC.CAN.CAN[0].INT[srcId]);
966 }
967 
968 
969 void IfxMultican_resetModule(Ifx_CAN *can)
970 {
972 
974  can->KRST0.B.RST = 1; /* Only if both Kernel reset bits are set a reset is executed */
975  can->KRST1.B.RST = 1;
976  IfxScuWdt_setCpuEndinit(passwd);
977 
978  while (0 == can->KRST0.B.RSTSTAT) /* Wait until reset is executed */
979 
980  {}
981 
983  can->KRSTCLR.B.CLR = 1; /* Clear Kernel reset status bit */
984  IfxScuWdt_setCpuEndinit(passwd);
985 }
986 
987 
988 void IfxMultican_setListCommand(Ifx_CAN *mcan, uint32 cmd, uint32 arg2, uint32 arg1)
989 {
990  Ifx_CAN_PANCTR panctr;
991 
992  panctr.B.PANAR1 = arg1;
993  panctr.B.PANAR2 = arg2;
994  panctr.B.PANCMD = cmd;
995 
996  /** - write to CAN_PANCTR */
997  mcan->PANCTR.U = panctr.U;
998 
1000 }