volatile与const的使用
#define __I volatile const /*!< defines 'read only' permissions */
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
他人文章精髓点
volatile:使用该关键字修饰变量时,则不从cache读取值,而是从变量地址处读取值,防止因其他地方(如硬件引脚、程序其他地方)修改变量值后导致读取变量值不准确的问题。
volatile: 表明变量能被后台程序修改
体会
volatile const : 状态随时会被外界改变,但是CPU内部不能改变这个值状态,也就是
read only
使用场景
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
代码举例
一个例子:
int main(void) { int b; volatile int* a = (int*)0x30000000; b = (*a) * (*a); return b; }
汇编后
mov r3, #805306368 ldr r2, [r3] ① ldr r0, [r3] ② mul r0, r2, r0 bx lr
程序本意是要计算平方。如果这段代码在运行至①这行汇编时,被调度开了,过了一阵调度回来继续运行②行,此时完全有可能 R2 != R0。那么计算出来的结果R0必然不等于那个平方值。
不加volatile
关键字,IAR优化等级开Medium
汇编后的结果
// 1 int main(void)
// 2 {
// 3 int b;
// 4 int* a = (int*)0x30000000;
// 5
// 6 b = (*a) * (*a);
// 7
// 8 return b;
main:
MOV R0,#+805306368
LDR R0,[R0, #+0]
MULS R0,R0,R0
BX LR ;; return
// 9 }
【注】:IAR优化等级开Low
时的效果,与加volatile
关键字相同。