我知道这里有很多关于挥发性的问题,但我还没有发现这种情况的具体内容。我正在使用微控制器。 我知道当我在ISR中修改一个全局变量并在我的main函数中读取它时,我必须使用volatile限定符。我也觉得非常适合记忆障碍,竞争条件等。
但是如果我只在主函数中写入一个全局变量(中断被禁用以强制执行原子写入)并且我正在我的ISR中读取和写入它。
举一个明确的例子假设这段代码:
int state = 0;
ISR()
{
switch(state)
{
case 0:
//do something
state=nextState; //go to another state
break;
case 1:
//do something
state=nextState; //go to another state
break;
case 2:
//do something
state=nextState; //go to another state
break;
//...some more states
default:
state=0;
break;
}
}
main(void)
{
while(true)
{
//do lots of stuff
if(someCondition)
{
EnterCriticalSection(); //Disable IRQs and memorybarrier
//write to global shared variable state here!!!
state=0;
ExitCriticalSection(); //Enable IRQs again
}
}
}
所以必须在这里挥发吗?
何时,为什么? (我从来没有真正使用主要内部的值) 编译器可以优化写入状态或其他东西。 或者编译器是否可以在ISR的多个调用中保持某些寄存器中缓存的状态值?现在我保持像状态不稳定的变量,但我很好奇这是否真的有必要。
编辑: 嗯,是的,我现在明白了答案。我道歉,我应该多考虑几分钟。当我想到它时,它与(只写)硬件寄存器非常相似。当然我需要volatile来确保main方法中的写操作。
答案 0 :(得分:5)
情况与您“知道”您需要易变的情况和相关案例没有区别。
它不是关于ISR和main()
以及哪些读取和写入,而是关于不同的执行线程上下文。这些线程上下文是什么并不重要 - 语言不是线程感知的,因此不会考虑用于优化目的 - 您必须通过volatile
告诉它,无论何时数据直接在上下文之间共享。< / p>
请看看Embedded.com上的Introduction to the volatile keyword,以及When to use – and not use – the volatile keyword,其中整理了很多关于此主题的文章,包括第一篇。
答案 1 :(得分:0)
事实上,您从未在state
内使用main
的值实际上使其更有可能被优化掉。
由于state
中main
仅在state
中设置为零,因此编译器可以通过将其设置为零一次进行优化,而不再对其进行写入。
如果您希望每次someCondition
为真时确保volatile
归零,则需要使用{{1}}。