如何让(1 << 9)通过MISRA? [复制]

2024-01-14

我们使用 Parasoft 静态分析并打开 MISRA C 2004 检查器。

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

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

这表明寄存器中的第 9 位应该是 1 才能打开电机。

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

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

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

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

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

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

我正在使用 IAR Embedded Workbench 和 8/32 位模式的 ARM7TDMI 处理器。

编辑 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

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

就像是:

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

然后在你的实际代码中:

#define MOTOR_ON LSHIFT(1, 9)

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

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

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

  • 在您想要放置位移位的源文件中,添加 MISRA 警告禁用注释,然后按照之前的方式放置代码。

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让(1 << 9)通过MISRA? [复制] 的相关文章

随机推荐