我已经在这里阅读了几十个关于使用volatile的问题和答案,我为发布另一个而道歉但我不认为我已经看到了我正在寻找的东西
我有一个用C ++编写的Arduino微控制器库。我有一个填充缓冲区的ISR,当它完成时,它会设置一个标志,让外界知道有可用的数据。我有缓冲区,一个告诉缓冲区中有多少字节的变量,以及告诉世界缓冲区有数据的标志。一旦我设置了#34;我已经完成填充缓冲区"在ISR中,ISR将永远不会再次更改缓冲区或其长度,直到/除非我重新启用。
通常我已经将标志,缓冲区和长度值都声明为volatile,因为这是你在ISR例程中应该做的事情。
然而,一旦它充满,我会对该缓冲区进行大量处理,这意味着我会在一些潜在的优化中欺骗自己。在我的ISR之外,如果我的代码类似于
if (flag== FINISHED) {
disable_my_ISR ();
/*do a bunch of stuff with the buffer*/
reenable_my_ISR();
}
然后理论上我认为我不需要将缓冲区作为volatile。那是对的吗?正如我所说的那样,我的关注是我的#"用缓冲区做了很多事情"没有得到优化,因为缓冲区是易失性的。
我在这个论坛的任何地方看到的唯一其他答案是this one但是我不确定这种情况是否真的相同。
答案 0 :(得分:2)
当您将某些内容标记为volatile
时,您说它的值可能会在代码中的写入/读取之间发生变化。这正是ISR访问变量时可能发生的情况,因此您需要volatile
。
您的ISR与主要代码之间共享的任何变量都应为volatile
。您的代码可能无法标记所有内容,但最终会回来咬你。
然后理论上我认为我不需要将缓冲区作为volatile。
不,如果主代码和ISR都使用了缓冲区,则需要将其标记为volatile
。我想你可能会担心错过优化问题。您始终可以将volatile
数组复制到普通数组中,进行处理,然后计算差异。
答案 1 :(得分:2)
甚至没有内存写入可以通过优化延迟 - 如果您的缓冲区未声明volatile
,您的编译器可能会使用它删除任何代码。举个例子:
int myBuffer[5] = {0};
if(flag == FINISHED) {
printf("%d", myBuffer[0]);
}
这可能总是打印0
,即使您的ISR更改了缓冲区的值,因为编译器不知道ISR如何更改程序流并因此假设myBuffer[0]
将使用时为0。