iLLD_TC27xC  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_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 "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_MO_COUNT - 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 
80  ctr.U = 1U << flag;
81 
82  hwObj->CTR.U = ctr.U;
83 }
84 
85 
86 void IfxMultican_MsgObj_deinit(Ifx_CAN *mcan, IfxMultican_MsgObjId msgObjId)
87 {
88  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
89  /* Remove the message object from any node */
90  /* Append message object to the end of the list */
91  IfxMultican_setListCommand(mcan, 0x2, 0, msgObjId);
92 
93  hwObj->CTR.U = 0x0000FFFFUL; /* to be written first */
94 
95  hwObj->FCR.U = 0x00000000UL;
96  hwObj->FGPR.U = 0x00000000UL;
97  hwObj->IPR.U = 0x00000000UL;
98  hwObj->AMR.U = 0x3FFFFFFFUL;
99  hwObj->DATAL.U = 0x00000000UL;
100  hwObj->DATAH.U = 0x00000000UL;
101  hwObj->AR.U = 0x00000000UL;
102 }
103 
104 
105 static void IfxMultican_MsgObj_doReadLongFrame(Ifx_CAN *mcan, IfxMultican_MsgObjId msgObjId, IfxMultican_Message *msg, uint32 *data)
106 {
107  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
108 
109  IfxMultican_MsgObjId topMsgObjId = hwObj->FGPR.B.TOP;
110  Ifx_CAN_MO *hwTopObj = IfxMultican_MsgObj_getPointer(mcan, topMsgObjId);
111 
112  IfxMultican_MsgObjId botMsgObjId = hwObj->FGPR.B.BOT;
113  Ifx_CAN_MO *hwBotObj = IfxMultican_MsgObj_getPointer(mcan, botMsgObjId);
114 
115  /* for standard message object and FIFO message objects*/
117 
118  /* copy the length code from hardware */
120 
121  /* read the data from the data registers */
122  if (lengthCode > IfxMultican_DataLengthCode_0) /* no.of bytes 0 to 8 */
123  {
124  *data++ = hwObj->DATAL.U;
125  *data++ = hwObj->DATAH.U;
126  }
127 
128  /* read from top message object extended data registers */
129  if (lengthCode > IfxMultican_DataLengthCode_8)
130  {
131  *data++ = hwTopObj->EDATA0.U;
132  }
133 
134  if (lengthCode > IfxMultican_DataLengthCode_12)
135  {
136  *data++ = hwTopObj->EDATA1.U;
137  }
138 
139  if (lengthCode > IfxMultican_DataLengthCode_16)
140  {
141  *data++ = hwTopObj->EDATA2.U;
142  }
143 
144  if (lengthCode > IfxMultican_DataLengthCode_20)
145  {
146  *data++ = hwTopObj->EDATA3.U;
147  }
148 
149  if (lengthCode > IfxMultican_DataLengthCode_24)
150  {
151  *data++ = hwTopObj->EDATA4.U;
152  *data++ = hwTopObj->EDATA5.U;
153  }
154 
155  if (lengthCode > IfxMultican_DataLengthCode_32)
156  {
157  *data++ = hwTopObj->EDATA6.U;
158  /* read from bottom message object extended data registers */
159  *data++ = hwBotObj->EDATA0.U;
160  *data++ = hwBotObj->EDATA1.U;
161  *data++ = hwBotObj->EDATA2.U;
162  }
163 
164  if (lengthCode > IfxMultican_DataLengthCode_48)
165  {
166  *data++ = hwBotObj->EDATA3.U;
167  *data++ = hwBotObj->EDATA4.U;
168  *data++ = hwBotObj->EDATA5.U;
169  *data++ = hwBotObj->EDATA6.U;
170  }
171 
172  msg->fastBitRate = hwObj->FCR.B.BRS;
173 
174  msg->lengthCode = lengthCode;
175 
176  /* copy the ID from the hardware */
177  boolean extendedFrame = IfxMultican_MsgObj_isExtendedFrame(hwObj);
178  msg->id = IfxMultican_MsgObj_getMessageId(hwObj, extendedFrame);
179 }
180 
181 
182 static void IfxMultican_MsgObj_doReadMessage(Ifx_CAN_MO *hwObj, IfxMultican_Message *msg)
183 {
184  /* for standard message object and FIFO message objects*/
186 
187  /* read the data from the data registers */
188  msg->data[0] = hwObj->DATAL.U;
189  msg->data[1] = hwObj->DATAH.U;
190 
191  /* copy the length code from hardware */
193 
194  /* copy the ID from the hardware */
195  boolean extendedFrame = IfxMultican_MsgObj_isExtendedFrame(hwObj);
196  msg->id = IfxMultican_MsgObj_getMessageId(hwObj, extendedFrame);
197 }
198 
199 
201 {
202  uint32 index = mcan->MSID[msgObjGroup].U;
203  IfxMultican_MsgObjId msgObjId = -1;
204 
205  if (index != 0x20U)
206  {
207  mcan->MSPND[msgObjGroup].U = ~(1UL << index);
208  msgObjId = index + (msgObjGroup << 5);
209  }
210 
211  return msgObjId;
212 }
213 
214 
216 {
217  IfxMultican_MsgObjStat status;
218 
219  status.U = hwObj->STAT.U;
220 
221  return status;
222 }
223 
224 
226 {
227  uint32 shift = (1U << flag);
228 
229  return (hwObj->STAT.U & shift) ? TRUE : FALSE;
230 }
231 
232 
234 {
235  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
237 
238  boolean longFrame = (hwObj->FCR.B.FDF != 0) ? TRUE : FALSE;
239 
240  if (longFrame)
241  {
243 
244  /* perform read from the hardware */
245  IfxMultican_MsgObj_doReadLongFrame(mcan, msgObjId, msg, data);
246 
247  /* for standard and FIFO message object */
248 
249  if (hwObj->STAT.B.RXUPD != 0)
250  { /* there's update while copying, declare as message lost */
252  }
253  else if (hwObj->STAT.B.NEWDAT != 0)
254  { /* repeat reception in case it HAS BEEN updated at end of previous attempt,
255  * here we assume that CPU is quick enough so that no new data could come again
256  * in between. */
257  /* perform read from the hardware */
258  IfxMultican_MsgObj_doReadLongFrame(mcan, msgObjId, msg, data);
260  }
261  else
262  {}
263  }
264  else
265  {
266  /* use normal read message API */
267  }
268 
269  return status;
270 }
271 
272 
274 {
276 
277  /* if new data available in the message object */
278  if (hwObj->STAT.B.NEWDAT != 0)
279  {
280  /* if there's update while copying */
281  if (hwObj->STAT.B.RXUPD != 0)
282  {
284  }
285  /* if the data is lost, declare as message lost */
286  else if (hwObj->STAT.B.MSGLST != 0)
287  {
289  }
290  else
291  {
292  /* for both standard and FIFO objects perform read from the hardware */
293  IfxMultican_MsgObj_doReadMessage(hwObj, msg);
294  }
295  }
296  else
297  {
299  }
300 
301  return status;
302 }
303 
304 
306 {
307  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
309 
310  /* get the base address of top and bottom message objects */
311  IfxMultican_MsgObjId topMsgObjId = hwObj->FGPR.B.TOP;
312  Ifx_CAN_MO *hwTopObj = IfxMultican_MsgObj_getPointer(mcan, topMsgObjId);
313 
314  IfxMultican_MsgObjId botMsgObjId = hwObj->FGPR.B.BOT;
315  Ifx_CAN_MO *hwBotObj = IfxMultican_MsgObj_getPointer(mcan, botMsgObjId);
316 
317  boolean longFrame = (hwObj->FCR.B.FDF != 0) ? TRUE : FALSE;
318 
319  /* in either of the below cases, the two conditions FDEN = 0, EDl = 1 and BRS = 0/1 will not reach */
320  /* long frame CAN FD */
321  /* FDEN = 1, EDL = 1 and BRS = 0/1 */
322  if (longFrame)
323  {
324  if (hwObj->STAT.B.TXRQ)
325  { /* previous message was not transferred, e.g. due to busy bus, BUS-OFF or others */
327  }
328  else
329  {
330  /* MSGVAL: Set message as not valid */
332 
333  if (msg->lengthCode > IfxMultican_DataLengthCode_0) /* no.of bytes 0 to 8 */
334  {
335  hwObj->DATAL.U = *data++;
336  hwObj->DATAH.U = *data++;
337  }
338 
339  /* load top message object extended data registers */
341  {
342  hwTopObj->EDATA0.U = *data++;
343  }
344 
346  {
347  hwTopObj->EDATA1.U = *data++;
348  }
349 
351  {
352  hwTopObj->EDATA2.U = *data++;
353  }
354 
356  {
357  hwTopObj->EDATA3.U = *data++;
358  }
359 
361  {
362  hwTopObj->EDATA4.U = *data++;
363  hwTopObj->EDATA5.U = *data++;
364  }
365 
367  {
368  hwTopObj->EDATA6.U = *data++;
369  /* load bottom message object extended data registers */
370  hwBotObj->EDATA0.U = *data++;
371  hwBotObj->EDATA1.U = *data++;
372  hwBotObj->EDATA2.U = *data++;
373  }
374 
376  {
377  hwBotObj->EDATA3.U = *data++;
378  hwBotObj->EDATA4.U = *data++;
379  hwBotObj->EDATA5.U = *data++;
380  hwBotObj->EDATA6.U = *data++;
381  }
382 
383  /* for long message */
384  {
385  /* set ID */
386  boolean extendedFrame = IfxMultican_MsgObj_isExtendedFrame(hwObj);
387  IfxMultican_MsgObj_setMessageId(hwObj, msg->id, extendedFrame);
388 
389  /* set data length code */
391 
392  /* set bit rate switch (fast bit rate enable/disable) */
394  }
395 
396  /* --- flags configuration --- */
397 
398  /* for standard and FIFO message object */
399  {
400  /* set new data flag */
402 
403  /* set message as valid */
405 
406  /* set RTSEL */
408 
409  /* set TXRQ */
411  }
412  }
413  }
414 
415  /* standard frame */
416  /* FDEN = 0/1, EDL = 0 and BRS = 0 (BRS = 1 also has no effect here) */
417  else
418  {
419  /* use normal send message API */
421  }
422 
423  return status;
424 }
425 
426 
428 {
430 
431  if (hwObj->STAT.B.TXRQ)
432  { /* previous message was not transferred, e.g. due to busy bus, BUS-OFF or others */
434  }
435  else
436  {
437  /* MSGVAL: Set message as not valid */
439 
440  /* for standard and FIFO message object */
441  hwObj->DATAL.U = msg->data[0]; /* Set the new data */
442  hwObj->DATAH.U = msg->data[1]; /* Set the new data */
443 
444  /* for standard and FIFO message object */
445  {
446  /* set ID */
447  boolean extendedFrame = IfxMultican_MsgObj_isExtendedFrame(hwObj);
448  IfxMultican_MsgObj_setMessageId(hwObj, msg->id, extendedFrame);
449 
450  /* standard frame */
451  /* in case of FD standard frame, FDEN = 0/1, EDL = 0 and BRS = 0 (BRS = 1 also has no effect here) */
452  /* set data length code */
454  }
455 
456  /* --- flags configuration --- */
457 
458  /* for standard and FIFO message object */
459  {
460  /* set new data flag */
462 
463  /* set message as valid, in case of FIFO mSGVAL has to be set before setting it to each slave object */
465 
466  /* set TXRQ, should not be set for FIFO base object */
468  }
469  }
470 
471  return status;
472 }
473 
474 
475 void IfxMultican_MsgObj_setFilter(Ifx_CAN_MO *hwObj, boolean extend, uint32 id, uint32 accMask)
476 {
477  Ifx_CAN_MO_CTR ctr;
478 
479  ctr.U = 0;
480  ctr.B.RESMSGVAL = 1; /* MSGVAL: Set message as not valid */
481  hwObj->CTR.U = ctr.U;
482 
483  hwObj->AMR.B.AM = accMask << ((extend != 0) ? 0 : 18);
484  hwObj->AR.B.IDE = (id << ((extend != 0) ? 0 : 18)) | (extend << 29);
485 
486  ctr.U = 0;
487  ctr.B.SETMSGVAL = 1; /* MSGVAL: Set message as valid */
488  hwObj->CTR.U = ctr.U;
489 }
490 
491 
493 {
494  Ifx_CAN_MO_CTR ctr;
495  ctr.U = 0;
496 
497  ctr.U = 1U << (flag + 16);
498 
499  hwObj->CTR.U = ctr.U;
500 }
501 
502 
503 void IfxMultican_Node_deinit(Ifx_CAN_N *hwNode)
504 {
505  hwNode->CR.U = 0x00000001;
506  hwNode->SR.U = 0x00000000;
507  hwNode->IPR.U = 0x00000000;
508  hwNode->PCR.U = 0x00000000;
509  hwNode->BTEVR.U = 0x00000000;
510  hwNode->ECNT.U = 0x00600000;
511  hwNode->FCR.U = 0x00000000;
512 }
513 
514 
516 {
517  IfxPort_setPinModeInput(rxd->pin.port, rxd->pin.pinIndex, mode);
518  hwNode->PCR.B.RXSEL = rxd->select;
519 
520  return TRUE;
521 }
522 
523 
525 {
526  IfxPort_setPinModeOutput(txd->pin.port, txd->pin.pinIndex, mode, txd->select);
528 
529  return TRUE;
530 }
531 
532 
534 {
536 
537  boolean busOffState = hwNode->SR.B.BOFF;
538  boolean errorWarningStatus = hwNode->SR.B.EWRN;
539 
540  /* if the node is in bus off state, initiaite the recovery process */
541  if ((busOffState != 0) && (hwNode->ECNT.B.TEC > 254))
542  {
543  status = IfxMultican_Status_busOff;
544 
545  /* reset error counters */
546  hwNode->ECNT.B.TEC = 0x01;
547  hwNode->ECNT.B.REC = 0x01;
548 
549  /* clear error warning status */
550  hwNode->SR.B.EWRN = 0;
551 
552  /* clear ALERT status */
553  hwNode->SR.B.ALERT = 0;
554 
555  /* disable node INIT = 1 */
557  }
558 
559  /* during recovery process, if REC counter reaches 0x60 */
560  else if ((busOffState != 0) && (errorWarningStatus != 0))
561  {
563  }
564 
565  /* if the recovery process is been finished or not in Bus off mode */
566  else if ((busOffState == 0) && (errorWarningStatus == 0))
567  {
568  /* enable node INIT = 0 */
570 
572  }
573 
574  return status;
575 }
576 
577 
578 void IfxMultican_Node_setBitTiming(Ifx_CAN_N *hwNode, float32 moduleFreq, uint32 baudrate, uint16 samplePoint, uint16 synchJumpWidth)
579 {
580  sint32 tempBRP, tempSJW, tempTSEG1 = 12;
581  sint32 bestBRP = 0, bestSJW = 0, bestTBAUD = 0, bestTSEG1 = 1, bestTSEG2;
582  sint32 bestError = 10000;
583 
584  /*
585  * Bit timing & sampling
586  * Tq = (BRP+1)/Fcan if DIV8 = 0
587  * Tq = 8*(BRP+1)/Fcan if DIV8 = 1
588  * TSync = 1.Tq
589  * TSeg1 = (TSEG1+1)*Tq >= 3Tq
590  * TSeg2 = (TSEG2+1)*Tq >= 2Tq
591  * Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
592  *
593  * Resynchronization:
594  *
595  * Tsjw = (SJW + 1)*Tq
596  * TSeg1 >= Tsjw + Tprop
597  * TSeg2 >= Tsjw
598  */
599 
600  /* search for best baudrate */
601  bestError = 10000;
602 
603  for (tempBRP = 1; tempBRP <= (0x3F + 1); tempBRP++)
604  {
605  float32 Fquanta = moduleFreq / tempBRP;
606  sint32 tempTBAUD = Fquanta / baudrate;
607  float32 tempBaudrate = Fquanta / tempTBAUD;
608  float32 error = __absf(tempBaudrate - baudrate);
609 
610  if ((tempTBAUD <= 20) && (bestError > error))
611  {
612  bestBRP = tempBRP;
613  bestTBAUD = tempTBAUD;
614  bestError = error;
615 
616  if (error < 0.1)
617  {
618  break;
619  }
620  }
621  }
622 
623  /* search for best sample point */
624  bestError = 10000;
625 
626  for (tempTSEG1 = 16; tempTSEG1 >= 3; tempTSEG1--)
627  {
628  sint32 tempSamplePoint = ((tempTSEG1 + 1) * 10000) / bestTBAUD;
629  sint32 error = __abs(tempSamplePoint - samplePoint);
630 
631  if (bestError > error)
632  {
633  bestTSEG1 = tempTSEG1;
634  bestError = error;
635  }
636 
637  if (tempSamplePoint < samplePoint)
638  {
639  break;
640  }
641  }
642 
643  bestTSEG2 = bestTBAUD - bestTSEG1 - 1;
644 
645  /* search for best SJW */
646  bestError = 10000;
647 
648  for (tempSJW = 1; tempSJW <= 4; tempSJW++)
649  {
650  sint32 tempSynchJumpWidth = (tempSJW * 10000) / bestTBAUD;
651  sint32 error = __abs(tempSynchJumpWidth - synchJumpWidth);
652 
653  if (bestError > error)
654  {
655  bestSJW = tempSJW;
656  bestError = error;
657  }
658  }
659 
660  {
661  Ifx_CAN_N_BTR nbtr;
662  nbtr.U = 0;
663  nbtr.B.BRP = bestBRP - 1;
664  nbtr.B.SJW = bestSJW - 1;
665  nbtr.B.TSEG1 = bestTSEG1 - 1;
666  nbtr.B.TSEG2 = bestTSEG2 - 1;
667  nbtr.B.DIV8 = 0;
668  //nbtr.B.FTX = 0; /* TTCAN only */
669 
670  hwNode->BTR.U = nbtr.U;
671  }
672 }
673 
674 
675 void IfxMultican_Node_setFastBitTiming(Ifx_CAN_N *hwNode, float32 moduleFreq, uint32 baudrate, uint16 samplePoint, uint16 synchJumpWidth)
676 {
677  sint32 tempFBRP, tempFSJW, tempFTSEG1 = 12;
678  sint32 bestFBRP = 0, bestFSJW = 0, bestFTBAUD = 0, bestFTSEG1 = 1, bestFTSEG2;
679  sint32 bestError = 10000;
680 
681  /*
682  * Bit timing & sampling
683  * Tq = (BRP+1)/Fcan if DIV8 = 0
684  * Tq = 8*(BRP+1)/Fcan if DIV8 = 1
685  * TSync = 1.Tq
686  * TSeg1 = (TSEG1+1)*Tq >= 3Tq
687  * TSeg2 = (TSEG2+1)*Tq >= 2Tq
688  * Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
689  *
690  * Resynchronization:
691  *
692  * Tsjw = (SJW + 1)*Tq
693  * TSeg1 >= Tsjw + Tprop
694  * TSeg2 >= Tsjw
695  */
696 
697  /* search for best baudrate */
698  bestError = 10000;
699 
700  for (tempFBRP = 1; tempFBRP <= (0x3F + 1); tempFBRP++)
701  {
702  float32 Fquanta = moduleFreq / tempFBRP;
703  sint32 tempTBAUD = Fquanta / baudrate;
704  float32 tempBaudrate = Fquanta / tempTBAUD;
705  float32 error = __absf(tempBaudrate - baudrate);
706 
707  if ((tempTBAUD <= 20) && (bestError > error))
708  {
709  bestFBRP = tempFBRP;
710  bestFTBAUD = tempTBAUD;
711  bestError = error;
712 
713  if (error < 0.1)
714  {
715  break;
716  }
717  }
718  }
719 
720  /* search for best sample point */
721  bestError = 10000;
722 
723  for (tempFTSEG1 = 16; tempFTSEG1 >= 3; tempFTSEG1--)
724  {
725  sint32 tempSamplePoint = ((tempFTSEG1 + 1) * 10000) / bestFTBAUD;
726  sint32 error = __abs(tempSamplePoint - samplePoint);
727 
728  if (bestError > error)
729  {
730  bestFTSEG1 = tempFTSEG1;
731  bestError = error;
732  }
733 
734  if (tempSamplePoint < samplePoint)
735  {
736  break;
737  }
738  }
739 
740  bestFTSEG2 = bestFTBAUD - bestFTSEG1 - 1;
741 
742  /* search for best SJW */
743  bestError = 10000;
744 
745  for (tempFSJW = 1; tempFSJW <= 4; tempFSJW++)
746  {
747  sint32 tempSynchJumpWidth = (tempFSJW * 10000) / bestFTBAUD;
748  sint32 error = __abs(tempSynchJumpWidth - synchJumpWidth);
749 
750  if (bestError > error)
751  {
752  bestFSJW = tempFSJW;
753  bestError = error;
754  }
755  }
756 
757  {
758  Ifx_CAN_N_FBTR nfbtr;
759  nfbtr.U = 0;
760  nfbtr.B.FBRP = bestFBRP - 1;
761  nfbtr.B.FSJW = bestFSJW - 1;
762  nfbtr.B.FTSEG1 = bestFTSEG1 - 1;
763  nfbtr.B.FTSEG2 = bestFTSEG2 - 1;
764 
765  hwNode->FBTR.U = nfbtr.U;
766  }
767 }
768 
769 
770 void IfxMultican_Node_setNominalBitTiming(Ifx_CAN_N *hwNode, float32 moduleFreq, uint32 baudrate, uint16 samplePoint, uint16 synchJumpWidth)
771 {
772  sint32 tempBRP, tempSJW, tempTSEG1 = 12;
773  sint32 bestBRP = 0, bestSJW = 0, bestTBAUD = 0, bestTSEG1 = 1, bestTSEG2;
774  sint32 bestError = 10000;
775 
776  /*
777  * Bit timing & sampling
778  * Tq = (BRP+1)/Fcan if DIV8 = 0
779  * Tq = 8*(BRP+1)/Fcan if DIV8 = 1
780  * TSync = 1.Tq
781  * TSeg1 = (TSEG1+1)*Tq >= 3Tq
782  * TSeg2 = (TSEG2+1)*Tq >= 2Tq
783  * Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
784  *
785  * Resynchronization:
786  *
787  * Tsjw = (SJW + 1)*Tq
788  * TSeg1 >= Tsjw + Tprop
789  * TSeg2 >= Tsjw
790  */
791 
792  /* search for best baudrate */
793  bestError = 10000;
794 
795  for (tempBRP = 1; tempBRP <= (0x3F + 1); tempBRP++)
796  {
797  float32 Fquanta = moduleFreq / tempBRP;
798  sint32 tempTBAUD = Fquanta / baudrate;
799  float32 tempBaudrate = Fquanta / tempTBAUD;
800  float32 error = __absf(tempBaudrate - baudrate);
801 
802  if ((tempTBAUD <= 20) && (bestError > error))
803  {
804  bestBRP = tempBRP;
805  bestTBAUD = tempTBAUD;
806  bestError = error;
807 
808  if (error < 0.1)
809  {
810  break;
811  }
812  }
813  }
814 
815  /* search for best sample point */
816  bestError = 10000;
817 
818  for (tempTSEG1 = 64; tempTSEG1 >= 3; tempTSEG1--)
819  {
820  sint32 tempSamplePoint = ((tempTSEG1 + 1) * 10000) / bestTBAUD;
821  sint32 error = __abs(tempSamplePoint - samplePoint);
822 
823  if (bestError > error)
824  {
825  bestTSEG1 = tempTSEG1;
826  bestError = error;
827  }
828 
829  if (tempSamplePoint < samplePoint)
830  {
831  break;
832  }
833  }
834 
835  bestTSEG2 = bestTBAUD - bestTSEG1 - 1;
836 
837  /* search for best SJW */
838  bestError = 10000;
839 
840  for (tempSJW = 1; tempSJW <= 16; tempSJW++)
841  {
842  sint32 tempSynchJumpWidth = (tempSJW * 10000) / bestTBAUD;
843  sint32 error = __abs(tempSynchJumpWidth - synchJumpWidth);
844 
845  if (bestError > error)
846  {
847  bestSJW = tempSJW;
848  bestError = error;
849  }
850  }
851 
852  {
853  Ifx_CAN_N_BTEVR nbtevr;
854  nbtevr.U = 0;
855  nbtevr.B.BRP = bestBRP - 1;
856  nbtevr.B.SJW = bestSJW - 1;
857  nbtevr.B.TSEG1 = bestTSEG1 - 1;
858  nbtevr.B.TSEG2 = bestTSEG2 - 1;
859  nbtevr.B.DIV8 = 0;
860  //nbtr.B.FTX = 0; /* TTCAN only */
861 
862  hwNode->BTEVR.U = nbtevr.U;
863  }
864 }
865 
866 
867 void IfxMultican_calcTimingFromBTR(float32 moduleFreq, uint32 btr, uint32 *baudrate, uint16 *samplePoint, uint16 *synchJumpWidth)
868 {
869  Ifx_CAN_N_BTR nbtr = {.U = btr};
870  uint32 tempBRP = 1U + nbtr.B.BRP;
871  uint32 tempSJW = 1U + nbtr.B.SJW;
872  uint32 tempTSEG1 = 1U + nbtr.B.TSEG1;
873  uint32 tempTSEG2 = 1U + nbtr.B.TSEG2;
874  uint32 tempDIV8 = (nbtr.B.DIV8 != 0) ? 8U : 1U;
875 
876  uint32 tempTSEG = 1 + tempTSEG1 + tempTSEG2;
877 
878  *baudrate = (uint32)(moduleFreq / (float32)(tempDIV8 * tempBRP * tempTSEG));
879  *samplePoint = (uint16)(((float32)tempTSEG1) * 10000 / ((float32)(tempTSEG)));
880  *synchJumpWidth = (uint16)(((float32)tempSJW) * 10000 / ((float32)(tempTSEG)));
881 }
882 
883 
884 void IfxMultican_deinit(Ifx_CAN *mcan)
885 {
886  // should use kernel reset functionality!
887  uint16 i;
888 
889  /* Ifx_CAN.CLC is reset last */
890  for (i = 0; i < IFXMULTICAN_MO_COUNT; i++)
891  {
892  IfxMultican_MsgObj_deinit(mcan, i);
893  }
894 
895  for (i = 0; i < IFXMULTICAN_NODE_COUNT; i++)
896  {
897  Ifx_CAN_N *hwNode = IfxMultican_Node_getPointer(mcan, IfxMultican_NodeId_0 + i);
898 
899  IfxMultican_Node_deinit(hwNode);
900  }
901 
902  for (i = 0; i < IFXMULTICAN_SRC_COUNT; i++)
903  {
904  MODULE_SRC.CAN.CAN[0].INT[i].U = 0x00000000;
905  }
906 
907  for (i = 0; i < 8; i++)
908  {
909  mcan->MSPND[i].U = 0x00000000;
910  }
911 
912  mcan->MSIMASK.U = 0x00000000;
913  mcan->MCR.U = 0x00000000;
914  {
917  mcan->FDR.U = 0x00000000;
918  IfxScuWdt_setCpuEndinit(passwd);
920  mcan->CLC.U = 0x00000001;
921  IfxScuWdt_setCpuEndinit(passwd);
922  }
923 }
924 
925 
926 volatile Ifx_SRC_SRCR *IfxMultican_getSrcPointer(Ifx_CAN *mcan, IfxMultican_SrcId srcId)
927 {
928  return &(MODULE_SRC.CAN.CAN[0].INT[srcId]);
929 }
930 
931 
932 void IfxMultican_setListCommand(Ifx_CAN *mcan, uint32 cmd, uint32 arg2, uint32 arg1)
933 {
934  Ifx_CAN_PANCTR panctr;
935 
936  panctr.B.PANAR1 = arg1;
937  panctr.B.PANAR2 = arg2;
938  panctr.B.PANCMD = cmd;
939 
940  /** - write to CAN_PANCTR */
941  mcan->PANCTR.U = panctr.U;
942 
944 }