The volatile keyword tells the compiler that an object can change outside the scope of a regular (that is, visible to the compiler) program stream. Therefore, the compiler performs this access in general . The last sentence relates to how access is performed, for example. byte read, unaligned read, etc.
Moreover, the compiler must perform all calls to such objects in the order specified by the program stream. Please note, however, that it can freely reorder calls to non-volatile objects, and the underlying equipment may think differently (the compiler may not know this).
The compiler can still optimize access to volatile objects that exist and are changed only in visible code. This is true for local variables where the address is not accepted (there may be other situations), since they cannot be reached outside the scope. This is not true for the pointers you use, because the compiler does not know about the object they are pointing to.
To discard the result of an expression without warning the compiler, simply add it to void :
volatile uint32_t *vi = ...; (void)*vi;
(If the target is read-only, add const .)
For more information on volatile access, see the gcc documentation. An implementation conforming to the C standard should provide this information.
Also note that the underlying hardware can still change the access order if the memory area does not use a strictly ordered / non-cached access policy. This is typical of peripheral registers with memory mapping. If a cache / MMU is used, it may be necessary to configure areas.
source share