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