Part Number: TMS320F28375D
I previously had a CAN Tx implementation using two mailboxes (17 and 18). There are about 18 to 36 nodes on the CAN bus, and each node sends 3 messages per second.
Unfortunately, I’m seeing missing CAN frames on the bus. At times, one of the CAN nodes goes completely silent for more than 30 seconds. This is not a bus‑off situation—I checked the error counters, and they remain at 0.
In my Tx implementation, three messages (with different IDs) are buffered in a software queue and then moved to the IFCMD registers after checking whether any of the mailboxes are free.
My debugging shows that the mailboxes are free, but after sending via the IF CMD registers, some messages still do not appear on the CAN bus.
Could you help me understand how to debug this further?
I also made a new change where I intentionally invalidate the existing mailbox before sending a new message through the IFCMD registers. This significantly improved performance, and now I see only very few missing CAN frames.
Please refer to the code below:
can_ll_send_message(uint32_t ui32ObjID, tCANMsgObject *pMsgObject)
{
uint32_t ui32CmdMaskReg;
uint32_t ui32MaskReg;
uint32_t ui32ArbReg;
uint32_t ui32MsgCtrl;
bool bTransferData;
bTransferData = 0;
// Wait for busy bit to clear
while(HWREGH(CAN_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY)
{
}
// New START
// Clear the MsgVal bit in the target mailbox first.
HWREGH(CAN_BASE + CAN_O_IF1ARB) = 0;
HWREGH(CAN_BASE + CAN_O_IF1ARB + 2) = 0;
// Send only the arbitration clear command to the mailbox.
HWREG_BP(CAN_BASE + CAN_O_IF1CMD) = CAN_IF1CMD_DIR | CAN_IF1CMD_ARB | (ui32ObjID & CAN_IF1CMD_MSG_NUM_M);
// Wait for this clear command to finish.
while(HWREGH(CAN_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY)
{
}
// New END
// This is always a write to the Message object as this call is setting a
// message object. This call will also always set all size bits so it sets
// both data bits. The call will use the CONTROL register to set control
// bits so this bit needs to be set as well.
ui32CmdMaskReg = (CAN_IF1CMD_DIR | CAN_IF1CMD_DATA_A | CAN_IF1CMD_DATA_B |
CAN_IF1CMD_CONTROL);
// Initialize the values to a known state before filling them in based on
// the type of message object that is being configured.
ui32ArbReg = 0;
ui32MsgCtrl = 0;
ui32MaskReg = 0;
// Set the TXRQST bit and the reset the rest of the register.
ui32CmdMaskReg |= CAN_IF1CMD_TXRQST;
ui32MsgCtrl |= CAN_IF1MCTL_TXRQST | CAN_IF1MCTL_NEWDAT;
ui32ArbReg = CAN_IF1ARB_DIR;
bTransferData = 1;
// Set the Arb bit so that this gets transferred to the Message object.
ui32CmdMaskReg |= CAN_IF1CMD_ARB;
// Configure the Arbitration registers.
// Set the 29 bit version of the Identifier for this message object.
// Mark the message as valid and set the extended ID bit.
ui32ArbReg |= (pMsgObject->ui32MsgID & CAN_IF1ARB_ID_M) |
CAN_IF1ARB_MSGVAL | CAN_IF1ARB_XTD;
// Set the data length since this is set for all transfers. This is also a
// single transfer and not a FIFO transfer so set EOB bit.
ui32MsgCtrl |= (pMsgObject->ui32MsgLen & CAN_IF1MCTL_DLC_M);
// Mark this as the last entry if this is not the last entry in a FIFO.
if((pMsgObject->ui32Flags & CAN_MSG_OBJ_FIFO) == 0)
{
ui32MsgCtrl |= CAN_IF1MCTL_EOB;
}
// Write the data out to the CAN Data registers if needed.
if(bTransferData)
{
CANDataRegWrite(pMsgObject->pucMsgData,
(uint32_t *)(CAN_BASE + CAN_O_IF1DATA),
pMsgObject->ui32MsgLen);
}
// Write out the registers to program the message object.
HWREGH(CAN_BASE + CAN_O_IF1MSK) = ui32MaskReg & CAN_REG_WORD_MASK;
HWREGH(CAN_BASE + CAN_O_IF1MSK + 2) = ui32MaskReg >> 16;
HWREGH(CAN_BASE + CAN_O_IF1ARB) = ui32ArbReg & CAN_REG_WORD_MASK;
HWREGH(CAN_BASE + CAN_O_IF1ARB + 2) = ui32ArbReg >> 16;
HWREGH(CAN_BASE + CAN_O_IF1MCTL) = ui32MsgCtrl & CAN_REG_WORD_MASK;
// Transfer the message object to the message object specific by ui32ObjID.
HWREG_BP(CAN_BASE + CAN_O_IF1CMD) = ui32CmdMaskReg | (ui32ObjID & CAN_IF1CMD_MSG_NUM_M);
// Wait for busy bit to clear
while(HWREGH(CAN_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY)
{
}
return;
}
It would be great if you could help explain what might be happening.
Note: I don't want to use Tx interrutps because of my application constraints.
Thanks,
Reeno Joseph