__IO
/ volatile
__IO
is not a C keyword. __IO
is a macro for volatile
- defined in STM32 standard peripheral library header files. E.g., in core_cm4.h
(might be in a CMSIS
sub-folder), you will find
#define __IO volatile
(If you use gcc
's -E
option to use only the pre-processor stage, you can see the macro's expansion.)
The volatile
keyword, in turn, is often applied to a variable to prevent the compiler from 'optimizing it out'. This is useful in embedded systems - where a variable might be used within an interrupt - and compiler optimizations could cause problems.
Short example ...
int main(void) {
int ms = 0;
ms++;
while (1);
return 0;
}
Here is the generated assembly (using sdcc
compiler for PIC12f629 target). As you can see, the ms
variable has been 'optimized out'.
_main:
; 2 exit points
_00113_DS_:
; .line 18; "main.c" while (1)
GOTO _00113_DS_
RETURN
; exit point of _main
If, on the other hand, we declare the variable as volatile
...
volatile int ms = 0;
ms++;
// etc.
the relevant instructions are preserved:
_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
static
The effect of the static
keyword depends on the scope in which the variable is declared.
- file scope - the variable's scope is limited to the current compilation unit (usually a file plus its
#include
d header files).
- block scope (e.g. within a function) - The variable is preserved in memory for the duration of the program. (For a function, this means that the value of the variable is preserved between subsequent calls to the function.)
Notes
- As vlk pointed out in a comment, another important use of
volatile
is for accessing peripheral registers (although you would use a pointer in that case).