]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Can.c
Re-added generic callout stubs file for Dcm (with make rule).
[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 /** @reqSettings DEFAULT_SPECIFICATION_REVISION=3.1.5 */\r
17 \r
18 /* Code TODO\r
19  * - REMOVE1\r
20  * - REMOVE2\r
21  * - Enable SOFT_RESET to guarantee that we get the same state every time\r
22  *   (do in Can_InitController ?)\r
23  */\r
24 \r
25 /* ----------------------------[information]----------------------------------*/\r
26 /*\r
27  * Author: mahi\r
28  *\r
29  * Part of Release:\r
30  *   3.1.5\r
31  *\r
32  * Description:\r
33  *   Implements the Can Driver module\r
34  *\r
35  * Support:\r
36  *   General                  Have Support\r
37  *   -------------------------------------------\r
38  *   CAN_DEV_ERROR_DETECT            Y\r
39  *   CAN_HW_TRANSMIT_CANCELLATION    N\r
40  *   CAN_IDENTICAL_ID_CANCELLATION   N\r
41  *   CAN_INDEX                       N\r
42  *   CAN_MULTIPLEXED_TRANSMISSION    N\r
43  *   CAN_TIMEOUT_DURATION            N\r
44  *   CAN_VERSION_INFO_API            N\r
45  *\r
46  *   Controller                  Have Support\r
47  *   -------------------------------------------\r
48  *   CAN_BUSOFF_PROCESSING           N  , Interrupt only\r
49  *   CAN_RX_PROCESSING               N  , Interrupt only\r
50  *   CAN_TX_PROCESSING               N  , Interrupt only\r
51  *   CAN_WAKEUP_PROCESSING           N  , Interrupt only\r
52  *   CAN_CPU_CLOCK_REFERENCE         N  , *)\r
53  *   CanWakeupSourceRef              N  , **)\r
54  *\r
55  *   *) It assumes that there is a PERIPHERAL clock defined.\r
56  *   **) The flexcan hardware cannot detect wakeup (at least now the ones\r
57  *       this driver supports)\r
58  *\r
59  *   Devices    CLK_SRC\r
60  *   ----------------------------------------------\r
61  *   MPC5604B   ?\r
62  *   MPC5606S   Only sys-clk it seems\r
63  *   MPC551x    Both sys-clk and XOSC, See 3.3\r
64  *   MPC5567    ?\r
65  *   MPC5668    ?\r
66  *\r
67  *   MPC5554 is NOT supported (no individual mask)\r
68  *\r
69  * Implementation Notes:\r
70  *   - Individual RXMASKs are always ON. No support for "old" chips.\r
71  *   FIFO\r
72  *   - Is always ON.\r
73  *   - Is masked ONLY against 8 extended IDs\r
74  *   - Have depth 6, with 8 ID and 8 RXMASK\r
75  *\r
76  *   MBOX ALLOCATION\r
77  *     RX\r
78  *       - First 8 boxes always allocated for RX FIFO\r
79  *       - software filter for RX FIFO, to identify the right HRH.\r
80  *       - HRHs are global indexed from 00\r
81  *     TX\r
82  *       - One HTH for each HOH (the HOH can have a number of mailboxes, in sequence)\r
83  *       - HTHs are global (at least for each driver) indexed from 0\r
84  *\r
85  *    EXAMPLE ALLOCATION\r
86  *      0 ,\r
87  *      1  |\r
88  *      2  |\r
89  *      3  |   RX FIFO -> software lookup to map to right HTH\r
90  *      4  |              1 FULL_CAN    HOH_0\r
91  *      5  |              1 BASIC_CAN   HOH_1\r
92  *      6  |\r
93  *      7 ยด\r
94  *\r
95  *      8   RX FULL_CAN  -  HOH_2\r
96  *      9   RX FULL_CAN  -  HOH_3\r
97  *      10  RX BASIC_CAN  - HOH_4   |  RX with 2 boxes\r
98  *      11                - HOH_4   |\r
99  *      12  TX FULL_CAN   - HOH_5\r
100  *      13  TX BASIC_CAN  - HOH_6   |  TX with 2 boxes\r
101  *      14                - HOH_6   |\r
102  *\r
103  *    LOOKUP\r
104  *      TX\r
105  *        Can_Write(..) sends with HTH as argument. We need find the HOH first\r
106  *        and then find one or more TX mailboxes.\r
107  *      RX\r
108  *        TODO.\r
109  *\r
110  *    RAM USAGE:\r
111  *      A "Can Unit":\r
112  *      - mbToHrh, max 64  (could be moved to const... but PB problems?)\r
113  *      - swPduHandles, max 64*2\r
114  *      Global:\r
115  *      - Can_HthToUnitIdMap, Number of HTHs\r
116  *      - Can_HthToHohMap, Number of HTHs\r
117 \r
118  *  64 + 64*2 = 192*2 =\r
119  *\r
120  *  OBJECT MODEL\r
121  *\r
122  *     Can_ControllerConfigType\r
123  *     |--- Can_Arc_Hoh -->  CanHardwareObjectConfig_CTRL_A\r
124  *\r
125  *     CanHardwareObjectConfig_CTRL_A\r
126  *     |--- CanObjectId\r
127  *\r
128  *\r
129  *\r
130  *\r
131  * Things left:\r
132  *   All tags. Tags only on public functions now.\r
133  *\r
134  */\r
135 \r
136 \r
137 /* ----------------------------[includes]------------------------------------*/\r
138 #include "Can.h"\r
139 #include <stdio.h>\r
140 #include "mpc55xx.h"\r
141 #include "Cpu.h"\r
142 #include "Mcu.h"\r
143 #include "CanIf_Cbk.h"\r
144 #include "Det.h"\r
145 #if defined(USE_DEM)\r
146 #include "Dem.h"\r
147 #endif\r
148 #include <assert.h>\r
149 #include <stdlib.h>\r
150 #include <string.h>\r
151 #include "Os.h"\r
152 #include "isr.h"\r
153 #include "irq.h"\r
154 #include "arc.h"\r
155 //#define USE_LDEBUG_PRINTF\r
156 #include "debug.h"\r
157 \r
158 \r
159 /* ----------------------------[private define]------------------------------*/\r
160 \r
161 #define MAX_NUM_OF_MAILBOXES    64\r
162 #define USE_CAN_STATISTICS      STD_OFF\r
163 \r
164 // Message box status defines\r
165 #define MB_TX_ONCE              0xc\r
166 #define MB_INACTIVE             0x8\r
167 #define MB_RX                   0x4\r
168 #define MB_ABORT                0x9\r
169 #define MB_RX_OVERRUN           0x6\r
170 \r
171 /* ----------------------------[private macro]-------------------------------*/\r
172 \r
173 #define CTRL_TO_UNIT_PTR(_controller)   &CanUnit[Can_Global.config->CanConfigSet->ArcCtrlToUnit[_controller]]\r
174 #define VALID_CONTROLLER(_ctrl)         (Can_Global.configuredMask & (1<<(_ctrl)))\r
175 #define GET_CALLBACKS()                 (Can_Global.config->CanConfigSet->CanCallbacks)\r
176 #define GET_CONTROLLER(_controller)     \\r
177                                                 ((struct FLEXCAN_tag *)(0xFFFC0000 + 0x4000*(_controller)))\r
178 \r
179 #define INSTALL_HANDLER4(_name, _can_entry, _vector, _priority, _app)\\r
180         do { \\r
181                 ISR_INSTALL_ISR2(_name, _can_entry, _vector+0, _priority, _app); \\r
182                 ISR_INSTALL_ISR2(_name, _can_entry, _vector+1, _priority, _app); \\r
183                 ISR_INSTALL_ISR2(_name, _can_entry, _vector+2, _priority, _app); \\r
184                 ISR_INSTALL_ISR2(_name, _can_entry, _vector+3, _priority, _app); \\r
185         } while(0)\r
186 \r
187 #define INSTALL_HANDLER16(_name, _can_entry, _vector, _priority, _app)\\r
188         do { \\r
189                 INSTALL_HANDLER4(_name, _can_entry, _vector+0, _priority, _app); \\r
190                 INSTALL_HANDLER4(_name, _can_entry, _vector+4, _priority, _app); \\r
191                 INSTALL_HANDLER4(_name, _can_entry, _vector+8, _priority, _app); \\r
192                 INSTALL_HANDLER4(_name, _can_entry, _vector+12,_priority, _app); \\r
193         } while(0)\r
194 \r
195 //-------------------------------------------------------------------\r
196 \r
197 #if ( CAN_DEV_ERROR_DETECT == STD_ON )\r
198 #define VALIDATE(_exp,_api,_err ) \\r
199         if( !(_exp) ) { \\r
200           Det_ReportError(MODULE_ID_CAN,0,_api,_err); \\r
201           return CAN_NOT_OK; \\r
202         }\r
203 \r
204 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
205         if( !(_exp) ) { \\r
206           Det_ReportError(MODULE_ID_CAN,0,_api,_err); \\r
207           return; \\r
208         }\r
209 \r
210 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)\r
211 #else\r
212 #define VALIDATE(_exp,_api,_err )\r
213 #define VALIDATE_NO_RV(_exp,_api,_err )\r
214 #define DET_REPORTERROR(_x,_y,_z,_q)\r
215 #endif\r
216 \r
217 #if defined(USE_DEM)\r
218 #define VALIDATE_DEM_NO_RV(_exp,_err ) \\r
219         if( !(_exp) ) { \\r
220           Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED); \\r
221           return; \\r
222         }\r
223 #else\r
224 #define VALIDATE_DEM_NO_RV(_exp,_err )\r
225 #endif\r
226 \r
227 \r
228 /* ----------------------------[private typedef]-----------------------------*/\r
229 \r
230 \r
231 typedef struct FLEXCAN_tag flexcan_t;\r
232 \r
233 #if defined(CFG_CAN_TEST)\r
234 Can_TestType Can_Test;\r
235 #endif\r
236 \r
237 typedef enum {\r
238     CAN_UNINIT = 0, CAN_READY\r
239 } Can_DriverStateType;\r
240 \r
241 \r
242 typedef union {\r
243     vuint32_t R;\r
244     struct {\r
245         vuint32_t :14;\r
246         vuint32_t TWRNINT :1;\r
247         vuint32_t RWRNINT :1;\r
248         vuint32_t BIT1ERR :1;\r
249         vuint32_t BIT0ERR :1;\r
250         vuint32_t ACKERR :1;\r
251         vuint32_t CRCERR :1;\r
252         vuint32_t FRMERR :1;\r
253         vuint32_t STFERR :1;\r
254         vuint32_t TXWRN :1;\r
255         vuint32_t RXWRN :1;\r
256         vuint32_t IDLE :1;\r
257         vuint32_t TXRX :1;\r
258         vuint32_t FLTCONF :2;\r
259         vuint32_t :1;\r
260         vuint32_t BOFFINT :1;\r
261         vuint32_t ERRINT :1;\r
262         vuint32_t WAKINT :1;\r
263     } B;\r
264 } ESRType; /* Error and Status Register */\r
265 \r
266 \r
267 /* Type for holding global information used by the driver */\r
268 typedef struct {\r
269     Can_DriverStateType     initRun;            /* If Can_Init() have been run */\r
270     const Can_ConfigType *  config;             /* Pointer to config */\r
271     uint32                  configuredMask;     /* What units are configured */\r
272 } Can_GlobalType;\r
273 \r
274 \r
275 /* Type for holding information about each controller */\r
276 typedef struct {\r
277     /* This unit have uses controller */\r
278     CanControllerIdType                 controllerId;\r
279     CanIf_ControllerModeType            state;\r
280     const Can_ControllerConfigType *    cfgCtrlPtr;     /* Pointer to controller config  */\r
281     const Can_HardwareObjectType *      cfgHohPtr;     /* List of HOHs */\r
282     flexcan_t *                         hwPtr;\r
283     uint32      lock_cnt;\r
284     uint64      Can_Arc_RxMbMask;\r
285     uint64      Can_Arc_TxMbMask;\r
286     uint64      mbTxFree;\r
287     uint8_t     mbMax;                              /* Max number of mailboxes used for this unit */\r
288 //    PduIdType   swPduHandles[MAX_NUM_OF_MAILBOXES]; /* Data stored for Txconfirmation callbacks to CanIf */\r
289 //    uint8_t     mbToHrh[MAX_NUM_OF_MAILBOXES];      /* Mapping from mailbox to HRH */\r
290 #if (USE_CAN_STATISTICS == STD_ON)\r
291     Can_Arc_StatisticsType stats;\r
292 #endif\r
293 } Can_UnitType;\r
294 \r
295 /* ----------------------------[private function prototypes]-----------------*/\r
296 static void Can_Isr(int unit);\r
297 static void Can_Err(int unit);\r
298 static void Can_BusOff(int unit);\r
299 \r
300 /* ----------------------------[private variables]---------------------------*/\r
301 \r
302 Can_UnitType    CanUnit[CAN_ARC_CTRL_CONFIG_CNT];\r
303 Can_GlobalType  Can_Global = { .initRun = CAN_UNINIT, };\r
304 /* Used by ISR */\r
305 //uint8_t         Can_CtrlToUnitMap[CAN_ARC_CTRL_CONFIG_CNT];\r
306 /* Used by Can_Write() */\r
307 //uint8_t         Can_HthToUnitIdMap[NUM_OF_HTHS];\r
308 //uint8_t         Can_HthToHohMap[NUM_OF_HTHS];\r
309 \r
310 /* ----------------------------[private functions]---------------------------*/\r
311 \r
312 static void clearMbFlag( flexcan_t * hw,  uint8_t mb ) {\r
313     if( mb >= 32) {\r
314         hw->IFRH.R = (1<<(mb-32));\r
315     } else {\r
316         hw->IFRL.R = (1<<mb);\r
317     }\r
318 }\r
319 \r
320 static inline uint64_t ilog2_64( uint64_t val ) {\r
321     uint32_t t = val >> 32;\r
322 \r
323     if( t != 0) {\r
324         return ilog2(t) + 32;\r
325     }\r
326     return ilog2((uint32_t)val);\r
327 }\r
328 \r
329 void Can_A_Isr(void)\r
330 {\r
331     Can_Isr(CAN_CTRL_A);\r
332 }\r
333 void Can_B_Isr(void)\r
334 {\r
335     Can_Isr(CAN_CTRL_B);\r
336 }\r
337 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)\r
338 void Can_C_Isr( void ) {Can_Isr(CAN_CTRL_C);}\r
339 void Can_D_Isr( void ) {Can_Isr(CAN_CTRL_D);}\r
340 void Can_E_Isr( void ) {Can_Isr(CAN_CTRL_E);}\r
341 #endif\r
342 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)\r
343 void Can_F_Isr( void ) {Can_Isr(CAN_CTRL_F);}\r
344 #endif\r
345 \r
346 void Can_A_Err(void)\r
347 {\r
348     Can_Err(CAN_CTRL_A);\r
349 }\r
350 void Can_B_Err(void)\r
351 {\r
352     Can_Err(CAN_CTRL_B);\r
353 }\r
354 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)\r
355 void Can_C_Err( void ) {Can_Err(CAN_CTRL_C);}\r
356 void Can_D_Err( void ) {Can_Err(CAN_CTRL_D);}\r
357 void Can_E_Err( void ) {Can_Err(CAN_CTRL_E);}\r
358 #endif\r
359 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)\r
360 void Can_F_Err( void ) {Can_Err(CAN_CTRL_F);}\r
361 #endif\r
362 \r
363 void Can_A_BusOff(void)\r
364 {\r
365     Can_BusOff(CAN_CTRL_A);\r
366 }\r
367 void Can_B_BusOff(void)\r
368 {\r
369     Can_BusOff(CAN_CTRL_B);\r
370 }\r
371 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)\r
372 void Can_C_BusOff( void ) {Can_BusOff(CAN_CTRL_C);}\r
373 void Can_D_BusOff( void ) {Can_BusOff(CAN_CTRL_D);}\r
374 void Can_E_BusOff( void ) {Can_BusOff(CAN_CTRL_E);}\r
375 #endif\r
376 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)\r
377 void Can_F_BusOff( void ) {Can_BusOff(CAN_CTRL_F);}\r
378 #endif\r
379 //-------------------------------------------------------------------\r
380 \r
381 #if defined(CFG_CAN_TEST)\r
382 Can_TestType * Can_Arc_GetTestInfo( void ) {\r
383         return &Can_Test;\r
384 }\r
385 #endif\r
386 \r
387 /**\r
388  * Hardware error ISR for CAN\r
389  *\r
390  * @param unit CAN controller number( from 0 )\r
391  */\r
392 \r
393 static void Can_Err(int unit)\r
394 {\r
395     flexcan_t *canHw = GET_CONTROLLER(unit);\r
396     Can_Arc_ErrorType err;\r
397     ESRType esr;\r
398     const ESRType esrWrite = { .B.ERRINT = 1 };\r
399     err.R = 0;\r
400 \r
401     /* Clear bits 16-23 by read */\r
402     esr.R = canHw->ESR.R;\r
403     if(esr.B.ERRINT == 1)\r
404     {\r
405                 if (GET_CALLBACKS()->Arc_Error != NULL) {\r
406                         GET_CALLBACKS()->Arc_Error(unit, err);\r
407                 }\r
408 \r
409                 Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272 Same handling as for busoff\r
410 \r
411                 // Clear ERRINT\r
412                 canHw->ESR.R = esrWrite.R;\r
413     }\r
414 }\r
415 \r
416 /**\r
417  *\r
418  * @param canHw\r
419  * @param canUnit\r
420  */\r
421 // Uses 25.4.5.1 Transmission Abort Mechanism\r
422 static void Can_AbortTx(flexcan_t *canHw, Can_UnitType *canUnit)\r
423 {\r
424  uint64_t mbMask;\r
425     uint8 mbNr;\r
426     // Find our Tx boxes.\r
427     mbMask = canUnit->Can_Arc_TxMbMask;\r
428     // Loop over the Mb's set to abort\r
429     for (; mbMask; mbMask &= ~(1ull << mbNr)) {\r
430         mbNr = ilog2_64(mbMask);\r
431         canHw->BUF[mbNr].CS.B.CODE = MB_ABORT;\r
432         // Did it take\r
433         if (canHw->BUF[mbNr].CS.B.CODE != MB_ABORT) {\r
434             // nope..\r
435             /* it's not sent... or being sent.\r
436              * Just wait for it\r
437              */\r
438             int i = 0;\r
439             while (*(uint64_t *) (&canHw->IFRH.R) & (1ull << mbNr)) {\r
440                 i++;\r
441                 if (i > 1000) {\r
442                     break;\r
443                 }\r
444             }\r
445         }\r
446 \r
447         // Clear interrupt\r
448         clearMbFlag(canHw,mbNr);\r
449         canUnit->mbTxFree |= (1ull << mbNr);\r
450     }\r
451 }\r
452 \r
453 \r
454 \r
455 /**\r
456  * BusOff ISR for CAN\r
457  *\r
458  * @param unit CAN controller number( from 0 )\r
459  */\r
460 static void Can_BusOff(int unit)\r
461 {\r
462     flexcan_t *canHw = GET_CONTROLLER(unit);\r
463     Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(unit);\r
464     Can_Arc_ErrorType err;\r
465     err.R = 0;\r
466 \r
467 #if (USE_CAN_STATISTICS == STD_ON)\r
468     if (canHw->ESR.B.TWRNINT) {\r
469         err.B.TXWRN = canHw->ESR.B.TXWRN;\r
470         canUnit->stats.txErrorCnt++;\r
471         canHw->ESR.B.TWRNINT = 1;\r
472     }\r
473 \r
474     if (canHw->ESR.B.RWRNINT) {\r
475         err.B.RXWRN = canHw->ESR.B.RXWRN;\r
476         canUnit->stats.rxErrorCnt++;\r
477         canHw->ESR.B.RWRNINT = 1;\r
478     }\r
479 #endif\r
480 \r
481     if (canHw->ESR.B.BOFFINT) {\r
482 #if (USE_CAN_STATISTICS == STD_ON)\r
483         canUnit->stats.boffCnt++;\r
484 #endif\r
485         if (GET_CALLBACKS()->ControllerBusOff != NULL) {\r
486             GET_CALLBACKS()->ControllerBusOff(unit);\r
487         }\r
488         Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272\r
489 \r
490         canHw->ESR.B.BOFFINT = 1;\r
491 \r
492         Can_AbortTx(canHw, canUnit); // CANIF273\r
493 \r
494         if (canHw->CR.B.BOFFREC) {\r
495                 canHw->CR.B.BOFFREC = 0;\r
496                 canHw->CR.B.BOFFREC = 1;\r
497         }\r
498     }\r
499 }\r
500 \r
501 /**\r
502  *\r
503  * @param uPtr\r
504  */\r
505 static void Can_Isr_Tx(Can_UnitType *uPtr)\r
506 {\r
507     uint8 mbNr;\r
508     flexcan_t *canHw;\r
509     PduIdType pduId;\r
510 \r
511 \r
512     canHw = uPtr->hwPtr;\r
513 \r
514     uint64_t mbMask = *(uint64_t *) (&canHw->IFRH.R);\r
515     mbMask &= uPtr->Can_Arc_TxMbMask;\r
516 \r
517     /*\r
518      * Tx\r
519      */\r
520 #if defined(CFG_CAN_TEST)\r
521     Can_Test.mbMaskTx |= mbMask;\r
522 #endif\r
523 \r
524 \r
525     for (; mbMask; mbMask &= ~(1ull << mbNr)) {\r
526         mbNr = ilog2_64(mbMask);\r
527 \r
528         pduId = uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart];\r
529         uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart] = 0;\r
530 \r
531         // Clear interrupt and mark txBox as Free\r
532         clearMbFlag(canHw,mbNr);\r
533         uPtr->mbTxFree |= (1ull << mbNr);\r
534 \r
535         if (GET_CALLBACKS()->TxConfirmation != NULL) {\r
536             GET_CALLBACKS()->TxConfirmation(pduId);\r
537         }\r
538     }\r
539 }\r
540 \r
541 static void Can_Isr_Rx(Can_UnitType *uPtr)\r
542 {\r
543     uint8 mbNr;\r
544     uint32 id;\r
545     uint32 mask;\r
546     uint32 tmp = 0;\r
547 \r
548     flexcan_t *canHw;\r
549     const Can_HardwareObjectType *hohPtr;\r
550 \r
551     canHw = uPtr->hwPtr;\r
552 \r
553     uint64_t iFlag = *(uint64_t*) (&canHw->IFRH.R);\r
554 \r
555 #if defined(CFG_CAN_TEST)\r
556     Can_Test.mbMaskRx |= iFlag & uPtr->Can_Arc_RxMbMask;\r
557 #endif\r
558 \r
559     while (iFlag & uPtr->Can_Arc_RxMbMask) {\r
560 \r
561         /* Find mailbox */\r
562         mbNr = ilog2_64(iFlag & uPtr->Can_Arc_RxMbMask);\r
563 \r
564         /* Check for FIFO interrupt */\r
565         if (canHw->MCR.B.FEN && ((uint32_t)iFlag & (1 << 5))) {\r
566 \r
567                 tmp++;\r
568 //              if( tmp > 2) {\r
569 //                      while(1){}\r
570 //              }\r
571 \r
572             /* Check overflow */\r
573             if (iFlag & (1 << 7)) {\r
574 #if (USE_CAN_STATISTICS == STD_ON)\r
575                 uPtr->stats.fifoOverflow++;\r
576 #endif\r
577                 canHw->IFRL.B.BUF07I = 1;\r
578 \r
579                 DET_REPORTERROR(MODULE_ID_CAN,0,0, CAN_E_DATALOST); /** @req 4.0.3/CAN395 */\r
580             }\r
581 \r
582 #if (USE_CAN_STATISTICS == STD_ON)\r
583             /* Check warning */\r
584             if (iFlag & (1 << 6)) {\r
585                 uPtr->stats.fifoWarning++;\r
586                 canHw->IFRL.B.BUF06I = 1;\r
587             }\r
588 #endif\r
589 \r
590             /* The manual is "fuzzy" here, read control and status */\r
591             (void) canHw->BUF[0].CS.R;\r
592 \r
593             if (canHw->BUF[0].CS.B.IDE) {\r
594                 id = canHw->BUF[0].ID.R;\r
595                 id |= 0x80000000;\r
596             } else {\r
597                 id = canHw->BUF[0].ID.B.STD_ID;\r
598             }\r
599 \r
600             LDEBUG_PRINTF("FIFO_ID=%x  ",(unsigned int)id);\r
601 \r
602             /* Must now do a manual match to find the right CanHardwareObject\r
603              * to pass to CanIf. We know that the FIFO objects are sorted first.\r
604              */\r
605             hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;\r
606 \r
607             /* Match in order */\r
608             vuint32_t *fifoIdPtr = (vuint32_t *) &canHw->BUF[6];\r
609 \r
610 \r
611             for (uint8 fifoNr = 0; fifoNr < uPtr->cfgCtrlPtr->Can_Arc_HohFifoCnt; fifoNr++) {\r
612                 mask = canHw->RXIMR[fifoNr].R;\r
613 \r
614                 if ((id & mask) != (fifoIdPtr[fifoNr] & mask)) {\r
615                     continue;\r
616                 }\r
617 \r
618                 if (GET_CALLBACKS()->RxIndication != NULL) {\r
619                     GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[fifoNr],\r
620                                 id,\r
621                             canHw->BUF[0].CS.B.LENGTH,\r
622                             (uint8 *) &canHw->BUF[0].DATA.W[0]);\r
623                 }\r
624                 break;\r
625             }\r
626 \r
627             // Clear the interrupt\r
628             canHw->IFRL.B.BUF05I = 1;\r
629 \r
630             if( canHw->IFRL.B.BUF05I == 0 ) {\r
631                 iFlag ^= 1ull << mbNr;\r
632             }\r
633 \r
634         } else {\r
635             /* Not FIFO */\r
636             iFlag ^= 1ull << mbNr;\r
637 \r
638 \r
639             /* activate the internal lock with a read*/\r
640             (void) canHw->BUF[mbNr].CS.R;\r
641 \r
642 \r
643             if (canHw->BUF[mbNr].CS.B.IDE) {\r
644                 id = canHw->BUF[mbNr].ID.R;\r
645                 id |= 0x80000000;\r
646             } else {\r
647                 id = canHw->BUF[mbNr].ID.B.STD_ID;\r
648             }\r
649 \r
650             LDEBUG_PRINTF("ID=%x  ",(unsigned int)id);\r
651 \r
652 \r
653 #if defined(USE_DET)\r
654             if( canHw->BUF[mbNr].CS.B.CODE == MB_RX_OVERRUN ) {\r
655                 /* We have overwritten one frame */\r
656                 Det_ReportError(MODULE_ID_CAN,0,0,CAN_E_DATALOST); /** @req 4.0.3/CAN395 */\r
657             }\r
658 #endif\r
659 \r
660             if (GET_CALLBACKS()->RxIndication != NULL) {\r
661                 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr], id,\r
662                         canHw->BUF[mbNr].CS.B.LENGTH,\r
663                         (uint8 *) &canHw->BUF[mbNr].DATA.W[0]);\r
664             }\r
665 #if (USE_CAN_STATISTICS == STD_ON)\r
666             uPtr->stats.rxSuccessCnt++;\r
667 #endif\r
668             /* unlock MB (dummy read timer) */\r
669             (void) canHw->TIMER.R;\r
670 \r
671             // Clear interrupt\r
672             clearMbFlag(canHw, mbNr);\r
673         }\r
674 \r
675     }\r
676 }\r
677 \r
678 \r
679 static void Can_Isr(int controller )\r
680 {\r
681     Can_UnitType *uPtr = CTRL_TO_UNIT_PTR(controller);\r
682 \r
683     if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){\r
684         Can_Isr_Tx(uPtr);\r
685     }\r
686 \r
687     if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ){\r
688         Can_Isr_Rx(uPtr);\r
689     }\r
690 }\r
691 \r
692 \r
693 //-------------------------------------------------------------------\r
694 \r
695 \r
696 static void Can_BuildMaps(Can_UnitType *uPtr)\r
697 {\r
698         (void)uPtr;\r
699 #if 0\r
700     uint8_t mbNr = 8;\r
701     uint8_t fifoNr = 0;\r
702 \r
703     const Can_HardwareObjectType *hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;\r
704 \r
705     printf("Found %d HOHs\n", uPtr->cfgCtrlPtr->Can_Arc_HohCnt);\r
706 \r
707     for (int i = 0; i < uPtr->cfgCtrlPtr->Can_Arc_HohCnt; i++, hohPtr++) {\r
708         if (hohPtr->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) {\r
709             /* First 8 boxes are FIFO */\r
710             if (hohPtr->Can_Arc_Flags & CAN_HOH_FIFO_MASK) {\r
711                 uPtr->mbToHrh[fifoNr++] = hohPtr->CanObjectId;\r
712                 uPtr->Can_Arc_RxMbMask |= (1<<5);\r
713             } else {\r
714                 uint64_t mask = (-1ULL);\r
715                 uPtr->mbToHrh[mbNr] = hohPtr->CanObjectId;\r
716 \r
717                 mask >>= (mbNr);\r
718                 mask <<= (mbNr);\r
719                 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
720                 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
721                 uPtr->Can_Arc_RxMbMask |= mask;\r
722 \r
723                 mbNr += hohPtr->ArcCanNumMailboxes;\r
724             }\r
725             printf("mbNr=%d fifoNr=%d\n", mbNr, fifoNr);\r
726 \r
727         } else {\r
728             uint64_t mask = (-1ULL);\r
729 \r
730             /* Hth to HOH\r
731              * i = index into the HOH list for this controller */\r
732             Can_HthToHohMap[ hohPtr->CanObjectId ] = i;\r
733             Can_HthToUnitIdMap[ hohPtr->CanObjectId ] = uPtr->controllerId;\r
734             /* HOH to Mailbox */\r
735             for( int j=0;j < hohPtr->ArcCanNumMailboxes; j++ ) {\r
736                 uPtr->mbToHrh[mbNr+j] = hohPtr->CanObjectId;\r
737             }\r
738 \r
739             mask >>= (mbNr);\r
740             mask <<= (mbNr);\r
741             mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
742             mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
743             uPtr->Can_Arc_TxMbMask |= mask;\r
744             mbNr += hohPtr->ArcCanNumMailboxes;\r
745         }\r
746     }\r
747     uPtr->mbMax = mbNr;\r
748 #endif\r
749 }\r
750 \r
751 // This initiates ALL can controllers\r
752 void Can_Init(const Can_ConfigType *config)\r
753 {\r
754     /** @req 3.1.5/CAN223 */\r
755     /** !req 3.1.5/CAN176 */\r
756 \r
757     Can_UnitType *unitPtr;\r
758 \r
759     /** @req 3.1.5/CAN174 */\r
760     VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), CAN_INIT_SERVICE_ID, CAN_E_TRANSITION );\r
761     /** @req 3.1.5/CAN175 */\r
762     VALIDATE_NO_RV( (config != NULL ), CAN_INIT_SERVICE_ID, CAN_E_PARAM_POINTER );\r
763 \r
764     // Save config\r
765     Can_Global.config = config;\r
766     Can_Global.initRun = CAN_READY;\r
767 \r
768     for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
769         const Can_ControllerConfigType *cfgCtrlPtr  = &Can_Global.config->CanConfigSet->CanController[configId];\r
770 \r
771         Can_Global.configuredMask |= (1 << cfgCtrlPtr->CanControllerId);\r
772         unitPtr = &CanUnit[configId];\r
773 \r
774         memset(unitPtr, 0, sizeof(Can_UnitType));\r
775 \r
776         unitPtr->controllerId = cfgCtrlPtr->CanControllerId;\r
777         unitPtr->hwPtr = GET_CONTROLLER(cfgCtrlPtr->CanControllerId);\r
778         unitPtr->cfgCtrlPtr = cfgCtrlPtr;\r
779         unitPtr->state = CANIF_CS_STOPPED;\r
780         unitPtr->cfgHohPtr = cfgCtrlPtr->Can_Arc_Hoh;\r
781 \r
782         unitPtr->Can_Arc_RxMbMask = cfgCtrlPtr->Can_Arc_RxMailBoxMask;\r
783         unitPtr->Can_Arc_TxMbMask = cfgCtrlPtr->Can_Arc_TxMailBoxMask;\r
784 \r
785         Can_BuildMaps(unitPtr);\r
786 \r
787         switch (cfgCtrlPtr->CanControllerId) {\r
788 #if defined(CFG_MPC560X)\r
789         case CAN_CTRL_A:\r
790                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
791                         ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_0_ESR_BOFF_INT, 2, 0);\r
792                 }\r
793                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
794                         ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_0_ESR_ERR_INT, 2, 0 );\r
795                 }\r
796                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
797                         INSTALL_HANDLER4( "Can", Can_A_Isr, FLEXCAN_0_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
798                         ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_16_31, 2, 0 );\r
799                         ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_32_63, 2, 0 );\r
800                 }\r
801         break;\r
802         case CAN_CTRL_B:\r
803                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
804                 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_1_ESR_BOFF_INT, 2, 0);\r
805                 }\r
806                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
807                 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_1_ESR_ERR_INT, 2, 0 );\r
808                 }\r
809                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
810                         INSTALL_HANDLER4( "Can", Can_B_Isr, FLEXCAN_1_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
811                         ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_16_31, 2, 0 );\r
812                         ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_32_63, 2, 0 );\r
813                 }\r
814         break;\r
815         #if defined(CFG_MPC5604B)\r
816         case CAN_CTRL_C:\r
817                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
818                 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_2_ESR_BOFF_INT, 2, 0);\r
819                 }\r
820                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
821                 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_2_ESR_ERR_INT, 2, 0 );\r
822                 }\r
823                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
824                 INSTALL_HANDLER4( "Can", Can_C_Isr, FLEXCAN_2_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
825                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_16_31, 2, 0 );\r
826                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_32_63, 2, 0 );\r
827                 }\r
828         break;\r
829         case CAN_CTRL_D:\r
830                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
831                 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_3_ESR_BOFF_INT, 2, 0);\r
832                 }\r
833                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
834                 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_3_ESR_ERR_INT, 2, 0 );\r
835                 }\r
836                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
837                 INSTALL_HANDLER4( "Can", Can_D_Isr, FLEXCAN_3_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
838                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_16_31, 2, 0 );\r
839                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_32_63, 2, 0 );\r
840                 }\r
841         break;\r
842         case CAN_CTRL_E:\r
843                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
844                 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_4_ESR_BOFF_INT, 2, 0);\r
845                 }\r
846                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
847                 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_4_ESR_ERR_INT, 2, 0 );\r
848                 }\r
849                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
850                 INSTALL_HANDLER4( "Can", Can_E_Isr, FLEXCAN_4_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
851                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_16_31, 2, 0 );\r
852                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_32_63, 2, 0 );\r
853                 }\r
854         break;\r
855         case CAN_CTRL_F:\r
856                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
857                 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_5_ESR_BOFF_INT, 2, 0);\r
858                 }\r
859                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
860                 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_5_ESR_ERR_INT, 2, 0 );\r
861                 }\r
862                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
863                 INSTALL_HANDLER4( "Can", Can_F_Isr, FLEXCAN_5_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
864                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_16_31, 2, 0 );\r
865                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_32_63, 2, 0 );\r
866                 }\r
867         break;\r
868         #endif\r
869 #elif defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668)\r
870         case CAN_CTRL_A:\r
871                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
872                 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_A_ESR_BOFF_INT, 2, 0);\r
873                 }\r
874                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
875                 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_A_ESR_ERR_INT, 2, 0 );\r
876                 }\r
877                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
878                 INSTALL_HANDLER16( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF0I, 2, 0 );\r
879                 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF31_16I, 2, 0 );\r
880                 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF63_32I, 2, 0 );\r
881                 }\r
882         break;\r
883         case CAN_CTRL_B:\r
884                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
885                 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_B_ESR_BOFF_INT, 2, 0 );\r
886                 }\r
887                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
888                 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_B_ESR_ERR_INT, 2, 0 );\r
889                 }\r
890                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
891                 INSTALL_HANDLER16( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF0I, 2, 0 );\r
892                 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF31_16I, 2, 0 );\r
893                 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF63_32I, 2, 0 );\r
894                 }\r
895         break;\r
896         case CAN_CTRL_C:\r
897                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
898                 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_C_ESR_BOFF_INT, 2, 0 );\r
899                 }\r
900                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
901                 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_C_ESR_ERR_INT, 2, 0 );\r
902                 }\r
903                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
904                 INSTALL_HANDLER16( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF0I, 2, 0 );\r
905                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF31_16I, 2, 0 );\r
906                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF63_32I, 2, 0 );\r
907                 }\r
908         break;\r
909         case CAN_CTRL_D:\r
910                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
911                 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_D_ESR_BOFF_INT, 2, 0 );\r
912                 }\r
913                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
914                 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_D_ESR_ERR_INT, 2, 0 );\r
915                 }\r
916                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
917                 INSTALL_HANDLER16( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF0I, 2, 0 );\r
918                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF31_16I, 2, 0 );\r
919                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF63_32I, 2, 0 );\r
920                 }\r
921         break;\r
922         case CAN_CTRL_E:\r
923                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
924                 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_E_ESR_BOFF_INT, 2, 0 );\r
925                 }\r
926                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
927                 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_E_ESR_ERR_INT, 2, 0 );\r
928                 }\r
929                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
930                 INSTALL_HANDLER16( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF0I, 2, 0 );\r
931                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF31_16I, 2, 0 );\r
932                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF63_32I, 2, 0 );\r
933                 }\r
934         break;\r
935         #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668)\r
936         case CAN_CTRL_F:\r
937                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
938                 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_F_ESR_BOFF_INT, 2, 0 );\r
939                 }\r
940                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
941                 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_F_ESR_ERR_INT, 2, 0 );\r
942                 }\r
943                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
944                 INSTALL_HANDLER16( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF0I, 2, 0 );\r
945                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF31_16I, 2, 0 );\r
946                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF63_32I, 2, 0 );\r
947                 }\r
948         break;\r
949         #endif\r
950 #endif\r
951         default:\r
952             assert(0);\r
953         }\r
954     }\r
955     return;\r
956 }\r
957 \r
958 // Unitialize the module\r
959 void Can_DeInit()\r
960 {\r
961     Can_UnitType *canUnit;\r
962     const Can_ControllerConfigType *cfgCtrlPtr;\r
963     uint32 ctlrId;\r
964 \r
965     for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
966         cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[(configId)];\r
967         ctlrId = cfgCtrlPtr->CanControllerId;\r
968 \r
969         canUnit = CTRL_TO_UNIT_PTR(ctlrId);\r
970 \r
971         Can_DisableControllerInterrupts(ctlrId);\r
972  \r
973         canUnit->state = CANIF_CS_UNINIT;\r
974 \r
975         canUnit->lock_cnt = 0;\r
976 \r
977 #if (USE_CAN_STATISTICS == STD_ON)\r
978         // Clear stats\r
979         memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));\r
980 #endif\r
981     }\r
982 \r
983     Can_Global.config = NULL;\r
984     Can_Global.initRun = CAN_UNINIT;\r
985 \r
986     return;\r
987 }\r
988 \r
989 void Can_InitController(uint8 controller,\r
990         const Can_ControllerConfigType *config)\r
991 {\r
992     /** @req 3.1.5/CAN229 */\r
993     /** !req 3.1.5/CAN192 */\r
994 \r
995     flexcan_t *canHw;\r
996     uint8_t tq;\r
997     uint8_t tq1;\r
998     uint8_t tq2;\r
999     uint32_t clock;\r
1000     Can_UnitType *canUnit;\r
1001     const Can_ControllerConfigType *cfgCtrlPtr;\r
1002     const Can_HardwareObjectType *hohPtr;\r
1003     uint8_t fifoNr;\r
1004 \r
1005     /** @req 3.1.5/CAN187 */\r
1006     VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_UNINIT );\r
1007     /** @req 3.1.5/CAN188 */\r
1008     VALIDATE_NO_RV( (config != NULL ), CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_POINTER);\r
1009     /** !req 3.1.5/CAN189 Controller is controller number, not a sequence number? */\r
1010     VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_INITCONTROLLER_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1011 \r
1012     canUnit = CTRL_TO_UNIT_PTR(controller);\r
1013     /** @req 3.1.5/CAN190 */\r
1014     VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_TRANSITION );\r
1015 \r
1016     canHw = canUnit->hwPtr;\r
1017     cfgCtrlPtr = canUnit->cfgCtrlPtr;\r
1018 \r
1019     // Start this baby up\r
1020     canHw->MCR.B.MDIS = 0;\r
1021 \r
1022     // Wait for it to reset\r
1023     if (!SIMULATOR()) {\r
1024         // Freeze to write all mem mapped registers ( see 25.4.8.1 )\r
1025         canHw->MCR.B.FRZ = 1;\r
1026         canHw->MCR.B.HALT = 1;\r
1027     }\r
1028 \r
1029     if( config->Can_Arc_Flags & CAN_CTRL_FIFO ) {\r
1030         canHw->MCR.B.FEN = 1;       /*  Enable FIFO */\r
1031         canHw->MCR.B.IDAM = 0;      /* We want extended id's to match with */\r
1032     }\r
1033     canHw->MCR.B.BCC = 1;           /* Enable all nice features */\r
1034 \r
1035     /* Use Fsys derivate */\r
1036     canHw->CR.B.CLKSRC = 1;\r
1037     canHw->MCR.B.MAXMB = cfgCtrlPtr->Can_Arc_MailboxMax - 1;\r
1038 \r
1039 \r
1040     /* Disable self-reception, if not loopback  */\r
1041     canHw->MCR.B.SRXDIS = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 0 : 1;\r
1042 \r
1043     /* Clock calucation\r
1044      * -------------------------------------------------------------------\r
1045      *\r
1046      * * 1 TQ = Sclk period( also called SCK )\r
1047      * * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk\r
1048      *   ( Fcanclk can come from crystal or from the peripheral dividers )\r
1049      *\r
1050      * -->\r
1051      * TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )\r
1052      * TQ is between 8 and 25\r
1053      */\r
1054 \r
1055     /* Calculate the number of timequanta's (from "Protocol Timing"( chap. 25.4.7.4 )) */\r
1056     tq1 = (config->CanControllerPropSeg + config->CanControllerSeg1 + 2);\r
1057     tq2 = (config->CanControllerSeg2 + 1);\r
1058     tq = 1 + tq1 + tq2;\r
1059 \r
1060     // Check TQ limitations..\r
1061     VALIDATE_DEM_NO_RV(( (tq1>=4) && (tq1<=16)), CAN_E_TIMEOUT );\r
1062     VALIDATE_DEM_NO_RV(( (tq2>=2) && (tq2<=8)), CAN_E_TIMEOUT );\r
1063     VALIDATE_DEM_NO_RV(( (tq>8) && (tq<25 )), CAN_E_TIMEOUT );\r
1064 \r
1065     // Assume we're using the peripheral clock instead of the crystal.\r
1066     clock = McuE_GetPeripheralClock((McuE_PeriperalClock_t) config->CanCpuClockRef);\r
1067 \r
1068     canHw->CR.B.PRESDIV = clock / (config->CanControllerBaudRate * 1000 * tq) - 1;\r
1069     canHw->CR.B.PROPSEG = config->CanControllerPropSeg;\r
1070     canHw->CR.B.PSEG1   = config->CanControllerSeg1;\r
1071     canHw->CR.B.PSEG2   = config->CanControllerSeg2;\r
1072     canHw->CR.B.SMP     = 1; // 3 samples better than 1 ??\r
1073     canHw->CR.B.LPB     = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 1 : 0;\r
1074     canHw->CR.B.BOFFREC = 1; // Disable bus off recovery\r
1075 \r
1076     /* Setup mailboxes for this controller */\r
1077     hohPtr = cfgCtrlPtr->Can_Arc_Hoh;\r
1078     uint8_t mbNr = 8;\r
1079     fifoNr = 0;\r
1080 \r
1081     assert( hohPtr != NULL );\r
1082 \r
1083     struct FLEXCAN_RXFIFO_t *fifoIdPtr = (struct FLEXCAN_RXFIFO_t *)&canHw->BUF[0];\r
1084 \r
1085     memset(&canHw->BUF[0],0,sizeof(struct canbuf_t)*cfgCtrlPtr->Can_Arc_MailboxMax);\r
1086 \r
1087     for( int i=0; i < 8;i++) {\r
1088         canHw->RXIMR[i].R = 0xfffffffful;\r
1089         fifoIdPtr->IDTABLE[i].R = 0x0;\r
1090     }\r
1091 \r
1092     /* The HOHs are sorted by FIFO(FULL_CAN), FIFO(BASIC_CAN),\r
1093      * FULL_CAN(no FIFO) and last BASIC_CAN(no FIFO) */\r
1094     for( int i=0; i < cfgCtrlPtr->Can_Arc_HohCnt;i++,hohPtr++)\r
1095     {\r
1096         if( ( hohPtr->CanObjectType != CAN_OBJECT_TYPE_RECEIVE) ) {\r
1097             continue;\r
1098         }\r
1099 \r
1100         /* Assign FIFO first it will search for match first there (its the first MBs) */\r
1101         if( fifoNr < cfgCtrlPtr->Can_Arc_HohFifoCnt ) {\r
1102             /* TODO : Set IDAM */\r
1103 \r
1104             /* Set the ID */\r
1105                 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1106                         fifoIdPtr->IDTABLE[fifoNr].R =  ((hohPtr->CanIdValue << 1) | 0x40000000) ;\r
1107                 } else {\r
1108                         fifoIdPtr->IDTABLE[fifoNr].R =  (hohPtr->CanIdValue << 19) ;\r
1109                 }\r
1110 \r
1111             /* The Mask (we have FULL_CAN here) */\r
1112             canHw->RXIMR[fifoNr].R = *hohPtr->CanFilterMaskRef;\r
1113             fifoNr++;\r
1114         } else {\r
1115                 /* loop for multiplexed mailboxes, set as same as first */\r
1116                 uint64  mbMask = hohPtr->ArcMailboxMask;\r
1117                 uint8   mbTmp;\r
1118 \r
1119             for (; mbMask; mbMask &= ~(1ull << mbTmp)) {\r
1120                 mbTmp = ilog2_64(mbMask);\r
1121 \r
1122                                 canHw->BUF[mbTmp].CS.B.CODE  = MB_RX;\r
1123                                 canHw->RXIMR[mbTmp].R        = *hohPtr->CanFilterMaskRef;\r
1124 \r
1125                                 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1126                                         canHw->BUF[mbTmp].CS.B.IDE    = 1;\r
1127                                         canHw->BUF[mbTmp].ID.R        = hohPtr->CanIdValue;\r
1128                                 } else {\r
1129                                         canHw->BUF[mbTmp].CS.B.IDE    = 0;\r
1130                                         canHw->BUF[mbTmp].ID.B.STD_ID = hohPtr->CanIdValue;\r
1131                                 }\r
1132 \r
1133                                 mbNr++;\r
1134             }\r
1135         }\r
1136     }\r
1137 \r
1138     canUnit->mbTxFree = canUnit->Can_Arc_TxMbMask;\r
1139     /* @req 3.1.5/CAN260 */\r
1140     canUnit->state = CANIF_CS_STOPPED;\r
1141 \r
1142     return;\r
1143 }\r
1144 \r
1145 Can_ReturnType Can_SetControllerMode(uint8 controller,\r
1146         Can_StateTransitionType transition)\r
1147 {\r
1148     /** @req 3.1.5/CAN230 */\r
1149     /** @req 3.1.5/CAN017 */\r
1150     /** !req 3.1.5/CAN294 Wakeup not supported */\r
1151     /** !req 3.1.5/CAN197 */\r
1152     /** !req 3.1.5/CAN201 */\r
1153 \r
1154     flexcan_t *canHw;\r
1155     imask_t state;\r
1156     Can_ReturnType rv = CAN_OK;\r
1157 \r
1158     /** @req 3.1.5/CAN198 */\r
1159     VALIDATE( (Can_Global.initRun == CAN_READY), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );\r
1160     /** @req 3.1.5/CAN199 */\r
1161     VALIDATE( VALID_CONTROLLER(controller), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1162     Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);\r
1163     VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );\r
1164 \r
1165     canHw = canUnit->hwPtr;\r
1166 \r
1167     switch (transition) {\r
1168     case CAN_T_START:\r
1169         canHw->MCR.B.HALT = 0;\r
1170         canUnit->state = CANIF_CS_STARTED;\r
1171         Irq_Save(state);\r
1172         /** @req 3.1.5/CAN196 */\r
1173         if (canUnit->lock_cnt == 0)\r
1174         {\r
1175             Can_EnableControllerInterrupts(controller);\r
1176         }\r
1177         Irq_Restore(state);\r
1178         break;\r
1179     case CAN_T_WAKEUP: //CAN267\r
1180     case CAN_T_SLEEP: //CAN258, CAN290\r
1181         // Should be reported to DEM but DET is the next best\r
1182         VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
1183     case CAN_T_STOP:\r
1184         // Stop\r
1185         canHw->MCR.B.HALT = 1;\r
1186         canUnit->state = CANIF_CS_STOPPED;\r
1187         Can_AbortTx(canHw, canUnit); // CANIF282\r
1188         break;\r
1189     default:\r
1190         // Should be reported to DEM but DET is the next best\r
1191         /** @req 3.1.5/CAN200 */\r
1192         VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
1193         break;\r
1194     }\r
1195 \r
1196     return rv;\r
1197 }\r
1198 \r
1199 void Can_DisableControllerInterrupts(uint8 controller)\r
1200 {\r
1201     /** @req 3.1.5/CAN231 */\r
1202     /** @req 3.1.5/CAN202 */\r
1203     /** !req 3.1.5/CAN204 */\r
1204     /** !req 3.1.5/CAN292 */\r
1205 \r
1206         VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1207     /** @req 3.1.5/CAN206 */\r
1208     VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1209     Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);\r
1210     flexcan_t *canHw;\r
1211     imask_t state;\r
1212 \r
1213     /** @req 3.1.5/CAN205 */\r
1214     VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1215 \r
1216 \r
1217 \r
1218     Irq_Save(state);\r
1219     /** @req 3.1.5/CAN049 */\r
1220     if (canUnit->lock_cnt > 0) {\r
1221         // Interrupts already disabled\r
1222         canUnit->lock_cnt++;\r
1223         Irq_Restore(state);\r
1224         return;\r
1225     }\r
1226     canUnit->lock_cnt++;\r
1227     Irq_Restore(state);\r
1228 \r
1229     /* Don't try to be intelligent, turn everything off */\r
1230     canHw = GET_CONTROLLER(controller);\r
1231 \r
1232     /* Turn off the interrupt mailboxes */\r
1233     canHw->IMRH.R = 0;\r
1234     canHw->IMRL.R = 0;\r
1235 \r
1236     /* Turn off the bus off/tx warning/rx warning and error */\r
1237     canHw->MCR.B.WRNEN = 0; /* Disable warning int */\r
1238     canHw->CR.B.ERRMSK = 0; /* Disable error interrupt */\r
1239     canHw->CR.B.BOFFMSK = 0; /* Disable bus-off interrupt */\r
1240     canHw->CR.B.TWRNMSK = 0; /* Disable Tx warning */\r
1241     canHw->CR.B.RWRNMSK = 0; /* Disable Rx warning */\r
1242 }\r
1243 \r
1244 void Can_EnableControllerInterrupts(uint8 controller)\r
1245 {\r
1246     /** @req 3.1.5/CAN232 */\r
1247     /** @req 3.1.5/CAN050 */\r
1248     /** !req 3.1.5/CAN293 Not applicable */\r
1249 \r
1250     Can_UnitType *canUnit;\r
1251     flexcan_t *canHw;\r
1252     imask_t state;\r
1253 \r
1254     /** @req 3.1.5/CAN209 */\r
1255         VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1256     /** @req 3.1.5/CAN210 */\r
1257     VALIDATE_NO_RV( VALID_CONTROLLER(controller), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1258     canUnit = CTRL_TO_UNIT_PTR(controller);\r
1259     VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1260 \r
1261     Irq_Save(state);\r
1262     if (canUnit->lock_cnt > 1) {\r
1263         /** @req 3.1.5/CAN208 */\r
1264         // IRQ should still be disabled so just decrement counter\r
1265         canUnit->lock_cnt--;\r
1266         Irq_Restore(state);\r
1267         return;\r
1268     } else if (canUnit->lock_cnt == 1) {\r
1269         canUnit->lock_cnt = 0;\r
1270     }\r
1271     Irq_Restore(state);\r
1272 \r
1273     canHw = canUnit->hwPtr;\r
1274 \r
1275     canHw->IMRH.R = 0;\r
1276     canHw->IMRL.R = 0;\r
1277 \r
1278     if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ) {\r
1279         /* Turn on the interrupt mailboxes */\r
1280         canHw->IMRL.R = canUnit->Can_Arc_RxMbMask;\r
1281         canHw->IMRH.R = (uint32_t)(canUnit->Can_Arc_RxMbMask>>32);\r
1282     }\r
1283 \r
1284     if (canUnit->cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_TX_PROCESSING_INTERRUPT) {\r
1285         /* Turn on the interrupt mailboxes */\r
1286         canHw->IMRL.R |= canUnit->Can_Arc_TxMbMask;\r
1287         canHw->IMRH.R |= (uint32_t)(canUnit->Can_Arc_TxMbMask>>32);\r
1288     }\r
1289 \r
1290     // BusOff and warnings\r
1291     if (canUnit->cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) {\r
1292         canHw->MCR.B.WRNEN = 1; /* Turn On warning int */\r
1293         canHw->CR.B.BOFFMSK = 1; /* Enable bus-off interrupt */\r
1294 \r
1295 #if (USE_CAN_STATISTICS == STD_ON)\r
1296         canHw->CR.B.TWRNMSK = 1; /* Enable Tx warning */\r
1297         canHw->CR.B.RWRNMSK = 1; /* Enable Rx warning */\r
1298 #endif\r
1299     }\r
1300 \r
1301     // errors\r
1302     if (canUnit->cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT) {\r
1303         canHw->CR.B.ERRMSK = 1; /* Enable error interrupt */\r
1304     }\r
1305 \r
1306     return;\r
1307 }\r
1308 \r
1309 Can_ReturnType Can_Write(Can_Arc_HTHType hth, Can_PduType *pduInfo)\r
1310 {\r
1311     /** @req 3.1.5/CAN223 */\r
1312     /** !req 3.1.5/CAN213 Priorities not supported */\r
1313     /** !req 3.1.5/CAN215 Priorities not supported */\r
1314     /** @req 3.1.5/CAN214 */\r
1315     /** @req 3.1.5/CAN272 */\r
1316 \r
1317     uint16_t timer;\r
1318     uint64_t iflag;\r
1319     Can_ReturnType rv = CAN_OK;\r
1320     uint32_t mbNr;\r
1321     flexcan_t *canHw;\r
1322     const Can_HardwareObjectType *hohObj;\r
1323     Can_UnitType *canUnit;\r
1324     imask_t state;\r
1325 \r
1326     /** @req 3.1.5/CAN216 */\r
1327     VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );\r
1328     /** @req 3.1.5/CAN219 */\r
1329     VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );\r
1330     /** @req 3.1.5/CAN218 */\r
1331     VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );\r
1332     /** @req 3.1.5/CAN217 */\r
1333     VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );\r
1334 \r
1335     canUnit = &CanUnit[Can_Global.config->CanConfigSet->ArcHthToUnit[hth]];\r
1336     hohObj  =  &canUnit->cfgHohPtr[Can_Global.config->CanConfigSet->ArcHthToHoh[hth]];\r
1337     canHw   =  canUnit->hwPtr;\r
1338 \r
1339     /* We have the hohObj, we need to know what box we can send on */\r
1340     Irq_Save(state);\r
1341     /* Get all free TX mboxes */\r
1342     uint64_t iHwFlag = *(uint64_t *)(&canHw->IFRH.R);  /* These are occupied */\r
1343     assert( (canUnit->Can_Arc_TxMbMask & hohObj->ArcMailboxMask) != 0);\r
1344     iflag = ~iHwFlag &  canUnit->mbTxFree & hohObj->ArcMailboxMask;\r
1345     /* Get the mbox(es) for this HTH */\r
1346 \r
1347     /** @req 3.1.5/CAN212 */\r
1348     if (iflag ) {\r
1349         mbNr = ilog2_64(iflag ); // find mb number\r
1350 \r
1351         /* Indicate that we are sending this MB */\r
1352         canUnit->mbTxFree &= ~(1ull<<mbNr);\r
1353 \r
1354         canHw->BUF[mbNr].CS.R = 0;\r
1355         canHw->BUF[mbNr].ID.R = 0;\r
1356 \r
1357         // Setup message box type\r
1358         if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1359             canHw->BUF[mbNr].CS.B.IDE = 1;\r
1360         } else if (hohObj->CanIdType == CAN_ID_TYPE_STANDARD) {\r
1361             canHw->BUF[mbNr].CS.B.IDE = 0;\r
1362         } else {\r
1363             // No support for mixed in this processor\r
1364             assert(0);\r
1365         }\r
1366 \r
1367         // Send on buf\r
1368         canHw->BUF[mbNr].CS.B.CODE = MB_INACTIVE; // Hold the transmit buffer inactive\r
1369         if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1370             canHw->BUF[mbNr].ID.R = pduInfo->id; // Write 29-bit MB IDs\r
1371         } else {\r
1372             assert( !(pduInfo->id & 0xfffff800) );\r
1373             canHw->BUF[mbNr].ID.B.STD_ID = pduInfo->id;\r
1374         }\r
1375 \r
1376 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S) || defined(CFG_MPC5604B) || defined(CFG_MPC5668)\r
1377         canHw->BUF[mbNr].ID.B.PRIO = 1; // Set Local Priority\r
1378 #endif\r
1379 \r
1380         memset(&canHw->BUF[mbNr].DATA, 0, 8);\r
1381         memcpy(&canHw->BUF[mbNr].DATA, pduInfo->sdu, pduInfo->length);\r
1382 \r
1383         canHw->BUF[mbNr].CS.B.SRR = 1;\r
1384         canHw->BUF[mbNr].CS.B.RTR = 0;\r
1385 \r
1386         canHw->BUF[mbNr].CS.B.LENGTH = pduInfo->length;\r
1387         canHw->BUF[mbNr].CS.B.CODE = MB_TX_ONCE; // Write tx once code\r
1388         timer = canHw->TIMER.R; // Unlock Message buffers\r
1389 \r
1390 #if (USE_CAN_STATISTICS == STD_ON)\r
1391         canUnit->stats.txSuccessCnt++;\r
1392 #endif\r
1393 \r
1394         // Store pdu handle in unit to be used by TxConfirmation\r
1395         canUnit->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-canUnit->cfgCtrlPtr->Can_Arc_TxMailboxStart] = pduInfo->swPduHandle;\r
1396 \r
1397     } else {\r
1398         rv = CAN_BUSY;\r
1399     }\r
1400     Irq_Restore(state);\r
1401 \r
1402     return rv;\r
1403 }\r
1404 \r
1405 void Can_Cbk_CheckWakeup( uint8 controller ) {\r
1406     /** !req 3.1.5/CAN360 */\r
1407     /** !req 3.1.5/CAN361 */\r
1408     /** !req 3.1.5/CAN362 */\r
1409     /** !req 3.1.5/CAN363 */\r
1410 \r
1411     /* NOT SUPPORTED */\r
1412         (void)controller;\r
1413 }\r
1414 \r
1415 \r
1416 void Can_MainFunction_Write( void ) {\r
1417     /** !req 3.1.5/CAN225 */\r
1418     /** !req 3.1.5/CAN031 */\r
1419     /** !req 3.1.5/CAN178 */\r
1420     /** !req 3.1.5/CAN179 */\r
1421     Can_UnitType *uPtr;\r
1422 \r
1423     for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {\r
1424         uPtr = &CanUnit[i];\r
1425         if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) == 0 ) {\r
1426             Can_Isr_Tx(uPtr);\r
1427         }\r
1428     }\r
1429 }\r
1430 \r
1431 void Can_MainFunction_Read(void)\r
1432 {\r
1433     /** !req 3.1.5/CAN226 */\r
1434     /** !req 3.1.5/CAN108 */\r
1435     /** !req 3.1.5/CAN180 */\r
1436     /** !req 3.1.5/CAN181 */\r
1437     Can_UnitType *uPtr;\r
1438 \r
1439     for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {\r
1440         uPtr = &CanUnit[i];\r
1441         if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT) == 0 ) {\r
1442             Can_Isr_Rx(uPtr);\r
1443         }\r
1444     }\r
1445 }\r
1446 \r
1447 void Can_MainFunction_BusOff(void)\r
1448 {\r
1449     /** !req 3.1.5/CAN227 */\r
1450     /** !req 3.1.5/CAN109 */\r
1451     /** !req 3.1.5/CAN183 */\r
1452     /** !req 3.1.5/CAN184 */\r
1453     /* Bus-off polling events */\r
1454     Can_UnitType *uPtr;\r
1455 \r
1456     for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {\r
1457         uPtr = &CanUnit[i];\r
1458         if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) == 0 ) {\r
1459                 Can_BusOff(uPtr->controllerId);\r
1460         }\r
1461     }\r
1462 }\r
1463 \r
1464 void Can_MainFunction_Error(void)\r
1465 {\r
1466     /** !req 3.1.5/CAN227 */\r
1467     /** !req 3.1.5/CAN109 */\r
1468     /** !req 3.1.5/CAN183 */\r
1469     /** !req 3.1.5/CAN184 */\r
1470     /* Error polling events */\r
1471     Can_UnitType *uPtr;\r
1472 \r
1473     for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {\r
1474         uPtr = &CanUnit[i];\r
1475         if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT) == 0 ) {\r
1476                 Can_Err(uPtr->controllerId);\r
1477         }\r
1478     }\r
1479 }\r
1480 \r
1481 void Can_MainFunction_Wakeup(void)\r
1482 {\r
1483     /** !req 3.1.5/CAN228 */\r
1484     /** !req 3.1.5/CAN112 */\r
1485     /** !req 3.1.5/CAN185 */\r
1486     /** !req 3.1.5/CAN186 */\r
1487     /* Wakeup polling events */\r
1488 \r
1489     /* NOT SUPPORTED */\r
1490 }\r
1491 \r
1492 #if 0\r
1493 Can_Arc_ProcessType Can_Arc_ProcessingMode( uint8 controller ) {\r
1494     Can_UnitType *uPtr = &CanUnit[controller];\r
1495 \r
1496 \r
1497     if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){\r
1498         Can_Isr_Tx(uPtr);\r
1499     }\r
1500 \r
1501 }\r
1502 #endif\r
1503 \r
1504 \r
1505 #if (USE_CAN_STATISTICS == STD_ON)\r
1506 /**\r
1507  * Get send/receive/error statistics for a controller\r
1508  *\r
1509  * @param controller The controller\r
1510  * @param stats Pointer to data to copy statistics to\r
1511  */\r
1512 \r
1513 \r
1514 void Can_Arc_GetStatistics(uint8 controller, Can_Arc_StatisticsType *stats)\r
1515 {\r
1516         if(Can_Global.initRun == CAN_READY)\r
1517         {\r
1518                 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);\r
1519                 *stats = canUnit->stats;\r
1520         }\r
1521 }\r
1522 #endif\r
1523 \r