C中的__IO和静态关键字有什么用?

naa*_*sif 3 c microcontroller static stm32 keyword

我正在查看为STM32F微控制器编写的一些代码,我在初始化变量之前发现了这些关键字.我想知道使用这个" __IO "和" 静态 "关键字有什么意义?

代码行是这样给出的:

static   __IO   uint32_t   sysTickCounter; 
Run Code Online (Sandbox Code Playgroud)

Dav*_*ins 7

__IO/volatile

欢迎来到该网站.__IO不是C关键字.__IO是一个宏volatile- 在STM32标准外设库头文件中定义.例如,在core_cm4.h(可能在CMSIS子文件夹中),你会发现

#define     __IO    volatile
Run Code Online (Sandbox Code Playgroud)

(如果使用gcc's -E选项仅使用预处理器阶段,则可以看到宏的扩展.)

volatile关键字,反过来,通常施加到一个变量,以防止编译器"优化出来".这在嵌入式系统中很有用 - 可能在中断中使用变量 - 编译器优化可能会导致问题.

简短的例子......

int main(void) {
    int ms = 0;

    ms++;
    while (1);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是生成的程序集(使用sdccPIC12f629目标的编译器).如您所见,ms变量已经"优化".

_main:
; 2 exit points
_00113_DS_:
;   .line   18; "main.c"    while (1)
    GOTO    _00113_DS_
    RETURN
; exit point of _main
Run Code Online (Sandbox Code Playgroud)

另一方面,如果我们将变量声明为volatile......

volatile int ms = 0;
ms++;
// etc.
Run Code Online (Sandbox Code Playgroud)

相关说明保留:

_main:
; 2 exit points
;   .line   16; "main.c"    volatile int ms = 0;
    CLRF    _main_ms_1_5
    CLRF    (_main_ms_1_5 + 1)
;   .line   19; "main.c"    ms++;
    INCF    _main_ms_1_5,F
    BTFSC   STATUS,2
    INCF    (_main_ms_1_5 + 1),F
_00113_DS_:
;   .line   21; "main.c"    while (1)
    GOTO    _00113_DS_
    RETURN
; exit point of _main
Run Code Online (Sandbox Code Playgroud)

static

static关键字的效果取决于声明变量的范围.

  • 文件范围 - 变量的范围仅限于当前编译单元(通常是文件加上其#included头文件).
  • 块范围(例如,在函数内) - 变量在程序的持续时间内保留在内存中.(对于函数,这意味着在对函数的后续调用之间保留变量的值.)

笔记

  • 正如vlk在注释中指出的那样,另一个重要用途volatile是访问外设寄存器(尽管在这种情况下你会使用指针).

  • 一个很好的答案,但这不仅用于中断,而且主要目的是定义映射到MCU具有外围设备和系统寄存器的地址(例如GPIO,SYSTICK,RCC等)的变量,因为无法访问这些寄存器。优化。 (2认同)
  • 大卫。它不会阻止任何优化。`volatile` 只保证变量每次使用时都会从其存储位置读取,并在每次更改后存储。 https://godbolt.org/g/hgv4hD (2认同)
  • `volatile` 对于任何不受编译器完全控制的东西来说都是*必不可少的*。编译器不知道是否/何时/是否曾经执行过使用变量的 ISR,因此可能看不到访问其当前值的相关性。内存映射 IO 也不受编译器控制:写入 IO 位置将对硬件产生影响,即使编译器认为这无关紧要,因为该值永远不会被读回。尽管软件没有写入该位置,但每次读取 IO 位置可能会产生不同的结果。这就是为什么需要 `volatile` 的原因。 (2认同)