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.

[参考译文] MSP430F5437A:读取 UCA0RXBUF 会导致 CPU 偶尔跳过随后的指令

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1414724/msp430f5437a-reading-uca0rxbuf-causes-cpu-occasionally-skip-the-subsequent-instruction

器件型号:MSP430F5437A

工具与软件:

我有一个长期运行的产品、其新固件构建在遇到大量传入串行端口流量时偶尔开始失败。 通过使用我们固件中内置的分析工具和调试器、我能够将问题隔离到固件代码的特定部分。

固件使用 TST 重复读取 UCARXBUF (UART 模式)。 B 指令、即使没有挂起字符也是如此。 (不要问为什么;但我没有发现任何禁止读取 UCA0RXBUF 的文档、即使 UCRXIFG 未置1。) 但是、有时、例如每1000000次执行一次 CPU 跳过后续指令、没有明显的原因。

由于该后续指令是 RETA、因此跳过它会导致执行流入完全错误的路径、从而使器件不工作。

0x37C64 TST。 b 0xC(R12)            ;该指令读取 UCA0RXBUF (R12=0x05C0)
0x37C68 RETA
0x37C6A MOVA  R13、0x8 (R12)        ;不应执行但有时在0x37C64之后执行的不相关指令
0x37C6E RETA

只要未执行指令上的断点停止执行、State Storage 就会显示该执行确实已在0x37C68处的 RETA 指令上跳过:

这一事件的发生概率以及必须有进入字节的事实使我感觉这与 UCRXIFG 在被读取 RXBUF 的同时由硬件设定的~情况有关。 然而、UCRXIE 和 GIE 被置位、所以所有进入的字符应该触发中断处理、但在状态存储中看不到中断处理。 (状态存储器在执行 TST 之后不久显示"IRQ=1"。 B 指令读取 RXBUF。 为什么它是那里、以及如果它是一个中断、为什么没有开始中断处理?)

我找不到任何有关 MSP430F5437A 勘误表的公告、它不能涵盖这种执行失控的情况。 发生了什么以及如何确保固件的可靠性? 当然、我可以在读取 UCA0RXBUF 后添加一个虚拟指令、但如果不确认根本原因、我就无法确保它能够可靠地解决此问题。 无论如何、CPU 上不应发生未记录的行为。

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

    修正: 如果状态存储配置为记录所有 CPU 周期、控制位"IRQ"似乎恰好在读取 UCA0RXBUF (0x05CC)的周期有效、然后执行将在0x37C6A 上"停止"一段时间(已忽略0x37C68处的 RETA?) 请注意、有意外的写入操作(!) 在最终读取0x37C6A 上指令的第二个字之前、还要添加0x133C 和0x133E (BSL 闪存区域?!)。

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

    您可能已经触发了中断系统的罕见问题。 如果它开始处理中断、但该中断源在读取向量之前被清除、则可以读取错误的向量。

    可能发生的情况是一个新字节到达、并设置 RXIFG。 中断系统随后开始处理中断。 如果、很可能、它必须等待该特定的 TST。 B 指令结束、那么 RXIFG 将被清零。 现在、当硬件选择要读取的矢量时、它会得到错误的矢量。 如果有其他中断待处理、它将使用该中断。 如果没有暂挂的中断、则不指定使用的矢量。 几乎是任何东西。

    解决此问题的常用方法是使用虚假中断向量。

    因此、当你启用接收中断时、除了在 ISR 中、不要读取 RXBUF。

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

    感谢您的评论。 实际上、中断处理似乎正在发生意外的事情。 是否有任何描述此行为的官方 TI 文档? 根据我的文学研究是,它不是官方"禁止"在任何时候阅读 RXBUF。

    在上面的示例中确实没有其他挂起的中断、否则、它应该已经被处理/改为被处理。 那么、这属于"几乎任何东西"类别。 首先我认为在 TST 之后只需添加一个 NOP。 B 指令确保一切正常工作、即使随后的指令偶尔被跳过也是如此。 但是,如果"几乎任何事情"可能发生,这将不是一个可靠的解决方案。

    想知道清除任何硬件中断标志的任何指令是否会发生这种情况? 例如、当相应的中断发生时、通过在同一时间向任何 xIFG 标志写入0。 如果是这种情况、应该有指导、除非相应的中断被禁用(通过 XIE 或 GIE)、否则绝不应写入 xIFG。 (在典型代码中是这种情况、因为 xIFG 在中断中被清零、并且中断在 GIE 未置1的情况下运行。)

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

    "几乎任何东西"都受到限制。 选择加载哪个向量的中断硬件将选择一个。 但是、当没有输入时、它将使用哪一个? 我怀疑这将是最低优先级。 最可能的情况是其值为0xFFFF。

    结果是、程序计数器将加载0xfffe (lsb 无关)、这会导致复位向量处的数据用作指令。 不好。

    在文档方面、该指南的一节中提供了有关中断的注意事项。 有关在启用中断之前清除中断标志的警告。 请注意、这是完全相同但相似的。

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

    观察到的行为不会跳转到0xfffe、而是跳过后续指令。 (这比跳转到0xfffe 致命错误更小、但仍可能导致问题、具体取决于跳过的重要指令。 在本例中、固件从跳转中恢复、但在返回正确流程之前不久执行的意外代码导致串行端口波特率发生变化、从而使问题显而易见。) 当然、所有这一切都属于"意外的 CPU 执行"范畴。

    如您所述、突出显示的器件与此问题最接近、但我认为它最初是不相关的。 这部分代码根本不启用/禁用中断、它"只"清除中断标志(虽然相应的中断被启用)。 快想一想、人们可能会认为清除一个 IFG、无论如何该值应为零(否则、中断会被处理以清除 IFG。。。)根本不会有什么坏处。 但由于上述推测的原因、这似乎是应该避免的。

    目前、我们的终端产品处于制造搁置状态。 我们官方不知道他们失败的原因、因为固件看起来好像没有任何非法操作。 由于销售损失、除了解决问题外、我还需要详细报告根本原因及其发生原因(=谁犯了错误)以及将来如何避免这种情况。 这就是为什么我要寻找现有的文档、这些文档应明确地阻止原始开发人员编写这样的代码。

    该固件充斥着对外设寄存器和无用变量的看似不必要的操作。 到目前为止、我只将它们视为丢失了代码存储器空间、但现在我还需要将它们视为对固件稳定性有影响的风险。

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

    因为我可能永远找不到一个"官方"语句、如果在启用中断的情况下读取 UCA0RXBUF 会发生什么情况、所以我尝试了分析我的观察结果并总结出我自己对 CPU 在这种情况下实际正在做什么的理解。

    (作为一个 Commodore64时代的黑客、我喜欢这些从20世纪90年代衍生出来的架构、因为人们可以期望 CPU 基于简单的逻辑、而无需任何昂贵的微代码或任何动态变化的部件。 为了完整和招待可能的类似想法的读者这个线程,我将分享我的分析下面。

    意外写入0x133C 的说明(请参阅上面显示所有周期的状态存储图):

    1. IRQ 干扰使 CPU 将 RETA 指令从0x37C68读取为"非获取"、并继续在0x37C6A 处读取指令字 MOVA R13、X (R12)。 (由于流水线、UCA0RXBUF 0x05CC 的读取正在中间这里发生。) 读取0x37C68字时、CPU 中已经发生了"某些事情"、因为"控制信号"包含值0x302、这与其他周期明显不同。
    2. 但是、也可以从0x37C6A 读取此已索引 MOVA 的目标索引字(PC 不先进)。 这会导致 MOVA 目标为0x133C (来自 R12的0x05C0 + 0x0D7C (MOVA R13的操作码字、X (R12))来自0x37C6A = 0x133C)。 (由于流水线、实际写操作会在几个周期之后执行。)
    3. 执行该指令后、PC 仍不前进、之后恢复正常运行。 现在通常提取并执行来自0x37C6A 的指令 MOVA R13、0x8 (R12)、导致写入0x05C8 (UCA0MCTL、来自 R12的0x05C0 + 0x0008 (目标索引字)= 0x05C8)。

    猜测并期望这正是 CPU 的不良行为、我可以分析我们固件的二进制文件、并向内部相关人员陈述 CPU 问题是否会导致包含这些固件版本的最终产品出现任何问题。

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

    在 ISR 外部读取 RXBUF 是一个问题、所以不应这么做。

    即使假设 ISR 被正确调用、如果未设置 RXIFG、ISR 中会发生什么情况?

    如果您坚持这样做、请先禁用中断。

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

    我同意;我已经从下一个固件版本中完全删除这些无用的 RXBUF 读取(排除 ISR 内的有效读取)。 但我仍然需要评估不必要的 RXBUF 读取在那些成千上万的产品在最后15 (?) 造成的影响。 为了实现这一目标、我唯一能做的就是希望 CPU 每次的行为都相似。 假设,我只需要反汇编二进制映像,看看在 RXBUF 读取后有什么指令,以及这种异常执行会如何影响每种情况下的产品操作,如果有的话。

    我被召唤进入这个案例、只是为了解释其他人几年前做了什么、并确定它是否引起重大召回