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