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