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
157 /* ----------------------------[private define]------------------------------*/
\r
159 #define MAX_NUM_OF_MAILBOXES 64
\r
160 #define USE_CAN_STATISTICS STD_OFF
\r
162 // Message box status defines
\r
163 #define MB_TX_ONCE 0xc
\r
164 #define MB_INACTIVE 0x8
\r
166 #define MB_ABORT 0x9
\r
167 #define MB_RX_OVERRUN 0x6
\r
169 /* ----------------------------[private macro]-------------------------------*/
\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
177 #define INSTALL_HANDLER4(_name, _can_entry, _vector, _priority, _app)\
\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
185 #define INSTALL_HANDLER16(_name, _can_entry, _vector, _priority, _app)\
\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
193 //-------------------------------------------------------------------
\r
195 #if ( CAN_DEV_ERROR_DETECT == STD_ON )
\r
196 #define VALIDATE(_exp,_api,_err ) \
\r
198 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
199 return CAN_NOT_OK; \
\r
202 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
204 Det_ReportError(MODULE_ID_CAN,0,_api,_err); \
\r
208 #define DET_REPORTERROR(_x,_y,_z,_q) Det_ReportError(_x, _y, _z, _q)
\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
215 #if defined(USE_DEM)
\r
216 #define VALIDATE_DEM_NO_RV(_exp,_err ) \
\r
218 Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED); \
\r
222 #define VALIDATE_DEM_NO_RV(_exp,_err )
\r
226 /* ----------------------------[private typedef]-----------------------------*/
\r
229 typedef struct FLEXCAN_tag flexcan_t;
\r
231 #if defined(CFG_CAN_TEST)
\r
232 Can_TestType Can_Test;
\r
236 CAN_UNINIT = 0, CAN_READY
\r
237 } Can_DriverStateType;
\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
256 vuint32_t FLTCONF :2;
\r
258 vuint32_t BOFFINT :1;
\r
259 vuint32_t ERRINT :1;
\r
260 vuint32_t WAKINT :1;
\r
262 } ESRType; /* Error and Status Register */
\r
265 /* Type for holding global information used by the driver */
\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
273 /* Type for holding information about each controller */
\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
282 uint64 Can_Arc_RxMbMask;
\r
283 uint64 Can_Arc_TxMbMask;
\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
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
298 /* ----------------------------[private variables]---------------------------*/
\r
300 Can_UnitType CanUnit[CAN_ARC_CTRL_CONFIG_CNT];
\r
301 Can_GlobalType Can_Global = { .initRun = CAN_UNINIT, };
\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
308 /* ----------------------------[private functions]---------------------------*/
\r
310 static void clearMbFlag( flexcan_t * hw, uint8_t mb ) {
\r
312 hw->IFRH.R = (1<<(mb-32));
\r
314 hw->IFRL.R = (1<<mb);
\r
318 static inline uint64_t ilog2_64( uint64_t val ) {
\r
319 uint32_t t = val >> 32;
\r
322 return ilog2(t) + 32;
\r
324 return ilog2((uint32_t)val);
\r
327 void Can_A_Isr(void)
\r
329 Can_Isr(CAN_CTRL_A);
\r
331 void Can_B_Isr(void)
\r
333 Can_Isr(CAN_CTRL_B);
\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
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
344 void Can_A_Err(void)
\r
346 Can_Err(CAN_CTRL_A);
\r
348 void Can_B_Err(void)
\r
350 Can_Err(CAN_CTRL_B);
\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
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
361 void Can_A_BusOff(void)
\r
363 Can_BusOff(CAN_CTRL_A);
\r
365 void Can_B_BusOff(void)
\r
367 Can_BusOff(CAN_CTRL_B);
\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
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
377 //-------------------------------------------------------------------
\r
379 #if defined(CFG_CAN_TEST)
\r
380 Can_TestType * Can_Arc_GetTestInfo( void ) {
\r
386 * Hardware error ISR for CAN
\r
388 * @param unit CAN controller number( from 0 )
\r
391 static void Can_Err(int unit)
\r
393 flexcan_t *canHw = GET_CONTROLLER(unit);
\r
394 Can_Arc_ErrorType err;
\r
396 const ESRType esrWrite = { .B.ERRINT = 1 };
\r
399 /* Clear bits 16-23 by read */
\r
400 esr.R = canHw->ESR.R;
\r
402 if (GET_CALLBACKS()->Arc_Error != NULL) {
\r
403 GET_CALLBACKS()->Arc_Error(unit, err);
\r
406 Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272 Same handling as for busoff
\r
409 canHw->ESR.R = esrWrite.R;
\r
417 // Uses 25.4.5.1 Transmission Abort Mechanism
\r
418 static void Can_AbortTx(flexcan_t *canHw, Can_UnitType *canUnit)
\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
429 if (canHw->BUF[mbNr].CS.B.CODE != MB_ABORT) {
\r
431 /* it's not sent... or being sent.
\r
435 while (*(uint64_t *) (&canHw->IFRH.R) & (1ull << mbNr)) {
\r
444 clearMbFlag(canHw,mbNr);
\r
445 canUnit->mbTxFree |= (1ull << mbNr);
\r
452 * BusOff ISR for CAN
\r
454 * @param unit CAN controller number( from 0 )
\r
456 static void Can_BusOff(int unit)
\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
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
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
477 if (canHw->ESR.B.BOFFINT) {
\r
478 #if (USE_CAN_STATISTICS == STD_ON)
\r
479 canUnit->stats.boffCnt++;
\r
481 if (GET_CALLBACKS()->ControllerBusOff != NULL) {
\r
482 GET_CALLBACKS()->ControllerBusOff(unit);
\r
484 Can_SetControllerMode(unit, CAN_T_STOP); // CANIF272
\r
486 canHw->ESR.B.BOFFINT = 1;
\r
488 Can_AbortTx(canHw, canUnit); // CANIF273
\r
496 static void Can_Isr_Tx(Can_UnitType *uPtr)
\r
501 canHw = uPtr->hwPtr;
\r
503 uint64_t mbMask = *(uint64_t *) (&canHw->IFRH.R);
\r
504 mbMask &= uPtr->Can_Arc_TxMbMask;
\r
509 #if defined(CFG_CAN_TEST)
\r
510 Can_Test.mbMaskTx |= mbMask;
\r
514 for (; mbMask; mbMask &= ~(1ull << mbNr)) {
\r
515 mbNr = ilog2_64(mbMask);
\r
517 uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart] = 0;
\r
519 // Clear interrupt and mark txBox as Free
\r
520 clearMbFlag(canHw,mbNr);
\r
521 uPtr->mbTxFree |= (1ull << mbNr);
\r
523 if (GET_CALLBACKS()->TxConfirmation != NULL) {
\r
524 GET_CALLBACKS()->TxConfirmation(uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart]);
\r
529 static void Can_Isr_Rx(Can_UnitType *uPtr)
\r
536 const Can_HardwareObjectType *hohPtr;
\r
538 canHw = uPtr->hwPtr;
\r
540 uint64_t iFlag = *(uint64_t*) (&canHw->IFRH.R);
\r
542 #if defined(CFG_CAN_TEST)
\r
543 Can_Test.mbMaskRx |= iFlag & uPtr->Can_Arc_RxMbMask;
\r
546 while (iFlag & uPtr->Can_Arc_RxMbMask) {
\r
549 mbNr = ilog2_64(iFlag & uPtr->Can_Arc_RxMbMask);
\r
550 iFlag ^= 1ull << mbNr;
\r
552 /* Check for FIFO interrupt */
\r
553 if (canHw->MCR.B.FEN && ((uint32_t)iFlag & (1 << 5))) {
\r
555 /* Check overflow */
\r
556 if (iFlag & (1 << 7)) {
\r
557 #if (USE_CAN_STATISTICS == STD_ON)
\r
558 uPtr->stats.fifoOverflow++;
\r
560 canHw->IFRL.B.BUF07I = 1;
\r
562 DET_REPORTERROR(MODULE_ID_CAN,0,0, CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
565 #if (USE_CAN_STATISTICS == STD_ON)
\r
566 /* Check warning */
\r
567 if (iFlag & (1 << 6)) {
\r
568 uPtr->stats.fifoWarning++;
\r
569 canHw->IFRL.B.BUF06I = 1;
\r
573 /* The manual is "fuzzy" here, read control and status */
\r
574 (void) canHw->BUF[0].CS.R;
\r
576 if (canHw->BUF[0].CS.B.IDE) {
\r
577 id = canHw->BUF[0].ID.R;
\r
580 id = canHw->BUF[0].ID.B.STD_ID;
\r
583 /* Must now do a manual match to find the right CanHardwareObject
\r
584 * to pass to CanIf. We know that the FIFO objects are sorted first.
\r
586 hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
588 /* Match in order */
\r
589 vuint32_t *fifoIdPtr = (vuint32_t *) &canHw->BUF[6];
\r
591 for (mbNr = 0; mbNr < uPtr->cfgCtrlPtr->Can_Arc_HohFifoCnt; mbNr++) {
\r
592 mask = canHw->RXIMR[mbNr].R;
\r
594 if ((id & mask) != (fifoIdPtr[mbNr] & mask)) {
\r
598 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
599 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr],
\r
600 canHw->BUF[0].ID.B.EXT_ID,
\r
601 canHw->BUF[0].CS.B.LENGTH,
\r
602 (uint8 *) &canHw->BUF[0].DATA.W[0]);
\r
607 // Clear the interrupt
\r
608 canHw->IFRL.B.BUF05I = 1;
\r
612 /* activate the internal lock with a read*/
\r
613 (void) canHw->BUF[mbNr].CS.R;
\r
615 if (canHw->BUF[mbNr].CS.B.IDE) {
\r
616 id = canHw->BUF[mbNr].ID.R;
\r
619 id = canHw->BUF[mbNr].ID.B.STD_ID;
\r
622 #if defined(USE_DET)
\r
623 if( canHw->BUF[mbNr].CS.B.CODE == MB_RX_OVERRUN ) {
\r
624 /* We have overwritten one frame */
\r
625 Det_ReportError(MODULE_ID_CAN,0,0,CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
629 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
630 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr], id,
\r
631 canHw->BUF[mbNr].CS.B.LENGTH,
\r
632 (uint8 *) &canHw->BUF[mbNr].DATA.W[0]);
\r
634 #if (USE_CAN_STATISTICS == STD_ON)
\r
635 uPtr->stats.rxSuccessCnt++;
\r
637 /* unlock MB (dummy read timer) */
\r
638 (void) canHw->TIMER.R;
\r
641 clearMbFlag(canHw, mbNr);
\r
647 static void Can_Isr(int controller )
\r
649 Can_UnitType *uPtr = CTRL_TO_UNIT_PTR(controller);
\r
651 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
655 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ){
\r
661 //-------------------------------------------------------------------
\r
664 static void Can_BuildMaps(Can_UnitType *uPtr)
\r
669 uint8_t fifoNr = 0;
\r
671 const Can_HardwareObjectType *hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
673 printf("Found %d HOHs\n", uPtr->cfgCtrlPtr->Can_Arc_HohCnt);
\r
675 for (int i = 0; i < uPtr->cfgCtrlPtr->Can_Arc_HohCnt; i++, hohPtr++) {
\r
676 if (hohPtr->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) {
\r
677 /* First 8 boxes are FIFO */
\r
678 if (hohPtr->Can_Arc_Flags & CAN_HOH_FIFO_MASK) {
\r
679 uPtr->mbToHrh[fifoNr++] = hohPtr->CanObjectId;
\r
680 uPtr->Can_Arc_RxMbMask |= (1<<5);
\r
682 uint64_t mask = (-1ULL);
\r
683 uPtr->mbToHrh[mbNr] = hohPtr->CanObjectId;
\r
687 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
688 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
689 uPtr->Can_Arc_RxMbMask |= mask;
\r
691 mbNr += hohPtr->ArcCanNumMailboxes;
\r
693 printf("mbNr=%d fifoNr=%d\n", mbNr, fifoNr);
\r
696 uint64_t mask = (-1ULL);
\r
699 * i = index into the HOH list for this controller */
\r
700 Can_HthToHohMap[ hohPtr->CanObjectId ] = i;
\r
701 Can_HthToUnitIdMap[ hohPtr->CanObjectId ] = uPtr->controllerId;
\r
702 /* HOH to Mailbox */
\r
703 for( int j=0;j < hohPtr->ArcCanNumMailboxes; j++ ) {
\r
704 uPtr->mbToHrh[mbNr+j] = hohPtr->CanObjectId;
\r
709 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
710 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
711 uPtr->Can_Arc_TxMbMask |= mask;
\r
712 mbNr += hohPtr->ArcCanNumMailboxes;
\r
715 uPtr->mbMax = mbNr;
\r
721 // This initiates ALL can controllers
\r
722 void Can_Init(const Can_ConfigType *config)
\r
724 /** @req 3.1.5/CAN223 */
\r
725 /** !req 3.1.5/CAN176 */
\r
727 Can_UnitType *unitPtr;
\r
729 /** @req 3.1.5/CAN174 */
\r
730 VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), CAN_INIT_SERVICE_ID, CAN_E_TRANSITION );
\r
731 /** @req 3.1.5/CAN175 */
\r
732 VALIDATE_NO_RV( (config != NULL ), CAN_INIT_SERVICE_ID, CAN_E_PARAM_POINTER );
\r
735 Can_Global.config = config;
\r
736 Can_Global.initRun = CAN_READY;
\r
738 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
739 const Can_ControllerConfigType *cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[configId];
\r
741 Can_Global.configuredMask |= (1 << cfgCtrlPtr->CanControllerId);
\r
742 unitPtr = &CanUnit[configId];
\r
744 memset(unitPtr, 0, sizeof(Can_UnitType));
\r
746 unitPtr->controllerId = cfgCtrlPtr->CanControllerId;
\r
747 unitPtr->hwPtr = GET_CONTROLLER(cfgCtrlPtr->CanControllerId);
\r
748 unitPtr->cfgCtrlPtr = cfgCtrlPtr;
\r
749 unitPtr->state = CANIF_CS_STOPPED;
\r
750 unitPtr->cfgHohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
752 unitPtr->Can_Arc_RxMbMask = cfgCtrlPtr->Can_Arc_RxMailBoxMask;
\r
753 unitPtr->Can_Arc_TxMbMask = cfgCtrlPtr->Can_Arc_TxMailBoxMask;
\r
755 Can_BuildMaps(unitPtr);
\r
757 switch (cfgCtrlPtr->CanControllerId) {
\r
758 #if defined(CFG_MPC560X)
\r
760 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_0_ESR_BOFF_INT, 2, 0);
\r
761 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_0_ESR_ERR_INT, 2, 0 );
\r
762 INSTALL_HANDLER4( "Can", Can_A_Isr, FLEXCAN_0_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
763 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_16_31, 2, 0 );
\r
764 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_32_63, 2, 0 );
\r
767 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_1_ESR_BOFF_INT, 2, 0);
\r
768 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_1_ESR_ERR_INT, 2, 0 );
\r
769 INSTALL_HANDLER4( "Can", Can_B_Isr, FLEXCAN_1_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
770 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_16_31, 2, 0 );
\r
771 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_32_63, 2, 0 );
\r
773 #if defined(CFG_MPC5604B)
\r
775 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_2_ESR_BOFF_INT, 2, 0);
\r
776 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_2_ESR_ERR_INT, 2, 0 );
\r
777 INSTALL_HANDLER4( "Can", Can_C_Isr, FLEXCAN_2_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
778 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_16_31, 2, 0 );
\r
779 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_32_63, 2, 0 );
\r
782 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_3_ESR_BOFF_INT, 2, 0);
\r
783 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_3_ESR_ERR_INT, 2, 0 );
\r
784 INSTALL_HANDLER4( "Can", Can_D_Isr, FLEXCAN_3_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
785 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_16_31, 2, 0 );
\r
786 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_32_63, 2, 0 );
\r
789 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_4_ESR_BOFF_INT, 2, 0);
\r
790 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_4_ESR_ERR_INT, 2, 0 );
\r
791 INSTALL_HANDLER4( "Can", Can_E_Isr, FLEXCAN_4_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
792 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_16_31, 2, 0 );
\r
793 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_32_63, 2, 0 );
\r
796 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_5_ESR_BOFF_INT, 2, 0);
\r
797 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_5_ESR_ERR_INT, 2, 0 );
\r
798 INSTALL_HANDLER4( "Can", Can_F_Isr, FLEXCAN_5_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
799 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_16_31, 2, 0 );
\r
800 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_32_63, 2, 0 );
\r
803 #elif defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668)
\r
805 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_A_ESR_BOFF_INT, 2, 0);
\r
806 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_A_ESR_ERR_INT, 2, 0 );
\r
807 INSTALL_HANDLER16( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF0I, 2, 0 );
\r
808 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF31_16I, 2, 0 );
\r
809 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF63_32I, 2, 0 );
\r
812 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_B_ESR_BOFF_INT, 2, 0 );
\r
813 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_B_ESR_ERR_INT, 2, 0 );
\r
814 INSTALL_HANDLER16( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF0I, 2, 0 );
\r
815 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF31_16I, 2, 0 );
\r
816 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_B_IFLAG1_BUF63_32I, 2, 0 );
\r
819 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_C_ESR_BOFF_INT, 2, 0 );
\r
820 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_C_ESR_ERR_INT, 2, 0 );
\r
821 INSTALL_HANDLER16( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF0I, 2, 0 );
\r
822 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF31_16I, 2, 0 );
\r
823 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_C_IFLAG1_BUF63_32I, 2, 0 );
\r
826 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_D_ESR_BOFF_INT, 2, 0 );
\r
827 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_D_ESR_ERR_INT, 2, 0 );
\r
828 INSTALL_HANDLER16( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF0I, 2, 0 );
\r
829 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF31_16I, 2, 0 );
\r
830 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_D_IFLAG1_BUF63_32I, 2, 0 );
\r
833 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_E_ESR_BOFF_INT, 2, 0 );
\r
834 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_E_ESR_ERR_INT, 2, 0 );
\r
835 INSTALL_HANDLER16( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF0I, 2, 0 );
\r
836 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF31_16I, 2, 0 );
\r
837 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_E_IFLAG1_BUF63_32I, 2, 0 );
\r
839 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668)
\r
841 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_F_ESR_BOFF_INT, 2, 0 );
\r
842 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_F_ESR_ERR_INT, 2, 0 );
\r
843 INSTALL_HANDLER16( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF0I, 2, 0 );
\r
844 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF31_16I, 2, 0 );
\r
845 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_F_IFLAG1_BUF63_32I, 2, 0 );
\r
856 // Unitialize the module
\r
859 Can_UnitType *canUnit;
\r
860 const Can_ControllerConfigType *cfgCtrlPtr;
\r
863 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
864 cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[(configId)];
\r
865 ctlrId = cfgCtrlPtr->CanControllerId;
\r
867 canUnit = CTRL_TO_UNIT_PTR(ctlrId);
\r
869 Can_DisableControllerInterrupts(ctlrId);
\r
871 canUnit->state = CANIF_CS_UNINIT;
\r
873 canUnit->lock_cnt = 0;
\r
875 #if (USE_CAN_STATISTICS == STD_ON)
\r
877 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
\r
881 Can_Global.config = NULL;
\r
882 Can_Global.initRun = CAN_UNINIT;
\r
887 void Can_InitController(uint8 controller,
\r
888 const Can_ControllerConfigType *config)
\r
890 /** @req 3.1.5/CAN229 */
\r
891 /** !req 3.1.5/CAN192 */
\r
898 Can_UnitType *canUnit;
\r
899 const Can_ControllerConfigType *cfgCtrlPtr;
\r
900 const Can_HardwareObjectType *hohPtr;
\r
903 /** @req 3.1.5/CAN187 */
\r
904 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_UNINIT );
\r
905 /** @req 3.1.5/CAN188 */
\r
906 VALIDATE_NO_RV( (config != NULL ), CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_POINTER);
\r
907 /** !req 3.1.5/CAN189 Controller is controller number, not a sequence number? */
\r
908 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_INITCONTROLLER_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
910 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
911 /** @req 3.1.5/CAN190 */
\r
912 VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_TRANSITION );
\r
914 canHw = canUnit->hwPtr;
\r
915 cfgCtrlPtr = canUnit->cfgCtrlPtr;
\r
917 // Start this baby up
\r
918 canHw->MCR.B.MDIS = 0;
\r
920 // Wait for it to reset
\r
921 if (!SIMULATOR()) {
\r
922 // Freeze to write all mem mapped registers ( see 25.4.8.1 )
\r
923 canHw->MCR.B.FRZ = 1;
\r
924 canHw->MCR.B.HALT = 1;
\r
927 if( config->Can_Arc_Flags & CAN_CTRL_FIFO ) {
\r
928 canHw->MCR.B.FEN = 1; /* Enable FIFO */
\r
929 canHw->MCR.B.IDAM = 0; /* We want extended id's to match with */
\r
931 canHw->MCR.B.BCC = 1; /* Enable all nice features */
\r
933 /* Use Fsys derivate */
\r
934 canHw->CR.B.CLKSRC = 1;
\r
935 canHw->MCR.B.MAXMB = cfgCtrlPtr->Can_Arc_MailboxMax - 1;
\r
938 /* Disable self-reception, if not loopback */
\r
939 canHw->MCR.B.SRXDIS = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 0 : 1;
\r
941 /* Clock calucation
\r
942 * -------------------------------------------------------------------
\r
944 * * 1 TQ = Sclk period( also called SCK )
\r
945 * * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk
\r
946 * ( Fcanclk can come from crystal or from the peripheral dividers )
\r
949 * TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )
\r
950 * TQ is between 8 and 25
\r
953 /* Calculate the number of timequanta's (from "Protocol Timing"( chap. 25.4.7.4 )) */
\r
954 tq1 = (config->CanControllerPropSeg + config->CanControllerSeg1 + 2);
\r
955 tq2 = (config->CanControllerSeg2 + 1);
\r
956 tq = 1 + tq1 + tq2;
\r
958 // Check TQ limitations..
\r
959 VALIDATE_DEM_NO_RV(( (tq1>=4) && (tq1<=16)), CAN_E_TIMEOUT );
\r
960 VALIDATE_DEM_NO_RV(( (tq2>=2) && (tq2<=8)), CAN_E_TIMEOUT );
\r
961 VALIDATE_DEM_NO_RV(( (tq>8) && (tq<25 )), CAN_E_TIMEOUT );
\r
963 // Assume we're using the peripheral clock instead of the crystal.
\r
964 clock = McuE_GetPeripheralClock((McuE_PeriperalClock_t) config->CanCpuClockRef);
\r
966 canHw->CR.B.PRESDIV = clock / (config->CanControllerBaudRate * 1000 * tq) - 1;
\r
967 canHw->CR.B.PROPSEG = config->CanControllerPropSeg;
\r
968 canHw->CR.B.PSEG1 = config->CanControllerSeg1;
\r
969 canHw->CR.B.PSEG2 = config->CanControllerSeg2;
\r
970 canHw->CR.B.SMP = 1; // 3 samples better than 1 ??
\r
971 canHw->CR.B.LPB = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 1 : 0;
\r
972 canHw->CR.B.BOFFREC = 1; // Disable bus off recovery
\r
974 /* Setup mailboxes for this controller */
\r
975 hohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
979 assert( hohPtr != NULL );
\r
981 struct FLEXCAN_RXFIFO_t *fifoIdPtr = (struct FLEXCAN_RXFIFO_t *)&canHw->BUF[0];
\r
983 memset(&canHw->BUF[0],0,sizeof(struct canbuf_t)*cfgCtrlPtr->Can_Arc_MailboxMax);
\r
985 for( int i=0; i < 8;i++) {
\r
986 canHw->RXIMR[i].R = 0xfffffffful;
\r
987 fifoIdPtr->IDTABLE[i].R = 0x0;
\r
990 /* The HOHs are sorted by FIFO(FULL_CAN), FIFO(BASIC_CAN),
\r
991 * FULL_CAN(no FIFO) and last BASIC_CAN(no FIFO) */
\r
992 for( int i=0; i < cfgCtrlPtr->Can_Arc_HohCnt;i++,hohPtr++)
\r
994 if( ( hohPtr->CanObjectType != CAN_OBJECT_TYPE_RECEIVE) ) {
\r
998 /* Assign FIFO first it will search for match first there (its the first MBs) */
\r
999 if( cfgCtrlPtr->Can_Arc_HohFifoCnt != 0 ) {
\r
1000 /* TODO : Set IDAM */
\r
1003 fifoIdPtr->IDTABLE[fifoNr].R = (hohPtr->CanIdValue << 1);
\r
1004 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1005 fifoIdPtr->IDTABLE[fifoNr].R |= 0x40000000;
\r
1008 /* The Mask (we have FULL_CAN here) */
\r
1009 canHw->RXIMR[fifoNr].R = *hohPtr->CanFilterMaskRef;
\r
1012 canHw->BUF[mbNr].CS.B.CODE = MB_RX;
\r
1013 canHw->RXIMR[mbNr].R = *hohPtr->CanFilterMaskRef;
\r
1015 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1016 canHw->BUF[mbNr].CS.B.IDE = 1;
\r
1017 canHw->BUF[mbNr].ID.R = hohPtr->CanIdValue;
\r
1019 canHw->BUF[mbNr].CS.B.IDE = 0;
\r
1020 canHw->BUF[mbNr].ID.B.STD_ID = hohPtr->CanIdValue;
\r
1026 canUnit->mbTxFree = canUnit->Can_Arc_TxMbMask;
\r
1027 /* @req 3.1.5/CAN260 */
\r
1028 canUnit->state = CANIF_CS_STOPPED;
\r
1033 Can_ReturnType Can_SetControllerMode(uint8 controller,
\r
1034 Can_StateTransitionType transition)
\r
1036 /** @req 3.1.5/CAN230 */
\r
1037 /** @req 3.1.5/CAN017 */
\r
1038 /** !req 3.1.5/CAN294 Wakeup not supported */
\r
1039 /** !req 3.1.5/CAN197 */
\r
1040 /** !req 3.1.5/CAN201 */
\r
1044 Can_ReturnType rv = CAN_OK;
\r
1046 /** @req 3.1.5/CAN198 */
\r
1047 VALIDATE( (Can_Global.initRun == CAN_READY), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1048 /** @req 3.1.5/CAN199 */
\r
1049 VALIDATE( VALID_CONTROLLER(controller), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1050 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1051 VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1053 canHw = canUnit->hwPtr;
\r
1055 switch (transition) {
\r
1057 canHw->MCR.B.HALT = 0;
\r
1058 canUnit->state = CANIF_CS_STARTED;
\r
1060 /** @req 3.1.5/CAN196 */
\r
1061 if (canUnit->lock_cnt == 0)
\r
1063 Can_EnableControllerInterrupts(controller);
\r
1065 Irq_Restore(state);
\r
1067 case CAN_T_WAKEUP: //CAN267
\r
1068 case CAN_T_SLEEP: //CAN258, CAN290
\r
1069 // Should be reported to DEM but DET is the next best
\r
1070 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1073 canHw->MCR.B.HALT = 1;
\r
1074 canUnit->state = CANIF_CS_STOPPED;
\r
1075 Can_AbortTx(canHw, canUnit); // CANIF282
\r
1078 // Should be reported to DEM but DET is the next best
\r
1079 /** @req 3.1.5/CAN200 */
\r
1080 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1087 void Can_DisableControllerInterrupts(uint8 controller)
\r
1089 /** @req 3.1.5/CAN231 */
\r
1090 /** @req 3.1.5/CAN202 */
\r
1091 /** !req 3.1.5/CAN204 */
\r
1092 /** !req 3.1.5/CAN292 */
\r
1094 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1095 /** @req 3.1.5/CAN206 */
\r
1096 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1097 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1101 /** @req 3.1.5/CAN205 */
\r
1102 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1107 /** @req 3.1.5/CAN049 */
\r
1108 if (canUnit->lock_cnt > 0) {
\r
1109 // Interrupts already disabled
\r
1110 canUnit->lock_cnt++;
\r
1111 Irq_Restore(state);
\r
1114 canUnit->lock_cnt++;
\r
1115 Irq_Restore(state);
\r
1117 /* Don't try to be intelligent, turn everything off */
\r
1118 canHw = GET_CONTROLLER(controller);
\r
1120 /* Turn off the interrupt mailboxes */
\r
1121 canHw->IMRH.R = 0;
\r
1122 canHw->IMRL.R = 0;
\r
1124 /* Turn off the bus off/tx warning/rx warning and error */
\r
1125 canHw->MCR.B.WRNEN = 0; /* Disable warning int */
\r
1126 canHw->CR.B.ERRMSK = 0; /* Disable error interrupt */
\r
1127 canHw->CR.B.BOFFMSK = 0; /* Disable bus-off interrupt */
\r
1128 canHw->CR.B.TWRNMSK = 0; /* Disable Tx warning */
\r
1129 canHw->CR.B.RWRNMSK = 0; /* Disable Rx warning */
\r
1132 void Can_EnableControllerInterrupts(uint8 controller)
\r
1134 /** @req 3.1.5/CAN232 */
\r
1135 /** @req 3.1.5/CAN050 */
\r
1136 /** !req 3.1.5/CAN293 Not applicable */
\r
1138 Can_UnitType *canUnit;
\r
1142 /** @req 3.1.5/CAN209 */
\r
1143 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1144 /** @req 3.1.5/CAN210 */
\r
1145 VALIDATE_NO_RV( VALID_CONTROLLER(controller), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1146 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1147 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1150 if (canUnit->lock_cnt > 1) {
\r
1151 /** @req 3.1.5/CAN208 */
\r
1152 // IRQ should still be disabled so just decrement counter
\r
1153 canUnit->lock_cnt--;
\r
1154 Irq_Restore(state);
\r
1156 } else if (canUnit->lock_cnt == 1) {
\r
1157 canUnit->lock_cnt = 0;
\r
1159 Irq_Restore(state);
\r
1161 canHw = canUnit->hwPtr;
\r
1163 canHw->IMRH.R = 0;
\r
1164 canHw->IMRL.R = 0;
\r
1166 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ) {
\r
1167 /* Turn on the interrupt mailboxes */
\r
1168 canHw->IMRL.R = canUnit->Can_Arc_RxMbMask;
\r
1169 canHw->IMRH.R = (uint32_t)(canUnit->Can_Arc_RxMbMask>>32);
\r
1172 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) {
\r
1173 /* Turn on the interrupt mailboxes */
\r
1174 canHw->IMRL.R |= canUnit->Can_Arc_TxMbMask;
\r
1175 canHw->IMRH.R |= (uint32_t)(canUnit->Can_Arc_TxMbMask>>32);
\r
1178 // BusOff here represents all errors and warnings
\r
1179 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) {
\r
1180 canHw->MCR.B.WRNEN = 1; /* Turn On warning int */
\r
1182 canHw->CR.B.ERRMSK = 1; /* Enable error interrupt */
\r
1183 canHw->CR.B.BOFFMSK = 1; /* Enable bus-off interrupt */
\r
1185 #if (USE_CAN_STATISTICS == STD_ON)
\r
1186 canHw->CR.B.TWRNMSK = 1; /* Enable Tx warning */
\r
1187 canHw->CR.B.RWRNMSK = 1; /* Enable Rx warning */
\r
1194 Can_ReturnType Can_Write(Can_Arc_HTHType hth, Can_PduType *pduInfo)
\r
1196 /** @req 3.1.5/CAN223 */
\r
1197 /** !req 3.1.5/CAN213 Priorities not supported */
\r
1198 /** !req 3.1.5/CAN215 Priorities not supported */
\r
1199 /** @req 3.1.5/CAN214 */
\r
1200 /** @req 3.1.5/CAN272 */
\r
1204 Can_ReturnType rv = CAN_OK;
\r
1207 const Can_HardwareObjectType *hohObj;
\r
1208 Can_UnitType *canUnit;
\r
1211 /** @req 3.1.5/CAN216 */
\r
1212 VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );
\r
1213 /** @req 3.1.5/CAN219 */
\r
1214 VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );
\r
1215 /** @req 3.1.5/CAN218 */
\r
1216 VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );
\r
1217 /** @req 3.1.5/CAN217 */
\r
1218 VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );
\r
1220 canUnit = &CanUnit[Can_Global.config->CanConfigSet->ArcHthToUnit[hth]];
\r
1221 hohObj = &canUnit->cfgHohPtr[Can_Global.config->CanConfigSet->ArcHthToHoh[hth]];
\r
1222 canHw = canUnit->hwPtr;
\r
1224 /* We have the hohObj, we need to know what box we can send on */
\r
1226 /* Get all free TX mboxes */
\r
1227 uint64_t iHwFlag = *(uint64_t *)(&canHw->IFRH.R); /* These are occupied */
\r
1228 assert( (canUnit->Can_Arc_TxMbMask & hohObj->ArcMailboxMask) != 0);
\r
1229 iflag = ~iHwFlag & canUnit->mbTxFree & hohObj->ArcMailboxMask;
\r
1230 /* Get the mbox(es) for this HTH */
\r
1232 /** @req 3.1.5/CAN212 */
\r
1234 mbNr = ilog2_64(iflag ); // find mb number
\r
1236 /* Indicate that we are sending this MB */
\r
1237 canUnit->mbTxFree &= ~(1ull<<mbNr);
\r
1239 canHw->BUF[mbNr].CS.R = 0;
\r
1240 canHw->BUF[mbNr].ID.R = 0;
\r
1242 // Setup message box type
\r
1243 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1244 canHw->BUF[mbNr].CS.B.IDE = 1;
\r
1245 } else if (hohObj->CanIdType == CAN_ID_TYPE_STANDARD) {
\r
1246 canHw->BUF[mbNr].CS.B.IDE = 0;
\r
1248 // No support for mixed in this processor
\r
1253 canHw->BUF[mbNr].CS.B.CODE = MB_INACTIVE; // Hold the transmit buffer inactive
\r
1254 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1255 canHw->BUF[mbNr].ID.R = pduInfo->id; // Write 29-bit MB IDs
\r
1257 assert( !(pduInfo->id & 0xfffff800) );
\r
1258 canHw->BUF[mbNr].ID.B.STD_ID = pduInfo->id;
\r
1261 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S) || defined(CFG_MPC5604B) || defined(CFG_MPC5668)
\r
1262 canHw->BUF[mbNr].ID.B.PRIO = 1; // Set Local Priority
\r
1265 memset(&canHw->BUF[mbNr].DATA, 0, 8);
\r
1266 memcpy(&canHw->BUF[mbNr].DATA, pduInfo->sdu, pduInfo->length);
\r
1268 canHw->BUF[mbNr].CS.B.SRR = 1;
\r
1269 canHw->BUF[mbNr].CS.B.RTR = 0;
\r
1271 canHw->BUF[mbNr].CS.B.LENGTH = pduInfo->length;
\r
1272 canHw->BUF[mbNr].CS.B.CODE = MB_TX_ONCE; // Write tx once code
\r
1273 timer = canHw->TIMER.R; // Unlock Message buffers
\r
1275 #if (USE_CAN_STATISTICS == STD_ON)
\r
1276 canUnit->stats.txSuccessCnt++;
\r
1279 // Store pdu handle in unit to be used by TxConfirmation
\r
1280 canUnit->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-canUnit->cfgCtrlPtr->Can_Arc_TxMailboxStart] = pduInfo->swPduHandle;
\r
1285 Irq_Restore(state);
\r
1290 void Can_Cbk_CheckWakeup( uint8 controller ) {
\r
1291 /** !req 3.1.5/CAN360 */
\r
1292 /** !req 3.1.5/CAN361 */
\r
1293 /** !req 3.1.5/CAN362 */
\r
1294 /** !req 3.1.5/CAN363 */
\r
1296 /* NOT SUPPORTED */
\r
1301 void Can_MainFunction_Write( void ) {
\r
1302 /** !req 3.1.5/CAN225 */
\r
1303 /** !req 3.1.5/CAN031 */
\r
1304 /** !req 3.1.5/CAN178 */
\r
1305 /** !req 3.1.5/CAN179 */
\r
1306 Can_UnitType *uPtr;
\r
1308 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1309 uPtr = &CanUnit[i];
\r
1310 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) == 0 ) {
\r
1316 void Can_MainFunction_Read(void)
\r
1318 /** !req 3.1.5/CAN226 */
\r
1319 /** !req 3.1.5/CAN108 */
\r
1320 /** !req 3.1.5/CAN180 */
\r
1321 /** !req 3.1.5/CAN181 */
\r
1322 Can_UnitType *uPtr;
\r
1324 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1325 uPtr = &CanUnit[i];
\r
1326 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT) == 0 ) {
\r
1332 void Can_MainFunction_BusOff(void)
\r
1334 /** !req 3.1.5/CAN227 */
\r
1335 /** !req 3.1.5/CAN109 */
\r
1336 /** !req 3.1.5/CAN183 */
\r
1337 /** !req 3.1.5/CAN184 */
\r
1338 /* Bus-off polling events */
\r
1342 void Can_MainFunction_Wakeup(void)
\r
1344 /** !req 3.1.5/CAN228 */
\r
1345 /** !req 3.1.5/CAN112 */
\r
1346 /** !req 3.1.5/CAN185 */
\r
1347 /** !req 3.1.5/CAN186 */
\r
1348 /* Wakeup polling events */
\r
1350 /* NOT SUPPORTED */
\r
1354 Can_Arc_ProcessType Can_Arc_ProcessingMode( uint8 controller ) {
\r
1355 Can_UnitType *uPtr = &CanUnit[controller];
\r
1358 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
1366 #if (USE_CAN_STATISTICS == STD_ON)
\r
1368 * Get send/receive/error statistics for a controller
\r
1370 * @param controller The controller
\r
1371 * @param stats Pointer to data to copy statistics to
\r
1375 void Can_Arc_GetStatistics(uint8 controller, Can_Arc_StatisticsType *stats)
\r
1377 if(Can_Global.initRun == CAN_READY)
\r
1379 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1380 *stats = canUnit->stats;
\r