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