【问题标题】:memcpy() crashes Cortex M4memcpy() 使 Cortex M4 崩溃
【发布时间】:2018-08-14 11:26:52
【问题描述】:

我正在为 STM32F4 控制器 (Cortex M4) 开发一些软件。 前几天我正在将我的代码移植到一个新的硬件平台,特此在“System Workbench for STM32”IDE 中创建一个新项目。

当我尝试运行新项目时,我发现 memcpy() 导致了 UsageFault,这是由 32 位宽的 Load/Store 访问不均匀的地址引起的。

然后我发现旧的工作代码已经与“-specs=nano”链接,而崩溃的代码没有,所以问题可以很容易地解决。我检查了 memcpy() 的反汇编,发现 Nano 库实际上与标准 (?) libc 的实现有很大不同。

不过,我很困惑!为什么 memcpy() 的实现不支持字节对齐地址?那将是一个相当微不足道的错误。应该还有更多吧?!有人知道吗?

【问题讨论】:

    标签: arm memcpy libc cortex-m


    【解决方案1】:

    当我尝试运行新项目时,我发现 memcpy() 导致了 UsageFault,这是由 32 位宽的 Load/Store 访问不均匀的地址引起的。

    您确定这是 32 位访问而不是 64 位访问(LDRD/STRD 指令)吗?前者应该不会在 Cortex-M4 上崩溃,除非 MCU 明确设置为这样做。

    所有 Armv7-M(包括除 Cortex-M0 之外的所有 Cortex-M)都支持具有奇数内存地址的 LDR 和 STR 指令。默认情况下,只有 64 位变体 LDRD/STRD 会因未对齐而崩溃。

    不幸的是,当未对齐时,FPU 加载和存储也会在 -M4F 上崩溃。在移植旧的 8 位内容时,这让我好几次。

    为什么 memcpy() 的实现不支持字节对齐地址?

    现代 GCC 可以使用 memcpy() 的内置插件,尤其是固定传输大小和指向大于一个字节的类型的指针(例如 uint32_t*float*)。 Nano memcpy() 是一个最小的实现,可以逐字节缓慢地复制。

    您也可以尝试将指针转换回字节大小的类型:

    uint32_t *pa,*pb;
    memcpy((uint8_t*)pa,(uint8_t*)pb, MEMCPY_SIZE);
    

    这应该提示编译器使用对对齐敏感的内置插件。

    【讨论】:

    • 非常感谢您的回复。好吧,我怕是我自己的错。我确实启用了 Unalignment Trap 并完全忘记了它......而且我也忘记了您可以关闭 Unalignment 检查。当我读到“除非 MCU 被明确设置为这样做”时,我很好奇并且......好吧......发现了我自己的代码。再次感谢。
    • LDM STM也需要对齐地址,那些和LDRDSTRD将导致皮质M4上的使用错误。
    猜你喜欢
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 2018-09-29
    • 2015-02-24
    相关资源
    最近更新 更多