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