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
494 if (canHw->CR.B.BOFFREC) {
\r
495 canHw->CR.B.BOFFREC = 0;
\r
496 canHw->CR.B.BOFFREC = 1;
\r
505 static void Can_Isr_Tx(Can_UnitType *uPtr)
\r
512 canHw = uPtr->hwPtr;
\r
514 uint64_t mbMask = *(uint64_t *) (&canHw->IFRH.R);
\r
515 mbMask &= uPtr->Can_Arc_TxMbMask;
\r
520 #if defined(CFG_CAN_TEST)
\r
521 Can_Test.mbMaskTx |= mbMask;
\r
525 for (; mbMask; mbMask &= ~(1ull << mbNr)) {
\r
526 mbNr = ilog2_64(mbMask);
\r
528 pduId = uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart];
\r
529 uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart] = 0;
\r
531 // Clear interrupt and mark txBox as Free
\r
532 clearMbFlag(canHw,mbNr);
\r
533 uPtr->mbTxFree |= (1ull << mbNr);
\r
535 if (GET_CALLBACKS()->TxConfirmation != NULL) {
\r
536 GET_CALLBACKS()->TxConfirmation(pduId);
\r
541 static void Can_Isr_Rx(Can_UnitType *uPtr)
\r
549 const Can_HardwareObjectType *hohPtr;
\r
551 canHw = uPtr->hwPtr;
\r
553 uint64_t iFlag = *(uint64_t*) (&canHw->IFRH.R);
\r
555 #if defined(CFG_CAN_TEST)
\r
556 Can_Test.mbMaskRx |= iFlag & uPtr->Can_Arc_RxMbMask;
\r
559 while (iFlag & uPtr->Can_Arc_RxMbMask) {
\r
562 mbNr = ilog2_64(iFlag & uPtr->Can_Arc_RxMbMask);
\r
564 /* Check for FIFO interrupt */
\r
565 if (canHw->MCR.B.FEN && ((uint32_t)iFlag & (1 << 5))) {
\r
572 /* Check overflow */
\r
573 if (iFlag & (1 << 7)) {
\r
574 #if (USE_CAN_STATISTICS == STD_ON)
\r
575 uPtr->stats.fifoOverflow++;
\r
577 canHw->IFRL.B.BUF07I = 1;
\r
579 DET_REPORTERROR(MODULE_ID_CAN,0,0, CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
582 #if (USE_CAN_STATISTICS == STD_ON)
\r
583 /* Check warning */
\r
584 if (iFlag & (1 << 6)) {
\r
585 uPtr->stats.fifoWarning++;
\r
586 canHw->IFRL.B.BUF06I = 1;
\r
590 /* The manual is "fuzzy" here, read control and status */
\r
591 (void) canHw->BUF[0].CS.R;
\r
593 if (canHw->BUF[0].CS.B.IDE) {
\r
594 id = canHw->BUF[0].ID.R;
\r
597 id = canHw->BUF[0].ID.B.STD_ID;
\r
600 LDEBUG_PRINTF("FIFO_ID=%x ",(unsigned int)id);
\r
602 /* Must now do a manual match to find the right CanHardwareObject
\r
603 * to pass to CanIf. We know that the FIFO objects are sorted first.
\r
605 hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
607 /* Match in order */
\r
608 vuint32_t *fifoIdPtr = (vuint32_t *) &canHw->BUF[6];
\r
611 for (uint8 fifoNr = 0; fifoNr < uPtr->cfgCtrlPtr->Can_Arc_HohFifoCnt; fifoNr++) {
\r
612 mask = canHw->RXIMR[fifoNr].R;
\r
614 if ((id & mask) != (fifoIdPtr[fifoNr] & mask)) {
\r
618 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
619 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[fifoNr],
\r
621 canHw->BUF[0].CS.B.LENGTH,
\r
622 (uint8 *) &canHw->BUF[0].DATA.W[0]);
\r
627 // Clear the interrupt
\r
628 canHw->IFRL.B.BUF05I = 1;
\r
630 if( canHw->IFRL.B.BUF05I == 0 ) {
\r
631 iFlag ^= 1ull << mbNr;
\r
636 iFlag ^= 1ull << mbNr;
\r
639 /* activate the internal lock with a read*/
\r
640 (void) canHw->BUF[mbNr].CS.R;
\r
643 if (canHw->BUF[mbNr].CS.B.IDE) {
\r
644 id = canHw->BUF[mbNr].ID.R;
\r
647 id = canHw->BUF[mbNr].ID.B.STD_ID;
\r
650 LDEBUG_PRINTF("ID=%x ",(unsigned int)id);
\r
653 #if defined(USE_DET)
\r
654 if( canHw->BUF[mbNr].CS.B.CODE == MB_RX_OVERRUN ) {
\r
655 /* We have overwritten one frame */
\r
656 Det_ReportError(MODULE_ID_CAN,0,0,CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
660 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
661 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr], id,
\r
662 canHw->BUF[mbNr].CS.B.LENGTH,
\r
663 (uint8 *) &canHw->BUF[mbNr].DATA.W[0]);
\r
665 #if (USE_CAN_STATISTICS == STD_ON)
\r
666 uPtr->stats.rxSuccessCnt++;
\r
668 /* unlock MB (dummy read timer) */
\r
669 (void) canHw->TIMER.R;
\r
672 clearMbFlag(canHw, mbNr);
\r
679 static void Can_Isr(int controller )
\r
681 Can_UnitType *uPtr = CTRL_TO_UNIT_PTR(controller);
\r
683 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
687 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ){
\r
693 //-------------------------------------------------------------------
\r
696 static void Can_BuildMaps(Can_UnitType *uPtr)
\r
701 uint8_t fifoNr = 0;
\r
703 const Can_HardwareObjectType *hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
705 printf("Found %d HOHs\n", uPtr->cfgCtrlPtr->Can_Arc_HohCnt);
\r
707 for (int i = 0; i < uPtr->cfgCtrlPtr->Can_Arc_HohCnt; i++, hohPtr++) {
\r
708 if (hohPtr->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) {
\r
709 /* First 8 boxes are FIFO */
\r
710 if (hohPtr->Can_Arc_Flags & CAN_HOH_FIFO_MASK) {
\r
711 uPtr->mbToHrh[fifoNr++] = hohPtr->CanObjectId;
\r
712 uPtr->Can_Arc_RxMbMask |= (1<<5);
\r
714 uint64_t mask = (-1ULL);
\r
715 uPtr->mbToHrh[mbNr] = hohPtr->CanObjectId;
\r
719 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
720 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
721 uPtr->Can_Arc_RxMbMask |= mask;
\r
723 mbNr += hohPtr->ArcCanNumMailboxes;
\r
725 printf("mbNr=%d fifoNr=%d\n", mbNr, fifoNr);
\r
728 uint64_t mask = (-1ULL);
\r
731 * i = index into the HOH list for this controller */
\r
732 Can_HthToHohMap[ hohPtr->CanObjectId ] = i;
\r
733 Can_HthToUnitIdMap[ hohPtr->CanObjectId ] = uPtr->controllerId;
\r
734 /* HOH to Mailbox */
\r
735 for( int j=0;j < hohPtr->ArcCanNumMailboxes; j++ ) {
\r
736 uPtr->mbToHrh[mbNr+j] = hohPtr->CanObjectId;
\r
741 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
742 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
743 uPtr->Can_Arc_TxMbMask |= mask;
\r
744 mbNr += hohPtr->ArcCanNumMailboxes;
\r
747 uPtr->mbMax = mbNr;
\r
751 // This initiates ALL can controllers
\r
752 void Can_Init(const Can_ConfigType *config)
\r
754 /** @req 3.1.5/CAN223 */
\r
755 /** !req 3.1.5/CAN176 */
\r
757 Can_UnitType *unitPtr;
\r
759 /** @req 3.1.5/CAN174 */
\r
760 VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), CAN_INIT_SERVICE_ID, CAN_E_TRANSITION );
\r
761 /** @req 3.1.5/CAN175 */
\r
762 VALIDATE_NO_RV( (config != NULL ), CAN_INIT_SERVICE_ID, CAN_E_PARAM_POINTER );
\r
765 Can_Global.config = config;
\r
766 Can_Global.initRun = CAN_READY;
\r
768 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
769 const Can_ControllerConfigType *cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[configId];
\r
771 Can_Global.configuredMask |= (1 << cfgCtrlPtr->CanControllerId);
\r
772 unitPtr = &CanUnit[configId];
\r
774 memset(unitPtr, 0, sizeof(Can_UnitType));
\r
776 unitPtr->controllerId = cfgCtrlPtr->CanControllerId;
\r
777 unitPtr->hwPtr = GET_CONTROLLER(cfgCtrlPtr->CanControllerId);
\r
778 unitPtr->cfgCtrlPtr = cfgCtrlPtr;
\r
779 unitPtr->state = CANIF_CS_STOPPED;
\r
780 unitPtr->cfgHohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
782 unitPtr->Can_Arc_RxMbMask = cfgCtrlPtr->Can_Arc_RxMailBoxMask;
\r
783 unitPtr->Can_Arc_TxMbMask = cfgCtrlPtr->Can_Arc_TxMailBoxMask;
\r
785 Can_BuildMaps(unitPtr);
\r
787 switch (cfgCtrlPtr->CanControllerId) {
\r
788 #if defined(CFG_MPC560X)
\r
790 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
791 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_0_ESR_BOFF_INT, 2, 0);
\r
793 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
794 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_0_ESR_ERR_INT, 2, 0 );
\r
796 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
797 INSTALL_HANDLER4( "Can", Can_A_Isr, FLEXCAN_0_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
798 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_16_31, 2, 0 );
\r
799 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_32_63, 2, 0 );
\r
803 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
804 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_1_ESR_BOFF_INT, 2, 0);
\r
806 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
807 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_1_ESR_ERR_INT, 2, 0 );
\r
809 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
810 INSTALL_HANDLER4( "Can", Can_B_Isr, FLEXCAN_1_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
811 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_16_31, 2, 0 );
\r
812 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_32_63, 2, 0 );
\r
815 #if defined(CFG_MPC5604B)
\r
817 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
818 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_2_ESR_BOFF_INT, 2, 0);
\r
820 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
821 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_2_ESR_ERR_INT, 2, 0 );
\r
823 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
824 INSTALL_HANDLER4( "Can", Can_C_Isr, FLEXCAN_2_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
825 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_16_31, 2, 0 );
\r
826 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_32_63, 2, 0 );
\r
830 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
831 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_3_ESR_BOFF_INT, 2, 0);
\r
833 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
834 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_3_ESR_ERR_INT, 2, 0 );
\r
836 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
837 INSTALL_HANDLER4( "Can", Can_D_Isr, FLEXCAN_3_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
838 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_16_31, 2, 0 );
\r
839 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_32_63, 2, 0 );
\r
843 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
844 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_4_ESR_BOFF_INT, 2, 0);
\r
846 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
847 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_4_ESR_ERR_INT, 2, 0 );
\r
849 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
850 INSTALL_HANDLER4( "Can", Can_E_Isr, FLEXCAN_4_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
851 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_16_31, 2, 0 );
\r
852 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_32_63, 2, 0 );
\r
856 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
857 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_5_ESR_BOFF_INT, 2, 0);
\r
859 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
860 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_5_ESR_ERR_INT, 2, 0 );
\r
862 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
863 INSTALL_HANDLER4( "Can", Can_F_Isr, FLEXCAN_5_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
864 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_16_31, 2, 0 );
\r
865 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_32_63, 2, 0 );
\r
869 #elif defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668)
\r
871 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
872 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_A_ESR_BOFF_INT, 2, 0);
\r
874 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
875 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_A_ESR_ERR_INT, 2, 0 );
\r
877 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
878 INSTALL_HANDLER16( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF0I, 2, 0 );
\r
879 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF31_16I, 2, 0 );
\r
880 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF63_32I, 2, 0 );
\r
884 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
885 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_B_ESR_BOFF_INT, 2, 0 );
\r
887 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
888 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_B_ESR_ERR_INT, 2, 0 );
\r
890 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
891 INSTALL_HANDLER16( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF0I, 2, 0 );
\r
892 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF31_16I, 2, 0 );
\r
893 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF63_32I, 2, 0 );
\r
897 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
898 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_C_ESR_BOFF_INT, 2, 0 );
\r
900 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
901 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_C_ESR_ERR_INT, 2, 0 );
\r
903 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
904 INSTALL_HANDLER16( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF0I, 2, 0 );
\r
905 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF31_16I, 2, 0 );
\r
906 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF63_32I, 2, 0 );
\r
910 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
911 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_D_ESR_BOFF_INT, 2, 0 );
\r
913 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
914 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_D_ESR_ERR_INT, 2, 0 );
\r
916 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
917 INSTALL_HANDLER16( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF0I, 2, 0 );
\r
918 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF31_16I, 2, 0 );
\r
919 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF63_32I, 2, 0 );
\r
923 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
924 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_E_ESR_BOFF_INT, 2, 0 );
\r
926 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
927 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_E_ESR_ERR_INT, 2, 0 );
\r
929 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
930 INSTALL_HANDLER16( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF0I, 2, 0 );
\r
931 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF31_16I, 2, 0 );
\r
932 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF63_32I, 2, 0 );
\r
935 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668)
\r
937 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT){
\r
938 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_F_ESR_BOFF_INT, 2, 0 );
\r
940 if(cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT){
\r
941 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_F_ESR_ERR_INT, 2, 0 );
\r
943 if(cfgCtrlPtr->Can_Arc_Flags & (CAN_CTRL_TX_PROCESSING_INTERRUPT | CAN_CTRL_RX_PROCESSING_INTERRUPT)){
\r
944 INSTALL_HANDLER16( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF0I, 2, 0 );
\r
945 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF31_16I, 2, 0 );
\r
946 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF63_32I, 2, 0 );
\r
958 // Unitialize the module
\r
961 Can_UnitType *canUnit;
\r
962 const Can_ControllerConfigType *cfgCtrlPtr;
\r
965 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
966 cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[(configId)];
\r
967 ctlrId = cfgCtrlPtr->CanControllerId;
\r
969 canUnit = CTRL_TO_UNIT_PTR(ctlrId);
\r
971 Can_DisableControllerInterrupts(ctlrId);
\r
973 canUnit->state = CANIF_CS_UNINIT;
\r
975 canUnit->lock_cnt = 0;
\r
977 #if (USE_CAN_STATISTICS == STD_ON)
\r
979 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
\r
983 Can_Global.config = NULL;
\r
984 Can_Global.initRun = CAN_UNINIT;
\r
989 void Can_InitController(uint8 controller,
\r
990 const Can_ControllerConfigType *config)
\r
992 /** @req 3.1.5/CAN229 */
\r
993 /** !req 3.1.5/CAN192 */
\r
1000 Can_UnitType *canUnit;
\r
1001 const Can_ControllerConfigType *cfgCtrlPtr;
\r
1002 const Can_HardwareObjectType *hohPtr;
\r
1005 /** @req 3.1.5/CAN187 */
\r
1006 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_UNINIT );
\r
1007 /** @req 3.1.5/CAN188 */
\r
1008 VALIDATE_NO_RV( (config != NULL ), CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_POINTER);
\r
1009 /** !req 3.1.5/CAN189 Controller is controller number, not a sequence number? */
\r
1010 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_INITCONTROLLER_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1012 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1013 /** @req 3.1.5/CAN190 */
\r
1014 VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_TRANSITION );
\r
1016 canHw = canUnit->hwPtr;
\r
1017 cfgCtrlPtr = canUnit->cfgCtrlPtr;
\r
1019 // Start this baby up
\r
1020 canHw->MCR.B.MDIS = 0;
\r
1022 // Wait for it to reset
\r
1023 if (!SIMULATOR()) {
\r
1024 // Freeze to write all mem mapped registers ( see 25.4.8.1 )
\r
1025 canHw->MCR.B.FRZ = 1;
\r
1026 canHw->MCR.B.HALT = 1;
\r
1029 if( config->Can_Arc_Flags & CAN_CTRL_FIFO ) {
\r
1030 canHw->MCR.B.FEN = 1; /* Enable FIFO */
\r
1031 canHw->MCR.B.IDAM = 0; /* We want extended id's to match with */
\r
1033 canHw->MCR.B.BCC = 1; /* Enable all nice features */
\r
1035 /* Use Fsys derivate */
\r
1036 canHw->CR.B.CLKSRC = 1;
\r
1037 canHw->MCR.B.MAXMB = cfgCtrlPtr->Can_Arc_MailboxMax - 1;
\r
1040 /* Disable self-reception, if not loopback */
\r
1041 canHw->MCR.B.SRXDIS = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 0 : 1;
\r
1043 /* Clock calucation
\r
1044 * -------------------------------------------------------------------
\r
1046 * * 1 TQ = Sclk period( also called SCK )
\r
1047 * * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk
\r
1048 * ( Fcanclk can come from crystal or from the peripheral dividers )
\r
1051 * TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )
\r
1052 * TQ is between 8 and 25
\r
1055 /* Calculate the number of timequanta's (from "Protocol Timing"( chap. 25.4.7.4 )) */
\r
1056 tq1 = (config->CanControllerPropSeg + config->CanControllerSeg1 + 2);
\r
1057 tq2 = (config->CanControllerSeg2 + 1);
\r
1058 tq = 1 + tq1 + tq2;
\r
1060 // Check TQ limitations..
\r
1061 VALIDATE_DEM_NO_RV(( (tq1>=4) && (tq1<=16)), CAN_E_TIMEOUT );
\r
1062 VALIDATE_DEM_NO_RV(( (tq2>=2) && (tq2<=8)), CAN_E_TIMEOUT );
\r
1063 VALIDATE_DEM_NO_RV(( (tq>8) && (tq<25 )), CAN_E_TIMEOUT );
\r
1065 // Assume we're using the peripheral clock instead of the crystal.
\r
1066 clock = McuE_GetPeripheralClock((McuE_PeriperalClock_t) config->CanCpuClockRef);
\r
1068 canHw->CR.B.PRESDIV = clock / (config->CanControllerBaudRate * 1000 * tq) - 1;
\r
1069 canHw->CR.B.PROPSEG = config->CanControllerPropSeg;
\r
1070 canHw->CR.B.PSEG1 = config->CanControllerSeg1;
\r
1071 canHw->CR.B.PSEG2 = config->CanControllerSeg2;
\r
1072 canHw->CR.B.SMP = 1; // 3 samples better than 1 ??
\r
1073 canHw->CR.B.LPB = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 1 : 0;
\r
1074 canHw->CR.B.BOFFREC = 1; // Disable bus off recovery
\r
1076 /* Setup mailboxes for this controller */
\r
1077 hohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
1081 assert( hohPtr != NULL );
\r
1083 struct FLEXCAN_RXFIFO_t *fifoIdPtr = (struct FLEXCAN_RXFIFO_t *)&canHw->BUF[0];
\r
1085 memset(&canHw->BUF[0],0,sizeof(struct canbuf_t)*cfgCtrlPtr->Can_Arc_MailboxMax);
\r
1087 for( int i=0; i < 8;i++) {
\r
1088 canHw->RXIMR[i].R = 0xfffffffful;
\r
1089 fifoIdPtr->IDTABLE[i].R = 0x0;
\r
1092 /* The HOHs are sorted by FIFO(FULL_CAN), FIFO(BASIC_CAN),
\r
1093 * FULL_CAN(no FIFO) and last BASIC_CAN(no FIFO) */
\r
1094 for( int i=0; i < cfgCtrlPtr->Can_Arc_HohCnt;i++,hohPtr++)
\r
1096 if( ( hohPtr->CanObjectType != CAN_OBJECT_TYPE_RECEIVE) ) {
\r
1100 /* Assign FIFO first it will search for match first there (its the first MBs) */
\r
1101 if( fifoNr < cfgCtrlPtr->Can_Arc_HohFifoCnt ) {
\r
1102 /* TODO : Set IDAM */
\r
1105 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1106 fifoIdPtr->IDTABLE[fifoNr].R = ((hohPtr->CanIdValue << 1) | 0x40000000) ;
\r
1108 fifoIdPtr->IDTABLE[fifoNr].R = (hohPtr->CanIdValue << 19) ;
\r
1111 /* The Mask (we have FULL_CAN here) */
\r
1112 canHw->RXIMR[fifoNr].R = *hohPtr->CanFilterMaskRef;
\r
1115 /* loop for multiplexed mailboxes, set as same as first */
\r
1116 uint64 mbMask = hohPtr->ArcMailboxMask;
\r
1119 for (; mbMask; mbMask &= ~(1ull << mbTmp)) {
\r
1120 mbTmp = ilog2_64(mbMask);
\r
1122 canHw->BUF[mbTmp].CS.B.CODE = MB_RX;
\r
1123 canHw->RXIMR[mbTmp].R = *hohPtr->CanFilterMaskRef;
\r
1125 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1126 canHw->BUF[mbTmp].CS.B.IDE = 1;
\r
1127 canHw->BUF[mbTmp].ID.R = hohPtr->CanIdValue;
\r
1129 canHw->BUF[mbTmp].CS.B.IDE = 0;
\r
1130 canHw->BUF[mbTmp].ID.B.STD_ID = hohPtr->CanIdValue;
\r
1138 canUnit->mbTxFree = canUnit->Can_Arc_TxMbMask;
\r
1139 /* @req 3.1.5/CAN260 */
\r
1140 canUnit->state = CANIF_CS_STOPPED;
\r
1145 Can_ReturnType Can_SetControllerMode(uint8 controller,
\r
1146 Can_StateTransitionType transition)
\r
1148 /** @req 3.1.5/CAN230 */
\r
1149 /** @req 3.1.5/CAN017 */
\r
1150 /** !req 3.1.5/CAN294 Wakeup not supported */
\r
1151 /** !req 3.1.5/CAN197 */
\r
1152 /** !req 3.1.5/CAN201 */
\r
1156 Can_ReturnType rv = CAN_OK;
\r
1158 /** @req 3.1.5/CAN198 */
\r
1159 VALIDATE( (Can_Global.initRun == CAN_READY), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1160 /** @req 3.1.5/CAN199 */
\r
1161 VALIDATE( VALID_CONTROLLER(controller), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1162 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1163 VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1165 canHw = canUnit->hwPtr;
\r
1167 switch (transition) {
\r
1169 canHw->MCR.B.HALT = 0;
\r
1170 canUnit->state = CANIF_CS_STARTED;
\r
1172 /** @req 3.1.5/CAN196 */
\r
1173 if (canUnit->lock_cnt == 0)
\r
1175 Can_EnableControllerInterrupts(controller);
\r
1177 Irq_Restore(state);
\r
1179 case CAN_T_WAKEUP: //CAN267
\r
1180 case CAN_T_SLEEP: //CAN258, CAN290
\r
1181 // Should be reported to DEM but DET is the next best
\r
1182 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1185 canHw->MCR.B.HALT = 1;
\r
1186 canUnit->state = CANIF_CS_STOPPED;
\r
1187 Can_AbortTx(canHw, canUnit); // CANIF282
\r
1190 // Should be reported to DEM but DET is the next best
\r
1191 /** @req 3.1.5/CAN200 */
\r
1192 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1199 void Can_DisableControllerInterrupts(uint8 controller)
\r
1201 /** @req 3.1.5/CAN231 */
\r
1202 /** @req 3.1.5/CAN202 */
\r
1203 /** !req 3.1.5/CAN204 */
\r
1204 /** !req 3.1.5/CAN292 */
\r
1206 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1207 /** @req 3.1.5/CAN206 */
\r
1208 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1209 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1213 /** @req 3.1.5/CAN205 */
\r
1214 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1219 /** @req 3.1.5/CAN049 */
\r
1220 if (canUnit->lock_cnt > 0) {
\r
1221 // Interrupts already disabled
\r
1222 canUnit->lock_cnt++;
\r
1223 Irq_Restore(state);
\r
1226 canUnit->lock_cnt++;
\r
1227 Irq_Restore(state);
\r
1229 /* Don't try to be intelligent, turn everything off */
\r
1230 canHw = GET_CONTROLLER(controller);
\r
1232 /* Turn off the interrupt mailboxes */
\r
1233 canHw->IMRH.R = 0;
\r
1234 canHw->IMRL.R = 0;
\r
1236 /* Turn off the bus off/tx warning/rx warning and error */
\r
1237 canHw->MCR.B.WRNEN = 0; /* Disable warning int */
\r
1238 canHw->CR.B.ERRMSK = 0; /* Disable error interrupt */
\r
1239 canHw->CR.B.BOFFMSK = 0; /* Disable bus-off interrupt */
\r
1240 canHw->CR.B.TWRNMSK = 0; /* Disable Tx warning */
\r
1241 canHw->CR.B.RWRNMSK = 0; /* Disable Rx warning */
\r
1244 void Can_EnableControllerInterrupts(uint8 controller)
\r
1246 /** @req 3.1.5/CAN232 */
\r
1247 /** @req 3.1.5/CAN050 */
\r
1248 /** !req 3.1.5/CAN293 Not applicable */
\r
1250 Can_UnitType *canUnit;
\r
1254 /** @req 3.1.5/CAN209 */
\r
1255 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1256 /** @req 3.1.5/CAN210 */
\r
1257 VALIDATE_NO_RV( VALID_CONTROLLER(controller), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1258 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1259 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1262 if (canUnit->lock_cnt > 1) {
\r
1263 /** @req 3.1.5/CAN208 */
\r
1264 // IRQ should still be disabled so just decrement counter
\r
1265 canUnit->lock_cnt--;
\r
1266 Irq_Restore(state);
\r
1268 } else if (canUnit->lock_cnt == 1) {
\r
1269 canUnit->lock_cnt = 0;
\r
1271 Irq_Restore(state);
\r
1273 canHw = canUnit->hwPtr;
\r
1275 canHw->IMRH.R = 0;
\r
1276 canHw->IMRL.R = 0;
\r
1278 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ) {
\r
1279 /* Turn on the interrupt mailboxes */
\r
1280 canHw->IMRL.R = canUnit->Can_Arc_RxMbMask;
\r
1281 canHw->IMRH.R = (uint32_t)(canUnit->Can_Arc_RxMbMask>>32);
\r
1284 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) {
\r
1285 /* Turn on the interrupt mailboxes */
\r
1286 canHw->IMRL.R |= canUnit->Can_Arc_TxMbMask;
\r
1287 canHw->IMRH.R |= (uint32_t)(canUnit->Can_Arc_TxMbMask>>32);
\r
1290 // BusOff and warnings
\r
1291 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) {
\r
1292 canHw->MCR.B.WRNEN = 1; /* Turn On warning int */
\r
1293 canHw->CR.B.BOFFMSK = 1; /* Enable bus-off interrupt */
\r
1295 #if (USE_CAN_STATISTICS == STD_ON)
\r
1296 canHw->CR.B.TWRNMSK = 1; /* Enable Tx warning */
\r
1297 canHw->CR.B.RWRNMSK = 1; /* Enable Rx warning */
\r
1302 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT) {
\r
1303 canHw->CR.B.ERRMSK = 1; /* Enable error interrupt */
\r
1309 Can_ReturnType Can_Write(Can_Arc_HTHType hth, Can_PduType *pduInfo)
\r
1311 /** @req 3.1.5/CAN223 */
\r
1312 /** !req 3.1.5/CAN213 Priorities not supported */
\r
1313 /** !req 3.1.5/CAN215 Priorities not supported */
\r
1314 /** @req 3.1.5/CAN214 */
\r
1315 /** @req 3.1.5/CAN272 */
\r
1319 Can_ReturnType rv = CAN_OK;
\r
1322 const Can_HardwareObjectType *hohObj;
\r
1323 Can_UnitType *canUnit;
\r
1326 /** @req 3.1.5/CAN216 */
\r
1327 VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );
\r
1328 /** @req 3.1.5/CAN219 */
\r
1329 VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );
\r
1330 /** @req 3.1.5/CAN218 */
\r
1331 VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );
\r
1332 /** @req 3.1.5/CAN217 */
\r
1333 VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );
\r
1335 canUnit = &CanUnit[Can_Global.config->CanConfigSet->ArcHthToUnit[hth]];
\r
1336 hohObj = &canUnit->cfgHohPtr[Can_Global.config->CanConfigSet->ArcHthToHoh[hth]];
\r
1337 canHw = canUnit->hwPtr;
\r
1339 /* We have the hohObj, we need to know what box we can send on */
\r
1341 /* Get all free TX mboxes */
\r
1342 uint64_t iHwFlag = *(uint64_t *)(&canHw->IFRH.R); /* These are occupied */
\r
1343 assert( (canUnit->Can_Arc_TxMbMask & hohObj->ArcMailboxMask) != 0);
\r
1344 iflag = ~iHwFlag & canUnit->mbTxFree & hohObj->ArcMailboxMask;
\r
1345 /* Get the mbox(es) for this HTH */
\r
1347 /** @req 3.1.5/CAN212 */
\r
1349 mbNr = ilog2_64(iflag ); // find mb number
\r
1351 /* Indicate that we are sending this MB */
\r
1352 canUnit->mbTxFree &= ~(1ull<<mbNr);
\r
1354 canHw->BUF[mbNr].CS.R = 0;
\r
1355 canHw->BUF[mbNr].ID.R = 0;
\r
1357 // Setup message box type
\r
1358 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1359 canHw->BUF[mbNr].CS.B.IDE = 1;
\r
1360 } else if (hohObj->CanIdType == CAN_ID_TYPE_STANDARD) {
\r
1361 canHw->BUF[mbNr].CS.B.IDE = 0;
\r
1363 // No support for mixed in this processor
\r
1368 canHw->BUF[mbNr].CS.B.CODE = MB_INACTIVE; // Hold the transmit buffer inactive
\r
1369 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1370 canHw->BUF[mbNr].ID.R = pduInfo->id; // Write 29-bit MB IDs
\r
1372 assert( !(pduInfo->id & 0xfffff800) );
\r
1373 canHw->BUF[mbNr].ID.B.STD_ID = pduInfo->id;
\r
1376 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S) || defined(CFG_MPC5604B) || defined(CFG_MPC5668)
\r
1377 canHw->BUF[mbNr].ID.B.PRIO = 1; // Set Local Priority
\r
1380 memset(&canHw->BUF[mbNr].DATA, 0, 8);
\r
1381 memcpy(&canHw->BUF[mbNr].DATA, pduInfo->sdu, pduInfo->length);
\r
1383 canHw->BUF[mbNr].CS.B.SRR = 1;
\r
1384 canHw->BUF[mbNr].CS.B.RTR = 0;
\r
1386 canHw->BUF[mbNr].CS.B.LENGTH = pduInfo->length;
\r
1387 canHw->BUF[mbNr].CS.B.CODE = MB_TX_ONCE; // Write tx once code
\r
1388 timer = canHw->TIMER.R; // Unlock Message buffers
\r
1390 #if (USE_CAN_STATISTICS == STD_ON)
\r
1391 canUnit->stats.txSuccessCnt++;
\r
1394 // Store pdu handle in unit to be used by TxConfirmation
\r
1395 canUnit->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-canUnit->cfgCtrlPtr->Can_Arc_TxMailboxStart] = pduInfo->swPduHandle;
\r
1400 Irq_Restore(state);
\r
1405 void Can_Cbk_CheckWakeup( uint8 controller ) {
\r
1406 /** !req 3.1.5/CAN360 */
\r
1407 /** !req 3.1.5/CAN361 */
\r
1408 /** !req 3.1.5/CAN362 */
\r
1409 /** !req 3.1.5/CAN363 */
\r
1411 /* NOT SUPPORTED */
\r
1416 void Can_MainFunction_Write( void ) {
\r
1417 /** !req 3.1.5/CAN225 */
\r
1418 /** !req 3.1.5/CAN031 */
\r
1419 /** !req 3.1.5/CAN178 */
\r
1420 /** !req 3.1.5/CAN179 */
\r
1421 Can_UnitType *uPtr;
\r
1423 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1424 uPtr = &CanUnit[i];
\r
1425 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) == 0 ) {
\r
1431 void Can_MainFunction_Read(void)
\r
1433 /** !req 3.1.5/CAN226 */
\r
1434 /** !req 3.1.5/CAN108 */
\r
1435 /** !req 3.1.5/CAN180 */
\r
1436 /** !req 3.1.5/CAN181 */
\r
1437 Can_UnitType *uPtr;
\r
1439 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1440 uPtr = &CanUnit[i];
\r
1441 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT) == 0 ) {
\r
1447 void Can_MainFunction_BusOff(void)
\r
1449 /** !req 3.1.5/CAN227 */
\r
1450 /** !req 3.1.5/CAN109 */
\r
1451 /** !req 3.1.5/CAN183 */
\r
1452 /** !req 3.1.5/CAN184 */
\r
1453 /* Bus-off polling events */
\r
1454 Can_UnitType *uPtr;
\r
1456 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1457 uPtr = &CanUnit[i];
\r
1458 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) == 0 ) {
\r
1459 Can_BusOff(uPtr->controllerId);
\r
1464 void Can_MainFunction_Error(void)
\r
1466 /** !req 3.1.5/CAN227 */
\r
1467 /** !req 3.1.5/CAN109 */
\r
1468 /** !req 3.1.5/CAN183 */
\r
1469 /** !req 3.1.5/CAN184 */
\r
1470 /* Error polling events */
\r
1471 Can_UnitType *uPtr;
\r
1473 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1474 uPtr = &CanUnit[i];
\r
1475 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_ERROR_PROCESSING_INTERRUPT) == 0 ) {
\r
1476 Can_Err(uPtr->controllerId);
\r
1481 void Can_MainFunction_Wakeup(void)
\r
1483 /** !req 3.1.5/CAN228 */
\r
1484 /** !req 3.1.5/CAN112 */
\r
1485 /** !req 3.1.5/CAN185 */
\r
1486 /** !req 3.1.5/CAN186 */
\r
1487 /* Wakeup polling events */
\r
1489 /* NOT SUPPORTED */
\r
1493 Can_Arc_ProcessType Can_Arc_ProcessingMode( uint8 controller ) {
\r
1494 Can_UnitType *uPtr = &CanUnit[controller];
\r
1497 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
1505 #if (USE_CAN_STATISTICS == STD_ON)
\r
1507 * Get send/receive/error statistics for a controller
\r
1509 * @param controller The controller
\r
1510 * @param stats Pointer to data to copy statistics to
\r
1514 void Can_Arc_GetStatistics(uint8 controller, Can_Arc_StatisticsType *stats)
\r
1516 if(Can_Global.initRun == CAN_READY)
\r
1518 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1519 *stats = canUnit->stats;
\r