【问题标题】:GCC variable mapping and MISRA-CGCC 变量映射和 MISRA-C
【发布时间】:2021-11-28 08:05:45
【问题描述】:

我知道用 GCC 声明内存映射寄存器的主要方法有两种(有很多变体,使用双域,每个外围设备的数据结构等...):

  • 要么使用指向正确地址的指针,如volatile uint32_t *pMyRegister = (uint32_t *)0xDEADBEEFUL;
  • 或者定义一个变量并像volatile uint32_t MyRegister __attribute((section(".register_section")));一样手动映射它,然后映射LD文件中的部分。

不幸的是,这些方式似乎都不符合 MISRA-C 编码规则,第一种方式是因为存在未经授权(由 MISRA)从整数到指针的强制转换,第二种方式是因为属性关键字。

我的问题是:有没有办法(使用第二种解决方案)在不影响代码的 ANSI 特性的情况下映射节中的变量(即没有编译器特定的关键字)。

谢谢

【问题讨论】:

  • 注意:有时您可能会编写直接与硬件交互的代码(或低级特定细节):如果您可以证明 MISRA-C 允许您违反某些规则(称为偏差)必须在非常具体的情况下打破规则,以允许低级别的交互。 MISRA 无法验证低级别的特定事物,因为它更像是一组“通用”规则。 See also this SO question.
  • 您使用的是哪个 MISRA-C 版本?
  • @LucaPolito MISRA-C 可以而且应该绝对验证低级别的东西,它在源代码上作为整体使用。对于内联汇编等它肯定无法验证的东西,对于如何处理这些代码也有特殊的规则。
  • @Lundin 是的,你是对的。我并不是说 MISRA-C 不能用于验证低级程序,我只是说它不能验证特定于低级的方面,例如地址 0xABCD 是一个有效的硬件地址。 MISRA-C 与平台无关。当你有低级程序时必须特别小心,因为 MISRA-C 通常需要对这类事情进行人工验证(例如合理地偏离规则)。

标签: c gcc stm32 misra


【解决方案1】:

首先,两者都不正确,因为缺少volatile。请参阅How to access a hardware register from firmware?,其中也简要介绍了 MISRA-C。

为了回答这个问题,这条规则 MISRA-C:2012 11.4 是建议性的,并附带说明(最后的注释由我附加):

"...但是在寻址内存映射寄存器或其他硬件特定功能时可能是必需的。如果使用整数和指针之间的强制转换,应注意..." [不会导致未对齐的未定义行为]

因此,您可以放心地在注册声明中忽略此规则,如果需要,请参阅规则 11.4 的基本原理。由于它是建议性的,因此不需要任何偏差(但最好您应该记录您仍然忽略该规则)。

值得注意的是,从 MISRA-C 的角度来看,您的两个版本中的前者更可取,因为它不包含您需要记录它们如何使用的非标准扩展,而其他 MISRA 规则则要求这样做。

【讨论】:

  • 是的,我忘记了volatile,当然会编辑它。
  • 您的评论很有意义,但它并没有严格回答我的问题(关于链接描述文件中的变量映射)。其实我可能已经找到了一个简单的解决方案。 gcc 能够为每个变量创建一个部分。我没有每个寄存器一个变量,而是每个外围设备一个变量。所以我只需要映射,比如.bss.My_SPI_Registers 部分在正确的地址,它只在 ld 文件中完成
  • @GuillaumePetitjean 根据我发布的链接,#define 宏版本是我过去在需要一切 的 MISRA 合规性时使用的 - 包括库。链接器脚本技巧版本具有这些对象实际出现在调试器中的优势,但是无论如何您都应该使用具有目标意识的调试器,所以这是一个可疑的优势(但工具供应商将其作为使用非标准语法的借口) )。
  • @Andrew 好吧,忽略它非常安全,因为您进行显式整数/指针转换的唯一地方是低级代码,如寄存器映射和内存处理驱动程序,程序员往往知道他们在做什么,而不是导致错位。请注意,与流行的看法相反,C 确实不允许 允许隐式整数/指针转换。
  • @Andrew 咨询规则会获得更高的地位,如果没有那么多具有咨询地位的可疑规则。这个特殊的规则很麻烦,因为它不能在低级代码上强制执行。唯一真正的危险是由于整数到指针转换导致的不对齐,因此最好有一个专门解决这个问题的规则。虽然我不能说我曾经在现实世界的嵌入式系统中遇到过一个错误,即从 int 进行显式转换会导致错位。我记得的几个错位错误与链接器脚本等有关。
猜你喜欢
  • 1970-01-01
  • 2016-03-06
  • 2011-09-11
  • 2015-07-26
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多