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.

[参考译文] TMS320F28075:清除 CAN 邮箱中 MsgLst 位的序列

Guru**** 2539500 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/610068/tms320f28075-clearing-sequence-of-msglst-bit-in-can-mailbox

器件型号:TMS320F28075

您好!
在技术参考手册中、我没有找到清除 CAN 接收邮箱的 MsgLst 位的正确序列的说明。
在第21.12.9节中、TRM 报告"MsgLst 不会自动复位"、但是如果寄存器将其清零、则中没有任何位。
相反、可以通过分别向 TXRQST 和 ClrIntPnd 位写入1来清除 NewDat 和 IndPnd 位。

我找到了以下基于读取-修改-写入操作的序列。

-------- 我的代码---

//局部变量
uint32_t msgCtrl = 0;

//
//--读取步骤---
//读取数据 A、数据 B、控制信息并清除 NewDat e IntPnd 位
//
HWREG_BP (CANB_BASE + CAN_O_IF2CMD)=(CAN_IF2CMD_DATA_A | CAN_IF2CMD_DATA_B |
                                                                                         CAN_IF2CMD_CONTROL | CAN_IF2CMD_TXRQST | CAN_IF2CMD_CLRINTPND |(Objid & CAN_IF2CMD_MSG_NUM_M);
//
//等待忙位清零
//
while ((HWREG_BP (CANB_BASE + CAN_O_IF2CMD)& CAN_IF2CMD_BUSY)!= 0)

   ;

//
//读出 IF 控制寄存器(保存在一个局部变量中)。
//
msgCtrl = HWREG_BP (CANB_BASE + CAN_O_IF2MCTL);



//
//--修改步骤---
//重置局部变量中的 MsgLst、NewDat 和 IntPnd 位(在读取步骤中、通过写入 IF2CMD、NewDat 和 IntPnd 已经在邮箱中被清除)。
//
msgCtrl &=~(CAN_IF2MCTL_MSGLST | CAN_IF2MCTL_NEWDAT | CAN_IF2MCTL_INTPND);



//
//--写入步骤---
//寄存器上的写入控制图像
//
HWREG_BP (CANB_BASE + CAN_O_IF2MCTL)= msgCtrl;
//
//将 CAN_IF2MCTL 传送到邮箱
//
HWREG_BP (CANB_BASE + CAN_O_IF2CMD)=(CAN_IF2CMD_DIR | CAN_IF2CMD_CONTROL |(Objid & CAN_IF2CMD_MSG_NUM_M));

//
//等待忙位清零
//
while ((HWREG_BP (CANB_BASE + CAN_O_IF2CMD)& CAN_IF2CMD_BUSY)!= 0)

   ;

-------- 我的代码的末尾---


该序列在写入步骤 MsgLst 位等于0的意义上有效。

但是、由于以下情况、我不确定这是清除 MsgLst 位的好方法。
假设一个新消息在读取步骤之后和写入步骤之前存储在接收邮箱中:邮箱中的 NewDat 和 IntPnd 位被设置为1。 但是、在写入步骤中、我会强制这两个值都为0。
然后、如果我再次从邮箱读取 NewDat、我将发现它等于0、因此我不知道新消息已经到达并且丢失!

在没有报文丢失或其他有害副作用的情况下清零 MsgLst 位的正确方法是什么?

谢谢你。

此致、

演示

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Demis、

    我现在要查看此帖子。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Demis、

               

    您能否确认您是否尝试过以下操作:

     

    在修改步骤之前(但在读取步骤之后)、向同一邮箱发送一个帧、并确保 NewDat 和 IntPnd 位为1。 现在、执行写入步骤并验证这些位是否确实清零。

     

    另外、我很好奇您为什么会遇到 MsgLst 情况。 您的应用程序是否已使用所有邮箱? 或者无法足够快地读取它们?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Demis、

               在您的帖子中概述的方法中、似乎存在无意中清除 NewDat 的风险。 该规范不指示清除 MsgLst 位的任何其他方法。

     

    我假设您在接收 ISR 中检查 MsgLst 位的值、并仅在该位被置位时将其清零。 因此、您将讨论一种同时设置 NewDat 和 MsgLst 位的情况、这意味着在 CPU 有机会传输数据之前、先前接收到的消息已被覆盖(丢失)。 现在、在清除 NewDat 和 IntPnd 位和清除 MsgLst 位的指令之间、确实可以想象一条新消息会到达窗口。 您是否验证了中断是否仍然有效、如果仍然有效、INTxID 字段是否指向已断言中断的邮箱? 我知道 IntPnd 位与 MsgLst 位一同清零。 尽管如此、当 IntPnd 处于活动状态且应接收中断时、仍有一个窗口

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Haresh、
    感谢您的分析。

    [引用 user="Haresesh J"]
    我很好奇您为什么会遇到 MsgLst 情况。 您的应用程序是否已使用所有邮箱? 或者无法足够快地读取它们?
    [/报价]
    我不会偶然遇到 MsgLst 情况、而是要特别检查 MsgLst 位是否变为高电平、并了解如何在不影响其他位的情况下清除它。

    [引用 user="Haresesh J"]
    在修改步骤之前(但在读取步骤之后)、向同一邮箱发送一个帧、并确保 NewDat 和 IntPnd 位为1。 现在、执行写入步骤并验证这些位是否确实清零。
    [/报价]
    我已经进行了测试、我看到在读取和修改步骤之间接收到帧后、NewDat 和 IntPnd 位为1。 然后、写入步骤之后、NewDat 和 IntPnd 位被清零。

    [引用 user="Haresesh J"]
    我假设您在接收 ISR 中检查 MsgLst 位的值、并仅在该位被置位时将其清零。
    [/报价]
    你是对的。

    [引用 user="Haresesh J"]
    因此、您将讨论一种同时设置 NewDat 和 MsgLst 位的情况、这意味着在 CPU 有机会传输数据之前、先前接收到的消息已被覆盖(丢失)。
    [/报价]
    再次出现。

    [引用 user="Haresesh J"]
    现在、在清除 NewDat 和 IntPnd 位和清除 MsgLst 位的指令之间、确实可以想象一条新消息会到达窗口。 您是否验证了中断是否仍然有效、如果仍然有效、INTxID 字段是否指向已断言中断的邮箱?
    [/报价]
    我已经验证、如果在读取和修改步骤之间收到新消息、INT0ID 字段将指向正确的邮箱(我在测试中使用 INT0中断线路)。 然而、写入步骤之后、INT0ID 被清零、就像 NewDat 和 IntPnd 位一样。

    [引用 user="Haresesh J"]
    我知道 IntPnd 位与 MsgLst 位一同清零。 尽管如此、当 IntPnd 处于活动状态且应接收中断时、仍有一个窗口
    [/报价]
    写入步骤后、我清除 CAN_GLB_INT_FLG 寄存器中的 INT0_FLG、这样就不会再发生中断。

    无论如何、我已经做了进一步的测试:我已经将代码更改为在 NewDat 和 IntPnd 清除之后清除 INT0_FLG、但在读取步骤之前清除 INT0_FLG。 如果在读取和修改步骤之间收到新消息、INT0ID 字段将指向正确的邮箱、并且 INT0_FLG 再次设置为1。 然而、写入步骤之后、INT0ID 字段被清零、而 INT0_FLG 仍然为1。 所以另一个中断被置为有效、但是 INT0ID 等于0、所以我无法识别中断的原因!

    实际上、我认为在中断例程结束之前清除 INT0_FLG 是正确的、如 TI 驱动程序示例所示。

    [引用 user="Haresesh J"]
    在您的帖子中概述的方法中、似乎存在无意中清除 NewDat 的风险。 该规范不指示清除 MsgLst 位的任何其他方法。
    [/报价]
    在我们的考虑和测试之后、我认为没有办法避免这种风险、对吧?

    感谢您的宝贵支持。

    此致、

    演示