C标准规定,当变量的值可能会在程序正常执行流程之外更改时,应在变量的定义中使用volatile关键字。
如果在正常执行流程中更改(写入)了全局变量,并且仅在该正常流程之外(在中断中)读取。这个变量需要可变吗?又为什么呢?
我读到了volatile内存映射硬件寄存器,ISR和多线程程序中C 关键字的用法.
1)注册
uint8_t volatile * pReg;
while (*pReg == 0) { // do sth } // pReg point to status register
Run Code Online (Sandbox Code Playgroud)
2)ISR
int volatile flag = 0;
int main()
{
while(!flag) { // do sth }
}
interrupt void rx_isr(void)
{
//change flag
}
Run Code Online (Sandbox Code Playgroud)
3)多线程
int volatile var = 0;
int task1()
{
while (var == 0) { // do sth }
}
int task2()
{
var++;
}
Run Code Online (Sandbox Code Playgroud)
我可以看出为什么编译器可以错误地优化while以防万一1)如果volatile不存在,'因为变量是由硬件进行的,编译器可能看不到代码所做的变量的任何变化. …
我目前正在使用 Atmel AVR 微控制器 (gcc),但希望答案一般适用于微控制器世界,即通常是单线程但带有中断。
我知道volatile在访问可以在 ISR 中修改的变量时如何在 C 代码中使用。例如:
uint8_t g_pushIndex = 0;
volatile uint8_t g_popIndex = 0;
uint8_t g_values[QUEUE_SIZE];
void waitForEmptyQueue()
{
bool isQueueEmpty = false;
while (!isQueueEmpty)
{
// Disable interrupts to ensure atomic access.
cli();
isQueueEmpty = (g_pushIndex == g_popIndex);
sei();
}
}
ISR(USART_UDRE_vect) // some interrupt routine
{
// Interrupts are disabled here.
if (g_pushIndex == g_popIndex)
{
usart::stopTransfer();
}
else
{
uint8_t value = g_values[g_popIndex++];
g_popIndex &= MASK;
usart::transmit(value);
}
}
Run Code Online (Sandbox Code Playgroud)
因为 …