I have a volatile char * start_address;
which is pointing to register sections (might change due to hardware behavior). I need to read it and I am using:
memcpy (
result_p, // starting address of destination
start_address, // starting address of source
result_len // for the length of the payload
);
I am getting this warning:
passing argument 2 of '
memcpy
' discards 'volatile
' qualifier from pointer target type
Is a safer way to read the sections or a better way to use memcpy and prevent this warning?
memcpy
is incompatible with volatile objects, and the mismatched pointer type in the function signature is helping point this out to you. memcpy
may copy in any order, in any unit size, read parts of the source multiple times, write parts of the destination multiple times, etc. On the other hand, volatile
expresses an intent that the sequence and number of accesses to the object must be exactly what they would be in the abstract machine. If you want to copy volatile
arrays, you need to write your own copy loop that looks like a naive memcpy
, and use the right volatile
type for the pointer in your loop.
General advice is not to use memcpy
for hardware peripheral registers or volatile
qualified objects in general, even iff they occupy a gap-less memory region. They typically need a specific access pattern memcpy
does not guarantee. This includes using optimised wider transfers, accessing the same location multiple times or changing the order of accesses.
For the reasons above and the following, don't even think about casting away the volatile
qualifier! The compiler might very well optimize the call away (e.g. if you have two identical calls without changes to source nor destination area in-between), combine two accesses or move the call before/after other hardware accesses.
Instead write your own copy function/loop keeping the qualifier. That will force the compiler to generate code which exactly does what you want. Remember to use the correct type for the copy pointers. Note also that the standard integer types are not a good choice for hardware registers of a specific size. Use the fixed-width types from stdint.h
like uint8_t
, uint16_t
, ... instead.
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