【问题标题】:HardFault with a Macro on a if or while statement in C language在 C 语言的 if 或 while 语句上带有宏的 HardFault
【发布时间】:2021-08-13 21:42:00
【问题描述】:

我有以下宏用于读取 STM32F091 上寄存器中的单个位:

#define GET_BIT(reg, pos)          (((reg)>>(pos))&0x00000001u)

我必须将此宏与这两个参数一起使用:

#define FLASH_KEYR                 (*((u32_t *)(0x40022004u)))
#define BSY_FLASH_SR_POS           (0u)

我没有任何问题使用这个宏来评估单个变量,例如:

uint32_t value = GET_BIT(FLASH_SR, BSY_FLASH_SR_POS);

但是,在这样的条件语句上使用这个宏:

    while (GET_BIT(FLASH_SR, BSY_FLASH_SR_POS) == 1u);

微机进入 ISR 以进行 HardFault。

...为什么?

【问题讨论】:

  • 什么是FLASH_SR - 即显示定义(不解释SR寄存器的作用)。 Waht 是 REGISTER_ADDRESS
  • 为什么是0x00000001u 而不是简单的1
  • @Toad __ - GET_BIT(((REGISTER_ADDRESS)>>(FIELD_POSITION))&0x00000001u) 不是 2 参数宏 GET_BIT(reg, pos) 的有效调用。
  • 您说的调用有效,与您说的中断不同,因此很可能与 if 或 while 无关,而是与参数无关。无论如何,这是一个可怕的想法。与其使用位位置宏,不如使用位掩码宏(可能已经在芯片头中定义)并直接测试位,或者使用位带地址直接读取位。
  • 现在,您是要移位寄存器地址还是寄存器值?您实际在做什么以及它在语义上是否有意义将取决于 FLASH_SR 的定义。宏不好,因为它们混淆了代码的语义。要调试一个,您必须考虑 full 扩展以及它在语法上和在这种情况下在语义上是否正确。

标签: c crash embedded stm32


【解决方案1】:

问题是你在重新发明轮子,结果是错误的。

与其帮助您重新发明另一个新轮子,这里是 ST 已经为您制造的现有轮子:

#include "stm32f0xx.h"

...

while ((FLASH->SR & FLASH_SR_BSY) != 0);

【讨论】:

  • 不,我没有重新发明轮子,因为我不能在这个安全关键项目中使用 ST 库
  • 我在 IEC-62304 医疗设备软件和机动车辆/军事项目中有着广泛的工作经验。任何拥有半个脑细胞的审计员都会相信来自硬件制造商的设备寄存器定义标头,这些标头用于数千个项目,远远超过您编写的任何东西。这同样不适用于 STL 或 HAL 库,但您应该毫无疑问地使用标头。事实证明这是正确的,因为您无法让它工作,并且在互联网上向随机的陌生人寻求帮助,以解决本应对安全至关重要的事情。
  • 要具体说明 SMT32 的事情:那些标头将寄存器定义为结构,而 ANSI-C 没有定义此类结构的内存占用,最好不要普遍使用它们。一般来说:我只是在写一些外围驱动程序,没什么复杂的。此外,你可以忘记我在 STM32 上,这个问题是通用的(“为什么这段代码不起作用”)。
  • 您没有使用“任何一般的编译器”。您正在使用兼容 ARM EABI 的编译器,或者您应该使用。在您的编译器验证文档包中引用 ARM EABI 标准,然后您可以依赖正式定义的结构打包。查看 ISO14971 医疗设备风险管理(或您所在行业的同等标准)。重新发明轮子的风险总是高于以标准方式进行并提供适当的文档说明为什么标准方式有效。
【解决方案2】:

如果你坚持重新发明轮子,那么它不能在循环中工作的原因是你错过了指针转换中的 volatile。

我的另一个答案仍然是正确的专业答案(尤其是在安全至关重要的环境中),但从 cmets 看来,这是您更愿意接受的答案。

【讨论】:

    猜你喜欢
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    • 2015-08-03
    • 2023-01-16
    • 1970-01-01
    • 2016-02-29
    相关资源
    最近更新 更多