Any optimization removes code (volatile pointer to array) - c

I'm writing simple code in C for STM32F0 discovery board. I'm generating different waveforms, according to external analog signal.
Declared global arrays with waveforms:
const uint32_t sinus[WAVELENGHTS] = {128,131,134,137,141,...}
const uint32_t square[WAVELENGHTS] = {0,0,0,0,0,0,0,0,0,0,...}
and pointer to array
const uint32_t (*currentWave)[WAVELENGHTS];
That pointer is used in timer irq to generate chosen waveform:
void TIM14_IRQHandler()
{
...
TIM2->CCR1 = (*currentWave)[(mainSynth.DDSAccumulator)>>24];
TIM14->SR &= ~(TIM_SR_CC1IF);
}
According to external value, in main loop I choose one of waveforms:
while(1) {
...
if(ADC_values[2] < 2048)
currentWave = &sinus;
else
currentWave = &square;
...
}
Without optimizations, currentWave value changes according to ADC_values[2] change (exactly: to TIM2->CCR1 are written values from good waveform, sinus or square), but enabling any optimization makes code working bad, it means assignment
currentWave = &sinus;
or
currentWave = &square;
never executes, currentWave always have initial value.
I also tried to declare both pointer and arrays as volatile, with no effect.
I need optimization for size to fit code in my device.
Any ideas?

I'm going to make a wild guess: you tried the volatile this way and it didn't work:
const volatile uint32_t (*currentWave)[WAVELENGHTS];
And that is to be expected, because this declaration makes volatile the uint32_t values of the array, not the pointer. And the pointer is what changes asynchronously.
Try instead:
const uint32_t (* volatile currentWave)[WAVELENGHTS];
And see what happens.
Note: if you find the syntax awkward, try with typedefs:
typedef const uint32_t waveform_t[WAVELENGHTS];
waveform_t *volatile currentWave;
You could even do:
typedef waveform_t *waveform_ptr;
volatile waveform_ptr currentWave;
but I find it excessive.

I guess you could try make the pointer volatile. Be sure not to just declare it a pointer to volatile uint32_t values, but to declare the pointer itself as volatile. My guess is that the compiler ignores it if the pointer itself is not volatile.
const volatile uint32_t *currentWave; <- "pointer" to "const volatile memory"
const uint32_t * volatile currentWave; <- "volatile pointer" to "const memory"
Also, I think there is no need for that extra indirection, you can just use a pointer, and assiging it like:
currentWave = sinus;
is perfectly valid, just as indexing it like
currentWave[(mainSynth.DDSAccumulator)>>24]
is valid C code.

Related

Reason for volatile nonstatic local variable in C

Refer to the following code:
void calledFunction(volatile uint8_t **inPtr);
volatile uint8_t buffer[] = {0,0,0,0,0,0};
volatile uint8_t *headPtr = buffer;
void foo(void)
{
volatile uint8_t *tmpPtr = NULL;
tmpPtr = headPtr;
//This function modifies tmpPtr
calledFunction(&tmpPtr);
headPtr = tmpPtr;
return;
}
This is a simplified version of code that I am attempting to make interrupt-safe, and I am not sure why this local is defined as a volatile. I know that there is no performance reason (i.e. to guarantee at least O(n) for this function) because this function should run as efficiently as possible.
This function can be called in both main execution and inside interrupts, but since tmpPtr is a nonstatic local variable, it should not be able to be modified by any other instance of foo().
I can't see any access pattern that would require the volatile keyword in this context.
In short, What is the purpose of the volatile keyword for tmpPtr in function foo()?
EDIT:Forgot a & in function argument
EDIT2: I have inherited this code and need to modify it.
My main question is whether the volatile keyword has any special effective reason for being in this context.
EDIT3: Added the prototype for calledFunction()
EDIT4: Added important clarification in original code that headPtr and buffer both have volatile
The reason tmpPtr has volatile is due to tmpPtr needing to reference a volatile uint8_t, not because tmpPtr itself is volatile (it isn't).
As initially pointed out by #Eugene Sh., this question came up due to a misunderstanding in syntax when defining volatile pointers and variables. This question has a great explanation of syntax for pointers to volatile vs volatile pointers.
Volatile restricts the compiler from optimizations when accessing (reading or writing) the data this pointer points to.
This comes up in embedded or interrupts often because memory-mapped peripherals can't have what would normally be "extraneous" reads or writes optimized out.
E.g.,
int32_t variable = 0;
variable = 1;
variable = 2;
variable = 3;
An optimizing compiler would skip setting the value of variable to 0, 1, and 2 and just set it to 3. That's fine generally, but if instead of writing to a normal variable we are writing to a memory-mapped port, we actually want each of those writes to happen.
This can happen even outside the world of hardware interfaces. If a separate thread is in a loop looking for variable to be set to 2, an optimizing compiler would preclude this from happening.
The fact that it's local is not material. It's just that most use cases for volatile happen be implemented with translation-unit (or cross-translation-unit using extern) scope.
Two examples are memory-mapped register definitions (the struct is typically global, often in a header file, and commonly the instance of the pointer to the struct is global though it doesn't have to be), and flags like our thread example.
I don't advocate for either design, but you will come across it frequently in embedded development.

How do I declare a static array with volatile elements?

Clarification about terminology used:
For static array I mean array statically memory allocated like: int x[10].
The problem
I need to declare a static array with volatile elements.
If I well understood how volatile qualifier works, it should be:
volatile uint8_t *x; // x is a pointer to volatile uint8_t
uint8_t *volatile x; // x is a volatile pointer to uint8_t
volatile uint8_t *volatile x; // x is a volatile pointer to volatile uint8_t
Ok, but now I need to do the same thing with a static array.
I tried with:
volatile uint8_t x[10]; // Only the pointer is decleared as volatile
uint8_t volatile x[10]; // Same as above
volatile uint8_t *x3[10]; // Casting problems and errors when I do ...
*x3[0] = 1; // ... something like this. Moreover, I do not know if this...
// ... statement declares the uint8_t element as volatile
Thanks!
UPDATE
Ok, as highlighted in the comments I should use:
volatile uint8_t x[10]
As I could understand, the problem is not in the declaration but in the usage of this variable in my code. I pass this element to a function whose prototype is:
static void functionName(uint8_t *buffer, uint32_t size);
I call the function in this way:
functionName(x, 10);
The compiler reports: passing argument 1 of 'functionName' discards 'volatile' qualifier from pointer target type
I can't change the function prototype, how can I solve the problem?
What you have to do to declare a static array of 10 volatile elements of type uint8_tis just:
volatile uint8_t x[10];
Be aware that this is a declaration of an array, which has nothing to see with pointers at this step.
Note: Later in your code, if you use x, it may decay to a pointer to the first volatile element, but in this case this pointer will have a constant value, given at the linking step. The pointed value is obviously volatile.
Stumbled across the problem myself today.
A variable CAN be 'sometimes' volatile.
Being volatile means, that its value can changed outside the program flow. By a parallel thread or an ISR.
Now if the ISR is what changes the value 'unexpectedly', it won't change unexpectedly inside the ISR itself. So for the ISR, the variable is not volatile and disabling compiler optimizations for it is counterproductive.
If I call a function from inside the ISR (and only from there), then the variable is not volatile and I don't want to pass a pointer to volatile, as it would produce inefficient code.
For this case, the solution I found was to have two declarations:
int a[x] = {};
volatile int * b = a;
Now the outside world uses b (globally declared in the header file) and treats the values pointed to by b as volatile, while the ISR (locally) defines both and uses a, treating the values as being not volatile.
Well, this is a very special case. In general, a function only sees the function parameter declaration. Which is either volatile or not, so the funciton will treat a parameter either always as being volatile or always as being not. It cannot automatically switch between two maybe completely differently compiled code blocks depending on the original volatile qualifier state of the passed parameter. Hence the warning.

C - use of a volatile pointer

Why would one create a volatile pointer? And suppose I want a volatile pointer which points to a volatile variable, which of the following declarations would accomplish this:
volatile int *pData;
or
volatile int * volatile pData;
Why would one create a volatile pointer?
Example: To access data whose pointer is updated by a background process.
Stuff * volatile VideoFrame;
for (;;) {
Block_Changes();
Stuff MyCopy = *VideoFrame;
Allow_Changes();
Use(&MyCopy);
}
I want a volatile pointer which points to a volatile variable, which of the following declarations would accomplish this:
The 2nd meets the goal. volatile int * volatile pData; is a:
pData as volatile pointer to volatile int
The 1st volatile int *pData; is a non-volatile pointer to volatile data:
pData as pointer to volatile int
The volitle keyword is most often used in this context. # Eugene Sh.
One reason to use the modifier `volatile' is so the compiler does not optimize the variable out of existence.
Another reason to use the modifier 'volatile' is so when ever the code references that variable, it accesses the actual variable and not the value left in some register.
Another reason to use the modifier 'volatile' is when the variable value can change outside the control of the current program. For instance a hardware register or when an 'interrupt' updates the variable that your application is reading.

Casting volatile variable in c

I think I have a tricky question, but I'm sure you will be able to help me.
Let's say I have a function like this:
char my_function (int example);
I use this function in multiple cases, sometimes the argument it receives is a volatile variable and sometimes a non-volatile variable.
That cause some warnings when I compile my code that can be easily removed by using casts, but I want to understand which is the safer scenario and why.
Scenario 1:
Prototype: char my_function (int example);
int a;
volatile int b;
my_function (a); // Everything is fine.
my_function ((int)b); // Avoided the warning, by casting the variable and saying it's no longer volatile.
Scenario 2:
Prototype: char my_function (volatile int example);
int a;
volatile int b;
my_function(b); // Everything is fine.
my_function((volatile int)a); // Avoided the warning, by casting 'a' saying that now it's volatile.
I understand how volatile modifier works, I mostly use it because I program micro-controllers and I need to ensure that some of my variables are never optimized out when they are hardware modified.
I am a bit confused about casting the volatile modifier and that is why I want to understand which is the safer scenario apart from just removing the warning.
It really depends on what my_function does with its argument.
Remember that volatile prevents certain optimizations - predominantly it forces the variable to be re-read every time it is referenced. Thus this code
volatile int a;
int b;
// ...
b = a + 1;
b = a + 2;
will read a for each statement and, as a may have changed values between them, give the correct result.
When you pass a volatile into a function as a parameter, you only get one read of the variable. This may then be used multiple times within the function (effectively losing the volatile nature).
Remember that C is pass-by-value. When you invoke the function as
my_function((int)b); // b is declared volatile
The compiler generates code to read b once in the calling code, and push the value it read onto the stack (usually), then invoke my_function. This copy is then referenced within my_function as example, and no matter how often you reference example you will always get the same value (even if the original b variable has since changed many times).
That might be exactly what you want - take a snapshot of the variable and do several computations on its value.
If it's not what you want, you need to consider passing in a pointer with the appropriate volatile qualifications.
char my_function( volatile int *example);
And call it thus:
my_function(&a);
my_function(&b);
Then reference *example inside my_function.
The cast doesn't actually do anything. In the call my_function (b); the code reads the volatile int b. That's where the "volatile" matters, during the read. The result of the read is already an int and not a volatile int. There are no volatile int values. Even if there were volatile int values, passing it to my_function would convert it to plain int, just as the cast does.
It may be that the compiler assumes that passing a volatile int variable to a function is something dangerous worth a warning, and by adding a cast to int you indicate that you know what you are doing.

const volatile pointer function argument

For a embedded SW project we need to use some const volatile TYPE * pointers. Now we have some calculation functions which are looking like following:
uint8 calc(const volatile uint8 *array, uint8 value) { ... }
The data of both variables is not changing during the function execution.
The calling code looks like following:
const volatile uint8 *array = (const volatile uint8 *)0x00010111;
uint8 value = 8;
uint8 result = calc(array, value);
The question is now, would be there a difference, if we design the calucation functions without volatile arguments:
uint8 calc(const uint8 *array, uint8 value) { ... }
For the call we cast away the volatile:
uint8 result = calc((const uint8 *)array, value);
Pros for the second solution are more flexibility: We can use the function also for non volatile variables. But does it make a difference, if we cast away the volatile and our compiler does some strong optimizations?
You can ALWAYS use the function with non-volatile arguments. Its just that the code in the function handles the given objects as if they were volatile (losing performance on the way, most likely). Its a bit hard to imagine what a function with volatile arguments ("because they might change without notice") could sensibly do. As you write, in your case the data doesn't change anyway, so the most flexible solution is to declare the parameters const and forget about volatile.
And pretty please, use "uint8_t" and not some homegrown type name like uint8 - its in the standard since 1996!
There are two cases: either the function is manipulating hardware registers etc directly. Then you must have volatile in the parameter. Or the function has nothing to do with hardware registers at all. Then it should not have volatile. There is no middle ground between those two cases.
Furthermore, calc((const uint8_t*)array, value); is just a bad, possibly buggy version of
const uint8_t* ptr = array;
calc(ptr, value);
The former form is bad, because the order of evaluation of function arguments is unspecified behavior. The compiler may chose to evaluate the left operand or the right operand first, and you cannot know or assume the order. Since accessing a volatile is a side-effect, your original code can give different results each time the program is built. This is especially problematic (and possibly dangerous) in real time embedded systems.
Therefore it is recommended practice to never access volatile variables inside expressions (see MISRA-C:2004 12.2).
That depends on what really can happen due to volatile-ness.
If the values in this array change during function execution and these changes should be noticed, let them be volatile.
If it doesn't matter, or if the "old" values are more important, omit the volatile.

Resources