Search code examples
cpointersarmcompiler-optimizationvolatile

Any optimization removes code (volatile pointer to array)


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?


Solution

  • 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.