我的问题是针对嵌入式开发,特别是STM32。
我非常清楚,在处理具有中断服务例程( ISR )的程序时,使用变量的volatile限定符至关重要,以便防止编译器优化在ISR和主线程中使用的变量。
在Atollic 中,可以在编译之前关闭带有-O0标志的GCC优化。问题是,对于ISR内外使用的变量是否绝对有必要使用volatile限定符,即使像这样关闭优化时也是如此。
发布于 2020-07-07 10:00:52
在禁用优化之后,似乎不太可能需要volatile。但是,即使在O0中,编译器也可以进行简单的优化。例如,它可能会删除它可以删除的部分代码,不会被使用。因此,不使用volatile将是一场赌博。我看不出为什么不应该使用volatile,尤其是在没有优化的情况下运行时。
此外,无论优化级别如何,变量都可以在带有数据缓存的高端MCU上预取缓存。然而,volatile是否解决/应该解决这个问题还有待商榷。
发布于 2020-07-07 10:50:37
程序必须是为人们阅读而编写的,而只为机器执行而编写。
我想我们可以引用这句话。假设有一种情况(正如user253751提到的),您从每个变量中删除关键字volatile,因为这里启用了优化。然后,几个月后,您必须启动优化。你能想象发生了什么灾难吗?
此外,我还使用代码,在裸金属固件之上有一个抽象层,当变量在这些层之间共享内存空间时,我们使用volatile关键字,以确保使用正确的值。因此,这是易失性的另一种用法,不仅在ISRs中,这意味着很难将其更改,并确保一切正常。
调试变量应该是volatile的代码并不难,但是像这样的but似乎发生了一些神奇的事情,而且您也不知道为什么,因为例如,在10k的代码执行中,就发生了一些事情。
摘要:在关闭优化时,对于删除volatile关键字并没有严格的“禁令”,但对我来说,编程实践非常糟糕。
发布于 2020-07-07 13:25:58
我非常清楚,在处理具有中断服务例程( ISR )的程序时,使用变量的
volatile限定符至关重要,以便防止编译器优化在ISR和主线程中使用的变量。
实际上,您应该记住,volatile是,而不是,是一个同步结构。
它不强制设置任何障碍,也不会阻止与其他非易失性变量重新排序。它只告诉编译器不要对相对于其他易失性变量的特定访问重新排序--即使这样也不能保证这些变量不会被CPU重新排序。
这就是为什么GCC很乐意编译这的原因
volatile int value = 0;
int old_value = 0;
void swap(void)
{
old_value = value;
value = 100;
}这样的事情:
// value will be changed before old_value
mov eax, value
mov value, 100
mov old_value, eax因此,如果您的函数使用volatile来发出诸如“到目前为止其他一切都已写入”之类的信号,请记住,这可能是不够的。
此外,如果您是为多核微控制器编写,重新排序的指令由CPU将使volatile关键字完全无用。
换句话说,处理同步的正确方法是使用C标准告诉您使用的东西,即库。这个库提供的结构保证是可移植的,并发出所有必要的编译器和CPU屏障。
https://stackoverflow.com/questions/62772301
复制相似问题