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
503 canHw = uPtr->hwPtr;
\r
505 uint64_t mbMask = *(uint64_t *) (&canHw->IFRH.R);
\r
506 mbMask &= uPtr->Can_Arc_TxMbMask;
\r
511 #if defined(CFG_CAN_TEST)
\r
512 Can_Test.mbMaskTx |= mbMask;
\r
516 for (; mbMask; mbMask &= ~(1ull << mbNr)) {
\r
517 mbNr = ilog2_64(mbMask);
\r
519 pduId = uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart];
\r
520 uPtr->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-uPtr->cfgCtrlPtr->Can_Arc_TxMailboxStart] = 0;
\r
522 // Clear interrupt and mark txBox as Free
\r
523 clearMbFlag(canHw,mbNr);
\r
524 uPtr->mbTxFree |= (1ull << mbNr);
\r
526 if (GET_CALLBACKS()->TxConfirmation != NULL) {
\r
527 GET_CALLBACKS()->TxConfirmation(pduId);
\r
532 static void Can_Isr_Rx(Can_UnitType *uPtr)
\r
539 const Can_HardwareObjectType *hohPtr;
\r
541 canHw = uPtr->hwPtr;
\r
543 uint64_t iFlag = *(uint64_t*) (&canHw->IFRH.R);
\r
545 #if defined(CFG_CAN_TEST)
\r
546 Can_Test.mbMaskRx |= iFlag & uPtr->Can_Arc_RxMbMask;
\r
549 while (iFlag & uPtr->Can_Arc_RxMbMask) {
\r
552 mbNr = ilog2_64(iFlag & uPtr->Can_Arc_RxMbMask);
\r
553 iFlag ^= 1ull << mbNr;
\r
555 /* Check for FIFO interrupt */
\r
556 if (canHw->MCR.B.FEN && ((uint32_t)iFlag & (1 << 5))) {
\r
558 /* Check overflow */
\r
559 if (iFlag & (1 << 7)) {
\r
560 #if (USE_CAN_STATISTICS == STD_ON)
\r
561 uPtr->stats.fifoOverflow++;
\r
563 canHw->IFRL.B.BUF07I = 1;
\r
565 DET_REPORTERROR(MODULE_ID_CAN,0,0, CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
568 #if (USE_CAN_STATISTICS == STD_ON)
\r
569 /* Check warning */
\r
570 if (iFlag & (1 << 6)) {
\r
571 uPtr->stats.fifoWarning++;
\r
572 canHw->IFRL.B.BUF06I = 1;
\r
576 /* The manual is "fuzzy" here, read control and status */
\r
577 (void) canHw->BUF[0].CS.R;
\r
579 if (canHw->BUF[0].CS.B.IDE) {
\r
580 id = canHw->BUF[0].ID.R;
\r
583 id = canHw->BUF[0].ID.B.STD_ID;
\r
586 /* Must now do a manual match to find the right CanHardwareObject
\r
587 * to pass to CanIf. We know that the FIFO objects are sorted first.
\r
589 hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
591 /* Match in order */
\r
592 vuint32_t *fifoIdPtr = (vuint32_t *) &canHw->BUF[6];
\r
594 for (mbNr = 0; mbNr < uPtr->cfgCtrlPtr->Can_Arc_HohFifoCnt; mbNr++) {
\r
595 mask = canHw->RXIMR[mbNr].R;
\r
597 if ((id & mask) != (fifoIdPtr[mbNr] & mask)) {
\r
601 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
602 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr],
\r
603 canHw->BUF[0].ID.B.EXT_ID,
\r
604 canHw->BUF[0].CS.B.LENGTH,
\r
605 (uint8 *) &canHw->BUF[0].DATA.W[0]);
\r
610 // Clear the interrupt
\r
611 canHw->IFRL.B.BUF05I = 1;
\r
615 /* activate the internal lock with a read*/
\r
616 (void) canHw->BUF[mbNr].CS.R;
\r
618 if (canHw->BUF[mbNr].CS.B.IDE) {
\r
619 id = canHw->BUF[mbNr].ID.R;
\r
622 id = canHw->BUF[mbNr].ID.B.STD_ID;
\r
625 #if defined(USE_DET)
\r
626 if( canHw->BUF[mbNr].CS.B.CODE == MB_RX_OVERRUN ) {
\r
627 /* We have overwritten one frame */
\r
628 Det_ReportError(MODULE_ID_CAN,0,0,CAN_E_DATALOST); /** @req 4.0.3/CAN395 */
\r
632 if (GET_CALLBACKS()->RxIndication != NULL) {
\r
633 GET_CALLBACKS()->RxIndication(uPtr->cfgCtrlPtr->Can_Arc_MailBoxToHrh[mbNr], id,
\r
634 canHw->BUF[mbNr].CS.B.LENGTH,
\r
635 (uint8 *) &canHw->BUF[mbNr].DATA.W[0]);
\r
637 #if (USE_CAN_STATISTICS == STD_ON)
\r
638 uPtr->stats.rxSuccessCnt++;
\r
640 /* unlock MB (dummy read timer) */
\r
641 (void) canHw->TIMER.R;
\r
644 clearMbFlag(canHw, mbNr);
\r
650 static void Can_Isr(int controller )
\r
652 Can_UnitType *uPtr = CTRL_TO_UNIT_PTR(controller);
\r
654 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
658 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ){
\r
664 //-------------------------------------------------------------------
\r
667 static void Can_BuildMaps(Can_UnitType *uPtr)
\r
672 uint8_t fifoNr = 0;
\r
674 const Can_HardwareObjectType *hohPtr = uPtr->cfgCtrlPtr->Can_Arc_Hoh;
\r
676 printf("Found %d HOHs\n", uPtr->cfgCtrlPtr->Can_Arc_HohCnt);
\r
678 for (int i = 0; i < uPtr->cfgCtrlPtr->Can_Arc_HohCnt; i++, hohPtr++) {
\r
679 if (hohPtr->CanObjectType == CAN_OBJECT_TYPE_RECEIVE) {
\r
680 /* First 8 boxes are FIFO */
\r
681 if (hohPtr->Can_Arc_Flags & CAN_HOH_FIFO_MASK) {
\r
682 uPtr->mbToHrh[fifoNr++] = hohPtr->CanObjectId;
\r
683 uPtr->Can_Arc_RxMbMask |= (1<<5);
\r
685 uint64_t mask = (-1ULL);
\r
686 uPtr->mbToHrh[mbNr] = hohPtr->CanObjectId;
\r
690 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
691 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
692 uPtr->Can_Arc_RxMbMask |= mask;
\r
694 mbNr += hohPtr->ArcCanNumMailboxes;
\r
696 printf("mbNr=%d fifoNr=%d\n", mbNr, fifoNr);
\r
699 uint64_t mask = (-1ULL);
\r
702 * i = index into the HOH list for this controller */
\r
703 Can_HthToHohMap[ hohPtr->CanObjectId ] = i;
\r
704 Can_HthToUnitIdMap[ hohPtr->CanObjectId ] = uPtr->controllerId;
\r
705 /* HOH to Mailbox */
\r
706 for( int j=0;j < hohPtr->ArcCanNumMailboxes; j++ ) {
\r
707 uPtr->mbToHrh[mbNr+j] = hohPtr->CanObjectId;
\r
712 mask <<= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
713 mask >>= 64 - (mbNr + hohPtr->ArcCanNumMailboxes);
\r
714 uPtr->Can_Arc_TxMbMask |= mask;
\r
715 mbNr += hohPtr->ArcCanNumMailboxes;
\r
718 uPtr->mbMax = mbNr;
\r
724 // This initiates ALL can controllers
\r
725 void Can_Init(const Can_ConfigType *config)
\r
727 /** @req 3.1.5/CAN223 */
\r
728 /** !req 3.1.5/CAN176 */
\r
730 Can_UnitType *unitPtr;
\r
732 /** @req 3.1.5/CAN174 */
\r
733 VALIDATE_NO_RV( (Can_Global.initRun == CAN_UNINIT), CAN_INIT_SERVICE_ID, CAN_E_TRANSITION );
\r
734 /** @req 3.1.5/CAN175 */
\r
735 VALIDATE_NO_RV( (config != NULL ), CAN_INIT_SERVICE_ID, CAN_E_PARAM_POINTER );
\r
738 Can_Global.config = config;
\r
739 Can_Global.initRun = CAN_READY;
\r
741 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
742 const Can_ControllerConfigType *cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[configId];
\r
744 Can_Global.configuredMask |= (1 << cfgCtrlPtr->CanControllerId);
\r
745 unitPtr = &CanUnit[configId];
\r
747 memset(unitPtr, 0, sizeof(Can_UnitType));
\r
749 unitPtr->controllerId = cfgCtrlPtr->CanControllerId;
\r
750 unitPtr->hwPtr = GET_CONTROLLER(cfgCtrlPtr->CanControllerId);
\r
751 unitPtr->cfgCtrlPtr = cfgCtrlPtr;
\r
752 unitPtr->state = CANIF_CS_STOPPED;
\r
753 unitPtr->cfgHohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
755 unitPtr->Can_Arc_RxMbMask = cfgCtrlPtr->Can_Arc_RxMailBoxMask;
\r
756 unitPtr->Can_Arc_TxMbMask = cfgCtrlPtr->Can_Arc_TxMailBoxMask;
\r
758 Can_BuildMaps(unitPtr);
\r
760 switch (cfgCtrlPtr->CanControllerId) {
\r
761 #if defined(CFG_MPC560X)
\r
763 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_0_ESR_BOFF_INT, 2, 0);
\r
764 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_0_ESR_ERR_INT, 2, 0 );
\r
765 INSTALL_HANDLER4( "Can", Can_A_Isr, FLEXCAN_0_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
766 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_16_31, 2, 0 );
\r
767 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_0_BUF_32_63, 2, 0 );
\r
770 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_1_ESR_BOFF_INT, 2, 0);
\r
771 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_1_ESR_ERR_INT, 2, 0 );
\r
772 INSTALL_HANDLER4( "Can", Can_B_Isr, FLEXCAN_1_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
773 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_16_31, 2, 0 );
\r
774 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_1_BUF_32_63, 2, 0 );
\r
776 #if defined(CFG_MPC5604B)
\r
778 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_2_ESR_BOFF_INT, 2, 0);
\r
779 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_2_ESR_ERR_INT, 2, 0 );
\r
780 INSTALL_HANDLER4( "Can", Can_C_Isr, FLEXCAN_2_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
781 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_16_31, 2, 0 );
\r
782 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_2_BUF_32_63, 2, 0 );
\r
785 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_3_ESR_BOFF_INT, 2, 0);
\r
786 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_3_ESR_ERR_INT, 2, 0 );
\r
787 INSTALL_HANDLER4( "Can", Can_D_Isr, FLEXCAN_3_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
788 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_16_31, 2, 0 );
\r
789 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_3_BUF_32_63, 2, 0 );
\r
792 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_4_ESR_BOFF_INT, 2, 0);
\r
793 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_4_ESR_ERR_INT, 2, 0 );
\r
794 INSTALL_HANDLER4( "Can", Can_E_Isr, FLEXCAN_4_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
795 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_16_31, 2, 0 );
\r
796 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_4_BUF_32_63, 2, 0 );
\r
799 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_5_ESR_BOFF_INT, 2, 0);
\r
800 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_5_ESR_ERR_INT, 2, 0 );
\r
801 INSTALL_HANDLER4( "Can", Can_F_Isr, FLEXCAN_5_BUF_00_03, 2, 0 ); /* 0-3, 4-7, 8-11, 12-15 */
\r
802 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_16_31, 2, 0 );
\r
803 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_5_BUF_32_63, 2, 0 );
\r
806 #elif defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5567) || defined(CFG_MPC5668)
\r
808 ISR_INSTALL_ISR2( "Can", Can_A_BusOff, FLEXCAN_A_ESR_BOFF_INT, 2, 0);
\r
809 ISR_INSTALL_ISR2( "Can", Can_A_Err, FLEXCAN_A_ESR_ERR_INT, 2, 0 );
\r
810 INSTALL_HANDLER16( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF0I, 2, 0 );
\r
811 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF31_16I, 2, 0 );
\r
812 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_A_IFLAG1_BUF63_32I, 2, 0 );
\r
815 ISR_INSTALL_ISR2( "Can", Can_B_BusOff, FLEXCAN_B_ESR_BOFF_INT, 2, 0 );
\r
816 ISR_INSTALL_ISR2( "Can", Can_B_Err, FLEXCAN_B_ESR_ERR_INT, 2, 0 );
\r
817 INSTALL_HANDLER16( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF0I, 2, 0 );
\r
818 ISR_INSTALL_ISR2( "Can", Can_B_Isr, FLEXCAN_B_IFLAG1_BUF31_16I, 2, 0 );
\r
819 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_B_IFLAG1_BUF63_32I, 2, 0 );
\r
822 ISR_INSTALL_ISR2( "Can", Can_C_BusOff, FLEXCAN_C_ESR_BOFF_INT, 2, 0 );
\r
823 ISR_INSTALL_ISR2( "Can", Can_C_Err, FLEXCAN_C_ESR_ERR_INT, 2, 0 );
\r
824 INSTALL_HANDLER16( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF0I, 2, 0 );
\r
825 ISR_INSTALL_ISR2( "Can", Can_C_Isr, FLEXCAN_C_IFLAG1_BUF31_16I, 2, 0 );
\r
826 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_C_IFLAG1_BUF63_32I, 2, 0 );
\r
829 ISR_INSTALL_ISR2( "Can", Can_D_BusOff, FLEXCAN_D_ESR_BOFF_INT, 2, 0 );
\r
830 ISR_INSTALL_ISR2( "Can", Can_D_Err, FLEXCAN_D_ESR_ERR_INT, 2, 0 );
\r
831 INSTALL_HANDLER16( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF0I, 2, 0 );
\r
832 ISR_INSTALL_ISR2( "Can", Can_D_Isr, FLEXCAN_D_IFLAG1_BUF31_16I, 2, 0 );
\r
833 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_D_IFLAG1_BUF63_32I, 2, 0 );
\r
836 ISR_INSTALL_ISR2( "Can", Can_E_BusOff, FLEXCAN_E_ESR_BOFF_INT, 2, 0 );
\r
837 ISR_INSTALL_ISR2( "Can", Can_E_Err, FLEXCAN_E_ESR_ERR_INT, 2, 0 );
\r
838 INSTALL_HANDLER16( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF0I, 2, 0 );
\r
839 ISR_INSTALL_ISR2( "Can", Can_E_Isr, FLEXCAN_E_IFLAG1_BUF31_16I, 2, 0 );
\r
840 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_E_IFLAG1_BUF63_32I, 2, 0 );
\r
842 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5668)
\r
844 ISR_INSTALL_ISR2( "Can", Can_F_BusOff, FLEXCAN_F_ESR_BOFF_INT, 2, 0 );
\r
845 ISR_INSTALL_ISR2( "Can", Can_F_Err, FLEXCAN_F_ESR_ERR_INT, 2, 0 );
\r
846 INSTALL_HANDLER16( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF0I, 2, 0 );
\r
847 ISR_INSTALL_ISR2( "Can", Can_F_Isr, FLEXCAN_F_IFLAG1_BUF31_16I, 2, 0 );
\r
848 ISR_INSTALL_ISR2( "Can", Can_A_Isr, FLEXCAN_F_IFLAG1_BUF63_32I, 2, 0 );
\r
859 // Unitialize the module
\r
862 Can_UnitType *canUnit;
\r
863 const Can_ControllerConfigType *cfgCtrlPtr;
\r
866 for (int configId = 0; configId < CAN_ARC_CTRL_CONFIG_CNT; configId++) {
\r
867 cfgCtrlPtr = &Can_Global.config->CanConfigSet->CanController[(configId)];
\r
868 ctlrId = cfgCtrlPtr->CanControllerId;
\r
870 canUnit = CTRL_TO_UNIT_PTR(ctlrId);
\r
872 Can_DisableControllerInterrupts(ctlrId);
\r
874 canUnit->state = CANIF_CS_UNINIT;
\r
876 canUnit->lock_cnt = 0;
\r
878 #if (USE_CAN_STATISTICS == STD_ON)
\r
880 memset(&canUnit->stats, 0, sizeof(Can_Arc_StatisticsType));
\r
884 Can_Global.config = NULL;
\r
885 Can_Global.initRun = CAN_UNINIT;
\r
890 void Can_InitController(uint8 controller,
\r
891 const Can_ControllerConfigType *config)
\r
893 /** @req 3.1.5/CAN229 */
\r
894 /** !req 3.1.5/CAN192 */
\r
901 Can_UnitType *canUnit;
\r
902 const Can_ControllerConfigType *cfgCtrlPtr;
\r
903 const Can_HardwareObjectType *hohPtr;
\r
906 /** @req 3.1.5/CAN187 */
\r
907 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_UNINIT );
\r
908 /** @req 3.1.5/CAN188 */
\r
909 VALIDATE_NO_RV( (config != NULL ), CAN_INITCONTROLLER_SERVICE_ID,CAN_E_PARAM_POINTER);
\r
910 /** !req 3.1.5/CAN189 Controller is controller number, not a sequence number? */
\r
911 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_INITCONTROLLER_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
913 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
914 /** @req 3.1.5/CAN190 */
\r
915 VALIDATE_NO_RV( (canUnit->state==CANIF_CS_STOPPED), CAN_INITCONTROLLER_SERVICE_ID, CAN_E_TRANSITION );
\r
917 canHw = canUnit->hwPtr;
\r
918 cfgCtrlPtr = canUnit->cfgCtrlPtr;
\r
920 // Start this baby up
\r
921 canHw->MCR.B.MDIS = 0;
\r
923 // Wait for it to reset
\r
924 if (!SIMULATOR()) {
\r
925 // Freeze to write all mem mapped registers ( see 25.4.8.1 )
\r
926 canHw->MCR.B.FRZ = 1;
\r
927 canHw->MCR.B.HALT = 1;
\r
930 if( config->Can_Arc_Flags & CAN_CTRL_FIFO ) {
\r
931 canHw->MCR.B.FEN = 1; /* Enable FIFO */
\r
932 canHw->MCR.B.IDAM = 0; /* We want extended id's to match with */
\r
934 canHw->MCR.B.BCC = 1; /* Enable all nice features */
\r
936 /* Use Fsys derivate */
\r
937 canHw->CR.B.CLKSRC = 1;
\r
938 canHw->MCR.B.MAXMB = cfgCtrlPtr->Can_Arc_MailboxMax - 1;
\r
941 /* Disable self-reception, if not loopback */
\r
942 canHw->MCR.B.SRXDIS = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 0 : 1;
\r
944 /* Clock calucation
\r
945 * -------------------------------------------------------------------
\r
947 * * 1 TQ = Sclk period( also called SCK )
\r
948 * * Ftq = Fcanclk / ( PRESDIV + 1 ) = Sclk
\r
949 * ( Fcanclk can come from crystal or from the peripheral dividers )
\r
952 * TQ = 1/Ftq = (PRESDIV+1)/Fcanclk --> PRESDIV = (TQ * Fcanclk - 1 )
\r
953 * TQ is between 8 and 25
\r
956 /* Calculate the number of timequanta's (from "Protocol Timing"( chap. 25.4.7.4 )) */
\r
957 tq1 = (config->CanControllerPropSeg + config->CanControllerSeg1 + 2);
\r
958 tq2 = (config->CanControllerSeg2 + 1);
\r
959 tq = 1 + tq1 + tq2;
\r
961 // Check TQ limitations..
\r
962 VALIDATE_DEM_NO_RV(( (tq1>=4) && (tq1<=16)), CAN_E_TIMEOUT );
\r
963 VALIDATE_DEM_NO_RV(( (tq2>=2) && (tq2<=8)), CAN_E_TIMEOUT );
\r
964 VALIDATE_DEM_NO_RV(( (tq>8) && (tq<25 )), CAN_E_TIMEOUT );
\r
966 // Assume we're using the peripheral clock instead of the crystal.
\r
967 clock = McuE_GetPeripheralClock((McuE_PeriperalClock_t) config->CanCpuClockRef);
\r
969 canHw->CR.B.PRESDIV = clock / (config->CanControllerBaudRate * 1000 * tq) - 1;
\r
970 canHw->CR.B.PROPSEG = config->CanControllerPropSeg;
\r
971 canHw->CR.B.PSEG1 = config->CanControllerSeg1;
\r
972 canHw->CR.B.PSEG2 = config->CanControllerSeg2;
\r
973 canHw->CR.B.SMP = 1; // 3 samples better than 1 ??
\r
974 canHw->CR.B.LPB = (config->Can_Arc_Flags & CAN_CTRL_LOOPBACK) ? 1 : 0;
\r
975 canHw->CR.B.BOFFREC = 1; // Disable bus off recovery
\r
977 /* Setup mailboxes for this controller */
\r
978 hohPtr = cfgCtrlPtr->Can_Arc_Hoh;
\r
982 assert( hohPtr != NULL );
\r
984 struct FLEXCAN_RXFIFO_t *fifoIdPtr = (struct FLEXCAN_RXFIFO_t *)&canHw->BUF[0];
\r
986 memset(&canHw->BUF[0],0,sizeof(struct canbuf_t)*cfgCtrlPtr->Can_Arc_MailboxMax);
\r
988 for( int i=0; i < 8;i++) {
\r
989 canHw->RXIMR[i].R = 0xfffffffful;
\r
990 fifoIdPtr->IDTABLE[i].R = 0x0;
\r
993 /* The HOHs are sorted by FIFO(FULL_CAN), FIFO(BASIC_CAN),
\r
994 * FULL_CAN(no FIFO) and last BASIC_CAN(no FIFO) */
\r
995 for( int i=0; i < cfgCtrlPtr->Can_Arc_HohCnt;i++,hohPtr++)
\r
997 if( ( hohPtr->CanObjectType != CAN_OBJECT_TYPE_RECEIVE) ) {
\r
1001 /* Assign FIFO first it will search for match first there (its the first MBs) */
\r
1002 if( cfgCtrlPtr->Can_Arc_HohFifoCnt != 0 ) {
\r
1003 /* TODO : Set IDAM */
\r
1006 fifoIdPtr->IDTABLE[fifoNr].R = (hohPtr->CanIdValue << 1);
\r
1007 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1008 fifoIdPtr->IDTABLE[fifoNr].R |= 0x40000000;
\r
1011 /* The Mask (we have FULL_CAN here) */
\r
1012 canHw->RXIMR[fifoNr].R = *hohPtr->CanFilterMaskRef;
\r
1015 canHw->BUF[mbNr].CS.B.CODE = MB_RX;
\r
1016 canHw->RXIMR[mbNr].R = *hohPtr->CanFilterMaskRef;
\r
1018 if (hohPtr->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1019 canHw->BUF[mbNr].CS.B.IDE = 1;
\r
1020 canHw->BUF[mbNr].ID.R = hohPtr->CanIdValue;
\r
1022 canHw->BUF[mbNr].CS.B.IDE = 0;
\r
1023 canHw->BUF[mbNr].ID.B.STD_ID = hohPtr->CanIdValue;
\r
1029 canUnit->mbTxFree = canUnit->Can_Arc_TxMbMask;
\r
1030 /* @req 3.1.5/CAN260 */
\r
1031 canUnit->state = CANIF_CS_STOPPED;
\r
1036 Can_ReturnType Can_SetControllerMode(uint8 controller,
\r
1037 Can_StateTransitionType transition)
\r
1039 /** @req 3.1.5/CAN230 */
\r
1040 /** @req 3.1.5/CAN017 */
\r
1041 /** !req 3.1.5/CAN294 Wakeup not supported */
\r
1042 /** !req 3.1.5/CAN197 */
\r
1043 /** !req 3.1.5/CAN201 */
\r
1047 Can_ReturnType rv = CAN_OK;
\r
1049 /** @req 3.1.5/CAN198 */
\r
1050 VALIDATE( (Can_Global.initRun == CAN_READY), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1051 /** @req 3.1.5/CAN199 */
\r
1052 VALIDATE( VALID_CONTROLLER(controller), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1053 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1054 VALIDATE( (canUnit->state!=CANIF_CS_UNINIT), CAN_SETCONTROLLERMODE_SERVICE_ID, CAN_E_UNINIT );
\r
1056 canHw = canUnit->hwPtr;
\r
1058 switch (transition) {
\r
1060 canHw->MCR.B.HALT = 0;
\r
1061 canUnit->state = CANIF_CS_STARTED;
\r
1063 /** @req 3.1.5/CAN196 */
\r
1064 if (canUnit->lock_cnt == 0)
\r
1066 Can_EnableControllerInterrupts(controller);
\r
1068 Irq_Restore(state);
\r
1070 case CAN_T_WAKEUP: //CAN267
\r
1071 case CAN_T_SLEEP: //CAN258, CAN290
\r
1072 // Should be reported to DEM but DET is the next best
\r
1073 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1076 canHw->MCR.B.HALT = 1;
\r
1077 canUnit->state = CANIF_CS_STOPPED;
\r
1078 Can_AbortTx(canHw, canUnit); // CANIF282
\r
1081 // Should be reported to DEM but DET is the next best
\r
1082 /** @req 3.1.5/CAN200 */
\r
1083 VALIDATE(canUnit->state == CANIF_CS_STOPPED, 0x3, CAN_E_TRANSITION);
\r
1090 void Can_DisableControllerInterrupts(uint8 controller)
\r
1092 /** @req 3.1.5/CAN231 */
\r
1093 /** @req 3.1.5/CAN202 */
\r
1094 /** !req 3.1.5/CAN204 */
\r
1095 /** !req 3.1.5/CAN292 */
\r
1097 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1098 /** @req 3.1.5/CAN206 */
\r
1099 VALIDATE_NO_RV( VALID_CONTROLLER(controller) , CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1100 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1104 /** @req 3.1.5/CAN205 */
\r
1105 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_DISABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1110 /** @req 3.1.5/CAN049 */
\r
1111 if (canUnit->lock_cnt > 0) {
\r
1112 // Interrupts already disabled
\r
1113 canUnit->lock_cnt++;
\r
1114 Irq_Restore(state);
\r
1117 canUnit->lock_cnt++;
\r
1118 Irq_Restore(state);
\r
1120 /* Don't try to be intelligent, turn everything off */
\r
1121 canHw = GET_CONTROLLER(controller);
\r
1123 /* Turn off the interrupt mailboxes */
\r
1124 canHw->IMRH.R = 0;
\r
1125 canHw->IMRL.R = 0;
\r
1127 /* Turn off the bus off/tx warning/rx warning and error */
\r
1128 canHw->MCR.B.WRNEN = 0; /* Disable warning int */
\r
1129 canHw->CR.B.ERRMSK = 0; /* Disable error interrupt */
\r
1130 canHw->CR.B.BOFFMSK = 0; /* Disable bus-off interrupt */
\r
1131 canHw->CR.B.TWRNMSK = 0; /* Disable Tx warning */
\r
1132 canHw->CR.B.RWRNMSK = 0; /* Disable Rx warning */
\r
1135 void Can_EnableControllerInterrupts(uint8 controller)
\r
1137 /** @req 3.1.5/CAN232 */
\r
1138 /** @req 3.1.5/CAN050 */
\r
1139 /** !req 3.1.5/CAN293 Not applicable */
\r
1141 Can_UnitType *canUnit;
\r
1145 /** @req 3.1.5/CAN209 */
\r
1146 VALIDATE_NO_RV( (Can_Global.initRun == CAN_READY), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1147 /** @req 3.1.5/CAN210 */
\r
1148 VALIDATE_NO_RV( VALID_CONTROLLER(controller), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_PARAM_CONTROLLER );
\r
1149 canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1150 VALIDATE_NO_RV( (canUnit->state!=CANIF_CS_UNINIT), CAN_ENABLECONTROLLERINTERRUPTS_SERVICE_ID, CAN_E_UNINIT );
\r
1153 if (canUnit->lock_cnt > 1) {
\r
1154 /** @req 3.1.5/CAN208 */
\r
1155 // IRQ should still be disabled so just decrement counter
\r
1156 canUnit->lock_cnt--;
\r
1157 Irq_Restore(state);
\r
1159 } else if (canUnit->lock_cnt == 1) {
\r
1160 canUnit->lock_cnt = 0;
\r
1162 Irq_Restore(state);
\r
1164 canHw = canUnit->hwPtr;
\r
1166 canHw->IMRH.R = 0;
\r
1167 canHw->IMRL.R = 0;
\r
1169 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT ) {
\r
1170 /* Turn on the interrupt mailboxes */
\r
1171 canHw->IMRL.R = canUnit->Can_Arc_RxMbMask;
\r
1172 canHw->IMRH.R = (uint32_t)(canUnit->Can_Arc_RxMbMask>>32);
\r
1175 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) {
\r
1176 /* Turn on the interrupt mailboxes */
\r
1177 canHw->IMRL.R |= canUnit->Can_Arc_TxMbMask;
\r
1178 canHw->IMRH.R |= (uint32_t)(canUnit->Can_Arc_TxMbMask>>32);
\r
1181 // BusOff here represents all errors and warnings
\r
1182 if (canUnit->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_BUSOFF_PROCESSING_INTERRUPT) {
\r
1183 canHw->MCR.B.WRNEN = 1; /* Turn On warning int */
\r
1185 canHw->CR.B.ERRMSK = 1; /* Enable error interrupt */
\r
1186 canHw->CR.B.BOFFMSK = 1; /* Enable bus-off interrupt */
\r
1188 #if (USE_CAN_STATISTICS == STD_ON)
\r
1189 canHw->CR.B.TWRNMSK = 1; /* Enable Tx warning */
\r
1190 canHw->CR.B.RWRNMSK = 1; /* Enable Rx warning */
\r
1197 Can_ReturnType Can_Write(Can_Arc_HTHType hth, Can_PduType *pduInfo)
\r
1199 /** @req 3.1.5/CAN223 */
\r
1200 /** !req 3.1.5/CAN213 Priorities not supported */
\r
1201 /** !req 3.1.5/CAN215 Priorities not supported */
\r
1202 /** @req 3.1.5/CAN214 */
\r
1203 /** @req 3.1.5/CAN272 */
\r
1207 Can_ReturnType rv = CAN_OK;
\r
1210 const Can_HardwareObjectType *hohObj;
\r
1211 Can_UnitType *canUnit;
\r
1214 /** @req 3.1.5/CAN216 */
\r
1215 VALIDATE( (Can_Global.initRun == CAN_READY), 0x6, CAN_E_UNINIT );
\r
1216 /** @req 3.1.5/CAN219 */
\r
1217 VALIDATE( (pduInfo != NULL), 0x6, CAN_E_PARAM_POINTER );
\r
1218 /** @req 3.1.5/CAN218 */
\r
1219 VALIDATE( (pduInfo->length <= 8), 0x6, CAN_E_PARAM_DLC );
\r
1220 /** @req 3.1.5/CAN217 */
\r
1221 VALIDATE( (hth < NUM_OF_HTHS ), 0x6, CAN_E_PARAM_HANDLE );
\r
1223 canUnit = &CanUnit[Can_Global.config->CanConfigSet->ArcHthToUnit[hth]];
\r
1224 hohObj = &canUnit->cfgHohPtr[Can_Global.config->CanConfigSet->ArcHthToHoh[hth]];
\r
1225 canHw = canUnit->hwPtr;
\r
1227 /* We have the hohObj, we need to know what box we can send on */
\r
1229 /* Get all free TX mboxes */
\r
1230 uint64_t iHwFlag = *(uint64_t *)(&canHw->IFRH.R); /* These are occupied */
\r
1231 assert( (canUnit->Can_Arc_TxMbMask & hohObj->ArcMailboxMask) != 0);
\r
1232 iflag = ~iHwFlag & canUnit->mbTxFree & hohObj->ArcMailboxMask;
\r
1233 /* Get the mbox(es) for this HTH */
\r
1235 /** @req 3.1.5/CAN212 */
\r
1237 mbNr = ilog2_64(iflag ); // find mb number
\r
1239 /* Indicate that we are sending this MB */
\r
1240 canUnit->mbTxFree &= ~(1ull<<mbNr);
\r
1242 canHw->BUF[mbNr].CS.R = 0;
\r
1243 canHw->BUF[mbNr].ID.R = 0;
\r
1245 // Setup message box type
\r
1246 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1247 canHw->BUF[mbNr].CS.B.IDE = 1;
\r
1248 } else if (hohObj->CanIdType == CAN_ID_TYPE_STANDARD) {
\r
1249 canHw->BUF[mbNr].CS.B.IDE = 0;
\r
1251 // No support for mixed in this processor
\r
1256 canHw->BUF[mbNr].CS.B.CODE = MB_INACTIVE; // Hold the transmit buffer inactive
\r
1257 if (hohObj->CanIdType == CAN_ID_TYPE_EXTENDED) {
\r
1258 canHw->BUF[mbNr].ID.R = pduInfo->id; // Write 29-bit MB IDs
\r
1260 assert( !(pduInfo->id & 0xfffff800) );
\r
1261 canHw->BUF[mbNr].ID.B.STD_ID = pduInfo->id;
\r
1264 #if defined(CFG_MPC5516) || defined(CFG_MPC5517) || defined(CFG_MPC5606S) || defined(CFG_MPC5604B) || defined(CFG_MPC5668)
\r
1265 canHw->BUF[mbNr].ID.B.PRIO = 1; // Set Local Priority
\r
1268 memset(&canHw->BUF[mbNr].DATA, 0, 8);
\r
1269 memcpy(&canHw->BUF[mbNr].DATA, pduInfo->sdu, pduInfo->length);
\r
1271 canHw->BUF[mbNr].CS.B.SRR = 1;
\r
1272 canHw->BUF[mbNr].CS.B.RTR = 0;
\r
1274 canHw->BUF[mbNr].CS.B.LENGTH = pduInfo->length;
\r
1275 canHw->BUF[mbNr].CS.B.CODE = MB_TX_ONCE; // Write tx once code
\r
1276 timer = canHw->TIMER.R; // Unlock Message buffers
\r
1278 #if (USE_CAN_STATISTICS == STD_ON)
\r
1279 canUnit->stats.txSuccessCnt++;
\r
1282 // Store pdu handle in unit to be used by TxConfirmation
\r
1283 canUnit->cfgCtrlPtr->Can_Arc_TxPduHandles[mbNr-canUnit->cfgCtrlPtr->Can_Arc_TxMailboxStart] = pduInfo->swPduHandle;
\r
1288 Irq_Restore(state);
\r
1293 void Can_Cbk_CheckWakeup( uint8 controller ) {
\r
1294 /** !req 3.1.5/CAN360 */
\r
1295 /** !req 3.1.5/CAN361 */
\r
1296 /** !req 3.1.5/CAN362 */
\r
1297 /** !req 3.1.5/CAN363 */
\r
1299 /* NOT SUPPORTED */
\r
1304 void Can_MainFunction_Write( void ) {
\r
1305 /** !req 3.1.5/CAN225 */
\r
1306 /** !req 3.1.5/CAN031 */
\r
1307 /** !req 3.1.5/CAN178 */
\r
1308 /** !req 3.1.5/CAN179 */
\r
1309 Can_UnitType *uPtr;
\r
1311 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1312 uPtr = &CanUnit[i];
\r
1313 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT) == 0 ) {
\r
1319 void Can_MainFunction_Read(void)
\r
1321 /** !req 3.1.5/CAN226 */
\r
1322 /** !req 3.1.5/CAN108 */
\r
1323 /** !req 3.1.5/CAN180 */
\r
1324 /** !req 3.1.5/CAN181 */
\r
1325 Can_UnitType *uPtr;
\r
1327 for(int i=0;i<CAN_ARC_CTRL_CONFIG_CNT; i++ ) {
\r
1328 uPtr = &CanUnit[i];
\r
1329 if( (uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_RX_PROCESSING_INTERRUPT) == 0 ) {
\r
1335 void Can_MainFunction_BusOff(void)
\r
1337 /** !req 3.1.5/CAN227 */
\r
1338 /** !req 3.1.5/CAN109 */
\r
1339 /** !req 3.1.5/CAN183 */
\r
1340 /** !req 3.1.5/CAN184 */
\r
1341 /* Bus-off polling events */
\r
1345 void Can_MainFunction_Wakeup(void)
\r
1347 /** !req 3.1.5/CAN228 */
\r
1348 /** !req 3.1.5/CAN112 */
\r
1349 /** !req 3.1.5/CAN185 */
\r
1350 /** !req 3.1.5/CAN186 */
\r
1351 /* Wakeup polling events */
\r
1353 /* NOT SUPPORTED */
\r
1357 Can_Arc_ProcessType Can_Arc_ProcessingMode( uint8 controller ) {
\r
1358 Can_UnitType *uPtr = &CanUnit[controller];
\r
1361 if(uPtr->cfgCtrlPtr->Can_Arc_Flags & CAN_CTRL_TX_PROCESSING_INTERRUPT ){
\r
1369 #if (USE_CAN_STATISTICS == STD_ON)
\r
1371 * Get send/receive/error statistics for a controller
\r
1373 * @param controller The controller
\r
1374 * @param stats Pointer to data to copy statistics to
\r
1378 void Can_Arc_GetStatistics(uint8 controller, Can_Arc_StatisticsType *stats)
\r
1380 if(Can_Global.initRun == CAN_READY)
\r
1382 Can_UnitType *canUnit = CTRL_TO_UNIT_PTR(controller);
\r
1383 *stats = canUnit->stats;
\r