Detailed explanation of __I, __O, __IO in embedded C language

Introduction to __I, __O, __IO in Embedded C Language

The definition of __I, __O, __IO in the code

这是ST库里面的宏定义,定义如下:  
#define __I volatile const  /*!< defines 'read only' permissions*/
#define  __O  volatile      /*  !< defines 'write only' permissions  */
#define __IO  volatile      /* !< defines 'read / write' permissions */

 

Two ways to change the value of a variable

 

C compiler optimization mechanism

 

When continuously changing the value of a variable, the C compiler will optimize it to:

 

The compiler will think that such frequent "continuous" changes are meaningless and are "a precursor to an infinite loop", so they must be optimized.

Function of __I

As the name suggests, the meaning of __I is to limit the variable to the "read-only state". The "read-only state" means that "the value of the variable can only be changed by reading the value of the register, and it can be changed continuously, but it cannot be artificially changed. Change the variables in the program".

In fact, this is the meaning of "embedded input", we only allow to change the variable by reading the value of the peripheral register, and it is not allowed to artificially change the value of the variable in the program.

 

Function of __O

As the name implies, the meaning of __O is to limit the variable to the "output state". The essence of the output state different from the input state is that the output state removes the const constant restriction on the variable, so that we can use any method (register/manual modification) To change the attributes (value and data type) of the variable and then process the variable.

 

Function of __IO

As the name implies, __IO refers to "the variable can be input and output operations-read/write operations". Its function is the same as __O.

Deep understanding of embedded

What is the meaning of the volatile symbol?

The Volatile keyword is mainly to declare those "variables that are frequently changed". Frequently changed situations and each change is meaningful. The situation is as follows:

1. Variables modified in the interrupt service program for detection by other programs need to add volatile;

2. The flags shared between tasks in a multitasking environment should be volatile;

3. The memory-mapped hardware register usually also needs to add volatile description, because each read and write to it may have a different meaning.

What is the meaning of the Const symbol?

The const keyword in embedded has the same meaning and function as the const keyword in ordinary C language, and both are used to limit variables that cannot be changed in the program.

Why a variable can be both volatile and const type, don't these two conflict?

Const mainly restricts "cannot be artificially changed in the program", while volatile restricts "variables can be frequently changed by registers". For different objects, the meaning is not contradictory.

For example: volatile indicates that the object may have unexpected changes, such as reading the temperature value from a register, it will continue to change, and const indicates that the object cannot be changed by the program, that is, it cannot be changed in the program. It assigns a value, the two are not contradictory.

If a variable is changed frequently, what kind of optimization will the C compiler make?

The purpose of this code is to return the square of the value pointed to by the pointer *ptr, but since *ptr points to a volatile parameter, the compiler will generate code similar to the following:

int square(volatile int *ptr)    
{     
    int a,b;     
    a = *ptr;    
    b = *ptr;    
    return a * b;     
// 中间*ptr的值可能会被寄存器所改变进而导致a,b两个变量不同,得不到a^2这样的结果
}    

 

Because the value of *ptr may be changed unexpectedly, a and b may be different. For example, *ptr=1, and then *ptr=2, which will cause the two variables a and b to be different. As a result, this code may not return the square value you expected! The correct code is as follows:

int square(int *ptr)    
{     
    int a,b;     
    a = *ptr;    
    b = *ptr;    
    return a * b;     
// 这样即使*ptr在函数体内发生相应改变编译器也会进行优化使得*ptr在函数内不会发生改变,最终a,b值相同,这也就是我们所期望的a^2
}   

 

Such a return value will always be the square of a fixed value, which is in line with the original intention.

Guess you like

Origin blog.csdn.net/weixin_45590473/article/details/109228449