开发中需要使用到volatile的情况
变量读写操作是 将变量写进一个内存,然后在内存中加减,最后再把内存里的值赋值给变量。如下图:变量bCanUse进行减一操作。
1.首先bCanUse写入一个叫R0的寄存器
2.在R0中减一
3.将R0的值写入bCanUse
在多个函数中:
函数是有顺序的,要也就是在一个函数会彻底执行完,就是内存的值会最终回给变量,函数B就会从这个变量读取到另一个内存,这个内存的值是正确的。
在freertos的多线程或者多任务中(需要volatile):
函数是轮询执行的,变量x假如在函数A中执行,虽然在内存中加减,但是可能执行一半就到函数B去执行,而变量x的值并没有改变,因为函数A没有执行完(内存的值没有赋值到变量x,也就步骤三没有执行完成)。那么函数B用到的变量x的值还是最初的值。
1. 硬件寄存器访问
硬件寄存器的值可能被硬件设备修改,而编译器无法感知这种修改。因此,访问硬件寄存器时需要使用 volatile
。
示例:访问 GPIO 寄存器
-
说明:
GPIO_DATA
是硬件寄存器的地址,其值可能被硬件修改。使用volatile
确保每次访问都从内存读取或写入。
2. 中断服务程序(ISR)中的变量
如果变量在 ISR 中被修改,而在主程序或其他函数中访问该变量,则需要 volatile
。
示例:ISR 修改的变量
-
说明:
flag
在 ISR 中被修改,而主程序中访问flag
。使用volatile
确保主程序每次访问flag
时都从内存读取最新值。
3. 多任务模拟中的共享变量
在裸机开发中,可能会通过状态机或轮询模拟多任务。如果多个任务共享变量,且没有使用同步机制,则需要 volatile
。
示例:多任务模拟
-
说明:
sharedVar
被两个任务共享,但没有使用同步机制。使用volatile
确保任务 2 每次访问sharedVar
时都从内存读取最新值。