处理内存访问时避免将整数转换为指针的最佳方法(MISRA 2008)

时间:2016-10-28 14:27:12

标签: c casting embedded bare-metal misra

我有一个裸机程序(驱动程序),它读/写一些内存映射寄存器。 e.g:

void foo_read(uint64_t reg_base, uint32_t *out_value)
{
    *out = READREG(reg_base + FOO_REG_OFFSET);
}
  • reg_base是内存映射设备的基址(64位 地址)
  • FOO_REG_OFFSET是寄存器(#define FOO_REG_OFFSET 0x00000123)的偏移量。注册" foo"是32位"宽"。

READREG的定义如下:

#define READREG(address)    (*(uint32_t*)(address))

你可以猜测MISRA 2008对于从无符号长指针到指针的演员表示不满意(报道为5-2-7 / 5-2-8)。我的问题是:访问内存和摆脱MISRA警告的最佳/适当方式是什么?我已经尝试在转换为指针之前强制转换为uintptr_t,但This didn't help

谢谢。

1 个答案:

答案 0 :(得分:1)

在这里确定一些事项 - 首先,您对READ_REG的定义缺少volatile - 它应该类似于

#define READREG(address)    (*(uint32_t volatile *)(address))

其次 - 这当然是CPU特定的 - 一般来说,从奇数地址(偏移量0x123)读取32位值不会起作用 - 至少它会很慢(多个总线周期)在许多架构上,您将遇到处理器异常。 (顺便说一句,请注意,指针算术不会在这里发挥作用,因为在投射到指针之前会添加2个值。)

回答你原来的问题:

  

访问内存和摆脱MISRA的最佳/适当方式是什么?   警告

嗯 - 你 违反了MISRA规则(在这种情况下,我们必须在那里......)所以你会得到警告。

因此,您需要做的是以严谨,系统和易于识别的方式抑制警告。在我看来,没有比Quantum Platform(QP)事件驱动框架的代码更好的例子和解释,它是开源的。具体做法是:

  • 查看QP's MISRA Compliance矩阵,了解如何处理此问题的示例 - 例如,只搜索PDF以查找Q_UINT2PTR_CAST
  • 查看QP的实际源代码 - 例如macro that wraps/encapsulates such "int to ptr" casts(这种方式以易于识别的方式完成,并且易于更改/禁止单个警告地方)
  • 最后,查看PC-Lint配置文件qpc.lnt,您可以在其中查看在单个位置抑制警告的方式/位置。这在this app note第6.3节中解释:
  

6.3规则5-2-8(req)

     

具有整数类型或指向void类型的指针的对象不应该是   转换为具有指针类型的对象。

     

QP / C ++应用程序可能会在需要时偏离规则5-2-8   直接访问特定的硬编码硬件地址。 QP / C ++   框架将此偏差封装在宏Q_UINT2PTR_CAST()中。   以下代码段提供了此宏的用例:   #define QK_ISR_EXIT() . . . \   *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \

我没有时间谈论MISRA警告抑制,合规性问题等,但上述内容为您提供了所需的一切。

P.S。不确定你指的是哪种MISRA指南 - 对于C,有2004和& 2012年指南,对于C ++,有2008年的指导方针(我知道,它差不多是2017年!)