器件型号: TMS320F28375D
我之前使用了两个邮箱 (17 和 18) 的 CAN Tx 实现。 CAN 总线上约有 18 到 36 个节点、每个节点每秒发送 3 条消息。
遗憾的是、我看到总线上缺少 CAN 帧。 有时、其中一个 CAN 节点完全静默超过 30 秒。 这不是总线‑关闭的情况—我检查了错误计数器、它们保持为 0。
在我的 Tx 实现中、三条具有不同 ID 的消息在软件队列中被缓冲、然后在检查是否有任何邮箱空闲后移动到 IFCMD 寄存器。
我的调试表明邮箱是空闲的、但通过 IF CMD 寄存器发送后、一些消息仍然不会出现在 CAN 总线上。
您能帮助我了解如何进一步调试吗?
我还进行了一项新的更改、在通过 IFCMD 寄存器发送新消息之前、我特意使现有邮箱无效。 这显著提高了性能、现在我只看到很少有丢失的 CAN 帧。
请参阅以下代码:
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;
}
如果您能帮助解释可能发生的情况、那将会很好。
注意:由于我的应用程序限制、我不想使用 Tx 中断。
谢谢、
Reeno Joseph