Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is is necessary to use volatile when writing to hardware in C or C++?

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.

like image 586
Nigel Davies Avatar asked Oct 15 '20 15:10

Nigel Davies


People also ask

When should I use volatile in C?

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.

What does volatile mean in C programming?

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.

Is volatile thread safe C?

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.

Where volatile variables are stored 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.


2 Answers

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.

like image 60
old_timer Avatar answered Oct 18 '22 17:10

old_timer


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:

  1. Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine.
  2. 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.
  3. 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.

like image 44
eerorika Avatar answered Oct 18 '22 17:10

eerorika