嵌入式开发中关键字_IO 和 volatile的用法

一、描述

在开发嵌入式过程中,常会看到_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这个变量操作该地址的数据。

经验分享 程序员 微信小程序 职场和发展