This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
I have two DCAN message objects configured with all parameters the same except for the 11-bit arbitration id (in DCANIF1ARB). Message object 5 is the first receive message object configured and is the lowest numbered (i.e. highest priority receive message). Message object 10 is configured following message object 5 and is a lower priority). So:
DCANIF1MSK=0xC00007FF, DCANIF1ARB=0x88880000, DCANIF1MCTL=0x00001486, DCANIF1CMD=0xF8, DCANIF1NO=0x5, DCAN1INT bit set active for message object 5 (0x222).
DCANIF1MSK=0xC00007FF, DCANIF1ARB=0x88A40000, DCANIF1MCTL=0x00001486, DCANIF1CMD=0xF8, DCANIF1NO=0xA, DCAN1INT bit set active for message object 10 (0x229).
My problem is that receipt of message 0x229 is recorded as 0x00050000 in DCANINT rather than expected 0x000A0000 (i.e. the message object associated with message id 0x222 and not message id 0x229). DCANNWDAT12 is also incorrectly set to 0x00000010 (for message object 5)
Receipt of message 0x222 is correctly reported in DCANINT (0x0005000) and DCANNWDAT12 (0x00000010).
I have the same problem with other message arbitration ids, on receipt, they are all reported in DCANINT as being sourced from message object 5 (the highest priority receive message object).
Does anybody have any idea what I am doing wrong, presumably a configuration problem?
Regards, Tony.
Hi Tony,
I'm in discussion with a CAN expert reagrding the issue that you are facing.
I will get back to you soon.
Best Regards,
Pratip
Hi Tony,
We tried to replicate this scenario and we do not see any issue from our side with your settings as you have explained above:
- 2 Nodes
- 2 Mail boxes [0x5 (configured for ID 0x222)and 0x10(configured for ID 0x229)]
I assume the configuration on the receive side is as on the transmit side.
I would like to know:
1. Which ID you transmit first and which one the second , which order do you receive the ID's ?
2. Do you clear the pending interrupt after you receive ?
If possible you can provide your code snippet for us to analise further .
You can also try without changing the values of DCANIF1MSK and leave it as default (after reset) - Not sure if this would help.
Do get back with your observations.
Regards,
Pratip
Hi Pratip,
Please excuse my slow response.
Answers to your questions are:
1. Which ID you transmit first and which one the second , which order do you receive the ID's ?
The order makes no difference. I can send the 'first configured message object' first or the 'second configured message object' first. It makes no difference, all registers indicate that the received message is always recognised/identified as 'first configured message object'.
2. Do you clear the pending interrupt after you receive ?
I believe so, I do this:
Set DCANIF1CMD to 0x08U
Set DCANIF1NO to <message object read from DCANINT
I don't really have an executable code snippet I can give you, I have a table driven implementation, but I have extracted everything relevant into the following file. These are all the registers I set, so maybe one is missing?
Regards,
Tony
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 */
Hi Tony,
Sorry for jumping in late.
So you mean you are receiving all the messages with the right ID but all in the one mail box (0x5)?
Is my understanding right ?
If so would you be able to check what happens :
1. On transmit side when you interchange the message objects (0xA (configured for ID 0x222)and 0x5(configured for ID 0x229)]) .
2. On the receive side apply the same configuraten of message box 0x5 to message box 0xA and see if all messages are received in 0xA, this time .
And one more question are you using two seperate CAN nodes and are both TMS470's ?
Best Regards,
Pratip
Hi Pratip,
This remains a real puzzle, I've stepped through assembler trying to find the obvious mistake but to no avail. Below are the answers to your questions:
You understanding is correct, I am receiving all my messages, but they are all placed in my highest priority defined mailbox (the one with the lowest number). The messages are all received with their correct IDs.
It doesn't matter in what order I transmit the messages.
My messages and message boxes all have exactly the same configuration except for the message id itself and the message box number of course. It doesn't matter in what order I actually configure the message boxes, lowest number first, or highest number first; messages are always routed to the lowest numbered message box.
I am using a single CAN node (DCAN2) with only two receive messages defined (I have removed my transmit message configuration and it makes no difference). My processor is a TMS570.
Regards, Tony.
Hi Pratip,
I have finally discovered the reason for all messages being routed to the first message box. It is a calibration error on my part. I am using an 11-bit message identifier (as opposed to 29-bit) and had not shifted my identifier mask bits into register DCANIFxMSK:Msk bits [28:18], they were defined at [10:0] instead. As you will understand, this means that my acceptance filter matched all my 11-bit identified messages to the first defined receive message box!
So, this problem is resolved for me. Thanks for your help, have a good holiday.
Regards, Tony.
Hi Tony,
Nice to hear this news. I was trying to make a simplifed version of the code I had, so that you could try it out.
Anyways. Hope you have a good time with your CAN software development.
Do get back if you have further queries. :-)
Regards,
Pratip