iLLD_TC29x  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 message reading from the message object
36  * \param hwObj Pointer to CAN message object registers
37  * \param msg This parameter is filled in by the function with the received message. Also when reading is not successful.
38  * \return None
39  */
40 static void IfxMultican_MsgObj_doReadMessage(Ifx_CAN_MO *hwObj, IfxMultican_Message *msg);
41 
42 /******************************************************************************/
43 /*-------------------------Function Implementations---------------------------*/
44 /******************************************************************************/
45 
46 boolean IfxMultican_MsgObj_cancelSend(Ifx_CAN_MO *hwObj)
47 {
48  boolean result = FALSE;
49  Ifx_CAN_MO_CTR ctr;
50  Ifx_CAN_MO_STAT stat;
51 
52  stat.U = hwObj->STAT.U;
53 
54  if ((stat.B.TXRQ != 0) && (stat.B.NEWDAT != 0))
55  {
56  ctr.U = 0;
57  ctr.B.RESRTSEL = 1; /* take out from transmission */
58  hwObj->CTR.U = ctr.U;
59  result = TRUE;
60  }
61 
62  return result;
63 }
64 
65 
67 {
68  Ifx_CAN_MO_CTR ctr;
69  ctr.U = 0;
70  ctr.U = 1U << flag;
71 
72  hwObj->CTR.U = ctr.U;
73 }
74 
75 
76 void IfxMultican_MsgObj_deinit(Ifx_CAN *mcan, IfxMultican_MsgObjId msgObjId)
77 {
78  Ifx_CAN_MO *hwObj = IfxMultican_MsgObj_getPointer(mcan, msgObjId);
79  /* Remove the message object from any node */
80  /* Append message object to the end of the list */
81  IfxMultican_setListCommand(mcan, 0x2, 0, msgObjId);
82 
83  hwObj->CTR.U = 0x0000FFFFUL; /* to be written first */
84 
85  hwObj->FCR.U = 0x00000000UL;
86  hwObj->FGPR.U = 0x00000000UL;
87  hwObj->IPR.U = 0x00000000UL;
88  hwObj->AMR.U = 0x3FFFFFFFUL;
89  hwObj->DATAL.U = 0x00000000UL;
90  hwObj->DATAH.U = 0x00000000UL;
91  hwObj->AR.U = 0x00000000UL;
92 }
93 
94 
95 static void IfxMultican_MsgObj_doReadMessage(Ifx_CAN_MO *hwObj, IfxMultican_Message *msg)
96 {
97  /* for standard message object and FIFO message objects*/
99 
100  /* read the data from the data registers */
101  msg->data[0] = hwObj->DATAL.U;
102  msg->data[1] = hwObj->DATAH.U;
103 
104  /* copy the length code from hardware */
106 
107  /* copy the ID from the hardware */
108  msg->id = IfxMultican_MsgObj_getMessageId(hwObj);
109 }
110 
111 
113 {
114  uint32 index = mcan->MSID[msgObjGroup].U;
115  IfxMultican_MsgObjId msgObjId = -1;
116 
117  if (index != 0x20U)
118  {
119  mcan->MSPND[msgObjGroup].U = ~(1UL << index);
120  msgObjId = index + (msgObjGroup << 5);
121  }
122 
123  return msgObjId;
124 }
125 
126 
128 {
129  IfxMultican_MsgObjStat status;
130 
131  status.U = hwObj->STAT.U;
132 
133  return status;
134 }
135 
136 
138 {
139  uint32 shift = (1U << flag);
140 
141  return (hwObj->STAT.U & shift) ? TRUE : FALSE;
142 }
143 
144 
146 {
148 
149  /* if new data available in the message object */
150  if (hwObj->STAT.B.NEWDAT != 0)
151  {
152  Ifx_CAN_MO_STAT stat;
153  IfxMultican_MsgObj_doReadMessage(hwObj, msg);
154  stat = hwObj->STAT; /* Cache the status after reading to reduce message lost propability */
155 
156  if (stat.B.RXUPD != 0)
157  { /* Data might be inconsistent (update while reading), declare as message lost, data will be read next time the API is called */
159  }
160  else if (stat.B.NEWDAT != 0)
161  { /* Data might be inconsistent (update while reading), force massage lost flag, read new incoming data */
162  Ifx_CAN_MO_STAT stat2;
164  /* perform read from the hardware */
165  IfxMultican_MsgObj_doReadMessage(hwObj, msg);
166 
167  stat2 = hwObj->STAT; /* Cache the status after reading */
168 
169  if ((stat2.B.NEWDAT == 0) && (stat2.B.RXUPD == 0))
170  {
171  status |= IfxMultican_Status_newData;
172  }
173  else
174  { /* Return message lost at 2nd read attempt, data will be read next time the API is called*/
175  }
176  }
177  else
178  {
180  }
181 
182  if (stat.B.MSGLST != 0)
183  { /* At least on message has been lost */
186  }
187  }
188  else
189  {
191  }
192 
193  return status;
194 }
195 
196 
198 {
200 
201  if (hwObj->STAT.B.TXRQ)
202  { /* previous message was not transferred, e.g. due to busy bus, BUS-OFF or others */
204  }
205  else
206  {
207  /* MSGVAL: Set message as not valid */
209 
210  /* for standard and FIFO message object */
211  hwObj->DATAL.U = msg->data[0]; /* Set the new data */
212  hwObj->DATAH.U = msg->data[1]; /* Set the new data */
213 
214  /* for standard and FIFO message object */
215  {
216  /* set ID */
217  boolean extendedFrame = IfxMultican_MsgObj_isExtendedFrame(hwObj);
218  IfxMultican_MsgObj_setMessageId(hwObj, msg->id, extendedFrame);
219 
220  /* standard frame */
221  /* set data length code */
223  }
224 
225  /* --- flags configuration --- */
226 
227  /* for standard and FIFO message object */
228  {
229  /* set new data flag */
231 
232  /* set message as valid, in case of FIFO mSGVAL has to be set before setting it to each slave object */
234 
235  /* set TXRQ, should not be set for FIFO base object */
237  }
238  }
239 
240  return status;
241 }
242 
243 
244 void IfxMultican_MsgObj_setFilter(Ifx_CAN_MO *hwObj, boolean extend, uint32 id, uint32 accMask)
245 {
246  Ifx_CAN_MO_CTR ctr;
247 
248  ctr.U = 0;
249  ctr.B.RESMSGVAL = 1; /* MSGVAL: Set message as not valid */
250  hwObj->CTR.U = ctr.U;
251 
252  hwObj->AMR.B.AM = accMask << ((extend != 0) ? 0 : 18);
253  hwObj->AR.B.IDE = (id << ((extend != 0) ? 0 : 18)) | (extend << 29);
254 
255  ctr.U = 0;
256  ctr.B.SETMSGVAL = 1; /* MSGVAL: Set message as valid */
257  hwObj->CTR.U = ctr.U;
258 }
259 
260 
262 {
263  Ifx_CAN_MO_CTR ctr;
264  ctr.U = 0;
265 
266  ctr.U = 1U << (flag + 16);
267 
268  hwObj->CTR.U = ctr.U;
269 }
270 
271 
272 void IfxMultican_Node_deinit(Ifx_CAN_N *hwNode)
273 {
274  hwNode->CR.U = 0x00000001;
275  hwNode->SR.U = 0x00000000;
276  hwNode->IPR.U = 0x00000000;
277  hwNode->PCR.U = 0x00000000;
278  hwNode->BTR.U = 0x00000000;
279  hwNode->ECNT.U = 0x00600000;
280  hwNode->FCR.U = 0x00000000;
281 }
282 
283 
285 {
286  IfxPort_setPinModeInput(rxd->pin.port, rxd->pin.pinIndex, mode);
287  hwNode->PCR.B.RXSEL = rxd->select;
288 
289  return TRUE;
290 }
291 
292 
294 {
295  IfxPort_setPinModeOutput(txd->pin.port, txd->pin.pinIndex, mode, txd->select);
297 
298  return TRUE;
299 }
300 
301 
303 {
305 
306  boolean busOffState = hwNode->SR.B.BOFF;
307  boolean errorWarningStatus = hwNode->SR.B.EWRN;
308 
309  /* if the node is in bus off state, initiaite the recovery process */
310  if ((busOffState != 0) && (hwNode->ECNT.B.TEC > 254))
311  {
312  status = IfxMultican_Status_busOff;
313 
314  /* reset error counters */
315  hwNode->ECNT.B.TEC = 0x01;
316  hwNode->ECNT.B.REC = 0x01;
317 
318  /* clear error warning status */
319  hwNode->SR.B.EWRN = 0;
320 
321  /* clear ALERT status */
322  hwNode->SR.B.ALERT = 0;
323 
324  /* disable node INIT = 1 */
326  }
327 
328  /* during recovery process, if REC counter reaches 0x60 */
329  else if ((busOffState != 0) && (errorWarningStatus != 0))
330  {
332  }
333 
334  /* if the recovery process is been finished or not in Bus off mode */
335  else if ((busOffState == 0) && (errorWarningStatus == 0))
336  {
337  /* enable node INIT = 0 */
339 
340  status = IfxMultican_Status_ok;
341  }
342 
343  return status;
344 }
345 
346 
347 void IfxMultican_Node_setBitTiming(Ifx_CAN_N *hwNode, float32 moduleFreq, uint32 baudrate, uint16 samplePoint, uint16 synchJumpWidth)
348 {
349  sint32 tempBRP, tempSJW, tempTSEG1 = 12;
350  sint32 bestBRP = 0, bestSJW = 0, bestTBAUD = 0, bestTSEG1 = 1, bestTSEG2;
351  sint32 bestError = 10000;
352 
353  /*
354  * Bit timing & sampling
355  * Tq = (BRP+1)/Fcan if DIV8 = 0
356  * Tq = 8*(BRP+1)/Fcan if DIV8 = 1
357  * TSync = 1.Tq
358  * TSeg1 = (TSEG1+1)*Tq >= 3Tq
359  * TSeg2 = (TSEG2+1)*Tq >= 2Tq
360  * Bit Time = TSync + TSeg1 + TSeg2 >= 8Tq
361  *
362  * Resynchronization:
363  *
364  * Tsjw = (SJW + 1)*Tq
365  * TSeg1 >= Tsjw + Tprop
366  * TSeg2 >= Tsjw
367  */
368 
369  /* search for best baudrate */
370  bestError = 10000;
371 
372  for (tempBRP = 1; tempBRP <= (0x3F + 1); tempBRP++)
373  {
374  float32 Fquanta = moduleFreq / tempBRP;
375  sint32 tempTBAUD = Fquanta / baudrate;
376  float32 tempBaudrate = Fquanta / tempTBAUD;
377  float32 error = __absf(tempBaudrate - baudrate);
378 
379  if ((tempTBAUD <= 20) && (bestError > error))
380  {
381  bestBRP = tempBRP;
382  bestTBAUD = tempTBAUD;
383  bestError = error;
384 
385  if (error < 0.1)
386  {
387  break;
388  }
389  }
390  }
391 
392  /* search for best sample point */
393  bestError = 10000;
394 
395  for (tempTSEG1 = 16; tempTSEG1 >= 3; tempTSEG1--)
396  {
397  sint32 tempSamplePoint = ((tempTSEG1 + 1) * 10000) / bestTBAUD;
398  sint32 error = __abs(tempSamplePoint - samplePoint);
399 
400  if (bestError > error)
401  {
402  bestTSEG1 = tempTSEG1;
403  bestError = error;
404  }
405 
406  if (tempSamplePoint < samplePoint)
407  {
408  break;
409  }
410  }
411 
412  bestTSEG2 = bestTBAUD - bestTSEG1 - 1;
413 
414  /* search for best SJW */
415  bestError = 10000;
416 
417  for (tempSJW = 1; tempSJW <= 4; tempSJW++)
418  {
419  sint32 tempSynchJumpWidth = (tempSJW * 10000) / bestTBAUD;
420  sint32 error = __abs(tempSynchJumpWidth - synchJumpWidth);
421 
422  if (bestError > error)
423  {
424  bestSJW = tempSJW;
425  bestError = error;
426  }
427  }
428 
429  {
430  Ifx_CAN_N_BTR nbtr;
431  nbtr.U = 0;
432  nbtr.B.BRP = bestBRP - 1;
433  nbtr.B.SJW = bestSJW - 1;
434  nbtr.B.TSEG1 = bestTSEG1 - 1;
435  nbtr.B.TSEG2 = bestTSEG2 - 1;
436  nbtr.B.DIV8 = 0;
437  //nbtr.B.FTX = 0; /* TTCAN only */
438 
439  hwNode->BTR.U = nbtr.U;
440  }
441 }
442 
443 
444 void IfxMultican_calcTimingFromBTR(float32 moduleFreq, uint32 btr, uint32 *baudrate, uint16 *samplePoint, uint16 *synchJumpWidth)
445 {
446  Ifx_CAN_N_BTR nbtr = {.U = btr};
447  uint32 tempBRP = 1U + nbtr.B.BRP;
448  uint32 tempSJW = 1U + nbtr.B.SJW;
449  uint32 tempTSEG1 = 1U + nbtr.B.TSEG1;
450  uint32 tempTSEG2 = 1U + nbtr.B.TSEG2;
451  uint32 tempDIV8 = (nbtr.B.DIV8 != 0) ? 8U : 1U;
452 
453  uint32 tempTSEG = 1 + tempTSEG1 + tempTSEG2;
454 
455  *baudrate = (uint32)(moduleFreq / (float32)(tempDIV8 * tempBRP * tempTSEG));
456  *samplePoint = (uint16)(((float32)tempTSEG1) * 10000 / ((float32)(tempTSEG)));
457  *synchJumpWidth = (uint16)(((float32)tempSJW) * 10000 / ((float32)(tempTSEG)));
458 }
459 
460 
461 void IfxMultican_deinit(Ifx_CAN *mcan)
462 {
463  // should use kernel reset functionality!
464  uint16 i;
465 
466  /* Ifx_CAN.CLC is reset last */
467  for (i = 0; i < IFXMULTICAN_NUM_MESSAGE_OBJECTS; i++)
468  {
469  IfxMultican_MsgObj_deinit(mcan, i);
470  }
471 
472  for (i = 0; i < IFXMULTICAN_NUM_NODES; i++)
473  {
474  Ifx_CAN_N *hwNode = IfxMultican_Node_getPointer(mcan, IfxMultican_NodeId_0 + i);
475 
476  IfxMultican_Node_deinit(hwNode);
477  }
478 
479  for (i = 0; i < IFXMULTICAN_NUM_SRC; i++)
480  {
481  MODULE_SRC.CAN.CAN[0].INT[i].U = 0x00000000;
482  }
483 
484  for (i = 0; i < 8; i++)
485  {
486  mcan->MSPND[i].U = 0x00000000;
487  }
488 
489  mcan->MSIMASK.U = 0x00000000;
490  mcan->MCR.U = 0x00000000;
491  {
494  mcan->FDR.U = 0x00000000;
495  IfxScuWdt_setCpuEndinit(passwd);
497  mcan->CLC.U = 0x00000001;
498  IfxScuWdt_setCpuEndinit(passwd);
499  }
500 }
501 
502 
503 volatile Ifx_SRC_SRCR *IfxMultican_getSrcPointer(Ifx_CAN *mcan, IfxMultican_SrcId srcId)
504 {
505  return &(MODULE_SRC.CAN.CAN[0].INT[srcId]);
506 }
507 
508 
509 void IfxMultican_resetModule(Ifx_CAN *can)
510 {
512 
514  can->KRST0.B.RST = 1; /* Only if both Kernel reset bits are set a reset is executed */
515  can->KRST1.B.RST = 1;
516  IfxScuWdt_setCpuEndinit(passwd);
517 
518  while (0 == can->KRST0.B.RSTSTAT) /* Wait until reset is executed */
519 
520  {}
521 
523  can->KRSTCLR.B.CLR = 1; /* Clear Kernel reset status bit */
524  IfxScuWdt_setCpuEndinit(passwd);
525 }
526 
527 
528 void IfxMultican_setListCommand(Ifx_CAN *mcan, uint32 cmd, uint32 arg2, uint32 arg1)
529 {
530  Ifx_CAN_PANCTR panctr;
531 
532  panctr.B.PANAR1 = arg1;
533  panctr.B.PANAR2 = arg2;
534  panctr.B.PANCMD = cmd;
535 
536  /** - write to CAN_PANCTR */
537  mcan->PANCTR.U = panctr.U;
538 
540 }