Is it necessary to use volatile
when writing to hardware (say a FIFO) in C or C++. It is easy to confirm from online documentation that volatile
is necessary when reading hardware, but what about writing? I am concerned that an optimiser could eliminate a loop to write an array of values to a FIFO, and just write the last entry.
Volatile is used in C programming when we need to go and read the value stored by the pointer at the address pointed by the pointer. If you need to change anything in your code that is out of compiler reach you can use this volatile keyword before the variable for which you want to change the value.
C's volatile keyword is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time--without any action being taken by the code the compiler finds nearby.
In Java volatile creates a memory barrier when it's read, so it can be used as a threadsafe flag that a method has ended since it enforces a happens-before relationship with the code before the flag was set. This is not the case in C.
on an AVR, both will probably be stored in SRAM. On an ARM, the volatile will be stored in SRAM and the const will probably be stored in flash. This is mainly because the AVR flash is not accessible as "normal memory" to C programs, and you can't put any variables there.
Just try it.
#define MYFIFOV (*((volatile unsigned char *)0x1000000))
#define MYFIFO (*((unsigned char *)0x1000000))
void funv ( void )
{
MYFIFOV=0;
MYFIFOV=0;
}
void fun ( void )
{
MYFIFO=0;
MYFIFO=0;
}
00000000 <funv>:
0: e3a03401 mov r3, #16777216 ; 0x1000000
4: e3a02000 mov r2, #0
8: e5c32000 strb r2, [r3]
c: e5c32000 strb r2, [r3]
10: e12fff1e bx lr
00000014 <fun>:
14: e3a03401 mov r3, #16777216 ; 0x1000000
18: e3a02000 mov r2, #0
1c: e5c32000 strb r2, [r3]
20: e12fff1e bx lr
strb means store byte. Without the volatile one of the writes was optimized out. So yes without volatile, writes can be optimized out. How and when the compiler decides to do it can vary. But assume it can happen and as a result cause you problems.
Is it necessary to use volatile when writing to hardware
Typically, yes.
I am concerned that an optimiser could eliminate a loop to write an array of values to a FIFO, and just write the last entry.
Your concern is valid. An optimiser may indeed perform such elimination given a non-volatile object. In fact, if it can prove that the written value will never be read, then it might eliminate all writes entirely.
Here is quote from C++ standard (latest draft):
[intro.abstract]
The semantic descriptions in this document define a parameterized nondeterministic abstract machine. This document places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input. ...
The least requirements on a conforming implementation are:
- Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine.
- At program termination, all data written into files shall be identical to one of the possible results that execution of the program according to the abstract semantics would have produced.
- The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input.
What constitutes an interactive device is implementation-defined.
These collectively are referred to as the observable behavior of the program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With