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