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.

[参考译文] TMS320F28379D:从 EMIF 地址复制会产生错误的值

Guru**** 2539500 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1362877/tms320f28379d-copy-from-emif-address-produces-wrong-value

器件型号:TMS320F28379D

我遇到了一个非常混杂的情况、非常感谢您提供任何建议。 我将 EMIF CS2配置为32位接口、并将所有时序设置为尽可能低的选项。 正常模式在启用延长等待时间的情况下使用。 当单步执行调试器时、从该 EMIF 复制值的函数偶尔会复制不正确的值、但实际上在 JTAG 中检查该 EMIF 地址的值会显示正确的值。

typedef union Field {
    float32_t f32;
    int32_t i32;
    uint32_t u32;
} Field;

typedef union {
    struct {
        uint8_t id:8;
        State state:8;  // Enum defined elsewhere
        uint8_t _16:4;
        bool message_refuse:1;
        uint8_t _21:3;
        MessageType message_type:8;  // Enum defined elsewhere
    };
    uint32_t all;
    struct {
        uint16_t lower;
        uint16_t upper;
    };
} Header;

typedef union {
    struct {
        uint8_t bcc:8;
        uint8_t _8:8;
        uint8_t speed:8;
        uint8_t acceleration:8;
    };
    uint32_t all;
    struct {
        uint16_t lower;
        uint16_t upper;
    };
} Footer;

typedef struct Message {
    Header header;
    Field sections[6];
    Footer footer;
} Message;

Message volatile const* const RECEIVE_MESSAGE = SOME_EMIF_ADDRESS;

void readMessage(Message* message_out) {
    Message volatile const* in = RECEIVE_MESSAGE;
    
    message_out->footer.all = in->footer.all;
    DELAY_US(0.2);

    message_out->header.all = in->header.all;
    DELAY_US(0.2);

    // Read sections
    for (int16_t i = 0; i < 6; ++i) {
        message_out->sections[i].u32 = in->sections[i].u32;
        DELAY_US(0.2);
    }
}

上面显示了 EMIF 地址的结构化读取的示例定义。 `re` adMessage `m函数、` essage_out `始终生成正确的标头/段、但似乎在页脚的` Bcc 代码中偶尔会失败(也总是具有相同的值、其中它应该是0x3、但应该是0x10)。 最有趣的是`m断点并观察调试器中的值时、页脚在实际的 EMIF 地址中是正确的、但仅在` essage_out `中` Bcc 代码是错误的。 这在某种程度上也是随机的/不频繁的。

为了解决这个问题、我已经尝试将 EMIF 时序配置降低到可用的最慢选项、在读取函数内增加不同数量的延迟、在延迟函数内重新排序副本、以及在读取函数内多次从 EMIF 地址复制页脚。 所有这些操作都不会在结果中产生任何变化(间歇性页脚`BCC`错误为0x10而不是0x3、仅在复制的`message_out`中出现)。

是否有人经历过类似的行为? 此时、我没有怀疑 EMIF 本身、因为它在直接读取时会生成正确的值、但我不明白从一个存储器区域到另一个存储器区域的简单副本如何会随机间隔产生具有相同值的完全相同的错误。

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

    进一步更新;中断禁用和恢复添加到驱动程序消息读取中、没有区别。 ``函数`m结束时的断点 JTAG 值的屏幕截图、请注意页脚的` BCC `Δ t in`(EMIF 地址)与刚刚复制的 μ s essage_out 之间的值差异、但所有其他字段/标头保持一致。

    此外、在函数末尾仅将 EMIF 地址的页脚读取到局部变量也会存储值16 (0x10)、尽管根据 JTAG 锁存了3个值。

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

    另一个额外更新:将消息中的页脚位置更改为页眉正下方、出现同样的问题。 这可能是与在 EMIF 中使用位域相关的编译器错误吗? (注意:实际的 EMIF 读取是32位、只有结构定义包含一个位字段。 这似乎不太可能与此相关、但也无法理解如果不是其他情况下该问题会如何发生。 此外、报头还定义为与位域的联合体、与页脚类似、但报头没有问题)。

    编辑:使用被定义为一个`uint32_t`数组而不是消息结构的 EMIF 地址进行测试。 发生相同的问题;似乎与位域的使用无关。

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

    许多微控制器对存储器访问具有对齐限制。 地址(RECEIVE_Messag)是否与32位边界对齐? 您的设置是否支持字节读取/写入 EMIF 存储器?  

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

    是的、它是32位边界对齐! 此外、我不进行字节读取/写入 EMIF;我仅以32位块进行读取/写入。 除非、否则为32位访问设置 EMIF 是否仍按字节读取/写入?

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

    您好、John:

    "const volatile"通常用于 指向存储器映射硬件寄存器的指针。 我不确定用户代码中的"volatile const* const "对于 EMIF 存储器的指针是否适用。

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

    " const* const"不应产生影响;它只是一个符号、显示了指针地址和指针本身的值、绝不应由 DSP 编程器分配。 您是说"volatile"不应用于 EMIF 存储器吗? 那么、编译器的优化器如何理解不应将此类指针访问重新排序/优化掉?

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

    Ah、此外、JTAG 调试会话屏幕截图中显示的"in"指针显示了正确的值、只有复制到"message_out"才会导致问题。 "volatile const*"用法是否可能在某种程度上仅影响复制,而不影响 JTAG 中的直接读取?

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

    我运行测试几分钟、代码未到达 bkpt (第143行)。  

    BTW,在您的代码中使用"volatile const* const"或使用"volatile const* const"有何优势?

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

    非常有趣、感谢您的尝试。 我们的某个相关电路板组件上可能存在间歇性硬件故障、但我仍不确定 JTAG 调试如何显示正确值...

    至于"volatile const* const"、"const* const"部分正是为了在发生任何意外尝试写入 EMIF 地址(应为只读地址)时、我们可以收到足够的编译器警告。 "volatile"只是为了避免在提高编译器优化级别时出现任何问题;我们之前在将编译器优化增加到-O4时遇到与这些 EMIF 地址交互的问题、但这些问题似乎可以通过适当的"volatile"注释来解决。

    到目前为止、该问题仍然是间歇性出现的、没有"易失性"。 我将继续测试,也没有" const* const",看看我是否能找到任何新的结果。

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

    编译器不会对 易失性 变量执行优化。  请尝试使用 "const*"代替"const* const"进行测试 。  

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

    是的、这是使用"volatile"的目的;特别是为了避免编译器执行不必要的优化。 我还使用"const*"和"*"进行了测试,结果相同。 "const* const"实际上不应该产生任何差异、因为第二个"常量"只是表示指针地址本身不应改变以指向新地址。

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

    您好、John:

    当您找到根本原因时、请及时告知我们最新情况。 谢谢