转载出处:https://blog.csdn.net/u010058695/article/details/101016142
作者:jianwang16
在开发嵌入式过程中,常会看到_IO 修饰符,这两个修饰符是在Core_cm3.h中被重定义:
/* IO definitions (access restrictions to peripheral registers) */
#ifdef __cplusplus
#define __I volatile /*!< defines 'read only' permissions */
#else
#define __I volatile const /*!< defines 'read only' permissions */
#endif
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
在嵌入式处理器中,为加速访问变量,有时变量的值是直接存储在寄存器,而当某些中断或硬件改变了内存中的值时,程序却读取的是寄存器的值,因此该值不是最新的值,在开启程序优化后,在实时处理一些任务的时候可能会导致致命错误。
例如有一下代码,我们需要对变量i进行操作,一旦开启了优化,编译器可能直接将i=1 赋值语句给优化掉。
uint8_t i;
......
i = 1;
i = 0;
......
二、用法
volatile关键字用于声明变量不被编译器优化,总是从该变量在内存中的地址处去获取数据。volatile修饰的变量,访问该数据任何时候都会直接访问该地址处内容,即通过cache提高访问速度的优化被取消 。
通常用于取绝对地址的数据:例如,要取位于0x20000000处的数据,使用*((volatile unsigned int*) 0x20000000)即可,就是内存映射机制。
具体分析:(volatile unsigned int*) 0x20000000表示把0x20000000的地址指代的数据强制转换成volatile unsigned int类型,此时可以用指针来表示例如ptr:
unsigned int * ptr = (volatile unsigned int*) 0x20000000;
通过*ptr即可取得数据。
用宏定义声明操作该变量的值:
#define VAL ((volatile unsigned int) 0x20000000)
程序中就可以用VAL这个变量操作该地址的数据。