Look at code 1 and code 2, below. When you enable the optimization in the IDE or compiler, it will produce an assembly code like below.
Because its value cannot change. The result is the infinite loop labeled. As a result, the assembly code that is generated for loop. In the following case, we need to use the volatile variable. If we do not use volatile qualifier the following problems may arise:. The above code sets the value in var to 1. It then starts to poll that value in a loop until the value of var becomes The compiler will then replace the function body with an infinite loop, similar to this:.
Include the keyword volatile before or after the data type in the variable. This type of pointer is very rarely used in embedded programming. Most embedded systems consist of a handful of peripherals devices.
The value of the registers of these peripheral devices may change asynchronously. What we need to do is to poll this status register until it becomes non-zero.
A typical optimizing compiler if optimization is turned ON will optimize the above code as below:. What the assumes while optimizing the code is easy to interpret. As the value stored at this address would initially be zero and it is never updated, this loop goes forever. The code beyond this point would never get executed and the system would go into a hanged state. So, what we essentially need to do here is to force the compiler to update the value stored at the address 0x whenever it does the comparison operation.
The volatile qualifier does the trick for us. Look at the code snippet below:. The assembly for the above code should be:. Subtler problems tend to arise with registers that have special properties. For instance, a lot of peripherals contain registers that are cleared simply by reading them.
Extra or fewer reads than you are intending can cause quite unexpected results in these cases. Sometimes we check a global variable in the main code and the variable is only changed by the interrupt service routine.
This code may work with optimization turned off. But almost all the optimizing compiler would optimize this code to something which is not intended here. So the compiler assumes the expression! Consequently, the system would never be able to exit the while loop. All the code after the while loop may even be removed by the optimizer or never be reached by the program. Some compiler may throw a warning, or some may not, depends completely on the particular compiler. Note: If any object qualifies by both volatile and const, the value of the object could not be altered by its own program, but could be altered by another process.
There is a lot of places where we need to use volatile and const together, in the below section, I am describing some important places where we have to require volatile and const together. One of the great use of volatile and const keyword together is at the time of accessing the GPIO registers. In that situation, volatile plays an important role and ensures that the compiler always read the value from the GPIO address and avoid to make any assumption.
After using the volatile keyword, you will get the proper value whenever you are accessing the ports but still here is one more problem because the pointer is not const type so it might be your program change the pointing address of the pointer. So we have to create a constant pointer with a volatile keyword. There is a lot of embedded software that can be calibrated at runtime. The const and volatile is useful when the flash is used as storage for a variable, if you reprogram this flash in runtime, the value of the variable will be updated by the new value.
There are a lot of registers which are used to reflect the status of the device at the different stage of the hardware. These registers are read-only types and their value changes by asynchronously by the other events. If you want to access these register, you have to use const and volatile together with pointers I have already explained at the beginning of the article. Here is how you would rewrite the example, making use of const and volatile to get what you want.
The rules about mixing volatile and regular types resemble those for const. A pointer to a volatile object can be assigned the address of a regular object with safety, but it is dangerous and needs a cast to take the address of a volatile object and put it into a pointer to a regular object.
Using such a derived pointer results in undefined behaviour. If an array, union or structure is declared with const or volatile attributes, then all of the members take on that attribute too.
This makes sense when you think about it—how could a member of a const structure be modifiable? That means that an alternative rewrite of the last example would be possible. Instead of declaring the device registers to be volatile in the structure, the pointer could have been declared to point to a volatile structure instead, like this:.
Since dvp points to a volatile object, it not permitted to optimize references through the pointer. Our feeling is that, although this would work, it is bad style.
The volatile declaration belongs in the structure: it is the device registers which are volatile and that is where the information should be kept; it reinforces the fact for a human reader.
So, for any object likely to be subject to modification either by hardware or asynchronous interrupt service routines, the volatile type qualifier is important. Now, just when you thought that you understood all that, here comes the final twist. A declaration like this:. A later declaration like this. Look at it this way round, which perhaps makes the situation more clear the two declarations are the same in their effect :.
If you do want to get a shorthand way of attaching a qualifier to another type, you can use typedef to do it:. To discuss this is any depth would take us beyond the scope of this book, but we can at least outline some of the issues. It is essential to make it volatile because of the asynchronous updates to it, and it is marked const because it should not be changed by anything other than the interrupt routine. If the program accesses it like this:. So when in the program ,we want to read the value of this varible , it should read the actual value with out any optimisation.
For this reason ,the variable can be declared as volatile too. But isnt like the constant variables will be stored by in ROM read only memory. Then how can the some process other than the code can change the value of const volatile.
Profile Answers by YanChenChi. Interrupt status register should be changed by the program. For example, if status register is updated by the hardware for some kind of interrupt. In our program we read the status register to service the interrupt using some ISR, but once the servicing is done, we should change the status register, other wise if next time we get the interrupt then we may not know whether the interrupt is new or the old one which we had already serviced.
0コメント