Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing volatile variable as constant argument in a function

Tags:

c

embedded

arm

I'm developing and Embedded code for a Cortex-M0 MC where I declare a variable as volatile char TOS_Mins_Char[3]; to store some values during an ISR which would be periodically changed. I want to convert these characters to an integer using the atoi() function, but atoi() has its argument type as pointer to a constant string: int atoi(const char *); This give me error unless I avoid the volatile keyword in the variable declaration. (Faced similar situation in other std functions also)

  1. Is there any solution for this other than writing a user defined function?
  2. If I use const char TOS_Mins_Char[3];, will it be a problem?
  3. Is it mandatory to use the volatile keyword, what is its use in contrast to an ARM MC ?
like image 218
Arun Joe Cheriyan Avatar asked Sep 19 '16 12:09

Arun Joe Cheriyan


People also ask

Can volatile variables be constant?

Yes a C++ variable be both const and volatile. It is used in situations like a read-only hardware register, or an output of another thread. Volatile means it may be changed by something external to the current thread and Const means that you do not write to it (in that program that is using the const declaration).

Can we use const with volatile in C?

Another use for a combination of const and volatile is where you have two or more processors communicating via a shared memory area and you're coding the side of this communications that will only be reading from a shared memory buffer.

Can you have constant volatile variable Yes you can have a volatile pointer?

Yes, a pointer can be volatile if the variable that it points to can change unexpectedly even though how this might happen is not evident from the code.

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.


1 Answers

The volatile keyword is necessary to tell the compiler to reload the characters from memory for each access.

If you know the array will not be modified during the conversion, you can use a cast to silence the warning:

int value = atoi((const char*)TOS_Mins_Char);

Note that the value returned by atoi() might be completely bogus if the interrupt routine modifies the array in the middle of the conversion. You can prevent this by disabling the interrupts around accesses to the array. To minimize the duration of processing with disabled interrupts, you might want to copy the array to a local array this way:

char buf[sizeof TOS_Mins_Char];
CLI;   // whatever macro use to disable interrupts
memcpy(buf, TOS_Mins_Char, sizeof TOS_Mins_Char);
STI;   // enable interrupts
int value = atoi(buf);

The problem with this approach is the non reentrency of the interrupt disable/enable mechanism: if interrupts are already disabled when entering the code, they will be enabled upon leaving, which is probably not intended and a likely cause of bugs in the calling code.

Another quick and dirty trick can be used to lower the likelihood of an interrupt clash:

int value, last = atoi((const char*)TOS_Mins_Char);
while ((value = atoi((const char*)TOS_Mins_Char)) != last) {
    last = value;
}

If the buffer was modified by the ISR during the conversion, the next conversion would produce a different result. The is a remove possibility that the next conversion also be interrupted by the ISR, but in a non life critical system, you might want to ignore this possibility.

like image 173
chqrlie Avatar answered Sep 21 '22 12:09

chqrlie