Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely convert/copy volatile variable?

Tags:

c

volatile

volatile char* sevensegment_char_value;

void ss_load_char(volatile char *digits) {
    ...
    int l=strlen(digits);
    ...
 }

 ss_load_char(sevensegment_char_value);

In the above example I've got warning from avr-gcc compiler

Warning 6   passing argument 1 of 'strlen' discards 'volatile' qualifier from pointer target type [enabled by default]

So I have to somehow copy the value from volatile to non-volatile var? What is the safe workaround?

like image 328
Pablo Avatar asked Nov 29 '12 12:11

Pablo


People also ask

What happens when a variable is declared as volatile?

Volatile is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time-without any action being taken by the code the compiler finds nearby.

Can you cast to volatile?

A cast of a non-volatile value to a volatile type has no effect. To access a non-volatile object using volatile semantics, its address must be cast to a pointer-to-volatile and then the access must be made through that pointer.

Why do we declare variable as volatile?

volatile is a keyword that must be used when declaring any variable that will reference a device register. If this is not done, the compile-time optimizer might optimize important accesses away.


2 Answers

There is no such thing like a "built in" Workaround in C. Volatile tells the compiler, that the contents of a variable (or in your case the memory the variable is pointing at) can change without the compiler noticing it and forces the compiler to read the data direct from the data bus rather than using a possibly existing copy in the registers. Therefore the volatile keyword is used to avoid odd behaviour induced through compiler optimizations. (I can explain this further if you like)

In your case, you have a character buffer declared as volatile. If your program changes the contents of this buffer in a different context like an ISR for example, you have to implement sort of a synchronisation mechanism (like disabling the particular interrupt or so) to avoid inconsistency of data. After aquiring the "lock" (disabling the interrupt) you can copy the data byte by byte to a local (non-volatile) buffer and work on this buffer for the rest of the routine.

If the buffer will not change "outside" of the context of your read accesses I suggest to omit the volatile keyword as there is no use for it.

To judge the correct solution, a little bit more information about your exact use case would be needed.

like image 189
junix Avatar answered Oct 07 '22 11:10

junix


Standard library routines aren't designed to work on volatile objects. The simplest solution is to read the volatile memory into normal memory before operating on it:

void ss_load_char(volatile char *digits) {
  char buf[BUFSIZE];
  int i = 0;
  for (i = 0; i < BUFSIZE; ++i) {
    buf[i] = digits[i];
  }
  int l=strlen(buf);
  ...
}

Here BUFSIZE is the size of the area of volatile memory.

Depending on how the volatile memory is configured, there may be routines you are supposed to call to copy out the contents, rather than just using a loop. Note that memcpy won't work as it is not designed to work with volatile memory.

like image 42
ecatmur Avatar answered Oct 07 '22 10:10

ecatmur