DCAN Module Configuration Parameters ==================================== /* CAN Module 2 Configuration */ static const CanModCfg_T sctCanMod2Cfg_M = /**< CAN Module 2 Configuration */ { 0x00021663UL, /* CAN Control Register (DCANCTL) ---- --00 ---0 0010 0-01 0110 011- 0011 0 WUBA = 0 (No automatic wake up on bus activity) 0 PDR = 0 (No application request for local low power down mode) 0 DE3 = 0 (DMA request line for IF3 disabled) 0 DE2 = 0 (DMA request line for IF2 disabled) 0 DE1 = 0 (DMA request line for IF1 disabled) 1 IE1 = 1 (Interrupt line 1 Enabled) 0 InitDbg = 0 (Not in debug mode) 0 SWR = 0 (SW Reset Enable Normal Operation) 01 01 PMD = 5 (Parity function disabled) 1 ABO = 1 (Auto-Bus-On enabled) 0 IDS = 0 (Interruption Debug Support disabled) 0 Test = 0 (Normal operation) 1 CCE = 1 (The CPU has write access to the configuration registers) 1 DAR = 1 (Automatic Retransmission enabled) 0 EIE = 0 (Error Interrupt disabled) 0 SIE = 0 (Status Change Interrupt disabled) 1 IE0 = 1 (Interrupt line 0 enabled) 1 Init = 1 (Initialization mode) */ 0x00000000UL, /* Auto-Bus-On Timer Register 0000 0000 0000 0000 0000 0000 0000 0000 ABO Time = 0 (Number of VCLK cycles before Bus-Off recovery */ 0x0000074FUL, /* Bit Timing Register - Set at 1MBaud ---- ---- ---- 0000 -000 0111 0100 1111 0000 BRPE = 0 (Baud Rate Prescaler Extension) 000 TSeg2 = 0 (Time segment after the sample point - 1) 0111 TSeg1 = 7 (Time segment before the sample point - 1) 01 SJW = 1 (Synchronisation Jump Width - 1) 00 1111 BRP = 15 (Baud Rate Prescaler - 1) */ }; This is used to congifure DCAN modules as follows: ================================================== /* Set to initialisation mode */ (regDcan[enumModId]).DCANCTL = ptrModCfg->nDcanCtl; /* CAN Control Register */ /* Clear all pending error flags and reset current status (reset by read) */ nTempUint32_M = (regDcan[enumModId]).DCANES; /* Error and Status Register (set/clear on read) */ /* Setup auto bus on timer period */ (regDcan[enumModId]).DCANABOTR = ptrModCfg->nDcanAbotr; /* Auto-Bus-On Timer Register */ /* Setup bit timing */ (regDcan[enumModId]).DCANBTR = ptrModCfg->nDcanBtr; /* Bit Timing Register */ /** - Setup TX pin to functional output */ (regDcan[enumModId]).DCANTIOC = 0x0000000CUL; /* CAN TX IO Control Register ---- ---- ---- -000 ---- ---- ---- 110- 0 PU = 0 (CAN_TX pull down is selected) 0 PD = 0 (CAN_TX pull is active) 0 OD = 0 (The CAN_TX pin is configured in push/pull mode) 1 Func = 1 (CAN_TX pin is in functional mode) 1 Dir = 1 (The CAN_TX pin in an output) 0 Out = 0 (The CAN_TX pin is driven to logic low) */ /** - Setup RX pin to functional input */ (regDcan[enumModId]).DCANRIOC = 0x00000008UL; /* CAN RX IO Control Register ---- ---- ---- -000 ---- ---- ---- 100- 0 PU = 0 (CAN_RX pull down is selected) 0 PD = 0 (CAN_RX pull is active) 0 OD = 0 (The CAN_RX pin is configured in push/pull mode) 1 Func = 1 (CAN_RX pin is in functional mode) 0 Dir = 0 (The CAN_RX pin in an input) 0 Out = 0 (The CAN_RX pin is driven to logic low) */ /* Configure message objects defined for this module */ if (OK_E == Can_InitDcanMsgObjs(enumModId, ptrMsgObjCfg)) { /* Configure DCAN interrupts for this module */ if (OK_E == Can_CfgCanInterrupts(enumModId)) { /* All done */ enumReturnValue = OK_E; } } /** - Leave configuration and initialization mode */ ((regDcan[enumModId]).DCANCTL) &= ~(uint32)0x00000041UL; /* CAN Control Register (DCANCTL) clearing ---- ---- ---- ---- ---- ---- -1-- ---1 1 Clear CCE to 0 (The CPU has no write access to the configuration registers) 1 Clear Init to 0 (Normal Operation) */ Message Object Configuration Parameters ======================================= /* DCAN2 Message Objects */ static const CanMsgObjCfg_T sctCanMod2MsgObjCfg_M[N_NUM_ACTUAL_DCAN2_MSGOBJ_C + 1] = /**< DCAN2 Message Objects */ { /* DCANIFxNO | DCANIFxMSK | DCANIFxARB | DCANIFxMCTL | DCANINTMUXx | */ /* nHth | MXtd, MDir, Msk | MsgVal, Xtd, Dir, ID | UMask, TxIE, RxIE, RmtEn, EoB, DLC | IntMux | tmsMaxAge */ /* | Used?, Used?, | Valid?, 29-bit?, Tx?, | Used?, Trig?, Trig?, set?, End?, | | */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ { N_CAN_PD_TORQUE_DEMAND_AS_C, TRUE, TRUE, 0x000007FFUL, TRUE, FALSE, FALSE, 0x010UL, TRUE, FALSE, TRUE, FALSE, TRUE, 6UL, CAN_INT_LEVEL_1_E, 50UL }, /* Received message PD_TORQUE_DEMAND_AS */ { N_CAN_PD_CTRL_TRQ_STATUS_AS_C, TRUE, TRUE, 0x000007FFUL, TRUE, FALSE, TRUE, 0x020UL, TRUE, FALSE, FALSE, FALSE, TRUE, 7UL, CAN_INT_LEVEL_1_E, 50UL }, /* Transmit message PD_CTRL_TRQ_STATUS_AS */ { N_CAN_PD_SPD_POS_FLT_STATUS_AS_C, TRUE, TRUE, 0x000007FFUL, TRUE, FALSE, TRUE, 0x030UL, TRUE, FALSE, FALSE, FALSE, TRUE, 8UL, CAN_INT_LEVEL_1_E, 50UL }, /* Transmit message PD_SPD_POS_FLT_STATUS_AS */ { N_CAN_PD_TORQUE_DEMAND_TM_C, TRUE, TRUE, 0x000007FFUL, TRUE, FALSE, FALSE, 0x040UL, TRUE, FALSE, TRUE, FALSE, TRUE, 6UL, CAN_INT_LEVEL_1_E, 50UL }, /* Received message PD_TORQUE_DEMAND_AS */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ { N_CAN_TERM_HTH_C, FALSE, FALSE, 0x1FFFFFFFUL, FALSE, FALSE, FALSE, 0x000UL, FALSE, FALSE, FALSE, FALSE, FALSE, 0UL, CAN_INT_LEVEL_0_E, 0UL }, /* Terminating record */ }; This table used to populate DCAN registers as follows: ====================================================== while (N_CAN_TERM_HTH_C > (ptrMsgObjCfg[nIndex]).nHth) { /* Check configured message object parameters first, this will take some time but is * only performed at initialisation and will ensure that the message objects have been * configured correctly. Any configuration errors will be reported in Can_CheckMsgObgCfg() * and do not need to be acted on here. */ if (OK_E == Can_CheckMsgObgCfg(&(ptrMsgObjCfg[nIndex]), enumModId)) { /* Wait until IF1 is ready for use */ if (OK_E == Can_WaitIfReg(&(regDcan[enumModId]).DCANIF1STAT)) { /* Build DCANIF1MSK */ nRegBuilder = ((uint32)(ptrMsgObjCfg[nIndex]).isMxtdUsed << 31); /* MXtd in bit 31 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).isMdirUsed << 30); /* MDir in bit 30 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).nMsk); /* Msk in bits [28:0] */ (regDcan[enumModId]).DCANIF1MSK = nRegBuilder; /* Build DCANIF1ARB */ nRegBuilder = ((uint32)(ptrMsgObjCfg[nIndex]).isMsgVal << 31); /* MsgVal in bit 31 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).isXtd29bit << 30); /* Xtd in bit 30 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).isDirTransmit << 29); /* Dir in bit 29 */ if (TRUE == (ptrMsgObjCfg[nIndex]).isXtd29bit) { /* 29-bit identifier, ID is located in bits [28:0] */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).nId); /* ID in bits [28:0] */ } else { /* 11-bit identifier, ID is located in bits [28:18] */ nIdentifier = (ptrMsgObjCfg[nIndex]).nId; /* Two stage operation required to prevent MISRA 12.8 */ nRegBuilder |= (nIdentifier << 18); /* ID in bits [28:18] */ } (regDcan[enumModId]).DCANIF1ARB = nRegBuilder; /* Build DCANIF1MCTL */ nRegBuilder = ((uint32)(ptrMsgObjCfg[nIndex]).isUmaskUsed << 12); /* UMask in bit 12 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).isTxieEnabled << 11); /* TxIE in bit 11 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).isRxieEnabled << 10); /* RxIE in bit 10 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).isRmtEn << 9); /* RmtEn in bit 9 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).isEob << 7); /* EoB in bit 7 */ nRegBuilder |= ((uint32)(ptrMsgObjCfg[nIndex]).nDlc); /* DLC in bits [3:0] */ (regDcan[enumModId]).DCANIF1MCTL = nRegBuilder; (regDcan[enumModId]).DCANIF1CMD = N_DCANIFXCMD_W_CONTROL_C; nBitNumber = ((ptrMsgObjCfg[nIndex]).nHth % N_MAX_DCAN1_MSGOBJ_C) + 1U; (regDcan[enumModId]).DCANIF1NO = (uint8)nBitNumber; /* Build DCANINTMUXx */ if (CAN_INT_LEVEL_1_E == (ptrMsgObjCfg[nIndex]).enumIntLevel) { nRegIndex = nBitNumber >> 5; /* Divide by 32 to get index into DCANINTMUXx[] */ nBitIndex = (uint32)1U << (nBitNumber & 0x1FUL); /* Determine bit offset within DCANINTMUXx[] */ nRegBuilder = ((regDcan[enumModId]).DCANINTMUXx)[nRegIndex]; nRegBuilder |= nBitIndex; ((regDcan[enumModId]).DCANINTMUXx)[nRegIndex] = nRegBuilder; } } else { /* Message object configuration failed */ enumReturnValue = NOT_OK_E; } } else { /* Message object configuration invalid */ enumReturnValue = NOT_OK_E; } /* Move on to next message object */ nIndex++; } Receive message interrupt service routine is: ============================================= /*--------------------------------------------------------------------------------------------*/ /** DCAN2 Level 0 (DCAN0INT) Interrupt Service Routine. *** *** \return void *//*------------------------------------------------------------------------------------------*/ static interrupt void Can_HandleDcan2Lev0Interrupt(void) { uint32 nMsgObj; CanHwHandle_T nHth; nMsgObj = (regDcan[DCAN_MODULE_2_E]).DCANINT; if (N_DCANINT_ESR_ERROR_C == nMsgObj) { Can_HandleError(DCAN_MODULE_2_E, (regDcan[DCAN_MODULE_2_E]).DCANES); } else { /* Setup IF1 for clear pending interrupt flag */ if (OK_E == Can_WaitIfReg(&(regDcan[DCAN_MODULE_2_E]).DCANIF1STAT)) { (regDcan[DCAN_MODULE_2_E]).DCANIF1CMD = N_DCANIFXCMD_W_CLR_INT_PND_C; (regDcan[DCAN_MODULE_2_E]).DCANIF1NO = (uint8)nMsgObj; /* Now handle received message, based on message object id */ nHth = Can_GetHthFromModMsgObj(DCAN_MODULE_2_E, (uint8)nMsgObj); Can_HandleRxMsg(nHth); } else { /* TODO Report Error */ } } } /*--------------------------------------------------------------------------------------------*/ /** DCAN2 Level 1 (DCAN1INT) Interrupt Service Routine. *** *** \return void *//*------------------------------------------------------------------------------------------*/ static interrupt void Can_HandleDcan2Lev1Interrupt(void) { uint32 nMsgObj; CanHwHandle_T nHth; #pragma CHECK_MISRA("-12.8") /* (MISRA-C:2004 12.8/R) The right-hand operand of a shift operator shall lie between zero and */ /* one less than the width in bits of the underlying type of the left-hand operand. This is a MISRA checker error */ nMsgObj = (uint32)((regDcan[DCAN_MODULE_2_E]).DCANINT) >> BITS_PER_SHORT; #pragma RESET_MISRA("12.8") /* Restore MISRA default setting for this rule */ /* Setup IF1 for clear pending interrupt flag */ if (OK_E == Can_WaitIfReg(&(regDcan[DCAN_MODULE_2_E]).DCANIF1STAT)) { (regDcan[DCAN_MODULE_2_E]).DCANIF1CMD = N_DCANIFXCMD_W_CLR_INT_PND_C; (regDcan[DCAN_MODULE_2_E]).DCANIF1NO = (uint8)nMsgObj; /* Now handle received message, based on message object id */ nHth = Can_GetHthFromModMsgObj(DCAN_MODULE_2_E, (uint8)nMsgObj); Can_HandleRxMsg(nHth); } else { /* TODO Report Error */ } } Associated #defines are: ======================== #define N_DCANIFXSTAT_BUSY_C ((uint8)0x80U) /**< Register DCANIFxSTAT Busy bit */ #define N_DCANIFXCMD_W_CLR_INT_PND_C 0x08U /**< Register DCANIFxCMD Write Clr Int/Pnd bit */ #define N_DCANIFXCMD_W_CONTROL_C 0xF8U /**< Register DCANIFxCMD Write Mask, Arb, Control, Clr Int/Pnd bits */ #define N_DCANIFXCMD_W_DATA_C 0x87U /**< Register DCANIFxCMD Write txRqst/NewDat, Data A, Data B bits */ #define N_DCANIFXCMD_R_DATA_C 0x17U /**< Register DCANIFxCMD Read txRqst/NewDat, Data A, Data B bits */ #define N_DCANIFXMCTL_MSG_LOST_C 0x4000U /**< Register DCANIFxMCTL Message Lost bit */ #define N_DCANINT_ESR_ERROR_C 0x8000U /**< Register DCANINT Error and Status Register value is not 0x07 */