Application C language keyword volatile in development

volatile

1.volatile role

volatile because the intention is much faster than accessing memory access register unit, so the compiler generally as "variable" to reduce access memory optimization, but there might read dirty data. When volatile declaration required variable values, the system memory is always re-read the data from it, even if it had preceding instruction just read data therefrom. Precisely, it is that this keyword encounters a variable declaration, the compiler of the variable access code will no longer be optimized, which can provide stable access to the specific address; if you do not use valatile, the compiler will be declared the statement to be optimized.

Simple put, is: volatile keyword affect the outcome of the compiler, represented by a variable volatile declare the variables may change at any time, associated with the variable operation, do not compile optimized to avoid mistakes
1> tells compiler can not do any optimization
2> using volatile variables defined outside the program is changed, each time must be read from memory, but can not be reused in the backup cache or registers.

2. The main scenario

1> variable detected by other programs in the interrupt service routine changes need to add volatile;
static int i=0;
int main(void)
{
    while (1){
  if (i) dosomething();
 }
/* Interrupt service routine. */
void ISR_2(void)
{
     i=1;
}

Intended program is to ISR_2 interrupt occurs, called the main function dosomething function, however, because the compiler determines not modified i in the main function inside, and therefore may be executed only once read from i to a register operation, and each of second only to determine if the use of "i copy" of the register inside, resulting in dosomething will never be called. If the variable is modified plus volatile, the compiler reads and writes variables to ensure that this will not be optimized (positive execution). In this example i should thus described.

2> multitasking environment shared among tasks is a sign should be added volatile

When the two threads to be used in a particular variable and the value of the variable will be changed, it should be declared with volatile, the key role is to prevent the compiler to optimize the variable from memory into the CPU registers. If the variable is loaded into the register, then two threads there is a possibility to use variables in memory, a register of variables, which can cause errors in the program execution. volatile does mean that each time the operation of the compiler variables must actually removed from memory, the register values ​​instead of using the already existing

volatile BOOL bStop = FALSE; //bStop 为共享全局变量
(1) 在一个线程中:  
  while( !bStop ) { ... }  
  bStop = FALSE;  
  return;    

(2) 在另外一个线程中,要终止上面的线程循环:  
  bStop = TRUE;  
  while( bStop ); 

Wait for the thread to terminate the above, if you do not use volatile bStop stated, then this cycle will be an infinite loop, because bStop has been read into the register, the register value bStop never become FALSE, coupled with volatile, program execution when reading from memory each time the value of bStop, it will not cycle of death.

3> generally memory mapped registers also add hardware voliate, because each may have its read a different meaning.
int *output = (unsigned int *)0xff800000;//定义一个IO端口;
int init(void)
{
      int i;
      for(i=0;i< 10;i++){
         *output = i;
        }
}

After a compiler optimization, the compiler front of circulation for a long time considered nonsense, no effect on the final result, because in the end this is just the output pointer with $ 9, you give the compiler to compile the final results compiled code is equivalent to:

int init(void)
{
     *output = 9;
}

If you process this external device must be initialized in the same order as the code above its assignment, apparently optimization process can not achieve their goals. On the other hand if you do not operate the port repeatedly written on it, but repeatedly read operation, the result is the same, the compiler optimized, maybe read your code to this address only once. However, from the point of view of the code is no problem. At this time in respect of the use of volatile inform the compiler that the variable is an unstable, not to optimize the experience this time variable.

E.g:

volatile int *output=(volatile unsigned int *)0xff800000;//定义一个I/O端口

3. Some Problems

1> parameter can be either a const can also be volatile?
Possible, such as read only status register. It is volatile because it may change unexpectedly. It is const because the program should not attempt to modify it.
2> a pointer can be volatile?
Can, when an interrupt service routine modifies a pointer to a buffer.

4.volatile nature:

1> compiler optimizations
in this thread, when reading a variable, in order to improve the access speed, the compiler optimization variables may be read into a first register; time later, and then take a variable value, directly from the register value; when the variable value is changed in this thread, will also copy the new value to the variable register, for consistency.

When the variable is changed due to the other threads and other values, the value of the register is not changed accordingly, resulting in a variable value and the actual value read inconsistent application.
When this register in other threads, etc. due to change the value, the value of the original variable is not changed, resulting in value and the actual value of the variable application reads inconsistent.

2> volatile should be interpreted as "direct access to raw memory address" more appropriate, this interpretation "volatile" It was a bit misleading.

5. What is wrong with the following function:

int square(volatile int *ptr)
{
 return *ptr * *ptr;
}

The purpose of the program is to return the pointer ptr points to a value of the square, but because ptr parameter points to a volatile, the compiler will generate code similar to the following:

int square(volatile int *ptr)
{
 int a,b;
 a = *ptr;
 b = *ptr;
 return a * b;
}

Since the value of the * ptr may be unexpectedly changed, and therefore a and b may be different. As a result, this code could return than you would expect squared value! The correct code is as follows:

long square(volatile int *ptr)
{
 int a;
 a = *ptr;
 return a * a;
}

Note: frequent use of volatile is likely to increase code size and reduce performance, and therefore rational use volatile.





Guess you like

Origin www.cnblogs.com/DaLinY/p/656bed417d38156a9255b53b0696f3d7.html