【问题标题】:log2 causes a fault in STM32F4 MCU in Clog2 在 C 中导致 STM32F4 MCU 出现故障
【发布时间】:2020-01-28 05:55:54
【问题描述】:

为什么这段代码会导致硬故障并跳入无限循环?

#include <stdint.h>
#include <math.h>

void myfunc()
{  
    const double val = 1;
    double log_res = log2(val); // <----- THIS CAUSES A FAULT
    //double log_res = log2(1); // This works
}

当我将 evil 行中的 val 替换为硬编码的 1 时,代码有效。所以只有当我将val 传递给log2 时才会出现问题(如代码所示)。为什么会这样?

我正在使用带有 STM32F429ZI MCU 的 STM32CubeIDE(基于 eclipse)。

更新:

在反汇编窗口中检查异常表明这是发生了异常:

fffffff9: 执行 MI 命令失败: -数据反汇编 -s 4294967289 -e 4294967429 -- 3 来自调试器后端的错误消息: 无法访问地址 0xffffffffe 的内存

有人知道为什么会这样吗?

更新 2:

在汇编指令中调试:

54            const double val = 1;
08000e0a:   mov.w   r3, #0
08000e0e:   ldr     r4, [pc, #64]   ; (0x8000e50 <myfunc+88>)
08000e10:   strd    r3, r4, [r7, #16]
55            double log_res = log2(val);
08000e14:   vldr    d0, [r7, #16] // <------ X THIS LINE CAUSES THE PROBLEM X
08000e18:   bl      0x8002a9c <log>
08000e1c:   vmov    r0, r1, d0
08000e20:   add     r3, pc, #36     ; (adr r3, 0x8000e48 <myfunc+80>)
08000e22:   ldrd    r2, r3, [r3]
08000e26:   bl      0x800085c <__divdf3>

强调的行有 d0=0, r7=0x2002ffcc

执行此行后,反汇编程序跳转到WWDG_IRQHandler

更新 3:

GCC 汇编器选项(不确定这是做什么的):

-mcpu=cortex-m4 -g3 -c -x assembler-with-cpp --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb

GCC 编译器选项:

-mcpu=cortex-m4 -std=gnu11 -g3 -DSTM32F429I_DISC1 -DSTM32 -DSTM32F429ZITx -DSTM32F4 -DDEBUG -DSTM32F429xx -c -I..\Inc -I../Inc/CMSIS/Include -I../Inc/CMSIS/Device/ST/STM32F4xx/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb

GCC 链接器选项:

-mcpu=cortex-m4 -T"C:\Users\mne\STM32CubeIDE\workspace_1.0.0\MyUSB\STM32F429ZITX_FLASH.ld" --specs=nosys.specs -Wl,-Map="${ProjName}.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group

更新4:

问题似乎发生在math.h 的许多功能上,例如fmin.

【问题讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • 你的MCU到底是什么?你的编译器选项是什么?看起来您正在使用 MCU 不支持的双精度指令。
  • @BumsikKim 我正在使用 STM32F429ZI,我不确定如何准确地与您分享我的编译器选项。我在问题中添加了 gcc 命令行选项,希望这就是您所需要的。
  • 如果您使用优化,编译器可能会为您折叠常量,甚至可能会调用 log2constexpr double first_setstatic const 也可能有效。您肯定会希望将它用于您的生产代码。
  • 你有-mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb作为汇编程序而不是编译器选项的原因吗?

标签: c arm stm32 stm32f4 stm32cubeide


【解决方案1】:

您似乎从编译器选项中省略了标志-mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb,并且仅将它们包含在您的汇编器选项中。 (您可以将-march=armv7-m -mtune=cortex-m4 替换为-mcpu=cortex-m4。)因此,您的编译器正在为错误的浮点ABI 生成代码。您指定了硬 ABI,但正在生成对软库函数的调用,而不是内联汇编指令。

编辑:如果编译器正在生成您的 FPU 不支持的指令,正如 ImageCraft 的 Richard 所观察到的,您可以尝试将标志更改为 --mcpu=cortex-m4 --mfpu=auto

请注意,任何级别的优化,甚至是-O1,都足以让 GCC 折叠常量并优化对double position = 0.0; 的调用。您可能需要使用函数 return position; 来让它发出带有优化的代码。 (我假设这是一个简化的 MCVE,因为您实际上不需要在运行时计算 log2(1)。)

【讨论】:

  • 我更新了问题中的编译器参数。不幸的是,问题仍然存在。
  • @MohammedNoureldin 不幸的是,我没有办法重现这个问题。定义多个声明目标架构的选项对我来说看起来很可疑,我会确保您包含并链接正确的库并且只有那些。
  • 参数实际上是IDE定义的,链接math.h时有什么特别需要注意的吗?再次在这里我没有做任何特别的事情,IDE添加了整个链接器参数(我没有在这里更改任何内容)。
【解决方案2】:

问题出在这里:

08000e14: vldr d0, [r7, #16] //

“d0”是一个 64 位 VFP 寄存器。但是,Cortex-M4F 只有 32 位 FPU(寄存器 s0、s1 等)。 Cortex-M7F 具有 64 位 FPU,但这不是您使用的。

因此该指令对导致故障的 Cortex-M4F 内核无效。我可以在 GCC 2018-Q4 版本中复制这一点。如果删除-mfloat-abi=hard,问题就会消失,因为它会使用 ARM 核心 CPU 寄存器来传递参数。所以这是我推荐的解决方法。

至于根本原因,我需要做更多的调查。

【讨论】:

  • 我更新了问题中的编译器参数。不幸的是,问题仍然存在。
  • @MohammedNoureldin 嗯。 -mcpu=cortex-m4 -mfpu=auto 有效吗?
  • 您删除了 -mfloat-abi=hard?您不必明确地说 -mfloat-abi=soft 而是继续尝试。如果仍然失败,请再次检查 asm 输出,它不应使用软 FP ABI 生成“vldr d0,..”(除非您的 GCC 非常损坏)。另外,您使用的 GCC 版本是什么?
  • 感谢您的努力并尝试重现错误!现在可以了!我想通了为什么这以前没有帮助,现在帮助了。我对项目进行了清理,然后使用新设置 -mfloat-abi=softno hardware FPU 对其进行了重建。清洁对于看到效果很重要(我之前没有做过清洁,这就是为什么这不起作用)。
  • @MohammedNoureldin 根本不使用硬件 FPU 只是作为最后的手段,您应该这样做。什么是实际的 FPU?您应该提供正确的编译器标志来使用它。
【解决方案3】:

关于你的问题:

当我用硬编码的 1 替换 evil 行中的 val 时,代码可以工作。所以只有当我将 val 传递给 log2 时才会出现问题(如代码所示)。为什么会这样?

以下声明:

double position = log2(first_set);

没有将变量 val 传递给函数:log2()

我预计这样的编码错误(因为未定义 first_set)会导致代码无法编译。

【讨论】:

  • 很抱歉让您感到困惑。我编辑了一些变量名称以使代码更容易,但忘记了调整文本。我又修复了代码和问题。
【解决方案4】:

STMF4 系列不支持双精度浮点数。将双精度浮点数更改为使用单精度浮点数。

【讨论】:

    猜你喜欢
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    • 2018-05-27
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多