7

我们正在使用启用 MISRA C 2004 检查器的 Parasoft 静态分析。

该软件是一个嵌入式系统。我们喜欢将常量描述如下:

[1]    #define MOTOR_ON (1 << 9)  

这将表明寄存器中的第 9 位应为 1 以打开电机。

该表达式未通过 MISRA,因此我们对其进行了更改:

[2]    #define MOTOR_ON (1U << 9U)

这些更改转换为无符号整数常量,因为移位最好使用无符号整数完成。

语句 2 中的表达式仍然失败,因为需要检查右手运算符 (9U)。根据 MISRA,如果右手运算符大于左手运算符的底层类型的位宽,就会出现问题。

问题的根源在于 1U 的底层类型为unsigned char8 位。
我们写入的寄存器是 16 位的,所以理论上没有问题。

如何更改 [2] 中的表达式以使其通过 MISRA C 2004,而不是使用强制转换?

我在 8/32 位模式下使用带有 ARM7TDMI 处理器的 IAR Embedded Workbench。

编辑 1:示例代码。

void turn_on_motor(void);
#define MOTOR_ON (1U << 9U)
void turn_on_motor(void)
{
    uint16_t * const p_motor_control = (uint16_t *)(0x01234567U);
    *p_motor_control = MOTOR_ON;
}

错误文本:用作移位运算符右手操作数的常数应受到限制。

来自 Parasoft 提供的 MISRA 规则文档:

Rule reports a violation if:

- the right-hand operand is a constant with negative value or with value that
  exceeds the length (in bits) of the left-hand operand

- the right-hand operand is not a constant and is not checked by specific
  pattern
4

3 回答 3

3

我的建议是定义一个隐藏丑陋铸件的宏,然后继续进行丑陋铸件以使 MISRA 满意。

就像是:

#define LSHIFT(x, n) \
    (((unsigned int)(x)) << ((unsigned int)(n)))

然后在您的实际代码中:

#define MOTOR_ON LSHIFT(1, 9)

编辑:在下面的评论中,@Lundin 说 MISRA 会抱怨类似函数的宏。我从未使用过 MISRA,所以我不知道。

快速的 Google 搜索发现 MISRA 有特殊的注释,您可以将其添加到代码中以禁用警告。这表明了两种可能性:

  • 在您定义LSHIFT()RSHIFT()任何其他位操作宏的头文件中,将宏定义包装在 MISRA 警告禁用注释中。

  • 在要放置位移的源文件中,添加 MISRA 警告禁用注释,然后像以前一样放置代码。

http://www.gimpel.com/Discussion.cfm?ThreadMode=Prev&ThreadID=2261

如果我理解正确,MISRA 具有全局启用/禁用,但没有禁用后跟“将其恢复原状”。因此,禁用然后启用的注释将始终全局启用检查,因此理想情况下,这些魔术注释不应位于头文件中。

所以我想我现在的建议是将您的原始位移代码放入 .C 源文件中,并放置魔术注释以禁用/启用位移代码周围的 MISRA 警告。

于 2014-02-04T02:41:21.340 回答
1

您也可以通过使用简单地规避转移问题

 #define MOTOR_ON ((uint16_t)512U)   /* 1 << 9 = 2^9 */
于 2014-02-04T09:06:22.160 回答
0

表达式的值被分配给类型更窄的对象。“1U << 9U”导致只保留低位。

“让 MISRA 高兴”与丑陋的铸造不会改变这个事实,虽然一个糟糕的工具可能会被玩弄,但它不应该。

直接的解决方案是使用显式强制转换:

#define MOTOR_ON ((uint16_t)0x200) /* 9th bit on turns on motor */

但是,如果您认为“转变对可读性更好”,那么只需关闭此案例的规则并记录推理。如果事实完全符合是不可能的,那么偏差过程在符合 MISRA 的开发中是非常好的(并且是鼓励的)。您必须有一个偏差管理流程才能完全合规。意识的证据是目标,而不是一致性的证据。

顺便说一句,@Thomas,你是对的,这不是 MISRA C:2004 的完全重复 ,你也写了位移错误。尽管它违反了规则 10.3,但所描述的“基础类型”的概念对于理解此特定问题的警告意图几乎没有帮助。我对所有人的建议是查看最新版本的 MISRA-C:2012(可在此处找到:http: //misra.org.uk)中对规则 10.3 的描述,这使得工程师的概念和意图更加清晰,并且工具制造商。

于 2014-02-04T02:29:05.900 回答