Jud*_*den 24 c embedded microcontroller volatile cpu-registers
微控制器通常需要读取寄存器以清除某些状态条件.在C中是否有可移植的方式来确保在不使用数据的情况下不优化读取?指向内存映射寄存器的指针是否足以声明为volatile?换句话说,以下是否始终适用于标准兼容编译器?
void func(void)
{
volatile unsigned int *REGISTER = (volatile unsigned int *) 0x12345678;
*REGISTER;
}
Run Code Online (Sandbox Code Playgroud)
我知道处理这样的功能会遇到编译器相关的问题.所以,在这种情况下,我对便携式设备的定义有点松散.我只是说它会尽可能广泛地使用最流行的工具链.
人们非常努力地争论究竟是什么volatile意思.我想大多数人都同意你所展示的结构是为了做你想要的,但是没有普遍认为C标准中的语言实际上保证它是C99的.(情况可能在C2011有所改善;我还没有读过.)
嵌入式编译器非标准但相当广泛的支持,可能更有可能的替代方案是
void func(void)
{
asm volatile ("" : : "r" (*(unsigned int *)0x12345678));
}
Run Code Online (Sandbox Code Playgroud)
('volatile'在这里应用于'asm'并且意味着'即使它没有输出操作数,也可能不会被删除.也没有必要将它放在指针上.)
此构造的主要缺点是您仍然无法保证编译器将生成单指令内存读取.使用C2011,使用_Atomic unsigned int 可能就足够了,但是如果没有这个功能,如果你需要保证,你几乎必须自己编写一个真实的(非空的)程序集插件.
编辑:今天早上发生了另一个皱纹.如果从内存位置读取具有更改该内存位置值的副作用,则需要
void func(void)
{
unsigned int *ptr = (unsigned int *)0x12345678;
asm volatile ("" : "=m" (*ptr) : "r" (*ptr));
}
Run Code Online (Sandbox Code Playgroud)
防止来自该位置的其他读取的错误优化.(要100%清除,此更改不会更改为func自身生成的汇编语言,但可能会影响周围代码的优化,尤其func是在内联时.)
是的,C 标准保证访问 volatile 变量的代码不会被优化掉。
C11 5.1.2.3/2
“访问易失性对象”……“都是副作用”
C11 5.1.2.3/4
“如果一个实际的实现可以推断出它的值未被使用并且没有产生所需的副作用(包括由调用函数或访问易失性对象引起的任何副作用),则它不需要评估表达式的一部分。”
C11 5.1.2.3/6
“对一致实现的最低要求是:
— 对 volatile 对象的访问严格按照抽象机器的规则进行评估。”