Other Parts Discussed in Thread: C2000WARE
器件型号: TMS320F28388D
主题: C2000WARE 中讨论的其他器件
工具/软件:C2000Ware 26.00.00.00 driverlib
摘要
我们在内部观察到一种罕见的断言失败 CAN_sendMessage() 、并试图了解根本原因。 我们注意到 CAN_sendMessage() 并 CAN_clearInterruptStatus() 使用 IF1 接口寄存器、我们想知道当从不同的优先级上下文调用这两者时、这是否会导致竞态条件。
我们的设置
- 使用
CAN_readMessage()(IF2) 和CAN_clearInterruptStatus()(IF1) 在 CAN ISR 中读取 CAN RX 消息 - CAN TX 消息使用
CAN_sendMessage()(IF1) 从周期性后台任务发送
我们理解一般建议是将 IF1 用于 TX、将 IF2 用于 RX 以避免冲突(请参阅有关 IF1/IF2 使用的 e2e 主题)。 我们注意到 CAN_clearInterruptStatus() 使用了 IF1、即使在本例中它是从 RX ISR 上下文调用的。
观察到的行为
CAN_sendMessage()__error__()断言检查之一进行命中-
__error__()回调报告 can.c 中的第 450 行、该行为空行。 调用堆栈指向第 455 行ASSERT((objID <= 32U) && (objID > 0U))()。 我们怀疑调试信息可能不准确、实际失败的断言可能是中的三个中的任何一个CAN_sendMessage()、包括第 482 行的 DLC 检查。 - 我们在
baseobjIDmsgLen调试器中验证了、和—所有值在出现故障时都是正确的。 - 消息对象配置正确(在调试器中验证了参数)
- 此故障非常罕见且是间歇性的、与时序相关的问题相一致
潜在比赛情景
CAN_sendMessage() 对 IF1 执行多步序列:
// Step 1: Request readback of message object control (can.c:464)
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CONTROL |
(objID & CAN_IF1CMD_MSG_NUM_M));
// Step 2: Wait for transfer (can.c:470)
while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY)
{
}
// Step 3: Read back DLC (can.c:477)
msgCtrl = HWREGH(base + CAN_O_IF1MCTL);
// Step 4: Assert DLC matches (can.c:482)
ASSERT((msgCtrl & CAN_IF1MCTL_DLC_M) == msgLen);
我们的担心是:如果 CAN RX ISR 在步骤 2 和步骤 3 之间触发、 CAN_clearInterruptStatus() 会为不同的消息对象向 IF1CMD 写入新命令:
// CAN_clearInterruptStatus (can.c:238)
HWREG_BP(base + CAN_O_IF1CMD) = ((uint32_t)CAN_IF1CMD_CLRINTPND |
(intClr & CAN_IF1CMD_MSG_NUM_M));
我们认为 CAN_sendMessage() 当 IF1MCTL 恢复时、可能会使用错误消息对象中的数据读回 IF1MCTL、从而导致步骤 4 中的 DLC 不匹配。 BUSY 位检查在这里不起作用、因为它仅保护 IF1 到 RAM 的传输、而不保护多步序列。
问题
-
CAN_sendMessage()和之间的这种 IF1 共享是否CAN_clearInterruptStatus()确实会导致我们看到的问题? - 是否有
CAN_clearInterruptStatus()使用 IF1 而不是 IF2 的具体原因、或者这是我们可能误解的事情? - 作为一种权
CAN_sendMessage()变措施、我们正在考虑在调用周围短暂禁用 CAN PIE 中断。 您会推荐这种方法、还是有更好的做法?
Interrupt_disable(CAN_CMD_INT0);
CAN_sendMessage(CAN_INTERFACE_BASE, msg_obj_id, msg_len, raw_data);
Interrupt_enable(CAN_CMD_INT0);
感谢您的分享。