]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Can.c
f260b2b3c91b8cb3ff587b9e914613e2ed42397a
[arc.git] / arch / ppc / mpc55xx / drivers / Can.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 \r
18 \r
19 \r
20 \r
21 \r
22 \r
23 #include "Can.h"\r
24 \r
25 #ifndef USE_CAN_STUB\r
26 #include "mpc55xx.h"\r
27 #include "Cpu.h"\r
28 #include "Mcu.h"\r
29 #include "CanIf_Cbk.h"\r
30 #include "Det.h"\r
31 #if defined(USE_DEM)\r
32 #include "Dem.h"\r
33 #endif\r
34 #include <assert.h>\r
35 #include <stdlib.h>\r
36 #include <string.h>\r
37 #if defined(USE_KERNEL)\r
38 #include "Os.h"\r
39 #include "irq.h"\r
40 #include "arc.h"\r
41 #endif\r
42 \r
43 \r
44 /* CONFIGURATION NOTES\r
45  * ------------------------------------------------------------------\r
46  * - CanHandleType must be CAN_ARC_HANDLE_TYPE_BASIC\r
47  *   i.e. CanHandleType=CAN_ARC_HANDLE_TYPE_FULL NOT supported\r
48  *   i.e CanIdValue is NOT supported\r
49  * - All CanXXXProcessing must be CAN_ARC_PROCESS_TYPE_INTERRUPT\r
50  *   ie CAN_ARC_PROCESS_TYPE_POLLED not supported\r
51  * - To select the Mailboxes to use in the CAN controller use Can_Arc_MbMask\r
52  * - HOH's for Tx are global and Rx are for each controller\r
53  * - CanControllerTimeQuanta is NOT used. The other CanControllerXXX selects\r
54  *   the proper time-quanta\r
55  * - Can_Arc_MbMask for Tx HOH must NOT overlap Can_Arc_MbMask for Rx.\r
56  * - ONLY global mask is supported( NOT 14,15 and individual )\r
57  * - Numbering the CanObjectId for Tx:\r
58  *     To do this correctly there are a number of things that are good to know\r
59  *     1. HTH's have unique numbers.\r
60  *     2. One HTH/HRH is maped to one HOH\r
61  *     3. The extension Can_Arc_MbMask binds FULL CAN boxes together.\r
62  *\r
63  *     Example:\r
64  *\r
65  *     HTH   B/F C  HOH\r
66  *     ---------------------\r
67  *      0    F   0  0\r
68  *      1    F   0  1\r
69  *      ..\r
70  *      16   B   0  16  |\r
71  *                  17  |    The use of Can_Arc_MbMask=0x000f0000 binds these to HTH 16\r
72  *                  18  |    ( bits 16 to 19 set here )\r
73  *                  19  |\r
74  *           ...\r
75  *      32   ... 1  32\r
76  *\r
77  *\r
78  *        B - BASIC CAN\r
79  *        F - FULL CAN\r
80  *        C - Controller number\r
81  *\r
82  */\r
83 \r
84 /* IMPLEMENTATION NOTES\r
85  * -----------------------------------------------\r
86  * - A HOH us unique for a controller( not a config-set )\r
87  * - Hrh's are numbered for each controller from 0\r
88  * - HOH is numbered for each controller in sequences of 0-31\r
89  *   ( since we have 6 controllers and Hth is only uint8( See Can_Write() proto )\r
90  * - loopback in HW NOT supported\r
91  * - 32 of 64 boxes supported ( limited by Hth type )\r
92   * - Fifo in HW NOT supported\r
93  */\r
94 \r
95 /* ABBREVATIONS\r
96  *  -----------------------------------------------\r
97  * - Can Hardware unit - One or multiple Can controllers of the same type.\r
98  * - Hrh - HOH with receive definitions\r
99  * - Hth - HOH with transmit definitions\r
100  *\r
101  */\r
102 \r
103 /* HW INFO\r
104  * ------------------------------------------------------------------\r
105  *   This controller should really be called FlexCan+ or something because\r
106  *   it's enhanced with:\r
107  *   - A RX Fifo !!!!! ( yep, it's fantastic ;) )\r
108  *   - A better matching process. From 25.4.4\r
109  *   "By programming    more than one MB with the same ID, received messages will\r
110  *    be queued into the MBs. The CPU can examine the time stamp field of the\r
111  *    MBs to determine the order in which the messages arrived."\r
112  *\r
113  *   Soo, now it seems that Freescale have finally done something right.\r
114  */\r
115 \r
116 //-------------------------------------------------------------------\r
117 \r
118 // Number of mailboxes used for each controller ( power of 2 only )\r
119 // ( It's NOT supported to set this to 64 )\r
120 #define MAX_NUM_OF_MAILBOXES 32\r
121 \r
122 #if defined(CFG_MPC5567)\r
123 #define GET_CONTROLLER(_controller)     \\r
124                                                 ((struct FLEXCAN2_tag *)(0xFFFC0000 + 0x4000*(_controller)))\r
125 #else\r
126 #define GET_CONTROLLER(_controller)     \\r
127                                                 ((struct FLEXCAN_tag *)(0xFFFC0000 + 0x4000*(_controller)))\r
128 #endif\r
129 \r
130 #define GET_CONTROLLER_CONFIG(_controller)      \\r
131                                                 &Can_Global.config->CanConfigSet->CanController[(_controller)]\r
132 \r
133 #define GET_CALLBACKS() \\r
134                                                         (Can_Global.config->CanConfigSet->CanCallbacks)\r
135 \r
136 #define GET_PRIVATE_DATA(_controller) \\r
137                                                                         &CanUnit[_controller]\r
138 \r
139 #define GET_CONTROLLER_CNT() (CAN_CONTROLLER_CNT)\r
140 \r
141 //-------------------------------------------------------------------\r
142 \r
143 #if ( CAN_DEV_ERROR_DETECT == STD_ON )\r
144 #define VALIDATE(_exp,_api,_err ) \\r
145         if( !(_exp) ) { \\r
146           Det_ReportError(MODULE_ID_CAN,0,_api,_err); \\r
147           return CAN_NOT_OK; \\r
148         }\r
149 \r
150 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
151         if( !(_exp) ) { \\r
152           Det_ReportError(MODULE_ID_CAN,0,_api,_err); \\r
153           return; \\r
154         }\r
155 \r
156 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)\r
157 #else\r
158 #define VALIDATE(_exp,_api,_err )\r
159 #define VALIDATE_NO_RV(_exp,_api,_err )\r
160 #define DET_REPORTERROR(_x,_y,_z,_q)\r
161 #endif\r
162 \r
163 #if defined(USE_DEM)\r
164 #define VALIDATE_DEM_NO_RV(_exp,_err ) \\r
165         if( !(_exp) ) { \\r
166           Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED); \\r
167           return; \\r
168         }\r
169 #else\r
170 #define VALIDATE_DEM_NO_RV(_exp,_err )\r
171 #endif\r
172 \r
173 //-------------------------------------------------------------------\r
174 \r
175 // Message box status defines\r
176 #define MB_TX_ONCE              0xc\r
177 #define MB_INACTIVE     0x8\r
178 #define MB_RX                           0x4\r
179 #define MB_ABORT                        0x9\r
180 \r
181 //-------------------------------------------------------------------\r
182 typedef enum\r
183 {\r
184   CAN_UNINIT = 0,\r
185   CAN_READY\r
186 } Can_DriverStateType;\r
187 \r
188 typedef union {\r
189     vuint32_t R;\r
190     struct {\r
191         vuint32_t:14;\r
192         vuint32_t TWRNINT:1;\r
193         vuint32_t RWRNINT:1;\r
194         vuint32_t BIT1ERR:1;\r
195         vuint32_t BIT0ERR:1;\r
196         vuint32_t ACKERR:1;\r
197         vuint32_t CRCERR:1;\r
198         vuint32_t FRMERR:1;\r
199         vuint32_t STFERR:1;\r
200         vuint32_t TXWRN:1;\r
201         vuint32_t RXWRN:1;\r
202         vuint32_t IDLE:1;\r
203         vuint32_t TXRX:1;\r
204         vuint32_t FLTCONF:2;\r
205           vuint32_t:1;\r
206         vuint32_t BOFFINT:1;\r
207         vuint32_t ERRINT:1;\r
208         vuint32_t WAKINT:1;\r
209     } B;\r
210 } ESRType;                  /* Error and Status Register */\r
211 \r
212 #if defined(CFG_MPC5567)\r
213 typedef struct FLEXCAN2_tag flexcan_t;\r
214 #else\r
215 typedef struct FLEXCAN_tag flexcan_t;\r
216 #endif\r
217 \r
218 // Mapping between HRH and Controller//HOH\r
219 typedef struct Can_Arc_ObjectHOHMapStruct\r
220 {\r
221   uint32 HxHRef;    // Reference to HRH or HTH\r
222   CanControllerIdType CanControllerRef;    // Reference to controller\r
223   const Can_HardwareObjectType* CanHOHRef;       // Reference to HOH.\r
224 } Can_Arc_ObjectHOHMapType;\r
225 \r
226 /* Type for holding global information used by the driver */\r
227 typedef struct {\r
228   Can_DriverStateType initRun;\r
229 \r
230   // Our config\r
231   const Can_ConfigType *config;\r
232 \r
233   // One bit for each channel that is configured.\r
234   // Used to determine if validity of a channel\r
235   // 1 - configured\r
236   // 0 - NOT configured\r
237   uint32  configured;\r
238   // Maps the a channel id to a configured channel id\r
239   uint8   channelMap[CAN_CONTROLLER_CNT];\r
240 \r
241   // This is a map that maps the HTH:s with the controller and Hoh. It is built\r
242   // during Can_Init and is used to make things faster during a transmit.\r
243   Can_Arc_ObjectHOHMapType CanHTHMap[NUM_OF_HTHS];\r
244 } Can_GlobalType;\r
245 \r
246 // Global config\r
247 Can_GlobalType Can_Global =\r
248 {\r
249     .initRun = CAN_UNINIT,\r
250 };\r
251 \r
252 \r
253 /* Type for holding information about each controller */\r
254 typedef struct {\r
255   CanIf_ControllerModeType state;\r
256   uint32                lock_cnt;\r
257   // Interrupt masks that is for all Mb's in this controller\r
258   uint32                Can_Arc_RxMbMask;\r
259   uint32                Can_Arc_TxMbMask;\r
260 \r
261   // Used at IFLG in controller at startup\r
262   uint32                iflagStart;\r
263 \r
264   // Statistics\r
265   Can_Arc_StatisticsType stats;\r
266 \r
267   // Data stored for Txconfirmation callbacks to CanIf\r
268   PduIdType swPduHandles[MAX_NUM_OF_MAILBOXES];\r
269 \r
270 } Can_UnitType;\r
271 \r
272 #if defined(CFG_MPC5567)\r
273 Can_UnitType CanUnit[CAN_CONTROLLER_CNT] =\r
274 {\r
275   {\r
276     .state = CANIF_CS_UNINIT,\r
277   },{\r
278     .state = CANIF_CS_UNINIT,\r
279   },{\r
280     .state = CANIF_CS_UNINIT,\r
281   },{\r
282     .state = CANIF_CS_UNINIT,\r
283   },{\r
284     .state = CANIF_CS_UNINIT,\r
285   },\r
286 };\r
287 #elif defined(CFG_MPC5606S)\r
288 Can_UnitType CanUnit[CAN_CONTROLLER_CNT] ={\r
289   {\r
290         .state = CANIF_CS_UNINIT,\r
291   },{\r
292         .state = CANIF_CS_UNINIT,\r
293   }\r
294 };\r
295 #else\r
296 Can_UnitType CanUnit[CAN_CONTROLLER_CNT] =\r
297 {\r
298   {\r
299     .state = CANIF_CS_UNINIT,\r
300   },{\r
301     .state = CANIF_CS_UNINIT,\r
302   },{\r
303     .state = CANIF_CS_UNINIT,\r
304   },{\r
305     .state = CANIF_CS_UNINIT,\r
306   },{\r
307     .state = CANIF_CS_UNINIT,\r
308   },{\r
309     .state = CANIF_CS_UNINIT,\r
310   }\r
311 };\r
312 #endif\r
313 \r
314 //-------------------------------------------------------------------\r
315 \r
316 //-------------------------------------------------------------------\r
317 /**\r
318  * Function that finds the Hoh( HardwareObjectHandle ) from a Hth\r
319  * A HTH may connect to one or several HOH's. Just find the first one.\r
320  *\r
321  * @param hth The transmit handle\r
322  * @returns Ptr to the Hoh\r
323  */\r
324 static const Can_HardwareObjectType * Can_FindHoh( Can_Arc_HTHType hth , uint32* controller)\r
325 {\r
326   const Can_HardwareObjectType *hohObj;\r
327   const Can_Arc_ObjectHOHMapType *map;\r
328   const Can_ControllerConfigType *canHwConfig;\r
329 \r
330   map = &Can_Global.CanHTHMap[hth];\r
331 \r
332   // Verify that this is the correct map\r
333   if (map->HxHRef != hth)\r
334   {\r
335     DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);\r
336   }\r
337 \r
338   canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[map->CanControllerRef]);\r
339 \r
340   hohObj = map->CanHOHRef;\r
341 \r
342   // Verify that this is the correct Hoh type\r
343   if ( hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)\r
344   {\r
345     *controller = map->CanControllerRef;\r
346     return hohObj;\r
347   }\r
348 \r
349   DET_REPORTERROR(MODULE_ID_CAN, 0, 0x6, CAN_E_PARAM_HANDLE);\r
350 \r
351   return NULL;\r
352 }\r
353 \r
354 //-------------------------------------------------------------------\r
355 \r
356 static void Can_Isr( int unit );\r
357 static void Can_Err( int unit );\r
358 static void Can_BusOff( int unit );\r
359 \r
360 void Can_A_Isr( void  ) {       Can_Isr(CAN_CTRL_A); }\r
361 void Can_B_Isr( void  ) {       Can_Isr(CAN_CTRL_B); }\r
362 #if !defined(CFG_MPC5606S)\r
363 void Can_C_Isr( void  ) {       Can_Isr(CAN_CTRL_C); }\r
364 void Can_D_Isr( void  ) {       Can_Isr(CAN_CTRL_D); }\r
365 void Can_E_Isr( void  ) {       Can_Isr(CAN_CTRL_E); }\r
366 #if defined(CFG_MPC5567)\r
367 #else\r
368 void Can_F_Isr( void  ) {       Can_Isr(CAN_CTRL_F); }\r
369 #endif\r
370 #endif\r
371 \r
372 void Can_A_Err( void  ) {       Can_Err(CAN_CTRL_A); }\r
373 void Can_B_Err( void  ) {       Can_Err(CAN_CTRL_B); }\r
374 #if !defined(CFG_MPC5606S)\r
375 void Can_C_Err( void  ) {       Can_Err(CAN_CTRL_C); }\r
376 void Can_D_Err( void  ) {       Can_Err(CAN_CTRL_D); }\r
377 void Can_E_Err( void  ) {       Can_Err(CAN_CTRL_E); }\r
378 #if defined(CFG_MPC5567)\r
379 #else\r
380 void Can_F_Err( void  ) {       Can_Err(CAN_CTRL_F); }\r
381 #endif\r
382 #endif\r
383 \r
384 void Can_A_BusOff( void  ) {    Can_BusOff(CAN_CTRL_A); }\r
385 void Can_B_BusOff( void  ) {    Can_BusOff(CAN_CTRL_B); }\r
386 #if !defined(CFG_MPC5606S)\r
387 void Can_C_BusOff( void  ) {    Can_BusOff(CAN_CTRL_C); }\r
388 void Can_D_BusOff( void  ) {    Can_BusOff(CAN_CTRL_D); }\r
389 void Can_E_BusOff( void  ) {    Can_BusOff(CAN_CTRL_E); }\r
390 #if defined(CFG_MPC5567)\r
391 #else\r
392 void Can_F_BusOff( void  ) {    Can_BusOff(CAN_CTRL_F); }\r
393 #endif\r
394 #endif\r
395 //-------------------------------------------------------------------\r
396 \r
397 \r
398 /**\r
399  * Hardware error ISR for CAN\r
400  *\r
401  * @param unit CAN controller number( from 0 )\r
402  */\r
403 \r
404 static void Can_Err( int unit ) {\r
405   flexcan_t *canHw = GET_CONTROLLER(unit);\r
406   Can_Arc_ErrorType err;\r
407   ESRType esr;\r
408   err.R = 0;\r
409 \r
410   esr.R = canHw->ESR.R;\r
411 \r
412   err.B.ACKERR = esr.B.ACKERR;\r
413   err.B.BIT0ERR = esr.B.BIT0ERR;\r
414   err.B.BIT1ERR = esr.B.BIT1ERR;\r
415   err.B.CRCERR = esr.B.CRCERR;\r
416   err.B.FRMERR = esr.B.FRMERR;\r
417   err.B.STFERR = esr.B.STFERR;\r
418   err.B.RXWRN = esr.B.RXWRN;\r
419   err.B.TXWRN = esr.B.TXWRN;\r
420 \r
421   if (GET_CALLBACKS()->Arc_Error != NULL)\r
422   {\r
423     GET_CALLBACKS()->Arc_Error(unit, err );\r
424   }\r
425   // Clear ERRINT\r
426   canHw->ESR.B.ERRINT = 1;\r
427 }\r
428 \r
429 \r
430 // Uses 25.4.5.1 Transmission Abort Mechanism\r
431 static void Can_AbortTx( flexcan_t *canHw, Can_UnitType *canUnit ) {\r
432   uint32 mbMask;\r
433   uint8 mbNr;\r
434 \r
435         // Find our Tx boxes.\r
436   mbMask = canUnit->Can_Arc_TxMbMask;\r
437 \r
438   // Loop over the Mb's set to abort\r
439   for (; mbMask; mbMask&=~(1<<mbNr)) {\r
440     mbNr = ilog2(mbMask);\r
441 \r
442     canHw->BUF[mbNr].CS.B.CODE = MB_ABORT;\r
443 \r
444     // Did it take\r
445     if( canHw->BUF[mbNr].CS.B.CODE != MB_ABORT ) {\r
446                         // nope..\r
447 \r
448         // it's not sent... or being sent.\r
449         // Just wait for it\r
450       int i = 0;\r
451         while( canHw->IFRL.R == (1<<mbNr) )\r
452         {\r
453           i++;\r
454           if (i > 1000)\r
455             break;\r
456         }\r
457     }\r
458   }\r
459 \r
460   // Ack tx interrupts\r
461   canHw->IFRL.R = canUnit->Can_Arc_TxMbMask;\r
462   canUnit->iflagStart = canUnit->Can_Arc_TxMbMask;\r
463 }\r
464 \r
465 //-------------------------------------------------------------------\r
466 \r
467 /**\r
468  * BussOff ISR for CAN\r
469  *\r
470  * @param unit CAN controller number( from 0 )\r
471  */\r
472 static void Can_BusOff( int unit ) {\r
473   flexcan_t *canHw = GET_CONTROLLER(unit);\r
474   Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);\r
475   Can_Arc_ErrorType err;\r
476   err.R = 0;\r
477 \r
478   if ( canHw->ESR.B.TWRNINT )\r
479   {\r
480     err.B.TXWRN = canHw->ESR.B.TXWRN;\r
481     canUnit->stats.txErrorCnt++;\r
482     canHw->ESR.B.TWRNINT = 1;\r
483   }\r
484 \r
485   if ( canHw->ESR.B.RWRNINT )\r
486   {\r
487     err.B.RXWRN = canHw->ESR.B.RXWRN;\r
488     canUnit->stats.rxErrorCnt++;\r
489     canHw->ESR.B.RWRNINT = 1;\r
490   }\r
491 \r
492   if (err.R != 0)\r
493   {\r
494     if (GET_CALLBACKS()->Arc_Error != NULL)\r
495     {\r
496       GET_CALLBACKS()->Arc_Error( unit, err );\r
497     }\r
498   }\r
499 \r
500   if( canHw->ESR.B.BOFFINT ) {\r
501 \r
502     canUnit->stats.boffCnt++;\r
503     if (GET_CALLBACKS()->ControllerBusOff != NULL)\r
504     {\r
505       GET_CALLBACKS()->ControllerBusOff(unit);\r
506     }\r
507     Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272\r
508 \r
509     canHw->ESR.B.BOFFINT = 1;\r
510 \r
511     Can_AbortTx( canHw, canUnit ); // CANIF273\r
512   }\r
513 }\r
514 \r
515 //-------------------------------------------------------------------\r
516 \r
517 /**\r
518  * ISR for CAN. Normal Rx/Tx operation\r
519  *\r
520  * @param unit CAN controller number( from 0 )\r
521  */\r
522 static void Can_Isr(int unit) {\r
523 \r
524   flexcan_t *canHw= GET_CONTROLLER(unit);\r
525   const Can_ControllerConfigType *canHwConfig= GET_CONTROLLER_CONFIG(Can_Global.channelMap[unit]);\r
526   uint32 iFlagLow = canHw->IFRL.R;\r
527   Can_UnitType *canUnit = GET_PRIVATE_DATA(unit);\r
528 \r
529   // Read interrupt flags to seeTxConfirmation what interrupt triggered the interrupt\r
530   if (iFlagLow & canHw->IMRL.R) {\r
531     // Check FIFO\r
532 \r
533 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S)\r
534         // Note!\r
535         //   FIFO code NOT tested\r
536     if (canHw->MCR.B.FEN) {\r
537 \r
538       // Check overflow\r
539       if (iFlagLow & (1<<7)) {\r
540         canUnit->stats.fifoOverflow++;\r
541         canHw->IFRL.B.BUF07I = 1;\r
542       }\r
543 \r
544       // Check warning\r
545       if (iFlagLow & (1<<6)) {\r
546         canUnit->stats.fifoWarning++;\r
547         canHw->IFRL.B.BUF06I = 1;\r
548       }\r
549 \r
550       // Pop fifo "realtime"\r
551       while (canHw->IFRL.B.BUF05I) {\r
552         // At\r
553         // TODO MAHI: Must read the entire data-buffer to unlock??\r
554         if (GET_CALLBACKS()->RxIndication != NULL)\r
555         {\r
556           GET_CALLBACKS()->RxIndication((-1), canHw->BUF[0].ID.B.EXT_ID,\r
557             canHw->BUF[0].CS.B.LENGTH, (uint8 *)&canHw->BUF[0].DATA.W[0] );\r
558         }\r
559         // Clear the interrupt\r
560         canHw->IFRL.B.BUF05I = 1;\r
561       }\r
562     } else {\r
563 #endif\r
564       // No FIFO used\r
565       const Can_HardwareObjectType *hohObj;\r
566       uint32 mbMask;\r
567       uint8 mbNr = 0;\r
568       uint32 data;\r
569       Can_IdType id;\r
570 \r
571       //\r
572       // Loop over all the Hoh's\r
573       //\r
574 \r
575       // Rx\r
576       hohObj= canHwConfig->Can_Arc_Hoh;\r
577       --hohObj;\r
578       do {\r
579         ++hohObj;\r
580 \r
581         mbMask = hohObj->Can_Arc_MbMask & iFlagLow;\r
582 \r
583         if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)\r
584         {\r
585           // Loop over the Mb's for this Hoh\r
586           for (; mbMask; mbMask&=~(1<<mbNr)) {\r
587             mbNr = ilog2(mbMask);\r
588 \r
589             // Do the necessary dummy reads to keep controller happy\r
590             data = canHw->BUF[mbNr].CS.R;\r
591             data = canHw->BUF[mbNr].DATA.W[0];\r
592 \r
593             // According to autosar MSB shuould be set if extended\r
594             if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
595               id = canHw->BUF[mbNr].ID.R;\r
596               id |= 0x80000000;\r
597             } else {\r
598               id = canHw->BUF[mbNr].ID.B.STD_ID;\r
599             }\r
600 \r
601             if (GET_CALLBACKS()->RxIndication != NULL)\r
602             {\r
603               GET_CALLBACKS()->RxIndication(hohObj->CanObjectId,\r
604                                             id,\r
605                                             canHw->BUF[mbNr].CS.B.LENGTH,\r
606                                             (uint8 *)&canHw->BUF[mbNr].DATA.W[0] );\r
607             }\r
608             // Increment statistics\r
609             canUnit->stats.rxSuccessCnt++;\r
610 \r
611             // unlock MB (dummy read timer)\r
612             (void)canHw->TIMER.R;\r
613 \r
614             // Clear interrupt\r
615             canHw->IFRL.R = (1<<mbNr);\r
616           }\r
617         }\r
618       } while ( !hohObj->Can_Arc_EOL);\r
619 \r
620       // Tx\r
621       hohObj= canHwConfig->Can_Arc_Hoh;\r
622       --hohObj;\r
623       do {\r
624         ++hohObj;\r
625 \r
626         if (hohObj->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)\r
627         {\r
628           mbMask = hohObj->Can_Arc_MbMask & iFlagLow;\r
629 \r
630           // Loop over the Mb's for this Hoh\r
631           for (; mbMask; mbMask&=~(1<<mbNr)) {\r
632             mbNr = ilog2(mbMask);\r
633 \r
634             if (GET_CALLBACKS()->TxConfirmation != NULL)\r
635             {\r
636               GET_CALLBACKS()->TxConfirmation(canUnit->swPduHandles[mbNr]);\r
637             }\r
638             canUnit->swPduHandles[mbNr] = 0;  // Is this really necessary ??\r
639 \r
640             // Clear interrupt\r
641             canUnit->iflagStart |= (1<<mbNr);\r
642             canHw->IFRL.R = (1<<mbNr);\r
643           }\r
644         }\r
645       } while ( !hohObj->Can_Arc_EOL);\r
646 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S)\r
647     } // FIFO code\r
648 #endif\r
649   } else {\r
650     // Note! Over 32 boxes is not implemented\r
651     // Other reasons that we end up here\r
652     // - Interupt on a masked box\r
653   }\r
654 \r
655   if (canHwConfig->Can_Arc_Fifo) {\r
656     /*\r
657      * NOTE!!!\r
658      * Do not enable RxFIFO. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 14593].\r
659      */\r
660      \r
661         /* Note\r
662          * NOT tested at all\r
663          */\r
664     while (canHw->IFRL.B.BUF05I) {\r
665       // At\r
666       // TODO MAHI: Must read the entire data-buffer to unlock??\r
667       if (GET_CALLBACKS()->RxIndication != NULL)\r
668       {\r
669         GET_CALLBACKS()->RxIndication((-1), canHw->BUF[0].ID.B.EXT_ID,\r
670                    canHw->BUF[0].CS.B.LENGTH, (uint8 *)&canHw->BUF[0].DATA.W[0] );\r
671       }\r
672       // Increment statistics\r
673       canUnit->stats.rxSuccessCnt++;\r
674 \r
675       // Clear the interrupt\r
676       canHw->IFRL.B.BUF05I = 1;\r
677     }\r
678   }\r
679 }\r
680 \r
681 //-------------------------------------------------------------------\r
682 \r
683 #if defined(USE_KERNEL)\r
684 #define INSTALL_HANDLERS( _can_name,_boff,_err,_start,_stop) \\r
685   do { \\r
686     TaskType tid; \\r
687     tid = Os_Arc_CreateIsr(_can_name ## _BusOff,2/*prio*/,"Can"); \\r
688     Irq_AttachIsr2(tid, NULL, (IrqType) _boff); \\r
689     tid = Os_Arc_CreateIsr(_can_name ## _Err,2/*prio*/,"Can"); \\r
690     Irq_AttachIsr2(tid, NULL, (IrqType) _err); \\r
691     for(i=_start;i<=_stop;i++) {  \\r
692       tid = Os_Arc_CreateIsr(_can_name ## _Isr,2/*prio*/,"Can"); \\r
693                         Irq_AttachIsr2(tid, NULL, (IrqType) i); \\r
694     } \\r
695   } while(0);\r
696 #else\r
697 #define INSTALL_HANDLERS( _can_name,_boff,_err,_start,_stop) \\r
698   Irq_InstallVector(_can_name ## _BusOff, _boff, 1, CPU_Z1); \\r
699   Irq_InstallVector(_can_name ## _Err, _err, 1, CPU_Z1);    \\r
700   for(i=_start;i<=_stop;i++) {                                                                                                                          \\r
701     Irq_InstallVector(_can_name ## _Isr, i, 1, CPU_Z1); \\r
702   }\r
703 #endif\r
704 \r
705 // This initiates ALL can controllers\r
706 void Can_Init( const Can_ConfigType *config ) {\r
707   Can_UnitType *canUnit;\r
708   const Can_ControllerConfigType *canHwConfig;\r
709   int i;\r
710   uint32 ctlrId;\r
711 \r
712   VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), 0x0, CAN_E_TRANSITION );\r
713   VALIDATE_NO_RV( (config != NULL ), 0x0, CAN_E_PARAM_POINTER );\r
714 \r
715   // Save config\r
716   Can_Global.config = config;\r
717   Can_Global.initRun = CAN_READY;\r
718 \r
719 \r
720   for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
721     canHwConfig = GET_CONTROLLER_CONFIG(configId);\r
722     ctlrId = canHwConfig->CanControllerId;\r
723 \r
724     // Assign the configuration channel used later..\r
725     Can_Global.channelMap[canHwConfig->CanControllerId] = configId;\r
726     Can_Global.configured |= (1<<ctlrId);\r
727 \r
728     canUnit = GET_PRIVATE_DATA(ctlrId);\r
729     canUnit->state = CANIF_CS_STOPPED;\r
730 \r
731     canUnit->lock_cnt = 0;\r
732 \r
733     // Clear stats\r
734     memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));\r
735 \r
736     Can_InitController(ctlrId, canHwConfig);\r
737 \r
738     // Loop through all Hoh:s and map them into the HTHMap\r
739     const Can_HardwareObjectType* hoh;\r
740     hoh = canHwConfig->Can_Arc_Hoh;\r
741     hoh--;\r
742     do\r
743     {\r
744       hoh++;\r
745 \r
746       if (hoh->CanObjectType == CAN_OBJECT_TYPE_TRANSMIT)\r
747       {\r
748         Can_Global.CanHTHMap[hoh->CanObjectId].CanControllerRef = canHwConfig->CanControllerId;\r
749         Can_Global.CanHTHMap[hoh->CanObjectId].CanHOHRef = hoh;\r
750         Can_Global.CanHTHMap[hoh->CanObjectId].HxHRef = hoh->CanObjectId;\r
751       }\r
752     } while (!hoh->Can_Arc_EOL);\r
753 \r
754     // Note!\r
755     // Could install handlers depending on HW objects to trap more errors\r
756     // in configuration\r
757 #if defined(CFG_MPC5567)\r
758     switch( canHwConfig->CanControllerId ) {\r
759     case CAN_CTRL_A:\r
760         INSTALL_HANDLERS(Can_A, FLEXCAN_A_ESR_BOFF_INT, FLEXCAN_A_ESR_ERR_INT, FLEXCAN_A_IFLAG1_BUF0I, FLEXCAN_A_IFLAG1_BUF31_16I);     break;\r
761     case CAN_CTRL_B:\r
762         INSTALL_HANDLERS(Can_B, FLEXCAN_B_ESR_BOFF_INT, FLEXCAN_B_ESR_ERR_INT, FLEXCAN_B_IFLAG1_BUF0I, FLEXCAN_B_IFLAG1_BUF31_16I);     break;\r
763     case CAN_CTRL_C:\r
764         INSTALL_HANDLERS(Can_C, FLEXCAN_C_ESR_BOFF_INT, FLEXCAN_C_ESR_ERR_INT, FLEXCAN_C_IFLAG1_BUF0I, FLEXCAN_C_IFLAG1_BUF31_16I);     break;\r
765     case CAN_CTRL_D:\r
766         INSTALL_HANDLERS(Can_D, FLEXCAN_D_ESR_BOFF_INT, FLEXCAN_D_ESR_ERR_INT, FLEXCAN_D_IFLAG1_BUF0I, FLEXCAN_D_IFLAG1_BUF31_16I);     break;\r
767     case CAN_CTRL_E:\r
768         INSTALL_HANDLERS(Can_E, FLEXCAN_E_ESR_BOFF_INT, FLEXCAN_E_ESR_ERR_INT, FLEXCAN_E_IFLAG1_BUF0I, FLEXCAN_E_IFLAG1_BUF31_16I);     break;\r
769     default:\r
770         assert(0);\r
771     }\r
772 #elif defined(CFG_MPC5606S)\r
773     switch( canHwConfig->CanControllerId )\r
774     {\r
775         case CAN_CTRL_A:\r
776             INSTALL_HANDLERS(Can_A, FLEXCAN_0_ESR_BOFF_INT, FLEXCAN_0_ESR_ERR_INT, FLEXCAN_0_BUF_00_03, FLEXCAN_0_BUF_32_63);\r
777             break;\r
778         case CAN_CTRL_B:\r
779             INSTALL_HANDLERS(Can_B, FLEXCAN_1_ESR_BOFF_INT, FLEXCAN_1_ESR_ERR_INT, FLEXCAN_1_BUF_00_03, FLEXCAN_1_BUF_32_63);\r
780             break;\r
781         default:\r
782             assert(0);\r
783     }\r
784 #else\r
785     switch( canHwConfig->CanControllerId ) {\r
786     case CAN_CTRL_A:\r
787         INSTALL_HANDLERS(Can_A, FLEXCAN_A_ESR_BOFF_INT, FLEXCAN_A_ESR_ERR_INT, FLEXCAN_A_IFLAG1_BUF0I, FLEXCAN_A_IFLAG1_BUF31_16I);     break;\r
788     case CAN_CTRL_B:\r
789         INSTALL_HANDLERS(Can_B, FLEXCAN_B_ESR_BOFF_INT, FLEXCAN_B_ESR_ERR_INT, FLEXCAN_B_IFLAG1_BUF0I, FLEXCAN_B_IFLAG1_BUF31_16I);     break;\r
790     case CAN_CTRL_C:\r
791         INSTALL_HANDLERS(Can_C, FLEXCAN_C_ESR_BOFF_INT, FLEXCAN_C_ESR_ERR_INT, FLEXCAN_C_IFLAG1_BUF0I, FLEXCAN_C_IFLAG1_BUF31_16I);     break;\r
792     case CAN_CTRL_D:\r
793         INSTALL_HANDLERS(Can_D, FLEXCAN_D_ESR_BOFF_INT, FLEXCAN_D_ESR_ERR_INT, FLEXCAN_D_IFLAG1_BUF0I, FLEXCAN_D_IFLAG1_BUF31_16I);     break;\r
794     case CAN_CTRL_E:\r
795         INSTALL_HANDLERS(Can_E, FLEXCAN_E_ESR_BOFF_INT, FLEXCAN_E_ESR_ERR_INT, FLEXCAN_E_IFLAG1_BUF0I, FLEXCAN_E_IFLAG1_BUF31_16I);     break;\r
796     case CAN_CTRL_F:\r
797         INSTALL_HANDLERS(Can_F, FLEXCAN_F_ESR_BOFF_INT, FLEXCAN_F_ESR_ERR_INT, FLEXCAN_F_IFLAG1_BUF0I, FLEXCAN_F_IFLAG1_BUF31_16I);     break;\r
798     default:\r
799         assert(0);\r
800     }\r
801 #endif\r
802   }\r
803   return;\r
804 }\r
805 \r
806 // Unitialize the module\r
807 void Can_DeInit()\r
808 {\r
809   Can_UnitType *canUnit;\r
810   const Can_ControllerConfigType *canHwConfig;\r
811   uint32 ctlrId;\r
812 \r
813   for (int configId=0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
814     canHwConfig = GET_CONTROLLER_CONFIG(configId);\r
815     ctlrId = canHwConfig->CanControllerId;\r
816 \r
817     canUnit = GET_PRIVATE_DATA(ctlrId);\r
818     canUnit->state = CANIF_CS_UNINIT;\r
819 \r
820     Can_DisableControllerInterrupts(ctlrId);\r
821 \r
822     canUnit->lock_cnt = 0;\r
823 \r
824     // Clear stats\r
825     memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));\r
826   }\r
827 \r
828   Can_Global.config = NULL;\r
829   Can_Global.initRun = CAN_UNINIT;\r
830 \r
831   return;\r
832 }\r
833 \r
834 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config) {\r
835 \r
836   flexcan_t *canHw;\r
837   uint8_t tq;\r
838   uint8_t tq1;\r
839   uint8_t tq2;\r
840   uint32_t clock;\r
841   int i;\r
842   Can_UnitType *canUnit;\r
843   uint8 cId = controller;\r
844   const Can_ControllerConfigType *canHwConfig;\r
845   const Can_HardwareObjectType *hohObj;\r
846 \r
847   VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), 0x2, CAN_E_UNINIT );\r
848   VALIDATE_NO_RV( (config != NULL ), 0x2,CAN_E_PARAM_POINTER);\r
849   VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x2, CAN_E_PARAM_CONTROLLER );\r
850 \r
851   canUnit = GET_PRIVATE_DATA(controller);\r
852 \r
853   VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), 0x2, CAN_E_TRANSITION );\r
854 \r
855   canHw = GET_CONTROLLER(cId);\r
856   canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[cId]);\r
857 \r
858   // Start this baby up\r
859   canHw->MCR.B.MDIS = 0;\r
860 \r
861   // Wait for it to reset\r
862   if( !SIMULATOR() ) {\r
863     // Make a reset so we have a known state\r
864     //canHw->MCR.B.SOFTRST = 1;  /* commented out for step-in debug mode */\r
865     //while( canHw->MCR.B.SOFTRST == 1);\r
866     // Freeze to write all mem mapped registers ( see 25.4.8.1 )\r
867     canHw->MCR.B.FRZ = 1;\r
868     //while( canHw->MCR.B.FRZACK == 0);\r
869   }\r
870 \r
871 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S)\r
872   // Note!\r
873   // FIFO implemenation not tested\r
874   if( config->Can_Arc_Fifo ) {\r
875     canHw->MCR.B.FEN = 1;       // Enable FIFO\r
876     canHw->MCR.B.IDAM = 0;      // We want extended id's to match with\r
877   }\r
878   canHw->MCR.B.BCC = 1; // Enable all nice features\r
879 #endif\r
880   /* Use Fsys derivate */\r
881   canHw->CR.B.CLKSRC = 1;\r
882   canHw->MCR.B.MAXMB = MAX_NUM_OF_MAILBOXES - 1;\r
883 \r
884   /* Disable selfreception */\r
885   canHw->MCR.B.SRXDIS = !config->Can_Arc_Loopback;\r
886 \r
887   // Clock calucation\r
888   // -------------------------------------------------------------------\r
889   //\r
890   // * 1 TQ = Sclk period( also called SCK )\r
891   // * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk\r
892   //   ( Fcanclk can come from crystal or from the peripheral dividers )\r
893   //\r
894   // -->\r
895   // TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )\r
896   // TQ is between 8 and 25\r
897 \r
898   // Calculate the number of timequanta's\r
899   // From "Protocol Timing"( chap. 25.4.7.4 )\r
900   tq1 = ( config->CanControllerPropSeg + config->CanControllerSeg1 + 2);\r
901   tq2 = (config->CanControllerSeg2 + 1);\r
902   tq = 1 + tq1 + tq2;\r
903 \r
904   // Check TQ limitations..\r
905   VALIDATE_DEM_NO_RV(( (tq1>=4) && (tq1<=16)), CAN_E_TIMEOUT );\r
906   VALIDATE_DEM_NO_RV(( (tq2>=2) && (tq2<=8)), CAN_E_TIMEOUT );\r
907   VALIDATE_DEM_NO_RV(( (tq>8) && (tq<25 )), CAN_E_TIMEOUT );\r
908 \r
909   // Assume we're using the peripheral clock instead of the crystal.\r
910   clock = McuE_GetPeripheralClock( (McuE_PeriperalClock_t) config->CanCpuClockRef );\r
911 \r
912   canHw->CR.B.PRESDIV = clock/(config->CanControllerBaudRate*1000*tq) - 1;\r
913   canHw->CR.B.PROPSEG = config->CanControllerPropSeg;\r
914   canHw->CR.B.PSEG1 = config->CanControllerSeg1;\r
915   canHw->CR.B.PSEG2 = config->CanControllerSeg2;\r
916   canHw->CR.B.SMP =     1;      // 3 samples better than 1 ??\r
917   canHw->CR.B.LPB =     config->Can_Arc_Loopback;\r
918   canHw->CR.B.BOFFREC = 1;  // Disable bus off recovery\r
919 \r
920   SIU.PSMI[0].R = 0x00;\r
921   SIU.PSMI[1].R = 0x00;\r
922 \r
923 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S)\r
924   // Check if we use individual masks. If so accept anything(=0) for now\r
925   if( canHw->MCR.B.BCC ) {\r
926     i = (config->Can_Arc_Fifo ? 8 : 0 );\r
927     for(;i<63;i++) {\r
928       canHw->RXIMR[i].R = 0;\r
929     }\r
930   }\r
931 #endif\r
932 #if defined(CFG_MPC5567)\r
933   // Enable individual Rx ID masking and the reception queue features.\r
934   canHw->MCR.B.MBFEN = 1;\r
935 #endif\r
936   // Set the id's\r
937   if( config->Can_Arc_Fifo ) {\r
938     // Clear ID's in FIFO also, MUST set extended bit here\r
939     uint32_t *fifoId = (uint32_t*)(((uint8_t *)canHw)+0xe0);\r
940     for(int k=0;k<8;k++) {\r
941       fifoId[k] = 0x40000000;   // accept extended frames\r
942     }\r
943   }\r
944 \r
945   // Mark all slots as inactive( depending on fifo )\r
946   i = (config->Can_Arc_Fifo ? 8 : 0 );\r
947   for(; i < 63; i++) {\r
948     //canHw->BUF[i].CS.B.CODE = 0;\r
949     canHw->BUF[i].CS.R = 0;\r
950     canHw->BUF[i].ID.R = 0;\r
951   }\r
952 \r
953   {\r
954     /* Build a global interrupt/mb mask for all Hoh's */\r
955     uint32 mbMask;\r
956     uint32 mbNr = 0;\r
957     Can_FilterMaskType mask = 0xffffffff;\r
958 \r
959     // Rx\r
960     hohObj = canHwConfig->Can_Arc_Hoh;\r
961     --hohObj;\r
962     do {\r
963       ++hohObj;\r
964 \r
965       mbMask = hohObj->Can_Arc_MbMask;\r
966       mbNr = 0;\r
967 \r
968       if (hohObj->CanObjectType == CAN_OBJECT_TYPE_RECEIVE)\r
969       {\r
970         for(;mbMask;mbMask&=~(1<<mbNr)) {\r
971           mbNr = ilog2(mbMask);\r
972           canHw->BUF[mbNr].CS.B.CODE = MB_RX;\r
973           if ( hohObj->CanIdType == CAN_ID_TYPE_EXTENDED )\r
974           {\r
975             canHw->BUF[mbNr].CS.B.IDE = 1;\r
976 #if defined(CFG_MPC5567)\r
977             canHw->RXIMR[mbNr].B.MI = *hohObj->CanFilterMaskRef;\r
978 #else\r
979             canHw->BUF[mbNr].ID.R = *hohObj->CanFilterMaskRef; // Write 29-bit MB IDs\r
980 #endif\r
981           }\r
982           else\r
983           {\r
984             canHw->BUF[mbNr].CS.B.IDE = 0;\r
985 #if defined(CFG_MPC5567)\r
986             canHw->RXIMR[mbNr].B.MI = *hohObj->CanFilterMaskRef;\r
987 #else\r
988             canHw->BUF[mbNr].ID.B.STD_ID = *hohObj->CanFilterMaskRef;\r
989 #endif\r
990          }\r
991         }\r
992 \r
993         // Add to global mask\r
994         canUnit->Can_Arc_RxMbMask |= hohObj->Can_Arc_MbMask;\r
995         if( hohObj->CanFilterMaskRef != NULL  ) {\r
996           mask &= *hohObj->CanFilterMaskRef;\r
997         }\r
998       }\r
999       else\r
1000       {\r
1001         canUnit->Can_Arc_TxMbMask |= hohObj->Can_Arc_MbMask;\r
1002       }\r
1003     } while( !hohObj->Can_Arc_EOL );\r
1004 \r
1005 #if defined(CFM_MPC5567)\r
1006 #else\r
1007     // Set global mask\r
1008     canHw->RXGMASK.R = mask;\r
1009     // Don't use them\r
1010     canHw->RX14MASK.R = 0;\r
1011     canHw->RX15MASK.R = 0;\r
1012 #endif\r
1013   }\r
1014 \r
1015   canUnit->iflagStart = canUnit->Can_Arc_TxMbMask;\r
1016 \r
1017   canUnit->state = CANIF_CS_STOPPED;\r
1018   Can_EnableControllerInterrupts(cId);\r
1019 \r
1020   return;\r
1021 }\r
1022 \r
1023 \r
1024 Can_ReturnType Can_SetControllerMode( uint8 controller, Can_StateTransitionType transition ) {\r
1025   flexcan_t *canHw;\r
1026   Can_ReturnType rv = CAN_OK;\r
1027   VALIDATE( (controller < GET_CONTROLLER_CNT()), 0x3, CAN_E_PARAM_CONTROLLER );\r
1028 \r
1029   Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);\r
1030 \r
1031   VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), 0x3, CAN_E_UNINIT );\r
1032   canHw = GET_CONTROLLER(controller);\r
1033 \r
1034   switch(transition )\r
1035   {\r
1036   case CAN_T_START:\r
1037     canHw->MCR.B.FRZ = 0;\r
1038     canHw->MCR.B.HALT = 0;\r
1039     canUnit->state = CANIF_CS_STARTED;\r
1040     imask_t state = McuE_EnterCriticalSection();\r
1041     if (canUnit->lock_cnt == 0)   // REQ CAN196\r
1042     {\r
1043       Can_EnableControllerInterrupts(controller);\r
1044     }\r
1045     McuE_ExitCriticalSection(state);\r
1046     break;\r
1047   case CAN_T_WAKEUP:  //CAN267\r
1048   case CAN_T_SLEEP:  //CAN258, CAN290\r
1049     // Should be reported to DEM but DET is the next best\r
1050     VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
1051   case CAN_T_STOP:\r
1052     // Stop\r
1053     canHw->MCR.B.FRZ = 1;\r
1054     canHw->MCR.B.HALT = 1;\r
1055     canUnit->state = CANIF_CS_STOPPED;\r
1056     Can_AbortTx( canHw, canUnit ); // CANIF282\r
1057     break;\r
1058   default:\r
1059     // Should be reported to DEM but DET is the next best\r
1060     VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
1061     break;\r
1062   }\r
1063 \r
1064   return rv;\r
1065 }\r
1066 \r
1067 void Can_DisableControllerInterrupts( uint8 controller )\r
1068 {\r
1069   Can_UnitType *canUnit;\r
1070   flexcan_t *canHw;\r
1071 \r
1072   VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x4, CAN_E_PARAM_CONTROLLER );\r
1073 \r
1074   canUnit = GET_PRIVATE_DATA(controller);\r
1075 \r
1076   VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x4, CAN_E_UNINIT );\r
1077 \r
1078   imask_t state = McuE_EnterCriticalSection();\r
1079   if(canUnit->lock_cnt > 0 )\r
1080   {\r
1081     // Interrupts already disabled\r
1082     canUnit->lock_cnt++;\r
1083     McuE_ExitCriticalSection(state);\r
1084     return;\r
1085   }\r
1086   canUnit->lock_cnt++;\r
1087   McuE_ExitCriticalSection(state);\r
1088 \r
1089   /* Don't try to be intelligent, turn everything off */\r
1090   canHw = GET_CONTROLLER(controller);\r
1091 \r
1092   /* Turn off the interrupt mailboxes */\r
1093   canHw->IMRH.R = 0;\r
1094   canHw->IMRL.R = 0;\r
1095 \r
1096   /* Turn off the bus off/tx warning/rx warning and error */\r
1097   canHw->MCR.B.WRNEN = 0;       /* Disable warning int */\r
1098   canHw->CR.B.ERRMSK = 0;       /* Disable error interrupt */\r
1099   canHw->CR.B.BOFFMSK = 0;      /* Disable bus-off interrupt */\r
1100   canHw->CR.B.TWRNMSK = 0;      /* Disable Tx warning */\r
1101   canHw->CR.B.RWRNMSK = 0;      /* Disable Rx warning */\r
1102 }\r
1103 \r
1104 void Can_EnableControllerInterrupts( uint8 controller ) {\r
1105   Can_UnitType *canUnit;\r
1106   flexcan_t *canHw;\r
1107   const Can_ControllerConfigType *canHwConfig;\r
1108   VALIDATE_NO_RV( (controller < GET_CONTROLLER_CNT()), 0x5, CAN_E_PARAM_CONTROLLER );\r
1109 \r
1110   canUnit = GET_PRIVATE_DATA(controller);\r
1111 \r
1112   VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), 0x5, CAN_E_UNINIT );\r
1113 \r
1114   imask_t state = McuE_EnterCriticalSection();\r
1115   if( canUnit->lock_cnt > 1 )\r
1116   {\r
1117     // IRQ should still be disabled so just decrement counter\r
1118     canUnit->lock_cnt--;\r
1119     McuE_ExitCriticalSection(state);\r
1120     return;\r
1121   } else if (canUnit->lock_cnt == 1)\r
1122   {\r
1123     canUnit->lock_cnt = 0;\r
1124   }\r
1125   McuE_ExitCriticalSection(state);\r
1126 \r
1127   canHw = GET_CONTROLLER(controller);\r
1128 \r
1129   canHwConfig = GET_CONTROLLER_CONFIG(Can_Global.channelMap[controller]);\r
1130 \r
1131   canHw->IMRH.R = 0;\r
1132   canHw->IMRL.R = 0;\r
1133 \r
1134   if( canHwConfig->CanRxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {\r
1135     /* Turn on the interrupt mailboxes */\r
1136     canHw->IMRL.R = canUnit->Can_Arc_RxMbMask;\r
1137   }\r
1138 \r
1139   if( canHwConfig->CanTxProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {\r
1140     /* Turn on the interrupt mailboxes */\r
1141     canHw->IMRL.R |= canUnit->Can_Arc_TxMbMask;\r
1142   }\r
1143 \r
1144   // BusOff here represents all errors and warnings\r
1145   if( canHwConfig->CanBusOffProcessing == CAN_ARC_PROCESS_TYPE_INTERRUPT ) {\r
1146     canHw->MCR.B.WRNEN = 1;     /* Turn On warning int */\r
1147 \r
1148     canHw->CR.B.ERRMSK = 1;     /* Enable error interrupt */\r
1149     canHw->CR.B.BOFFMSK = 1;    /* Enable bus-off interrupt */\r
1150     canHw->CR.B.TWRNMSK = 1;    /* Enable Tx warning */\r
1151     canHw->CR.B.RWRNMSK = 1;    /* Enable Rx warning */\r
1152   }\r
1153 \r
1154   return;\r
1155 }\r
1156 \r
1157 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo ) {\r
1158   uint16_t timer;\r
1159   uint32_t iflag;\r
1160   Can_ReturnType rv = CAN_OK;\r
1161   uint32_t mbNr;\r
1162   flexcan_t *canHw;\r
1163   const Can_HardwareObjectType *hohObj;\r
1164   uint32 controller;\r
1165   uint32 oldMsr;\r
1166 \r
1167   VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );\r
1168   VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );\r
1169   VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );\r
1170   VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );\r
1171 \r
1172   hohObj = Can_FindHoh(hth, &controller);\r
1173   if (hohObj == NULL)\r
1174     return CAN_NOT_OK;\r
1175 \r
1176   Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);\r
1177 \r
1178   canHw = GET_CONTROLLER(controller);\r
1179   oldMsr = McuE_EnterCriticalSection();\r
1180   iflag = canHw->IFRL.R & canUnit->Can_Arc_TxMbMask;\r
1181 \r
1182   // check for any free box\r
1183   // Normally we would just use the iflag to get the free box\r
1184   // but that does not work the first time( iflag == 0 ) so we\r
1185   // create one( iflagStart )\r
1186   if( iflag | canUnit->iflagStart ) {\r
1187     mbNr =  ilog2((iflag | canUnit->iflagStart));       // find mb number\r
1188     // clear flag\r
1189     canHw->IFRL.R = (1<<mbNr);\r
1190     canUnit->iflagStart &= ~(1<<mbNr);\r
1191 \r
1192     // Setup message box type\r
1193     if( hohObj->CanIdType == CAN_ID_TYPE_EXTENDED ) {\r
1194       canHw->BUF[mbNr].CS.B.IDE = 1;\r
1195     } else if ( hohObj->CanIdType == CAN_ID_TYPE_STANDARD ) {\r
1196       canHw->BUF[mbNr].CS.B.IDE = 0;\r
1197     } else {\r
1198       // No support for mixed in this processor\r
1199       assert(0);\r
1200     }\r
1201 \r
1202     // Send on buf\r
1203     canHw->BUF[mbNr].CS.B.CODE = MB_INACTIVE;   // Hold the transmit buffer inactive\r
1204     if( hohObj->CanIdType == CAN_ID_TYPE_EXTENDED ) {\r
1205       canHw->BUF[mbNr].ID.R = pduInfo->id; // Write 29-bit MB IDs\r
1206     } else {\r
1207       assert( !(pduInfo->id & 0xfffff800) );\r
1208       canHw->BUF[mbNr].ID.B.STD_ID = pduInfo->id;\r
1209     }\r
1210 \r
1211 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S)\r
1212     canHw->BUF[mbNr].ID.B.PRIO = 1;                     // Set Local Priority\r
1213 #endif\r
1214 \r
1215     memset(&canHw->BUF[mbNr].DATA, 0, 8);\r
1216     memcpy(&canHw->BUF[mbNr].DATA, pduInfo->sdu, pduInfo->length);\r
1217 \r
1218     canHw->BUF[mbNr].CS.B.SRR = 1;\r
1219     canHw->BUF[mbNr].CS.B.RTR = 0;\r
1220 \r
1221     canHw->BUF[mbNr].CS.B.LENGTH = pduInfo->length;\r
1222     canHw->BUF[mbNr].CS.B.CODE = MB_TX_ONCE;                    // Write tx once code\r
1223     timer = canHw->TIMER.R;                                             // Unlock Message buffers\r
1224 \r
1225     canUnit->stats.txSuccessCnt++;\r
1226 \r
1227     // Store pdu handle in unit to be used by TxConfirmation\r
1228     canUnit->swPduHandles[mbNr] = pduInfo->swPduHandle;\r
1229 \r
1230   } else {\r
1231     rv = CAN_BUSY;\r
1232   }\r
1233   McuE_ExitCriticalSection(oldMsr);\r
1234 \r
1235   return rv;\r
1236 }\r
1237 \r
1238 void Can_MainFunction_Read( void ) {\r
1239 \r
1240         /* NOT SUPPORTED */\r
1241 }\r
1242 \r
1243 void Can_MainFunction_BusOff( void ) {\r
1244   /* Bus-off polling events */\r
1245 \r
1246         /* NOT SUPPORTED */\r
1247 }\r
1248 \r
1249 void Can_MainFunction_Wakeup( void ) {\r
1250   /* Wakeup polling events */\r
1251 \r
1252         /* NOT SUPPORTED */\r
1253 }\r
1254 \r
1255 \r
1256 /**\r
1257  * Get send/receive/error statistics for a controller\r
1258  *\r
1259  * @param controller The controller\r
1260  * @param stats Pointer to data to copy statistics to\r
1261  */\r
1262 \r
1263 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType *stats)\r
1264 {\r
1265   Can_UnitType *canUnit = GET_PRIVATE_DATA(controller);\r
1266   *stats = canUnit->stats;\r
1267 }\r
1268 \r
1269 \r
1270 \r
1271 #else // Stub all functions for use in simulator environment\r
1272 \r
1273 #include "debug.h"\r
1274 \r
1275 void Can_Init( const Can_ConfigType *Config )\r
1276 {\r
1277   // Do initial configuration of layer here\r
1278 }\r
1279 \r
1280 void Can_InitController( uint8 controller, const Can_ControllerConfigType *config)\r
1281 {\r
1282         // Do initialisation of controller here.\r
1283 }\r
1284 \r
1285 Can_ReturnType Can_SetControllerMode( uint8 Controller, Can_StateTransitionType transition )\r
1286 {\r
1287         // Turn on off controller here depending on transition\r
1288         return E_OK;\r
1289 }\r
1290 \r
1291 Can_ReturnType Can_Write( Can_Arc_HTHType hth, Can_PduType *pduInfo )\r
1292 {\r
1293         // Write to mailbox on controller here.\r
1294         DEBUG(DEBUG_MEDIUM, "Can_Write(stub): Received data ");\r
1295         for (int i = 0; i < pduInfo->length; i++) {\r
1296                 DEBUG(DEBUG_MEDIUM, "%d ", pduInfo->sdu[i]);\r
1297         }\r
1298         DEBUG(DEBUG_MEDIUM, "\n");\r
1299 \r
1300         return E_OK;\r
1301 }\r
1302 \r
1303 extern void CanIf_RxIndication(uint8 Hrh, Can_IdType CanId, uint8 CanDlc, const uint8 *CanSduPtr);\r
1304 Can_ReturnType Can_ReceiveAFrame()\r
1305 {\r
1306         // This function is not part of autosar but needed to feed the stack with data\r
1307         // from the mailboxes. Normally this is an interrup but probably not in the PCAN case.\r
1308         uint8 CanSduData[] = {1,2,1,0,0,0,0,0};\r
1309         CanIf_RxIndication(CAN_HRH_A_1, 3, 8, CanSduData);\r
1310 \r
1311         return E_OK;\r
1312 }\r
1313 \r
1314 void Can_DisableControllerInterrupts( uint8 controller )\r
1315 {\r
1316 }\r
1317 \r
1318 void Can_EnableControllerInterrupts( uint8 controller )\r
1319 {\r
1320 }\r
1321 \r
1322 \r
1323 // Hth - for Flexcan, the hardware message box number... .We don't care\r
1324 void Can_Cbk_CheckWakeup( uint8 controller ){}\r
1325 \r
1326 void Can_MainFunction_Write( void ){}\r
1327 void Can_MainFunction_Read( void ){}\r
1328 void Can_MainFunction_BusOff( void ){}\r
1329 void Can_MainFunction_Wakeup( void ){}\r
1330 \r
1331 void Can_Arc_GetStatistics( uint8 controller, Can_Arc_StatisticsType * stat){}\r
1332 \r
1333 #endif\r
1334 \r
1335 \r