]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Can.c
Merge with 0b3233f0611f4fbd877d050f763435bc3ad22fc6
[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 }\r
495 \r
496 /**\r
497  *\r
498  * @param uPtr\r
499  */\r
500 static void Can_Isr_Tx(Can_UnitType *uPtr)\r
501 {\r
502     uint8 mbNr;\r
503     flexcan_t *canHw;\r
504     PduIdType pduId;\r
505 \r
506 \r
507     canHw = uPtr->hwPtr;\r
508 \r
509     uint64_t mbMask = *(uint64_t *) (&canHw->IFRH.R);\r
510     mbMask &= uPtr->Can_Arc_TxMbMask;\r
511 \r
512     /*\r
513      * Tx\r
514      */\r
515 #if defined(CFG_CAN_TEST)\r
516     Can_Test.mbMaskTx |= mbMask;\r
517 #endif\r
518 \r
519 \r
520     for (; mbMask; mbMask &= ~(1ull << mbNr)) {\r
521         mbNr = ilog2_64(mbMask);\r
522 \r
523         pduId = uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart];\r
524         uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart] = 0;\r
525 \r
526         // Clear interrupt and mark txBox as Free\r
527         clearMbFlag(canHw,mbNr);\r
528         uPtr->mbTxFree |= (1ull << mbNr);\r
529 \r
530         if (GET_CALLBACKS()->TxConfirmation != NULL) {\r
531             GET_CALLBACKS()->TxConfirmation(pduId);\r
532         }\r
533     }\r
534 }\r
535 \r
536 static void Can_Isr_Rx(Can_UnitType *uPtr)\r
537 {\r
538     uint8 mbNr;\r
539     uint32 id;\r
540     uint32 mask;\r
541     uint32 tmp = 0;\r
542 \r
543     flexcan_t *canHw;\r
544     const Can_HardwareObjectType *hohPtr;\r
545 \r
546     canHw = uPtr->hwPtr;\r
547 \r
548     uint64_t iFlag = *(uint64_t*) (&canHw->IFRH.R);\r
549 \r
550 #if defined(CFG_CAN_TEST)\r
551     Can_Test.mbMaskRx |= iFlag & uPtr->Can_Arc_RxMbMask;\r
552 #endif\r
553 \r
554     while (iFlag & uPtr->Can_Arc_RxMbMask) {\r
555 \r
556         /* Find mailbox */\r
557         mbNr = ilog2_64(iFlag & uPtr->Can_Arc_RxMbMask);\r
558 \r
559         /* Check for FIFO interrupt */\r
560         if (canHw->MCR.B.FEN && ((uint32_t)iFlag & (1 << 5))) {\r
561 \r
562                 tmp++;\r
563 //              if( tmp > 2) {\r
564 //                      while(1){}\r
565 //              }\r
566 \r
567             /* Check overflow */\r
568             if (iFlag & (1 << 7)) {\r
569 #if (USE_CAN_STATISTICS == STD_ON)\r
570                 uPtr->stats.fifoOverflow++;\r
571 #endif\r
572                 canHw->IFRL.B.BUF07I = 1;\r
573 \r
574                 DET_REPORTERROR(MODULE_ID_CAN,0,0, CAN_E_DATALOST); /** @req 4.0.3/CAN395 */\r
575             }\r
576 \r
577 #if (USE_CAN_STATISTICS == STD_ON)\r
578             /* Check warning */\r
579             if (iFlag & (1 << 6)) {\r
580                 uPtr->stats.fifoWarning++;\r
581                 canHw->IFRL.B.BUF06I = 1;\r
582             }\r
583 #endif\r
584 \r
585             /* The manual is "fuzzy" here, read control and status */\r
586             (void) canHw->BUF[0].CS.R;\r
587 \r
588             if (canHw->BUF[0].CS.B.IDE) {\r
589                 id = canHw->BUF[0].ID.R;\r
590                 id |= 0x80000000;\r
591             } else {\r
592                 id = canHw->BUF[0].ID.B.STD_ID;\r
593             }\r
594 \r
595             LDEBUG_PRINTF("FIFO_ID=%x  ",(unsigned int)id);\r
596 \r
597             /* Must now do a manual match to find the right CanHardwareObject\r
598              * to pass to CanIf. We know that the FIFO objects are sorted first.\r
599              */\r
600             hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;\r
601 \r
602             /* Match in order */\r
603             vuint32_t *fifoIdPtr = (vuint32_t *) &canHw->BUF[6];\r
604 \r
605 \r
606             for (uint8 fifoNr = 0; fifoNr < uPtr->cfgCtrlPtr->Can_Arc_HohFifoCnt; fifoNr++) {\r
607                 mask = canHw->RXIMR[fifoNr].R;\r
608 \r
609                 if ((id & mask) != (fifoIdPtr[fifoNr] & mask)) {\r
610                     continue;\r
611                 }\r
612 \r
613                 if (GET_CALLBACKS()->RxIndication != NULL) {\r
614                     GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[fifoNr],\r
615                                 id,\r
616                             canHw->BUF[0].CS.B.LENGTH,\r
617                             (uint8 *) &canHw->BUF[0].DATA.W[0]);\r
618                 }\r
619                 break;\r
620             }\r
621 \r
622             // Clear the interrupt\r
623             canHw->IFRL.B.BUF05I = 1;\r
624 \r
625             if( canHw->IFRL.B.BUF05I == 0 ) {\r
626                 iFlag ^= 1ull << mbNr;\r
627             }\r
628 \r
629         } else {\r
630             /* Not FIFO */\r
631             iFlag ^= 1ull << mbNr;\r
632 \r
633 \r
634             /* activate the internal lock with a read*/\r
635             (void) canHw->BUF[mbNr].CS.R;\r
636 \r
637 \r
638             if (canHw->BUF[mbNr].CS.B.IDE) {\r
639                 id = canHw->BUF[mbNr].ID.R;\r
640                 id |= 0x80000000;\r
641             } else {\r
642                 id = canHw->BUF[mbNr].ID.B.STD_ID;\r
643             }\r
644 \r
645             LDEBUG_PRINTF("ID=%x  ",(unsigned int)id);\r
646 \r
647 \r
648 #if defined(USE_DET)\r
649             if( canHw->BUF[mbNr].CS.B.CODE == MB_RX_OVERRUN ) {\r
650                 /* We have overwritten one frame */\r
651                 Det_ReportError(MODULE_ID_CAN,0,0,CAN_E_DATALOST); /** @req 4.0.3/CAN395 */\r
652             }\r
653 #endif\r
654 \r
655             if (GET_CALLBACKS()->RxIndication != NULL) {\r
656                 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr], id,\r
657                         canHw->BUF[mbNr].CS.B.LENGTH,\r
658                         (uint8 *) &canHw->BUF[mbNr].DATA.W[0]);\r
659             }\r
660 #if (USE_CAN_STATISTICS == STD_ON)\r
661             uPtr->stats.rxSuccessCnt++;\r
662 #endif\r
663             /* unlock MB (dummy read timer) */\r
664             (void) canHw->TIMER.R;\r
665 \r
666             // Clear interrupt\r
667             clearMbFlag(canHw, mbNr);\r
668         }\r
669 \r
670     }\r
671 }\r
672 \r
673 \r
674 static void Can_Isr(int controller )\r
675 {\r
676     Can_UnitType *uPtr = CTRL_TO_UNIT_PTR(controller);\r
677 \r
678     if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){\r
679         Can_Isr_Tx(uPtr);\r
680     }\r
681 \r
682     if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ){\r
683         Can_Isr_Rx(uPtr);\r
684     }\r
685 }\r
686 \r
687 \r
688 //-------------------------------------------------------------------\r
689 \r
690 \r
691 static void Can_BuildMaps(Can_UnitType *uPtr)\r
692 {\r
693         (void)uPtr;\r
694 #if 0\r
695     uint8_t mbNr = 8;\r
696     uint8_t fifoNr = 0;\r
697 \r
698     const Can_HardwareObjectType *hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;\r
699 \r
700     printf("Found %d HOHs\n", uPtr->cfgCtrlPtr->Can_Arc_HohCnt);\r
701 \r
702     for (int i = 0; i < uPtr->cfgCtrlPtr->Can_Arc_HohCnt; i++, hohPtr++) {\r
703         if (hohPtr->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) {\r
704             /* First 8 boxes are FIFO */\r
705             if (hohPtr->Can_Arc_Flags & CAN_HOH_FIFO_MASK) {\r
706                 uPtr->mbToHrh[fifoNr++] = hohPtr->CanObjectId;\r
707                 uPtr->Can_Arc_RxMbMask |= (1<<5);\r
708             } else {\r
709                 uint64_t mask = (-1ULL);\r
710                 uPtr->mbToHrh[mbNr] = hohPtr->CanObjectId;\r
711 \r
712                 mask >>= (mbNr);\r
713                 mask <<= (mbNr);\r
714                 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
715                 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
716                 uPtr->Can_Arc_RxMbMask |= mask;\r
717 \r
718                 mbNr += hohPtr->ArcCanNumMailboxes;\r
719             }\r
720             printf("mbNr=%d fifoNr=%d\n", mbNr, fifoNr);\r
721 \r
722         } else {\r
723             uint64_t mask = (-1ULL);\r
724 \r
725             /* Hth to HOH\r
726              * i = index into the HOH list for this controller */\r
727             Can_HthToHohMap[ hohPtr->CanObjectId ] = i;\r
728             Can_HthToUnitIdMap[ hohPtr->CanObjectId ] = uPtr->controllerId;\r
729             /* HOH to Mailbox */\r
730             for( int j=0;j < hohPtr->ArcCanNumMailboxes; j++ ) {\r
731                 uPtr->mbToHrh[mbNr+j] = hohPtr->CanObjectId;\r
732             }\r
733 \r
734             mask >>= (mbNr);\r
735             mask <<= (mbNr);\r
736             mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
737             mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);\r
738             uPtr->Can_Arc_TxMbMask |= mask;\r
739             mbNr += hohPtr->ArcCanNumMailboxes;\r
740         }\r
741     }\r
742     uPtr->mbMax = mbNr;\r
743 #endif\r
744 }\r
745 \r
746 // This initiates ALL can controllers\r
747 void Can_Init(const Can_ConfigType *config)\r
748 {\r
749     /** @req 3.1.5/CAN223 */\r
750     /** !req 3.1.5/CAN176 */\r
751 \r
752     Can_UnitType *unitPtr;\r
753 \r
754     /** @req 3.1.5/CAN174 */\r
755     VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), CAN_INIT_SERVICE_ID, CAN_E_TRANSITION );\r
756     /** @req 3.1.5/CAN175 */\r
757     VALIDATE_NO_RV( (config != NULL ), CAN_INIT_SERVICE_ID, CAN_E_PARAM_POINTER );\r
758 \r
759     // Save config\r
760     Can_Global.config = config;\r
761     Can_Global.initRun = CAN_READY;\r
762 \r
763     for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
764         const Can_ControllerConfigType *cfgCtrlPtr  = &Can_Global.config->CanConfigSet->CanController[configId];\r
765 \r
766         Can_Global.configuredMask |= (1 << cfgCtrlPtr->CanControllerId);\r
767         unitPtr = &CanUnit[configId];\r
768 \r
769         memset(unitPtr, 0, sizeof(Can_UnitType));\r
770 \r
771         unitPtr->controllerId = cfgCtrlPtr->CanControllerId;\r
772         unitPtr->hwPtr = GET_CONTROLLER(cfgCtrlPtr->CanControllerId);\r
773         unitPtr->cfgCtrlPtr = cfgCtrlPtr;\r
774         unitPtr->state = CANIF_CS_STOPPED;\r
775         unitPtr->cfgHohPtr = cfgCtrlPtr->Can_Arc_Hoh;\r
776 \r
777         unitPtr->Can_Arc_RxMbMask = cfgCtrlPtr->Can_Arc_RxMailBoxMask;\r
778         unitPtr->Can_Arc_TxMbMask = cfgCtrlPtr->Can_Arc_TxMailBoxMask;\r
779 \r
780         Can_BuildMaps(unitPtr);\r
781 \r
782         switch (cfgCtrlPtr->CanControllerId) {\r
783 #if defined(CFG_MPC560X)\r
784         case CAN_CTRL_A:\r
785                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
786                         ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_0_ESR_BOFF_INT, 2, 0);\r
787                 }\r
788                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
789                         ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_0_ESR_ERR_INT, 2, 0 );\r
790                 }\r
791                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
792                         INSTALL_HANDLER4( "Can", Can_A_Isr, FLEXCAN_0_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
793                         ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_16_31, 2, 0 );\r
794                         ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_32_63, 2, 0 );\r
795                 }\r
796         break;\r
797         case CAN_CTRL_B:\r
798                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
799                 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_1_ESR_BOFF_INT, 2, 0);\r
800                 }\r
801                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
802                 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_1_ESR_ERR_INT, 2, 0 );\r
803                 }\r
804                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
805                         INSTALL_HANDLER4( "Can", Can_B_Isr, FLEXCAN_1_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
806                         ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_16_31, 2, 0 );\r
807                         ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_32_63, 2, 0 );\r
808                 }\r
809         break;\r
810         #if defined(CFG_MPC5604B)\r
811         case CAN_CTRL_C:\r
812                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
813                 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_2_ESR_BOFF_INT, 2, 0);\r
814                 }\r
815                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
816                 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_2_ESR_ERR_INT, 2, 0 );\r
817                 }\r
818                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
819                 INSTALL_HANDLER4( "Can", Can_C_Isr, FLEXCAN_2_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
820                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_16_31, 2, 0 );\r
821                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_32_63, 2, 0 );\r
822                 }\r
823         break;\r
824         case CAN_CTRL_D:\r
825                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
826                 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_3_ESR_BOFF_INT, 2, 0);\r
827                 }\r
828                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
829                 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_3_ESR_ERR_INT, 2, 0 );\r
830                 }\r
831                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
832                 INSTALL_HANDLER4( "Can", Can_D_Isr, FLEXCAN_3_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
833                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_16_31, 2, 0 );\r
834                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_32_63, 2, 0 );\r
835                 }\r
836         break;\r
837         case CAN_CTRL_E:\r
838                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
839                 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_4_ESR_BOFF_INT, 2, 0);\r
840                 }\r
841                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
842                 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_4_ESR_ERR_INT, 2, 0 );\r
843                 }\r
844                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
845                 INSTALL_HANDLER4( "Can", Can_E_Isr, FLEXCAN_4_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
846                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_16_31, 2, 0 );\r
847                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_32_63, 2, 0 );\r
848                 }\r
849         break;\r
850         case CAN_CTRL_F:\r
851                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
852                 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_5_ESR_BOFF_INT, 2, 0);\r
853                 }\r
854                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
855                 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_5_ESR_ERR_INT, 2, 0 );\r
856                 }\r
857                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
858                 INSTALL_HANDLER4( "Can", Can_F_Isr, FLEXCAN_5_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */\r
859                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_16_31, 2, 0 );\r
860                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_32_63, 2, 0 );\r
861                 }\r
862         break;\r
863         #endif\r
864 #elif defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668)\r
865         case CAN_CTRL_A:\r
866                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
867                 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_A_ESR_BOFF_INT, 2, 0);\r
868                 }\r
869                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
870                 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_A_ESR_ERR_INT, 2, 0 );\r
871                 }\r
872                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
873                 INSTALL_HANDLER16( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF0I, 2, 0 );\r
874                 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF31_16I, 2, 0 );\r
875                 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF63_32I, 2, 0 );\r
876                 }\r
877         break;\r
878         case CAN_CTRL_B:\r
879                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
880                 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_B_ESR_BOFF_INT, 2, 0 );\r
881                 }\r
882                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
883                 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_B_ESR_ERR_INT, 2, 0 );\r
884                 }\r
885                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
886                 INSTALL_HANDLER16( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF0I, 2, 0 );\r
887                 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF31_16I, 2, 0 );\r
888                 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF63_32I, 2, 0 );\r
889                 }\r
890         break;\r
891         case CAN_CTRL_C:\r
892                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
893                 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_C_ESR_BOFF_INT, 2, 0 );\r
894                 }\r
895                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
896                 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_C_ESR_ERR_INT, 2, 0 );\r
897                 }\r
898                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
899                 INSTALL_HANDLER16( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF0I, 2, 0 );\r
900                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF31_16I, 2, 0 );\r
901                 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF63_32I, 2, 0 );\r
902                 }\r
903         break;\r
904         case CAN_CTRL_D:\r
905                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
906                 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_D_ESR_BOFF_INT, 2, 0 );\r
907                 }\r
908                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
909                 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_D_ESR_ERR_INT, 2, 0 );\r
910                 }\r
911                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
912                 INSTALL_HANDLER16( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF0I, 2, 0 );\r
913                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF31_16I, 2, 0 );\r
914                 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF63_32I, 2, 0 );\r
915                 }\r
916         break;\r
917         case CAN_CTRL_E:\r
918                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
919                 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_E_ESR_BOFF_INT, 2, 0 );\r
920                 }\r
921                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
922                 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_E_ESR_ERR_INT, 2, 0 );\r
923                 }\r
924                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
925                 INSTALL_HANDLER16( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF0I, 2, 0 );\r
926                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF31_16I, 2, 0 );\r
927                 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF63_32I, 2, 0 );\r
928                 }\r
929         break;\r
930         #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668)\r
931         case CAN_CTRL_F:\r
932                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){\r
933                 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_F_ESR_BOFF_INT, 2, 0 );\r
934                 }\r
935                 if(cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT){\r
936                 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_F_ESR_ERR_INT, 2, 0 );\r
937                 }\r
938                 if(cfgCtrlPtr->Can_Arc_Flags &  (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){\r
939                 INSTALL_HANDLER16( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF0I, 2, 0 );\r
940                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF31_16I, 2, 0 );\r
941                 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF63_32I, 2, 0 );\r
942                 }\r
943         break;\r
944         #endif\r
945 #endif\r
946         default:\r
947             assert(0);\r
948         }\r
949     }\r
950     return;\r
951 }\r
952 \r
953 // Unitialize the module\r
954 void Can_DeInit()\r
955 {\r
956     Can_UnitType *canUnit;\r
957     const Can_ControllerConfigType *cfgCtrlPtr;\r
958     uint32 ctlrId;\r
959 \r
960     for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {\r
961         cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[(configId)];\r
962         ctlrId = cfgCtrlPtr->CanControllerId;\r
963 \r
964         canUnit = CTRL_TO_UNIT_PTR(ctlrId);\r
965 \r
966         Can_DisableControllerInterrupts(ctlrId);\r
967  \r
968         canUnit->state = CANIF_CS_UNINIT;\r
969 \r
970         canUnit->lock_cnt = 0;\r
971 \r
972 #if (USE_CAN_STATISTICS == STD_ON)\r
973         // Clear stats\r
974         memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));\r
975 #endif\r
976     }\r
977 \r
978     Can_Global.config = NULL;\r
979     Can_Global.initRun = CAN_UNINIT;\r
980 \r
981     return;\r
982 }\r
983 \r
984 void Can_InitController(uint8 controller,\r
985         const Can_ControllerConfigType *config)\r
986 {\r
987     /** @req 3.1.5/CAN229 */\r
988     /** !req 3.1.5/CAN192 */\r
989 \r
990     flexcan_t *canHw;\r
991     uint8_t tq;\r
992     uint8_t tq1;\r
993     uint8_t tq2;\r
994     uint32_t clock;\r
995     Can_UnitType *canUnit;\r
996     const Can_ControllerConfigType *cfgCtrlPtr;\r
997     const Can_HardwareObjectType *hohPtr;\r
998     uint8_t fifoNr;\r
999 \r
1000     /** @req 3.1.5/CAN187 */\r
1001     VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_UNINIT );\r
1002     /** @req 3.1.5/CAN188 */\r
1003     VALIDATE_NO_RV( (config != NULL ), CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_POINTER);\r
1004     /** !req 3.1.5/CAN189 Controller is controller number, not a sequence number? */\r
1005     VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_INITCONTROLLER_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1006 \r
1007     canUnit = CTRL_TO_UNIT_PTR(controller);\r
1008     /** @req 3.1.5/CAN190 */\r
1009     VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_TRANSITION );\r
1010 \r
1011     canHw = canUnit->hwPtr;\r
1012     cfgCtrlPtr = canUnit->cfgCtrlPtr;\r
1013 \r
1014     // Start this baby up\r
1015     canHw->MCR.B.MDIS = 0;\r
1016 \r
1017     // Wait for it to reset\r
1018     if (!SIMULATOR()) {\r
1019         // Freeze to write all mem mapped registers ( see 25.4.8.1 )\r
1020         canHw->MCR.B.FRZ = 1;\r
1021         canHw->MCR.B.HALT = 1;\r
1022     }\r
1023 \r
1024     if( config->Can_Arc_Flags & CAN_CTRL_FIFO ) {\r
1025         canHw->MCR.B.FEN = 1;       /*  Enable FIFO */\r
1026         canHw->MCR.B.IDAM = 0;      /* We want extended id's to match with */\r
1027     }\r
1028     canHw->MCR.B.BCC = 1;           /* Enable all nice features */\r
1029 \r
1030     /* Use Fsys derivate */\r
1031     canHw->CR.B.CLKSRC = 1;\r
1032     canHw->MCR.B.MAXMB = cfgCtrlPtr->Can_Arc_MailboxMax - 1;\r
1033 \r
1034 \r
1035     /* Disable self-reception, if not loopback  */\r
1036     canHw->MCR.B.SRXDIS = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 0 : 1;\r
1037 \r
1038     /* Clock calucation\r
1039      * -------------------------------------------------------------------\r
1040      *\r
1041      * * 1 TQ = Sclk period( also called SCK )\r
1042      * * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk\r
1043      *   ( Fcanclk can come from crystal or from the peripheral dividers )\r
1044      *\r
1045      * -->\r
1046      * TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )\r
1047      * TQ is between 8 and 25\r
1048      */\r
1049 \r
1050     /* Calculate the number of timequanta's (from "Protocol Timing"( chap. 25.4.7.4 )) */\r
1051     tq1 = (config->CanControllerPropSeg + config->CanControllerSeg1 + 2);\r
1052     tq2 = (config->CanControllerSeg2 + 1);\r
1053     tq = 1 + tq1 + tq2;\r
1054 \r
1055     // Check TQ limitations..\r
1056     VALIDATE_DEM_NO_RV(( (tq1>=4) && (tq1<=16)), CAN_E_TIMEOUT );\r
1057     VALIDATE_DEM_NO_RV(( (tq2>=2) && (tq2<=8)), CAN_E_TIMEOUT );\r
1058     VALIDATE_DEM_NO_RV(( (tq>8) && (tq<25 )), CAN_E_TIMEOUT );\r
1059 \r
1060     // Assume we're using the peripheral clock instead of the crystal.\r
1061     clock = McuE_GetPeripheralClock((McuE_PeriperalClock_t) config->CanCpuClockRef);\r
1062 \r
1063     canHw->CR.B.PRESDIV = clock / (config->CanControllerBaudRate * 1000 * tq) - 1;\r
1064     canHw->CR.B.PROPSEG = config->CanControllerPropSeg;\r
1065     canHw->CR.B.PSEG1   = config->CanControllerSeg1;\r
1066     canHw->CR.B.PSEG2   = config->CanControllerSeg2;\r
1067     canHw->CR.B.SMP     = 1; // 3 samples better than 1 ??\r
1068     canHw->CR.B.LPB     = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 1 : 0;\r
1069     canHw->CR.B.BOFFREC = 1; // Disable bus off recovery\r
1070 \r
1071     /* Setup mailboxes for this controller */\r
1072     hohPtr = cfgCtrlPtr->Can_Arc_Hoh;\r
1073     uint8_t mbNr = 8;\r
1074     fifoNr = 0;\r
1075 \r
1076     assert( hohPtr != NULL );\r
1077 \r
1078     struct FLEXCAN_RXFIFO_t *fifoIdPtr = (struct FLEXCAN_RXFIFO_t *)&canHw->BUF[0];\r
1079 \r
1080     memset(&canHw->BUF[0],0,sizeof(struct canbuf_t)*cfgCtrlPtr->Can_Arc_MailboxMax);\r
1081 \r
1082     for( int i=0; i < 8;i++) {\r
1083         canHw->RXIMR[i].R = 0xfffffffful;\r
1084         fifoIdPtr->IDTABLE[i].R = 0x0;\r
1085     }\r
1086 \r
1087     /* The HOHs are sorted by FIFO(FULL_CAN), FIFO(BASIC_CAN),\r
1088      * FULL_CAN(no FIFO) and last BASIC_CAN(no FIFO) */\r
1089     for( int i=0; i < cfgCtrlPtr->Can_Arc_HohCnt;i++,hohPtr++)\r
1090     {\r
1091         if( ( hohPtr->CanObjectType != CAN_OBJECT_TYPE_RECEIVE) ) {\r
1092             continue;\r
1093         }\r
1094 \r
1095         /* Assign FIFO first it will search for match first there (its the first MBs) */\r
1096         if( fifoNr < cfgCtrlPtr->Can_Arc_HohFifoCnt ) {\r
1097             /* TODO : Set IDAM */\r
1098 \r
1099             /* Set the ID */\r
1100                 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1101                         fifoIdPtr->IDTABLE[fifoNr].R =  ((hohPtr->CanIdValue << 1) | 0x40000000) ;\r
1102                 } else {\r
1103                         fifoIdPtr->IDTABLE[fifoNr].R =  (hohPtr->CanIdValue << 19) ;\r
1104                 }\r
1105 \r
1106             /* The Mask (we have FULL_CAN here) */\r
1107             canHw->RXIMR[fifoNr].R = *hohPtr->CanFilterMaskRef;\r
1108             fifoNr++;\r
1109         } else {\r
1110                 /* loop for multiplexed mailboxes, set as same as first */\r
1111                 uint64  mbMask = hohPtr->ArcMailboxMask;\r
1112                 uint8   mbTmp;\r
1113 \r
1114             for (; mbMask; mbMask &= ~(1ull << mbTmp)) {\r
1115                 mbTmp = ilog2_64(mbMask);\r
1116 \r
1117                                 canHw->BUF[mbTmp].CS.B.CODE  = MB_RX;\r
1118                                 canHw->RXIMR[mbTmp].R        = *hohPtr->CanFilterMaskRef;\r
1119 \r
1120                                 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1121                                         canHw->BUF[mbTmp].CS.B.IDE    = 1;\r
1122                                         canHw->BUF[mbTmp].ID.R        = hohPtr->CanIdValue;\r
1123                                 } else {\r
1124                                         canHw->BUF[mbTmp].CS.B.IDE    = 0;\r
1125                                         canHw->BUF[mbTmp].ID.B.STD_ID = hohPtr->CanIdValue;\r
1126                                 }\r
1127 \r
1128                                 mbNr++;\r
1129             }\r
1130         }\r
1131     }\r
1132 \r
1133     canUnit->mbTxFree = canUnit->Can_Arc_TxMbMask;\r
1134     /* @req 3.1.5/CAN260 */\r
1135     canUnit->state = CANIF_CS_STOPPED;\r
1136 \r
1137     return;\r
1138 }\r
1139 \r
1140 Can_ReturnType Can_SetControllerMode(uint8 controller,\r
1141         Can_StateTransitionType transition)\r
1142 {\r
1143     /** @req 3.1.5/CAN230 */\r
1144     /** @req 3.1.5/CAN017 */\r
1145     /** !req 3.1.5/CAN294 Wakeup not supported */\r
1146     /** !req 3.1.5/CAN197 */\r
1147     /** !req 3.1.5/CAN201 */\r
1148 \r
1149     flexcan_t *canHw;\r
1150     imask_t state;\r
1151     Can_ReturnType rv = CAN_OK;\r
1152 \r
1153     /** @req 3.1.5/CAN198 */\r
1154     VALIDATE( (Can_Global.initRun == CAN_READY), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );\r
1155     /** @req 3.1.5/CAN199 */\r
1156     VALIDATE( VALID_CONTROLLER(controller), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1157     Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);\r
1158     VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );\r
1159 \r
1160     canHw = canUnit->hwPtr;\r
1161 \r
1162     switch (transition) {\r
1163     case CAN_T_START:\r
1164         canHw->MCR.B.HALT = 0;\r
1165         canUnit->state = CANIF_CS_STARTED;\r
1166         Irq_Save(state);\r
1167         /** @req 3.1.5/CAN196 */\r
1168         if (canUnit->lock_cnt == 0)\r
1169         {\r
1170             Can_EnableControllerInterrupts(controller);\r
1171         }\r
1172         Irq_Restore(state);\r
1173         break;\r
1174     case CAN_T_WAKEUP: //CAN267\r
1175     case CAN_T_SLEEP: //CAN258, CAN290\r
1176         // Should be reported to DEM but DET is the next best\r
1177         VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
1178     case CAN_T_STOP:\r
1179         // Stop\r
1180         canHw->MCR.B.HALT = 1;\r
1181         canUnit->state = CANIF_CS_STOPPED;\r
1182         Can_AbortTx(canHw, canUnit); // CANIF282\r
1183         break;\r
1184     default:\r
1185         // Should be reported to DEM but DET is the next best\r
1186         /** @req 3.1.5/CAN200 */\r
1187         VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);\r
1188         break;\r
1189     }\r
1190 \r
1191     return rv;\r
1192 }\r
1193 \r
1194 void Can_DisableControllerInterrupts(uint8 controller)\r
1195 {\r
1196     /** @req 3.1.5/CAN231 */\r
1197     /** @req 3.1.5/CAN202 */\r
1198     /** !req 3.1.5/CAN204 */\r
1199     /** !req 3.1.5/CAN292 */\r
1200 \r
1201         VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1202     /** @req 3.1.5/CAN206 */\r
1203     VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1204     Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);\r
1205     flexcan_t *canHw;\r
1206     imask_t state;\r
1207 \r
1208     /** @req 3.1.5/CAN205 */\r
1209     VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1210 \r
1211 \r
1212 \r
1213     Irq_Save(state);\r
1214     /** @req 3.1.5/CAN049 */\r
1215     if (canUnit->lock_cnt > 0) {\r
1216         // Interrupts already disabled\r
1217         canUnit->lock_cnt++;\r
1218         Irq_Restore(state);\r
1219         return;\r
1220     }\r
1221     canUnit->lock_cnt++;\r
1222     Irq_Restore(state);\r
1223 \r
1224     /* Don't try to be intelligent, turn everything off */\r
1225     canHw = GET_CONTROLLER(controller);\r
1226 \r
1227     /* Turn off the interrupt mailboxes */\r
1228     canHw->IMRH.R = 0;\r
1229     canHw->IMRL.R = 0;\r
1230 \r
1231     /* Turn off the bus off/tx warning/rx warning and error */\r
1232     canHw->MCR.B.WRNEN = 0; /* Disable warning int */\r
1233     canHw->CR.B.ERRMSK = 0; /* Disable error interrupt */\r
1234     canHw->CR.B.BOFFMSK = 0; /* Disable bus-off interrupt */\r
1235     canHw->CR.B.TWRNMSK = 0; /* Disable Tx warning */\r
1236     canHw->CR.B.RWRNMSK = 0; /* Disable Rx warning */\r
1237 }\r
1238 \r
1239 void Can_EnableControllerInterrupts(uint8 controller)\r
1240 {\r
1241     /** @req 3.1.5/CAN232 */\r
1242     /** @req 3.1.5/CAN050 */\r
1243     /** !req 3.1.5/CAN293 Not applicable */\r
1244 \r
1245     Can_UnitType *canUnit;\r
1246     flexcan_t *canHw;\r
1247     imask_t state;\r
1248 \r
1249     /** @req 3.1.5/CAN209 */\r
1250         VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1251     /** @req 3.1.5/CAN210 */\r
1252     VALIDATE_NO_RV( VALID_CONTROLLER(controller), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );\r
1253     canUnit = CTRL_TO_UNIT_PTR(controller);\r
1254     VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );\r
1255 \r
1256     Irq_Save(state);\r
1257     if (canUnit->lock_cnt > 1) {\r
1258         /** @req 3.1.5/CAN208 */\r
1259         // IRQ should still be disabled so just decrement counter\r
1260         canUnit->lock_cnt--;\r
1261         Irq_Restore(state);\r
1262         return;\r
1263     } else if (canUnit->lock_cnt == 1) {\r
1264         canUnit->lock_cnt = 0;\r
1265     }\r
1266     Irq_Restore(state);\r
1267 \r
1268     canHw = canUnit->hwPtr;\r
1269 \r
1270     canHw->IMRH.R = 0;\r
1271     canHw->IMRL.R = 0;\r
1272 \r
1273     if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ) {\r
1274         /* Turn on the interrupt mailboxes */\r
1275         canHw->IMRL.R = canUnit->Can_Arc_RxMbMask;\r
1276         canHw->IMRH.R = (uint32_t)(canUnit->Can_Arc_RxMbMask>>32);\r
1277     }\r
1278 \r
1279     if (canUnit->cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_TX_PROCESSING_INTERRUPT) {\r
1280         /* Turn on the interrupt mailboxes */\r
1281         canHw->IMRL.R |= canUnit->Can_Arc_TxMbMask;\r
1282         canHw->IMRH.R |= (uint32_t)(canUnit->Can_Arc_TxMbMask>>32);\r
1283     }\r
1284 \r
1285     // BusOff and warnings\r
1286     if (canUnit->cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) {\r
1287         canHw->MCR.B.WRNEN = 1; /* Turn On warning int */\r
1288         canHw->CR.B.BOFFMSK = 1; /* Enable bus-off interrupt */\r
1289 \r
1290 #if (USE_CAN_STATISTICS == STD_ON)\r
1291         canHw->CR.B.TWRNMSK = 1; /* Enable Tx warning */\r
1292         canHw->CR.B.RWRNMSK = 1; /* Enable Rx warning */\r
1293 #endif\r
1294     }\r
1295 \r
1296     // errors\r
1297     if (canUnit->cfgCtrlPtr->Can_Arc_Flags &  CAN_CTRL_ERROR_PROCESSING_INTERRUPT) {\r
1298         canHw->CR.B.ERRMSK = 1; /* Enable error interrupt */\r
1299     }\r
1300 \r
1301     return;\r
1302 }\r
1303 \r
1304 Can_ReturnType Can_Write(Can_Arc_HTHType hth, Can_PduType *pduInfo)\r
1305 {\r
1306     /** @req 3.1.5/CAN223 */\r
1307     /** !req 3.1.5/CAN213 Priorities not supported */\r
1308     /** !req 3.1.5/CAN215 Priorities not supported */\r
1309     /** @req 3.1.5/CAN214 */\r
1310     /** @req 3.1.5/CAN272 */\r
1311 \r
1312     uint16_t timer;\r
1313     uint64_t iflag;\r
1314     Can_ReturnType rv = CAN_OK;\r
1315     uint32_t mbNr;\r
1316     flexcan_t *canHw;\r
1317     const Can_HardwareObjectType *hohObj;\r
1318     Can_UnitType *canUnit;\r
1319     imask_t state;\r
1320 \r
1321     /** @req 3.1.5/CAN216 */\r
1322     VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );\r
1323     /** @req 3.1.5/CAN219 */\r
1324     VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );\r
1325     /** @req 3.1.5/CAN218 */\r
1326     VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );\r
1327     /** @req 3.1.5/CAN217 */\r
1328     VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );\r
1329 \r
1330     canUnit = &CanUnit[Can_Global.config->CanConfigSet->ArcHthToUnit[hth]];\r
1331     hohObj  =  &canUnit->cfgHohPtr[Can_Global.config->CanConfigSet->ArcHthToHoh[hth]];\r
1332     canHw   =  canUnit->hwPtr;\r
1333 \r
1334     /* We have the hohObj, we need to know what box we can send on */\r
1335     Irq_Save(state);\r
1336     /* Get all free TX mboxes */\r
1337     uint64_t iHwFlag = *(uint64_t *)(&canHw->IFRH.R);  /* These are occupied */\r
1338     assert( (canUnit->Can_Arc_TxMbMask & hohObj->ArcMailboxMask) != 0);\r
1339     iflag = ~iHwFlag &  canUnit->mbTxFree & hohObj->ArcMailboxMask;\r
1340     /* Get the mbox(es) for this HTH */\r
1341 \r
1342     /** @req 3.1.5/CAN212 */\r
1343     if (iflag ) {\r
1344         mbNr = ilog2_64(iflag ); // find mb number\r
1345 \r
1346         /* Indicate that we are sending this MB */\r
1347         canUnit->mbTxFree &= ~(1ull<<mbNr);\r
1348 \r
1349         canHw->BUF[mbNr].CS.R = 0;\r
1350         canHw->BUF[mbNr].ID.R = 0;\r
1351 \r
1352         // Setup message box type\r
1353         if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1354             canHw->BUF[mbNr].CS.B.IDE = 1;\r
1355         } else if (hohObj->CanIdType == CAN_ID_TYPE_STANDARD) {\r
1356             canHw->BUF[mbNr].CS.B.IDE = 0;\r
1357         } else {\r
1358             // No support for mixed in this processor\r
1359             assert(0);\r
1360         }\r
1361 \r
1362         // Send on buf\r
1363         canHw->BUF[mbNr].CS.B.CODE = MB_INACTIVE; // Hold the transmit buffer inactive\r
1364         if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {\r
1365             canHw->BUF[mbNr].ID.R = pduInfo->id; // Write 29-bit MB IDs\r
1366         } else {\r
1367             assert( !(pduInfo->id & 0xfffff800) );\r
1368             canHw->BUF[mbNr].ID.B.STD_ID = pduInfo->id;\r
1369         }\r
1370 \r
1371 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S) || defined(CFG_MPC5604B) || defined(CFG_MPC5668)\r
1372         canHw->BUF[mbNr].ID.B.PRIO = 1; // Set Local Priority\r
1373 #endif\r
1374 \r
1375         memset(&canHw->BUF[mbNr].DATA, 0, 8);\r
1376         memcpy(&canHw->BUF[mbNr].DATA, pduInfo->sdu, pduInfo->length);\r
1377 \r
1378         canHw->BUF[mbNr].CS.B.SRR = 1;\r
1379         canHw->BUF[mbNr].CS.B.RTR = 0;\r
1380 \r
1381         canHw->BUF[mbNr].CS.B.LENGTH = pduInfo->length;\r
1382         canHw->BUF[mbNr].CS.B.CODE = MB_TX_ONCE; // Write tx once code\r
1383         timer = canHw->TIMER.R; // Unlock Message buffers\r
1384 \r
1385 #if (USE_CAN_STATISTICS == STD_ON)\r
1386         canUnit->stats.txSuccessCnt++;\r
1387 #endif\r
1388 \r
1389         // Store pdu handle in unit to be used by TxConfirmation\r
1390         canUnit->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-canUnit->cfgCtrlPtr->Can_Arc_TxMailboxStart] = pduInfo->swPduHandle;\r
1391 \r
1392     } else {\r
1393         rv = CAN_BUSY;\r
1394     }\r
1395     Irq_Restore(state);\r
1396 \r
1397     return rv;\r
1398 }\r
1399 \r
1400 void Can_Cbk_CheckWakeup( uint8 controller ) {\r
1401     /** !req 3.1.5/CAN360 */\r
1402     /** !req 3.1.5/CAN361 */\r
1403     /** !req 3.1.5/CAN362 */\r
1404     /** !req 3.1.5/CAN363 */\r
1405 \r
1406     /* NOT SUPPORTED */\r
1407         (void)controller;\r
1408 }\r
1409 \r
1410 \r
1411 void Can_MainFunction_Write( void ) {\r
1412     /** !req 3.1.5/CAN225 */\r
1413     /** !req 3.1.5/CAN031 */\r
1414     /** !req 3.1.5/CAN178 */\r
1415     /** !req 3.1.5/CAN179 */\r
1416     Can_UnitType *uPtr;\r
1417 \r
1418     for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {\r
1419         uPtr = &CanUnit[i];\r
1420         if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) == 0 ) {\r
1421             Can_Isr_Tx(uPtr);\r
1422         }\r
1423     }\r
1424 }\r
1425 \r
1426 void Can_MainFunction_Read(void)\r
1427 {\r
1428     /** !req 3.1.5/CAN226 */\r
1429     /** !req 3.1.5/CAN108 */\r
1430     /** !req 3.1.5/CAN180 */\r
1431     /** !req 3.1.5/CAN181 */\r
1432     Can_UnitType *uPtr;\r
1433 \r
1434     for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {\r
1435         uPtr = &CanUnit[i];\r
1436         if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT) == 0 ) {\r
1437             Can_Isr_Rx(uPtr);\r
1438         }\r
1439     }\r
1440 }\r
1441 \r
1442 void Can_MainFunction_BusOff(void)\r
1443 {\r
1444     /** !req 3.1.5/CAN227 */\r
1445     /** !req 3.1.5/CAN109 */\r
1446     /** !req 3.1.5/CAN183 */\r
1447     /** !req 3.1.5/CAN184 */\r
1448     /* Bus-off polling events */\r
1449 \r
1450 }\r
1451 \r
1452 void Can_MainFunction_Wakeup(void)\r
1453 {\r
1454     /** !req 3.1.5/CAN228 */\r
1455     /** !req 3.1.5/CAN112 */\r
1456     /** !req 3.1.5/CAN185 */\r
1457     /** !req 3.1.5/CAN186 */\r
1458     /* Wakeup polling events */\r
1459 \r
1460     /* NOT SUPPORTED */\r
1461 }\r
1462 \r
1463 #if 0\r
1464 Can_Arc_ProcessType Can_Arc_ProcessingMode( uint8 controller ) {\r
1465     Can_UnitType *uPtr = &CanUnit[controller];\r
1466 \r
1467 \r
1468     if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){\r
1469         Can_Isr_Tx(uPtr);\r
1470     }\r
1471 \r
1472 }\r
1473 #endif\r
1474 \r
1475 \r
1476 #if (USE_CAN_STATISTICS == STD_ON)\r
1477 /**\r
1478  * Get send/receive/error statistics for a controller\r
1479  *\r
1480  * @param controller The controller\r
1481  * @param stats Pointer to data to copy statistics to\r
1482  */\r
1483 \r
1484 \r
1485 void Can_Arc_GetStatistics(uint8 controller, Can_Arc_StatisticsType *stats)\r
1486 {\r
1487         if(Can_Global.initRun == CAN_READY)\r
1488         {\r
1489                 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);\r
1490                 *stats = canUnit->stats;\r
1491         }\r
1492 }\r
1493 #endif\r
1494 \r