What is the use of __IO & static keywords in C?
Sophia Terry
I was checking out some code written for STM32F microcontroller and I found these keywords used before initializing a variable. I would like to know what is the significance of using this "__IO" & "static" keywords?
The line of code was given like that:
static __IO uint32_t sysTickCounter; 9 1 Answer
__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 _mainIf, 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 _mainstatic
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
#included 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
volatileis for accessing peripheral registers (although you would use a pointer in that case).