1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
16 /** @reqSettings DEFAULT_SPECIFICATION_REVISION=3.1.5 */
\r
21 * - Enable SOFT_RESET to guarantee that we get the same state every time
\r
22 * (do in Can_InitController ?)
\r
25 /* ----------------------------[information]----------------------------------*/
\r
33 * Implements the Can Driver module
\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
42 * CAN_MULTIPLEXED_TRANSMISSION N
\r
43 * CAN_TIMEOUT_DURATION N
\r
44 * CAN_VERSION_INFO_API N
\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
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
60 * ----------------------------------------------
\r
62 * MPC5606S Only sys-clk it seems
\r
63 * MPC551x Both sys-clk and XOSC, See 3.3
\r
67 * MPC5554 is NOT supported (no individual mask)
\r
69 * Implementation Notes:
\r
70 * - Individual RXMASKs are always ON. No support for "old" chips.
\r
73 * - Is masked ONLY against 8 extended IDs
\r
74 * - Have depth 6, with 8 ID and 8 RXMASK
\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
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
85 * EXAMPLE ALLOCATION
\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
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
99 * 12 TX FULL_CAN - HOH_5
\r
100 * 13 TX BASIC_CAN - HOH_6 | TX with 2 boxes
\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
112 * - mbToHrh, max 64 (could be moved to const... but PB problems?)
\r
113 * - swPduHandles, max 64*2
\r
115 * - Can_HthToUnitIdMap, Number of HTHs
\r
116 * - Can_HthToHohMap, Number of HTHs
\r
118 * 64 + 64*2 = 192*2 =
\r
122 * Can_ControllerConfigType
\r
123 * |--- Can_Arc_Hoh --> CanHardwareObjectConfig_CTRL_A
\r
125 * CanHardwareObjectConfig_CTRL_A
\r
132 * All tags. Tags only on public functions now.
\r
137 /* ----------------------------[includes]------------------------------------*/
\r
140 #include "mpc55xx.h"
\r
143 #include "CanIf_Cbk.h"
\r
145 #if defined(USE_DEM)
\r
148 #include <assert.h>
\r
149 #include <stdlib.h>
\r
150 #include <string.h>
\r
155 //#define USE_LDEBUG_PRINTF
\r
159 /* ----------------------------[private define]------------------------------*/
\r
161 #define MAX_NUM_OF_MAILBOXES 64
\r
162 #define USE_CAN_STATISTICS STD_OFF
\r
164 // Message box status defines
\r
165 #define MB_TX_ONCE 0xc
\r
166 #define MB_INACTIVE 0x8
\r
168 #define MB_ABORT 0x9
\r
169 #define MB_RX_OVERRUN 0x6
\r
171 /* ----------------------------[private macro]-------------------------------*/
\r
173 #define CTRL_TO_UNIT_PTR(_controller) &CanUnit[Can_Global.config->CanConfigSet->ArcCtrlToUnit[_controller]]
\r
174 #define VALID_CONTROLLER(_ctrl) (Can_Global.configuredMask & (1<<(_ctrl)))
\r
175 #define GET_CALLBACKS() (Can_Global.config->CanConfigSet->CanCallbacks)
\r
176 #define GET_CONTROLLER(_controller) \
\r
177 ((struct FLEXCAN_tag *)(0xFFFC0000 + 0x4000*(_controller)))
\r
179 #define INSTALL_HANDLER4(_name, _can_entry, _vector, _priority, _app)\
\r
181 ISR_INSTALL_ISR2(_name, _can_entry, _vector+0, _priority, _app); \
\r
182 ISR_INSTALL_ISR2(_name, _can_entry, _vector+1, _priority, _app); \
\r
183 ISR_INSTALL_ISR2(_name, _can_entry, _vector+2, _priority, _app); \
\r
184 ISR_INSTALL_ISR2(_name, _can_entry, _vector+3, _priority, _app); \
\r
187 #define INSTALL_HANDLER16(_name, _can_entry, _vector, _priority, _app)\
\r
189 INSTALL_HANDLER4(_name, _can_entry, _vector+0, _priority, _app); \
\r
190 INSTALL_HANDLER4(_name, _can_entry, _vector+4, _priority, _app); \
\r
191 INSTALL_HANDLER4(_name, _can_entry, _vector+8, _priority, _app); \
\r
192 INSTALL_HANDLER4(_name, _can_entry, _vector+12,_priority, _app); \
\r
195 //-------------------------------------------------------------------
\r
197 #if ( CAN_DEV_ERROR_DETECT == STD_ON )
\r
198 #define VALIDATE(_exp,_api,_err ) \
\r
200 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
201 return CAN_NOT_OK; \
\r
204 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
206 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
210 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)
\r
212 #define VALIDATE(_exp,_api,_err )
\r
213 #define VALIDATE_NO_RV(_exp,_api,_err )
\r
214 #define DET_REPORTERROR(_x,_y,_z,_q)
\r
217 #if defined(USE_DEM)
\r
218 #define VALIDATE_DEM_NO_RV(_exp,_err ) \
\r
220 Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED); \
\r
224 #define VALIDATE_DEM_NO_RV(_exp,_err )
\r
228 /* ----------------------------[private typedef]-----------------------------*/
\r
231 typedef struct FLEXCAN_tag flexcan_t;
\r
233 #if defined(CFG_CAN_TEST)
\r
234 Can_TestType Can_Test;
\r
238 CAN_UNINIT = 0, CAN_READY
\r
239 } Can_DriverStateType;
\r
246 vuint32_t TWRNINT :1;
\r
247 vuint32_t RWRNINT :1;
\r
248 vuint32_t BIT1ERR :1;
\r
249 vuint32_t BIT0ERR :1;
\r
250 vuint32_t ACKERR :1;
\r
251 vuint32_t CRCERR :1;
\r
252 vuint32_t FRMERR :1;
\r
253 vuint32_t STFERR :1;
\r
254 vuint32_t TXWRN :1;
\r
255 vuint32_t RXWRN :1;
\r
258 vuint32_t FLTCONF :2;
\r
260 vuint32_t BOFFINT :1;
\r
261 vuint32_t ERRINT :1;
\r
262 vuint32_t WAKINT :1;
\r
264 } ESRType; /* Error and Status Register */
\r
267 /* Type for holding global information used by the driver */
\r
269 Can_DriverStateType initRun; /* If Can_Init() have been run */
\r
270 const Can_ConfigType * config; /* Pointer to config */
\r
271 uint32 configuredMask; /* What units are configured */
\r
275 /* Type for holding information about each controller */
\r
277 /* This unit have uses controller */
\r
278 CanControllerIdType controllerId;
\r
279 CanIf_ControllerModeType state;
\r
280 const Can_ControllerConfigType * cfgCtrlPtr; /* Pointer to controller config */
\r
281 const Can_HardwareObjectType * cfgHohPtr; /* List of HOHs */
\r
284 uint64 Can_Arc_RxMbMask;
\r
285 uint64 Can_Arc_TxMbMask;
\r
287 uint8_t mbMax; /* Max number of mailboxes used for this unit */
\r
288 // PduIdType swPduHandles[MAX_NUM_OF_MAILBOXES]; /* Data stored for Txconfirmation callbacks to CanIf */
\r
289 // uint8_t mbToHrh[MAX_NUM_OF_MAILBOXES]; /* Mapping from mailbox to HRH */
\r
290 #if (USE_CAN_STATISTICS == STD_ON)
\r
291 Can_Arc_StatisticsType stats;
\r
295 /* ----------------------------[private function prototypes]-----------------*/
\r
296 static void Can_Isr(int unit);
\r
297 static void Can_Err(int unit);
\r
298 static void Can_BusOff(int unit);
\r
300 /* ----------------------------[private variables]---------------------------*/
\r
302 Can_UnitType CanUnit[CAN_ARC_CTRL_CONFIG_CNT];
\r
303 Can_GlobalType Can_Global = { .initRun = CAN_UNINIT, };
\r
305 //uint8_t Can_CtrlToUnitMap[CAN_ARC_CTRL_CONFIG_CNT];
\r
306 /* Used by Can_Write() */
\r
307 //uint8_t Can_HthToUnitIdMap[NUM_OF_HTHS];
\r
308 //uint8_t Can_HthToHohMap[NUM_OF_HTHS];
\r
310 /* ----------------------------[private functions]---------------------------*/
\r
312 static void clearMbFlag( flexcan_t * hw, uint8_t mb ) {
\r
314 hw->IFRH.R = (1<<(mb-32));
\r
316 hw->IFRL.R = (1<<mb);
\r
320 static inline uint64_t ilog2_64( uint64_t val ) {
\r
321 uint32_t t = val >> 32;
\r
324 return ilog2(t) + 32;
\r
326 return ilog2((uint32_t)val);
\r
329 void Can_A_Isr(void)
\r
331 Can_Isr(CAN_CTRL_A);
\r
333 void Can_B_Isr(void)
\r
335 Can_Isr(CAN_CTRL_B);
\r
337 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)
\r
338 void Can_C_Isr( void ) {Can_Isr(CAN_CTRL_C);}
\r
339 void Can_D_Isr( void ) {Can_Isr(CAN_CTRL_D);}
\r
340 void Can_E_Isr( void ) {Can_Isr(CAN_CTRL_E);}
\r
342 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)
\r
343 void Can_F_Isr( void ) {Can_Isr(CAN_CTRL_F);}
\r
346 void Can_A_Err(void)
\r
348 Can_Err(CAN_CTRL_A);
\r
350 void Can_B_Err(void)
\r
352 Can_Err(CAN_CTRL_B);
\r
354 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)
\r
355 void Can_C_Err( void ) {Can_Err(CAN_CTRL_C);}
\r
356 void Can_D_Err( void ) {Can_Err(CAN_CTRL_D);}
\r
357 void Can_E_Err( void ) {Can_Err(CAN_CTRL_E);}
\r
359 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)
\r
360 void Can_F_Err( void ) {Can_Err(CAN_CTRL_F);}
\r
363 void Can_A_BusOff(void)
\r
365 Can_BusOff(CAN_CTRL_A);
\r
367 void Can_B_BusOff(void)
\r
369 Can_BusOff(CAN_CTRL_B);
\r
371 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)
\r
372 void Can_C_BusOff( void ) {Can_BusOff(CAN_CTRL_C);}
\r
373 void Can_D_BusOff( void ) {Can_BusOff(CAN_CTRL_D);}
\r
374 void Can_E_BusOff( void ) {Can_BusOff(CAN_CTRL_E);}
\r
376 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668) || defined(CFG_MPC5604B)
\r
377 void Can_F_BusOff( void ) {Can_BusOff(CAN_CTRL_F);}
\r
379 //-------------------------------------------------------------------
\r
381 #if defined(CFG_CAN_TEST)
\r
382 Can_TestType * Can_Arc_GetTestInfo( void ) {
\r
388 * Hardware error ISR for CAN
\r
390 * @param unit CAN controller number( from 0 )
\r
393 static void Can_Err(int unit)
\r
395 flexcan_t *canHw = GET_CONTROLLER(unit);
\r
396 Can_Arc_ErrorType err;
\r
398 const ESRType esrWrite = { .B.ERRINT = 1 };
\r
401 /* Clear bits 16-23 by read */
\r
402 esr.R = canHw->ESR.R;
\r
403 if(esr.B.ERRINT == 1)
\r
405 if (GET_CALLBACKS()->Arc_Error != NULL) {
\r
406 GET_CALLBACKS()->Arc_Error(unit, err);
\r
409 Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272 Same handling as for busoff
\r
412 canHw->ESR.R = esrWrite.R;
\r
421 // Uses 25.4.5.1 Transmission Abort Mechanism
\r
422 static void Can_AbortTx(flexcan_t *canHw, Can_UnitType *canUnit)
\r
426 // Find our Tx boxes.
\r
427 mbMask = canUnit->Can_Arc_TxMbMask;
\r
428 // Loop over the Mb's set to abort
\r
429 for (; mbMask; mbMask &= ~(1ull << mbNr)) {
\r
430 mbNr = ilog2_64(mbMask);
\r
431 canHw->BUF[mbNr].CS.B.CODE = MB_ABORT;
\r
433 if (canHw->BUF[mbNr].CS.B.CODE != MB_ABORT) {
\r
435 /* it's not sent... or being sent.
\r
439 while (*(uint64_t *) (&canHw->IFRH.R) & (1ull << mbNr)) {
\r
448 clearMbFlag(canHw,mbNr);
\r
449 canUnit->mbTxFree |= (1ull << mbNr);
\r
456 * BusOff ISR for CAN
\r
458 * @param unit CAN controller number( from 0 )
\r
460 static void Can_BusOff(int unit)
\r
462 flexcan_t *canHw = GET_CONTROLLER(unit);
\r
463 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(unit);
\r
464 Can_Arc_ErrorType err;
\r
467 #if (USE_CAN_STATISTICS == STD_ON)
\r
468 if (canHw->ESR.B.TWRNINT) {
\r
469 err.B.TXWRN = canHw->ESR.B.TXWRN;
\r
470 canUnit->stats.txErrorCnt++;
\r
471 canHw->ESR.B.TWRNINT = 1;
\r
474 if (canHw->ESR.B.RWRNINT) {
\r
475 err.B.RXWRN = canHw->ESR.B.RXWRN;
\r
476 canUnit->stats.rxErrorCnt++;
\r
477 canHw->ESR.B.RWRNINT = 1;
\r
481 if (canHw->ESR.B.BOFFINT) {
\r
482 #if (USE_CAN_STATISTICS == STD_ON)
\r
483 canUnit->stats.boffCnt++;
\r
485 if (GET_CALLBACKS()->ControllerBusOff != NULL) {
\r
486 GET_CALLBACKS()->ControllerBusOff(unit);
\r
488 Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272
\r
490 canHw->ESR.B.BOFFINT = 1;
\r
492 Can_AbortTx(canHw, canUnit); // CANIF273
\r
500 static void Can_Isr_Tx(Can_UnitType *uPtr)
\r
507 canHw = uPtr->hwPtr;
\r
509 uint64_t mbMask = *(uint64_t *) (&canHw->IFRH.R);
\r
510 mbMask &= uPtr->Can_Arc_TxMbMask;
\r
515 #if defined(CFG_CAN_TEST)
\r
516 Can_Test.mbMaskTx |= mbMask;
\r
520 for (; mbMask; mbMask &= ~(1ull << mbNr)) {
\r
521 mbNr = ilog2_64(mbMask);
\r
523 pduId = uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart];
\r
524 uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart] = 0;
\r
526 // Clear interrupt and mark txBox as Free
\r
527 clearMbFlag(canHw,mbNr);
\r
528 uPtr->mbTxFree |= (1ull << mbNr);
\r
530 if (GET_CALLBACKS()->TxConfirmation != NULL) {
\r
531 GET_CALLBACKS()->TxConfirmation(pduId);
\r
536 static void Can_Isr_Rx(Can_UnitType *uPtr)
\r
544 const Can_HardwareObjectType *hohPtr;
\r
546 canHw = uPtr->hwPtr;
\r
548 uint64_t iFlag = *(uint64_t*) (&canHw->IFRH.R);
\r
550 #if defined(CFG_CAN_TEST)
\r
551 Can_Test.mbMaskRx |= iFlag & uPtr->Can_Arc_RxMbMask;
\r
554 while (iFlag & uPtr->Can_Arc_RxMbMask) {
\r
557 mbNr = ilog2_64(iFlag & uPtr->Can_Arc_RxMbMask);
\r
559 /* Check for FIFO interrupt */
\r
560 if (canHw->MCR.B.FEN && ((uint32_t)iFlag & (1 << 5))) {
\r
567 /* Check overflow */
\r
568 if (iFlag & (1 << 7)) {
\r
569 #if (USE_CAN_STATISTICS == STD_ON)
\r
570 uPtr->stats.fifoOverflow++;
\r
572 canHw->IFRL.B.BUF07I = 1;
\r
574 DET_REPORTERROR(MODULE_ID_CAN,0,0, CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
577 #if (USE_CAN_STATISTICS == STD_ON)
\r
578 /* Check warning */
\r
579 if (iFlag & (1 << 6)) {
\r
580 uPtr->stats.fifoWarning++;
\r
581 canHw->IFRL.B.BUF06I = 1;
\r
585 /* The manual is "fuzzy" here, read control and status */
\r
586 (void) canHw->BUF[0].CS.R;
\r
588 if (canHw->BUF[0].CS.B.IDE) {
\r
589 id = canHw->BUF[0].ID.R;
\r
592 id = canHw->BUF[0].ID.B.STD_ID;
\r
595 LDEBUG_PRINTF("FIFO_ID=%x ",(unsigned int)id);
\r
597 /* Must now do a manual match to find the right CanHardwareObject
\r
598 * to pass to CanIf. We know that the FIFO objects are sorted first.
\r
600 hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
602 /* Match in order */
\r
603 vuint32_t *fifoIdPtr = (vuint32_t *) &canHw->BUF[6];
\r
606 for (uint8 fifoNr = 0; fifoNr < uPtr->cfgCtrlPtr->Can_Arc_HohFifoCnt; fifoNr++) {
\r
607 mask = canHw->RXIMR[fifoNr].R;
\r
609 if ((id & mask) != (fifoIdPtr[fifoNr] & mask)) {
\r
613 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
614 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[fifoNr],
\r
616 canHw->BUF[0].CS.B.LENGTH,
\r
617 (uint8 *) &canHw->BUF[0].DATA.W[0]);
\r
622 // Clear the interrupt
\r
623 canHw->IFRL.B.BUF05I = 1;
\r
625 if( canHw->IFRL.B.BUF05I == 0 ) {
\r
626 iFlag ^= 1ull << mbNr;
\r
631 iFlag ^= 1ull << mbNr;
\r
634 /* activate the internal lock with a read*/
\r
635 (void) canHw->BUF[mbNr].CS.R;
\r
638 if (canHw->BUF[mbNr].CS.B.IDE) {
\r
639 id = canHw->BUF[mbNr].ID.R;
\r
642 id = canHw->BUF[mbNr].ID.B.STD_ID;
\r
645 LDEBUG_PRINTF("ID=%x ",(unsigned int)id);
\r
648 #if defined(USE_DET)
\r
649 if( canHw->BUF[mbNr].CS.B.CODE == MB_RX_OVERRUN ) {
\r
650 /* We have overwritten one frame */
\r
651 Det_ReportError(MODULE_ID_CAN,0,0,CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
655 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
656 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr], id,
\r
657 canHw->BUF[mbNr].CS.B.LENGTH,
\r
658 (uint8 *) &canHw->BUF[mbNr].DATA.W[0]);
\r
660 #if (USE_CAN_STATISTICS == STD_ON)
\r
661 uPtr->stats.rxSuccessCnt++;
\r
663 /* unlock MB (dummy read timer) */
\r
664 (void) canHw->TIMER.R;
\r
667 clearMbFlag(canHw, mbNr);
\r
674 static void Can_Isr(int controller )
\r
676 Can_UnitType *uPtr = CTRL_TO_UNIT_PTR(controller);
\r
678 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
682 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ){
\r
688 //-------------------------------------------------------------------
\r
691 static void Can_BuildMaps(Can_UnitType *uPtr)
\r
696 uint8_t fifoNr = 0;
\r
698 const Can_HardwareObjectType *hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
700 printf("Found %d HOHs\n", uPtr->cfgCtrlPtr->Can_Arc_HohCnt);
\r
702 for (int i = 0; i < uPtr->cfgCtrlPtr->Can_Arc_HohCnt; i++, hohPtr++) {
\r
703 if (hohPtr->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) {
\r
704 /* First 8 boxes are FIFO */
\r
705 if (hohPtr->Can_Arc_Flags & CAN_HOH_FIFO_MASK) {
\r
706 uPtr->mbToHrh[fifoNr++] = hohPtr->CanObjectId;
\r
707 uPtr->Can_Arc_RxMbMask |= (1<<5);
\r
709 uint64_t mask = (-1ULL);
\r
710 uPtr->mbToHrh[mbNr] = hohPtr->CanObjectId;
\r
714 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
715 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
716 uPtr->Can_Arc_RxMbMask |= mask;
\r
718 mbNr += hohPtr->ArcCanNumMailboxes;
\r
720 printf("mbNr=%d fifoNr=%d\n", mbNr, fifoNr);
\r
723 uint64_t mask = (-1ULL);
\r
726 * i = index into the HOH list for this controller */
\r
727 Can_HthToHohMap[ hohPtr->CanObjectId ] = i;
\r
728 Can_HthToUnitIdMap[ hohPtr->CanObjectId ] = uPtr->controllerId;
\r
729 /* HOH to Mailbox */
\r
730 for( int j=0;j < hohPtr->ArcCanNumMailboxes; j++ ) {
\r
731 uPtr->mbToHrh[mbNr+j] = hohPtr->CanObjectId;
\r
736 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
737 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
738 uPtr->Can_Arc_TxMbMask |= mask;
\r
739 mbNr += hohPtr->ArcCanNumMailboxes;
\r
742 uPtr->mbMax = mbNr;
\r
746 // This initiates ALL can controllers
\r
747 void Can_Init(const Can_ConfigType *config)
\r
749 /** @req 3.1.5/CAN223 */
\r
750 /** !req 3.1.5/CAN176 */
\r
752 Can_UnitType *unitPtr;
\r
754 /** @req 3.1.5/CAN174 */
\r
755 VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), CAN_INIT_SERVICE_ID, CAN_E_TRANSITION );
\r
756 /** @req 3.1.5/CAN175 */
\r
757 VALIDATE_NO_RV( (config != NULL ), CAN_INIT_SERVICE_ID, CAN_E_PARAM_POINTER );
\r
760 Can_Global.config = config;
\r
761 Can_Global.initRun = CAN_READY;
\r
763 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
764 const Can_ControllerConfigType *cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[configId];
\r
766 Can_Global.configuredMask |= (1 << cfgCtrlPtr->CanControllerId);
\r
767 unitPtr = &CanUnit[configId];
\r
769 memset(unitPtr, 0, sizeof(Can_UnitType));
\r
771 unitPtr->controllerId = cfgCtrlPtr->CanControllerId;
\r
772 unitPtr->hwPtr = GET_CONTROLLER(cfgCtrlPtr->CanControllerId);
\r
773 unitPtr->cfgCtrlPtr = cfgCtrlPtr;
\r
774 unitPtr->state = CANIF_CS_STOPPED;
\r
775 unitPtr->cfgHohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
777 unitPtr->Can_Arc_RxMbMask = cfgCtrlPtr->Can_Arc_RxMailBoxMask;
\r
778 unitPtr->Can_Arc_TxMbMask = cfgCtrlPtr->Can_Arc_TxMailBoxMask;
\r
780 Can_BuildMaps(unitPtr);
\r
782 switch (cfgCtrlPtr->CanControllerId) {
\r
783 #if defined(CFG_MPC560X)
\r
785 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
786 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_0_ESR_BOFF_INT, 2, 0);
\r
788 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
789 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_0_ESR_ERR_INT, 2, 0 );
\r
791 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
792 INSTALL_HANDLER4( "Can", Can_A_Isr, FLEXCAN_0_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
793 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_16_31, 2, 0 );
\r
794 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_32_63, 2, 0 );
\r
798 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
799 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_1_ESR_BOFF_INT, 2, 0);
\r
801 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
802 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_1_ESR_ERR_INT, 2, 0 );
\r
804 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
805 INSTALL_HANDLER4( "Can", Can_B_Isr, FLEXCAN_1_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
806 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_16_31, 2, 0 );
\r
807 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_32_63, 2, 0 );
\r
810 #if defined(CFG_MPC5604B)
\r
812 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
813 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_2_ESR_BOFF_INT, 2, 0);
\r
815 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
816 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_2_ESR_ERR_INT, 2, 0 );
\r
818 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
819 INSTALL_HANDLER4( "Can", Can_C_Isr, FLEXCAN_2_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
820 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_16_31, 2, 0 );
\r
821 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_32_63, 2, 0 );
\r
825 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
826 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_3_ESR_BOFF_INT, 2, 0);
\r
828 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
829 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_3_ESR_ERR_INT, 2, 0 );
\r
831 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
832 INSTALL_HANDLER4( "Can", Can_D_Isr, FLEXCAN_3_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
833 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_16_31, 2, 0 );
\r
834 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_32_63, 2, 0 );
\r
838 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
839 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_4_ESR_BOFF_INT, 2, 0);
\r
841 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
842 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_4_ESR_ERR_INT, 2, 0 );
\r
844 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
845 INSTALL_HANDLER4( "Can", Can_E_Isr, FLEXCAN_4_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
846 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_16_31, 2, 0 );
\r
847 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_32_63, 2, 0 );
\r
851 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
852 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_5_ESR_BOFF_INT, 2, 0);
\r
854 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
855 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_5_ESR_ERR_INT, 2, 0 );
\r
857 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
858 INSTALL_HANDLER4( "Can", Can_F_Isr, FLEXCAN_5_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
859 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_16_31, 2, 0 );
\r
860 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_32_63, 2, 0 );
\r
864 #elif defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668)
\r
866 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
867 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_A_ESR_BOFF_INT, 2, 0);
\r
869 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
870 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_A_ESR_ERR_INT, 2, 0 );
\r
872 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
873 INSTALL_HANDLER16( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF0I, 2, 0 );
\r
874 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF31_16I, 2, 0 );
\r
875 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF63_32I, 2, 0 );
\r
879 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
880 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_B_ESR_BOFF_INT, 2, 0 );
\r
882 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
883 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_B_ESR_ERR_INT, 2, 0 );
\r
885 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
886 INSTALL_HANDLER16( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF0I, 2, 0 );
\r
887 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF31_16I, 2, 0 );
\r
888 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF63_32I, 2, 0 );
\r
892 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
893 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_C_ESR_BOFF_INT, 2, 0 );
\r
895 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
896 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_C_ESR_ERR_INT, 2, 0 );
\r
898 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
899 INSTALL_HANDLER16( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF0I, 2, 0 );
\r
900 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF31_16I, 2, 0 );
\r
901 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF63_32I, 2, 0 );
\r
905 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
906 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_D_ESR_BOFF_INT, 2, 0 );
\r
908 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
909 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_D_ESR_ERR_INT, 2, 0 );
\r
911 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
912 INSTALL_HANDLER16( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF0I, 2, 0 );
\r
913 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF31_16I, 2, 0 );
\r
914 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF63_32I, 2, 0 );
\r
918 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
919 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_E_ESR_BOFF_INT, 2, 0 );
\r
921 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
922 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_E_ESR_ERR_INT, 2, 0 );
\r
924 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
925 INSTALL_HANDLER16( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF0I, 2, 0 );
\r
926 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF31_16I, 2, 0 );
\r
927 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF63_32I, 2, 0 );
\r
930 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668)
\r
932 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
933 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_F_ESR_BOFF_INT, 2, 0 );
\r
935 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
936 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_F_ESR_ERR_INT, 2, 0 );
\r
938 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
939 INSTALL_HANDLER16( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF0I, 2, 0 );
\r
940 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF31_16I, 2, 0 );
\r
941 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF63_32I, 2, 0 );
\r
953 // Unitialize the module
\r
956 Can_UnitType *canUnit;
\r
957 const Can_ControllerConfigType *cfgCtrlPtr;
\r
960 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
961 cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[(configId)];
\r
962 ctlrId = cfgCtrlPtr->CanControllerId;
\r
964 canUnit = CTRL_TO_UNIT_PTR(ctlrId);
\r
966 Can_DisableControllerInterrupts(ctlrId);
\r
968 canUnit->state = CANIF_CS_UNINIT;
\r
970 canUnit->lock_cnt = 0;
\r
972 #if (USE_CAN_STATISTICS == STD_ON)
\r
974 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
\r
978 Can_Global.config = NULL;
\r
979 Can_Global.initRun = CAN_UNINIT;
\r
984 void Can_InitController(uint8 controller,
\r
985 const Can_ControllerConfigType *config)
\r
987 /** @req 3.1.5/CAN229 */
\r
988 /** !req 3.1.5/CAN192 */
\r
995 Can_UnitType *canUnit;
\r
996 const Can_ControllerConfigType *cfgCtrlPtr;
\r
997 const Can_HardwareObjectType *hohPtr;
\r
1000 /** @req 3.1.5/CAN187 */
\r
1001 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_UNINIT );
\r
1002 /** @req 3.1.5/CAN188 */
\r
1003 VALIDATE_NO_RV( (config != NULL ), CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_POINTER);
\r
1004 /** !req 3.1.5/CAN189 Controller is controller number, not a sequence number? */
\r
1005 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_INITCONTROLLER_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1007 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1008 /** @req 3.1.5/CAN190 */
\r
1009 VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_TRANSITION );
\r
1011 canHw = canUnit->hwPtr;
\r
1012 cfgCtrlPtr = canUnit->cfgCtrlPtr;
\r
1014 // Start this baby up
\r
1015 canHw->MCR.B.MDIS = 0;
\r
1017 // Wait for it to reset
\r
1018 if (!SIMULATOR()) {
\r
1019 // Freeze to write all mem mapped registers ( see 25.4.8.1 )
\r
1020 canHw->MCR.B.FRZ = 1;
\r
1021 canHw->MCR.B.HALT = 1;
\r
1024 if( config->Can_Arc_Flags & CAN_CTRL_FIFO ) {
\r
1025 canHw->MCR.B.FEN = 1; /* Enable FIFO */
\r
1026 canHw->MCR.B.IDAM = 0; /* We want extended id's to match with */
\r
1028 canHw->MCR.B.BCC = 1; /* Enable all nice features */
\r
1030 /* Use Fsys derivate */
\r
1031 canHw->CR.B.CLKSRC = 1;
\r
1032 canHw->MCR.B.MAXMB = cfgCtrlPtr->Can_Arc_MailboxMax - 1;
\r
1035 /* Disable self-reception, if not loopback */
\r
1036 canHw->MCR.B.SRXDIS = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 0 : 1;
\r
1038 /* Clock calucation
\r
1039 * -------------------------------------------------------------------
\r
1041 * * 1 TQ = Sclk period( also called SCK )
\r
1042 * * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk
\r
1043 * ( Fcanclk can come from crystal or from the peripheral dividers )
\r
1046 * TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )
\r
1047 * TQ is between 8 and 25
\r
1050 /* Calculate the number of timequanta's (from "Protocol Timing"( chap. 25.4.7.4 )) */
\r
1051 tq1 = (config->CanControllerPropSeg + config->CanControllerSeg1 + 2);
\r
1052 tq2 = (config->CanControllerSeg2 + 1);
\r
1053 tq = 1 + tq1 + tq2;
\r
1055 // Check TQ limitations..
\r
1056 VALIDATE_DEM_NO_RV(( (tq1>=4) && (tq1<=16)), CAN_E_TIMEOUT );
\r
1057 VALIDATE_DEM_NO_RV(( (tq2>=2) && (tq2<=8)), CAN_E_TIMEOUT );
\r
1058 VALIDATE_DEM_NO_RV(( (tq>8) && (tq<25 )), CAN_E_TIMEOUT );
\r
1060 // Assume we're using the peripheral clock instead of the crystal.
\r
1061 clock = McuE_GetPeripheralClock((McuE_PeriperalClock_t) config->CanCpuClockRef);
\r
1063 canHw->CR.B.PRESDIV = clock / (config->CanControllerBaudRate * 1000 * tq) - 1;
\r
1064 canHw->CR.B.PROPSEG = config->CanControllerPropSeg;
\r
1065 canHw->CR.B.PSEG1 = config->CanControllerSeg1;
\r
1066 canHw->CR.B.PSEG2 = config->CanControllerSeg2;
\r
1067 canHw->CR.B.SMP = 1; // 3 samples better than 1 ??
\r
1068 canHw->CR.B.LPB = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 1 : 0;
\r
1069 canHw->CR.B.BOFFREC = 1; // Disable bus off recovery
\r
1071 /* Setup mailboxes for this controller */
\r
1072 hohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
1076 assert( hohPtr != NULL );
\r
1078 struct FLEXCAN_RXFIFO_t *fifoIdPtr = (struct FLEXCAN_RXFIFO_t *)&canHw->BUF[0];
\r
1080 memset(&canHw->BUF[0],0,sizeof(struct canbuf_t)*cfgCtrlPtr->Can_Arc_MailboxMax);
\r
1082 for( int i=0; i < 8;i++) {
\r
1083 canHw->RXIMR[i].R = 0xfffffffful;
\r
1084 fifoIdPtr->IDTABLE[i].R = 0x0;
\r
1087 /* The HOHs are sorted by FIFO(FULL_CAN), FIFO(BASIC_CAN),
\r
1088 * FULL_CAN(no FIFO) and last BASIC_CAN(no FIFO) */
\r
1089 for( int i=0; i < cfgCtrlPtr->Can_Arc_HohCnt;i++,hohPtr++)
\r
1091 if( ( hohPtr->CanObjectType != CAN_OBJECT_TYPE_RECEIVE) ) {
\r
1095 /* Assign FIFO first it will search for match first there (its the first MBs) */
\r
1096 if( fifoNr < cfgCtrlPtr->Can_Arc_HohFifoCnt ) {
\r
1097 /* TODO : Set IDAM */
\r
1100 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1101 fifoIdPtr->IDTABLE[fifoNr].R = ((hohPtr->CanIdValue << 1) | 0x40000000) ;
\r
1103 fifoIdPtr->IDTABLE[fifoNr].R = (hohPtr->CanIdValue << 19) ;
\r
1106 /* The Mask (we have FULL_CAN here) */
\r
1107 canHw->RXIMR[fifoNr].R = *hohPtr->CanFilterMaskRef;
\r
1110 /* loop for multiplexed mailboxes, set as same as first */
\r
1111 uint64 mbMask = hohPtr->ArcMailboxMask;
\r
1114 for (; mbMask; mbMask &= ~(1ull << mbTmp)) {
\r
1115 mbTmp = ilog2_64(mbMask);
\r
1117 canHw->BUF[mbTmp].CS.B.CODE = MB_RX;
\r
1118 canHw->RXIMR[mbTmp].R = *hohPtr->CanFilterMaskRef;
\r
1120 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1121 canHw->BUF[mbTmp].CS.B.IDE = 1;
\r
1122 canHw->BUF[mbTmp].ID.R = hohPtr->CanIdValue;
\r
1124 canHw->BUF[mbTmp].CS.B.IDE = 0;
\r
1125 canHw->BUF[mbTmp].ID.B.STD_ID = hohPtr->CanIdValue;
\r
1133 canUnit->mbTxFree = canUnit->Can_Arc_TxMbMask;
\r
1134 /* @req 3.1.5/CAN260 */
\r
1135 canUnit->state = CANIF_CS_STOPPED;
\r
1140 Can_ReturnType Can_SetControllerMode(uint8 controller,
\r
1141 Can_StateTransitionType transition)
\r
1143 /** @req 3.1.5/CAN230 */
\r
1144 /** @req 3.1.5/CAN017 */
\r
1145 /** !req 3.1.5/CAN294 Wakeup not supported */
\r
1146 /** !req 3.1.5/CAN197 */
\r
1147 /** !req 3.1.5/CAN201 */
\r
1151 Can_ReturnType rv = CAN_OK;
\r
1153 /** @req 3.1.5/CAN198 */
\r
1154 VALIDATE( (Can_Global.initRun == CAN_READY), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1155 /** @req 3.1.5/CAN199 */
\r
1156 VALIDATE( VALID_CONTROLLER(controller), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1157 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1158 VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1160 canHw = canUnit->hwPtr;
\r
1162 switch (transition) {
\r
1164 canHw->MCR.B.HALT = 0;
\r
1165 canUnit->state = CANIF_CS_STARTED;
\r
1167 /** @req 3.1.5/CAN196 */
\r
1168 if (canUnit->lock_cnt == 0)
\r
1170 Can_EnableControllerInterrupts(controller);
\r
1172 Irq_Restore(state);
\r
1174 case CAN_T_WAKEUP: //CAN267
\r
1175 case CAN_T_SLEEP: //CAN258, CAN290
\r
1176 // Should be reported to DEM but DET is the next best
\r
1177 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1180 canHw->MCR.B.HALT = 1;
\r
1181 canUnit->state = CANIF_CS_STOPPED;
\r
1182 Can_AbortTx(canHw, canUnit); // CANIF282
\r
1185 // Should be reported to DEM but DET is the next best
\r
1186 /** @req 3.1.5/CAN200 */
\r
1187 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1194 void Can_DisableControllerInterrupts(uint8 controller)
\r
1196 /** @req 3.1.5/CAN231 */
\r
1197 /** @req 3.1.5/CAN202 */
\r
1198 /** !req 3.1.5/CAN204 */
\r
1199 /** !req 3.1.5/CAN292 */
\r
1201 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1202 /** @req 3.1.5/CAN206 */
\r
1203 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1204 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1208 /** @req 3.1.5/CAN205 */
\r
1209 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1214 /** @req 3.1.5/CAN049 */
\r
1215 if (canUnit->lock_cnt > 0) {
\r
1216 // Interrupts already disabled
\r
1217 canUnit->lock_cnt++;
\r
1218 Irq_Restore(state);
\r
1221 canUnit->lock_cnt++;
\r
1222 Irq_Restore(state);
\r
1224 /* Don't try to be intelligent, turn everything off */
\r
1225 canHw = GET_CONTROLLER(controller);
\r
1227 /* Turn off the interrupt mailboxes */
\r
1228 canHw->IMRH.R = 0;
\r
1229 canHw->IMRL.R = 0;
\r
1231 /* Turn off the bus off/tx warning/rx warning and error */
\r
1232 canHw->MCR.B.WRNEN = 0; /* Disable warning int */
\r
1233 canHw->CR.B.ERRMSK = 0; /* Disable error interrupt */
\r
1234 canHw->CR.B.BOFFMSK = 0; /* Disable bus-off interrupt */
\r
1235 canHw->CR.B.TWRNMSK = 0; /* Disable Tx warning */
\r
1236 canHw->CR.B.RWRNMSK = 0; /* Disable Rx warning */
\r
1239 void Can_EnableControllerInterrupts(uint8 controller)
\r
1241 /** @req 3.1.5/CAN232 */
\r
1242 /** @req 3.1.5/CAN050 */
\r
1243 /** !req 3.1.5/CAN293 Not applicable */
\r
1245 Can_UnitType *canUnit;
\r
1249 /** @req 3.1.5/CAN209 */
\r
1250 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1251 /** @req 3.1.5/CAN210 */
\r
1252 VALIDATE_NO_RV( VALID_CONTROLLER(controller), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1253 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1254 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1257 if (canUnit->lock_cnt > 1) {
\r
1258 /** @req 3.1.5/CAN208 */
\r
1259 // IRQ should still be disabled so just decrement counter
\r
1260 canUnit->lock_cnt--;
\r
1261 Irq_Restore(state);
\r
1263 } else if (canUnit->lock_cnt == 1) {
\r
1264 canUnit->lock_cnt = 0;
\r
1266 Irq_Restore(state);
\r
1268 canHw = canUnit->hwPtr;
\r
1270 canHw->IMRH.R = 0;
\r
1271 canHw->IMRL.R = 0;
\r
1273 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ) {
\r
1274 /* Turn on the interrupt mailboxes */
\r
1275 canHw->IMRL.R = canUnit->Can_Arc_RxMbMask;
\r
1276 canHw->IMRH.R = (uint32_t)(canUnit->Can_Arc_RxMbMask>>32);
\r
1279 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) {
\r
1280 /* Turn on the interrupt mailboxes */
\r
1281 canHw->IMRL.R |= canUnit->Can_Arc_TxMbMask;
\r
1282 canHw->IMRH.R |= (uint32_t)(canUnit->Can_Arc_TxMbMask>>32);
\r
1285 // BusOff and warnings
\r
1286 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) {
\r
1287 canHw->MCR.B.WRNEN = 1; /* Turn On warning int */
\r
1288 canHw->CR.B.BOFFMSK = 1; /* Enable bus-off interrupt */
\r
1290 #if (USE_CAN_STATISTICS == STD_ON)
\r
1291 canHw->CR.B.TWRNMSK = 1; /* Enable Tx warning */
\r
1292 canHw->CR.B.RWRNMSK = 1; /* Enable Rx warning */
\r
1297 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT) {
\r
1298 canHw->CR.B.ERRMSK = 1; /* Enable error interrupt */
\r
1304 Can_ReturnType Can_Write(Can_Arc_HTHType hth, Can_PduType *pduInfo)
\r
1306 /** @req 3.1.5/CAN223 */
\r
1307 /** !req 3.1.5/CAN213 Priorities not supported */
\r
1308 /** !req 3.1.5/CAN215 Priorities not supported */
\r
1309 /** @req 3.1.5/CAN214 */
\r
1310 /** @req 3.1.5/CAN272 */
\r
1314 Can_ReturnType rv = CAN_OK;
\r
1317 const Can_HardwareObjectType *hohObj;
\r
1318 Can_UnitType *canUnit;
\r
1321 /** @req 3.1.5/CAN216 */
\r
1322 VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );
\r
1323 /** @req 3.1.5/CAN219 */
\r
1324 VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );
\r
1325 /** @req 3.1.5/CAN218 */
\r
1326 VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );
\r
1327 /** @req 3.1.5/CAN217 */
\r
1328 VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );
\r
1330 canUnit = &CanUnit[Can_Global.config->CanConfigSet->ArcHthToUnit[hth]];
\r
1331 hohObj = &canUnit->cfgHohPtr[Can_Global.config->CanConfigSet->ArcHthToHoh[hth]];
\r
1332 canHw = canUnit->hwPtr;
\r
1334 /* We have the hohObj, we need to know what box we can send on */
\r
1336 /* Get all free TX mboxes */
\r
1337 uint64_t iHwFlag = *(uint64_t *)(&canHw->IFRH.R); /* These are occupied */
\r
1338 assert( (canUnit->Can_Arc_TxMbMask & hohObj->ArcMailboxMask) != 0);
\r
1339 iflag = ~iHwFlag & canUnit->mbTxFree & hohObj->ArcMailboxMask;
\r
1340 /* Get the mbox(es) for this HTH */
\r
1342 /** @req 3.1.5/CAN212 */
\r
1344 mbNr = ilog2_64(iflag ); // find mb number
\r
1346 /* Indicate that we are sending this MB */
\r
1347 canUnit->mbTxFree &= ~(1ull<<mbNr);
\r
1349 canHw->BUF[mbNr].CS.R = 0;
\r
1350 canHw->BUF[mbNr].ID.R = 0;
\r
1352 // Setup message box type
\r
1353 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1354 canHw->BUF[mbNr].CS.B.IDE = 1;
\r
1355 } else if (hohObj->CanIdType == CAN_ID_TYPE_STANDARD) {
\r
1356 canHw->BUF[mbNr].CS.B.IDE = 0;
\r
1358 // No support for mixed in this processor
\r
1363 canHw->BUF[mbNr].CS.B.CODE = MB_INACTIVE; // Hold the transmit buffer inactive
\r
1364 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1365 canHw->BUF[mbNr].ID.R = pduInfo->id; // Write 29-bit MB IDs
\r
1367 assert( !(pduInfo->id & 0xfffff800) );
\r
1368 canHw->BUF[mbNr].ID.B.STD_ID = pduInfo->id;
\r
1371 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S) || defined(CFG_MPC5604B) || defined(CFG_MPC5668)
\r
1372 canHw->BUF[mbNr].ID.B.PRIO = 1; // Set Local Priority
\r
1375 memset(&canHw->BUF[mbNr].DATA, 0, 8);
\r
1376 memcpy(&canHw->BUF[mbNr].DATA, pduInfo->sdu, pduInfo->length);
\r
1378 canHw->BUF[mbNr].CS.B.SRR = 1;
\r
1379 canHw->BUF[mbNr].CS.B.RTR = 0;
\r
1381 canHw->BUF[mbNr].CS.B.LENGTH = pduInfo->length;
\r
1382 canHw->BUF[mbNr].CS.B.CODE = MB_TX_ONCE; // Write tx once code
\r
1383 timer = canHw->TIMER.R; // Unlock Message buffers
\r
1385 #if (USE_CAN_STATISTICS == STD_ON)
\r
1386 canUnit->stats.txSuccessCnt++;
\r
1389 // Store pdu handle in unit to be used by TxConfirmation
\r
1390 canUnit->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-canUnit->cfgCtrlPtr->Can_Arc_TxMailboxStart] = pduInfo->swPduHandle;
\r
1395 Irq_Restore(state);
\r
1400 void Can_Cbk_CheckWakeup( uint8 controller ) {
\r
1401 /** !req 3.1.5/CAN360 */
\r
1402 /** !req 3.1.5/CAN361 */
\r
1403 /** !req 3.1.5/CAN362 */
\r
1404 /** !req 3.1.5/CAN363 */
\r
1406 /* NOT SUPPORTED */
\r
1411 void Can_MainFunction_Write( void ) {
\r
1412 /** !req 3.1.5/CAN225 */
\r
1413 /** !req 3.1.5/CAN031 */
\r
1414 /** !req 3.1.5/CAN178 */
\r
1415 /** !req 3.1.5/CAN179 */
\r
1416 Can_UnitType *uPtr;
\r
1418 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1419 uPtr = &CanUnit[i];
\r
1420 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) == 0 ) {
\r
1426 void Can_MainFunction_Read(void)
\r
1428 /** !req 3.1.5/CAN226 */
\r
1429 /** !req 3.1.5/CAN108 */
\r
1430 /** !req 3.1.5/CAN180 */
\r
1431 /** !req 3.1.5/CAN181 */
\r
1432 Can_UnitType *uPtr;
\r
1434 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1435 uPtr = &CanUnit[i];
\r
1436 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT) == 0 ) {
\r
1442 void Can_MainFunction_BusOff(void)
\r
1444 /** !req 3.1.5/CAN227 */
\r
1445 /** !req 3.1.5/CAN109 */
\r
1446 /** !req 3.1.5/CAN183 */
\r
1447 /** !req 3.1.5/CAN184 */
\r
1448 /* Bus-off polling events */
\r
1452 void Can_MainFunction_Wakeup(void)
\r
1454 /** !req 3.1.5/CAN228 */
\r
1455 /** !req 3.1.5/CAN112 */
\r
1456 /** !req 3.1.5/CAN185 */
\r
1457 /** !req 3.1.5/CAN186 */
\r
1458 /* Wakeup polling events */
\r
1460 /* NOT SUPPORTED */
\r
1464 Can_Arc_ProcessType Can_Arc_ProcessingMode( uint8 controller ) {
\r
1465 Can_UnitType *uPtr = &CanUnit[controller];
\r
1468 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
1476 #if (USE_CAN_STATISTICS == STD_ON)
\r
1478 * Get send/receive/error statistics for a controller
\r
1480 * @param controller The controller
\r
1481 * @param stats Pointer to data to copy statistics to
\r
1485 void Can_Arc_GetStatistics(uint8 controller, Can_Arc_StatisticsType *stats)
\r
1487 if(Can_Global.initRun == CAN_READY)
\r
1489 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1490 *stats = canUnit->stats;
\r