编程微控制器时,有时需要读取寄存器以重置某些标志。这些寄存器是内存映射的,并在代码中声明为volatile的指针。
假设下一个代码段为例:
typedef volatile struct _Ifx_SCU
{
...
uint32_t reg;
...
}Ifx_SCU;
#define MODULE_SCU ((*(Ifx_SCU*)0xF0036000u))
void foo(void)
{
...
MODULE_SCU.reg; /* Read required to reset bits in reg */
...
}
为了重置它的位,必须读取 reg ,没有其他方法可以重置其他读取它们的位,因此,MISRA规则检查器抱怨存在死代码没错。
我的问题是什么是替代阅读和丢弃** reg 值的方式,以避免出现“死代码”?**因为在帖子{{3}中使用了该方法} 情况非常相似,我仍然违反了MISRA c 2012规则。我无法改变 #define MODULE_SCU 或结构中的任何内容,因此可以采用正确的替代方法。
当我从这个帖子中读取时,我不想让编译器的转换无效:Casting the results of a volatile expression to void因为如果我转换为void,那么优化器可以优化掉那个读取,这是不可取的。
不要过分关注代码片段的正确性,我只是将其包含在内以说明问题
答案 0 :(得分:4)
这里必须读取reg以重置它的位,没有其他的 重置一些其他读取它们的方法,所以,MISRA规则 检查员抱怨说有死代码,这是正确的。
死代码是什么都不做的代码。技术上死代码是一种没有副作用的声明。在这种情况下,volatile
关键字表示它确实在做某事,它正在读取内存并因此重置位,这是一个明确的副作用。
volatile关键字还确保合规优化器不会删除该行。
因此,实际上MISRA规则检查程序是错误的,代码完全正常,不应该被标记。
没有必要找到正确方法的替代方案。
答案 1 :(得分:3)
读取对象并丢弃结果的正确方法是:
(void)object;
演员实际上没有必要,但可能会让编译器不抱怨(实际上不确定MISRA)。仅供参考:它是expression-statement。
如果object
是合格的volatile
,则编译器可能无法优化访问,因为此关键字告诉编译器存在副作用,即使编译器没有看到它。强制转换应用于表达式的结果("读取"),而不是对象,因此不删除限定符,如评论所暗示的那样。
MISRA检查员不应该抱怨,因为线路实际上确实某事。 (volatile
限定符暗示了这一点。如果该工具仍然抱怨,请将其丢弃。甚至更多,因为这不是你第一次遇到麻烦。