Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

passing argument 2 of 'memcpy' discards 'volatile' qualifier from pointer target type

Tags:

c

embedded

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?

like image 775
Hani_l Avatar asked Apr 19 '16 20:04

Hani_l


2 Answers

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.

like image 106
R.. GitHub STOP HELPING ICE Avatar answered Nov 16 '22 02:11

R.. GitHub STOP HELPING ICE


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.

like image 33
too honest for this site Avatar answered Nov 16 '22 00:11

too honest for this site