2

在对微控制器进行编程时,有时需要读取寄存器以重置某些标志。这些寄存器是内存映射的,并在代码中声明为指向 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值以避免出现“死代码”的另一种方法?** 因为使用帖子中的方法将 volatile 表达式的结果转换为 void 具有非常相似的在这种情况下,我仍然违反了 MISRA c 2012 规则。我无法从#define MODULE_SCU或结构中更改任何内容,因此正确的替代方法是可行的方法。

当我从这个线程中读到时,我不想让编译器强制转换为 void:什么是 void 强制转换?因为如果我强制转换为 void,那么优化器可能会优化掉该读取,这是不可取的。

不要太在意片段的正确性,我只是为了说明问题而包含它

4

2 回答 2

4

这里必须读取 reg 才能重置它的位,除了读取它们之外,没有其他方法可以重置一些位,因此,MISRA 规则检查器抱怨有死代码,这是正确的。

死代码是什么都不做的代码。从技术上讲,死代码是没有副作用的语句。在这种情况下,volatile关键字表明它确实在做某事,它正在读取内存并因此重置位,这是一个明确的副作用。

volatile 关键字还确保兼容的优化器不会删除该行。

所以,事实上 MISRA 规则检查器是错误的,代码完全没有问题,不应该被标记。

无需找到正确方法的替代方法。

于 2015-08-11T20:24:35.480 回答
3

读取对象并丢弃结果的正确方法是:

(void)object;

强制转换实际上不是必需的,但可能会阻止编译器抱怨(实际上不确定 MISRA)。仅供参考:这是一个表达式语句

如果object是限定volatile的,编译器可能不会优化访问,因为这个关键字告诉编译器存在副作用,即使编译器没有看到它。强制转换适用于表达式的结果(“读取”),而不是对象,因此它不会您的评论所暗示的那样删除限定符。

MISRA-checker 不应该抱怨,因为这条线确实了一些事情。volatile (这是由限定词暗示的)。如果该工具仍然抱怨,请将其丢弃。更重要的是,这不是您第一次遇到麻烦。

于 2015-08-11T20:41:34.090 回答