I have been working with a microprocessor to read the temperature from a sensor and have run into the following warning regarding a volatile declaration.
"assignment discards 'volatile' qualifier from pointer target type"
I was receiving a single value for the temperature and the value wouldn't change until I restarted the program.
volatile uint16_t temp_value = 0;
if (value_type == UA_TYPE_UInt16)
{
data_value.value_UInt16 = &temp_value; // warning*******
switch (handle)
{
case HANDLE_TEMP1:
temp_value = ADC_GetConversionValue(ADC3);
break;
}
}
After searching through stack overflow I realized declaring my temp_value as volatile will signify that temp_value will change values. What I could not find on this site was why I can't use a volatile unsigned integer for data_value.value_UInt16
I am storing the ADC value in a server and would like to access the updated value at any time. Is there an additional typecast I should have that points to temp_value? Thanks for reading.
Your volatile uint16_t temp_value
says to the compiler "my variable temp_value
may be changed by things that you are not aware of" (particularly, other processes accessing and writing to the memory used to store the variable). Among other things, it prevents the compiler from doing certain optimizations.
When you do :
data_value.value_UInt16 = &temp_value;
(I assume that value_UInt16
is non volatile)
You assign the address of your volatile
to a non volatile field : the compiler warns you that it is allowed to make optimizations on it, ignoring that the pointee object might be changed "by things it is not aware of".
Solutions :
data_value.value_UInt16 = *(uint16_t*)&temp_value
, saying to the compiler : "I know what I'm doing, I know that I am ignoring the volatile qualifier here".Or,
value_UInt16
a volatile
field as wellImportant note:
You tagged C++ and C but :
You should add the embedded
tag.
Unless you can have the linker assign the variable to a specific address, the hardware should always be accessed via pointer or reference:
// Using linker notation:
volatile uint16_t temperature @ "temperature_segment";
// Using pointer, pointer to a volatile uint16_t
uint16_t volatile * temperature = 0x44000025; // Example address
// Because the variable is a pointer to a volatile value,
// a "snapshot" copy should be made before using.
uint16_t snapshot_temperature = *temperature;
if (snapshot_temperature > 100 /* celsius */)
{
SYSTEM_FAILURE(TEMPERATURE_OVERHEATING);
}
The volatile
keyword instructs the compiler to refrain from optimizing code related to the temperature variable. Also since the target value (hardware register) may change, a snapshot copy should be made before making any comparisons.
Volatile works in mostly the same the way that const does. This code
const int i = 1;
int* iPtr = &i; //error
is invalid because it tries to assign a pointer to const to a pointer to non-const. Similarly,
volatile int i = 1;
int* iPtr = &i; //error
is invalid for the same reason, except with volatile. Though your example is incomplete, this is what the issue appears to be.
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