cancel
Showing results for 
Search instead for 
Did you mean: 

Losing timer compare interrupts

sebkeinert
Associate II
Posted on July 05, 2016 at 09:02

Hi,

I try to setup two compare channels on TIM5 of a STM32F446 device to generate two independent time triggers. Both triggers have a frequency of approximately 8kHz but differ by a few timer ticks. Hence it is inevitable that both interrupts will coincide after some periods or one interrupt will trigger when the other is serviced in a ISR. Initially this seems to be an easy task but does not work. When both captures fall together one of the CC interrupts can get lost. It cost me several hours to figure out that this apparently happens when one interrupt is serviced in the ISR and the other raises at the wrong moment. My sample code is like that:

void
sek::foc::TIM5_Handler()
{ 
if
( TIM5->SR & TIM_SR_CC3IF )
{
TIM5->SR &= ~TIM_SR_CC3IF;
if
( IRStatus & BIT0 )
{
IRStatus &= ~BIT0;
//...do some work here
TIM5->CCR3 = TIM5->CNT + Ticks3Dist; 
}
else
{
IRStatus |= BIT0;
//...do some work here
TIM5->CCR3 += Ticks3On;
} 
} 
if
( TIM5->SR & TIM_SR_CC4IF )
{
TIM5->SR &= ~TIM_SR_CC4IF;
//...do some work here
TIM5->CCR4 += TimerEventInterval;
}
}

As you can see I use CC3 and CC4. CC4 has a fixed interval, CC3 periode toggles with every interrupt. CC4 is the compare that gets lost in most cases. As I add a fixed interval to the compare value it stops triggering when the counter value of the timer is greater then CCR4. Any idea? Regards #stm32f4-timer-compare-interrupt
5 REPLIES 5
Posted on July 05, 2016 at 10:36

Stop using the RMW method to clear the interrupt, this will cause the exact failure you complain about.

Just write the mask per documentation.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
sebkeinert
Associate II
Posted on July 05, 2016 at 11:33

Hello clive1,

many thanks, that solution works!

It is obvious for me why the RMW method failed. But what I do not understand: My first approach was to read/write the interrupt flags with bit banding. ST states that this operations are atomic and should modify only a single bit of the SR register. Also this solution did not lead to the desired result.
Radosław
Senior
Posted on July 05, 2016 at 11:39

Bitband is atomic only for core. This is still RMW but done by bus driver.

Posted on July 05, 2016 at 11:58

> read/write the interrupt flags with bit banding. ST states

Where?

> that this operations are atomic and should modify only a single bit of the SR register. 

While bitbanding writes are atomic indeed, i.e. they can't be interrupted not even by an other master on the bus matrix (e.g. DMA access to the same AHB/APB bus won't happen until bit-banding operation finished), they are still read-modify-write from the point of view of the peripheral. 

Bit-banding is performed by an attachment to the processor-to-busmatrix interface, which reads the word from the peripheral while locking down the bus (disabling other masters to access it), performs the required bit set or clear, then writes the word back while unlocking the bus. This is transparent to the programmer, who performs only a single write to the bit-banding area, but this is how the hardware ''performs'' that single write.

So, if the peripheral's register is not purely memory-like, as is the case of the timers' status register (and also often the case of other peripherals' status register, too), performing bit-banding write on them may have the same unexpected results as explicit RMW.

Just a sidenote - GPIO's output-bit-set/-clear registers are of different character - the individual-bit-change is performed in hardware directly in the GPIO peripheral.

JW

sebkeinert
Associate II
Posted on July 05, 2016 at 13:34

Hello JW

>> read/write the interrupt flags with bit banding. ST states

>Where?

Sorry, my statement was wrong. It is exactly as you explained it. The atomicity of the bit banding operations is declared in the ARM Cortex Reference Manual and not in ST's documentations. 

Now everything seems clear to me, although it has to be mentioned that it is diffucult to get this information from any ST documention.

Thanks to all.