14

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.

rayray
  • 301
  • 2
  • 3
  • 8

4 Answers4

24

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 :

  1. Typecast 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,

  1. Make value_UInt16 a volatile field as well

Important note:

You tagged C++ and C but :

  • In C++, this is an error (invalid conversion), example here.
  • In C, it is a warning (the one you showed)
quantdev
  • 23,517
  • 5
  • 55
  • 88
  • Thanks quantdev. You assumed correctly, value_UInt16 is non volatile and when I declare it as a volatile by entering; volatile value_UInt16; a line before the if statement I get the following warning; type defaults to 'int' in declaration of 'value_UInt16'. – rayray Jul 03 '14 at 17:39
1

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.

Falias
  • 636
  • 4
  • 7
1

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.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
0

I opened the declaration of data_value.value_UInt16 to find more information about the type since the issue was the types it accepted wasn't the type I set it equal to. Turns out it only accepts data types that were been predefined in another header file.

To fix it, I simply looked at the types that it would accept and inserted one of those as seen below;

   typedef enum 
   {
     UA_TYPE_Invalid         = 0,  /**< Invalid type */
     UA_TYPE_Boolean         = 1,  /**< Boolean */
     UA_TYPE_SByte           = 2,  /**< signed byte */
     UA_TYPE_Byte            = 3,  /**< unsigned byte */
     UA_TYPE_Int16           = 4,  /**< signed 16 bit integer */
     UA_TYPE_UInt16          = 5,  /**< unsigned 16 bit integer */
     UA_TYPE_Int32           = 6,  /**< signed 32 bit integer */
     UA_TYPE_UInt32          = 7,  /**< unsigned 32 bit integer */
     UA_TYPE_Int64           = 8,  /**< signed 64 bit integer */
     UA_TYPE_UInt64          = 9,  /**< unsigned 64 bit integer */
     UA_TYPE_Float           = 10, /**< 32 bit single precision floating point */
     UA_TYPE_Double          = 11, /**< 64 bit double precision floating point */
     UA_TYPE_String          = 12, /**< UTF8 string */
     UA_TYPE_DateTime        = 13, /**< 64 bit signed integer containing date and time */
     UA_TYPE_Guid            = 14, /**< 16 byte long array of unsigned bytes */
     UA_TYPE_ByteString      = 15, /**< variable length array of unsigned bytes */
     UA_TYPE_XmlElement      = 16, /**< UTF8 string containing XML */
     UA_TYPE_NodeId          = 17, /**< Not supported for application */
     UA_TYPE_ExpandedNodeId  = 18, /**< Not supported for application */
     UA_TYPE_StatusCode      = 19, /**< Not supported for application */
     UA_TYPE_QualifiedName   = 20, /**< Not supported for application */
     UA_TYPE_LocalizedText   = 21, /**< Not supported for application */
     UA_TYPE_ExtensionObject = 22, /**< Not supported for application */
     UA_TYPE_DataValue       = 23, /**< Not supported for application */
     UA_TYPE_Variant         = 24, /**< Not supported for application */
     UA_TYPE_Range           = 884,/**< Not supported for application */
     UA_TYPE_EUInformation   = 887 /**< Not supported for application */
   } UA_Value_type_t;

    uint16_t server_value   = 0;

    if (value_type == UA_TYPE_UInt16)
    {
    data_value.value_UInt16 = &server_value;
    source_timestamp = my_variables[handle - 1].source_timestamp;
    status_code = my_variables[handle - 1].status_code;

    ADC_SoftwareStartConv(ADC3);
rayray
  • 301
  • 2
  • 3
  • 8