2015-08-05 10:55 AM
Hello:
I am using a stm32F407 and working on getting the timer overflow working correctly and I am seeing a strange thing. Basically, I seem to be getting two TIM5 interrupts for each overflow of the counter. Nothing really happens with the second interrupt as the UIF flag is cleared but I really dont want to get two interrupts. Do I need to clear the NVIC Pending flag for this interrupt for some reason? I did not think I needed to do that. Here is a gdb dump of TIM5: gdb) p {TIM_TypeDef}0x40000c00 $3 = {CR1 = 5, CR2 = 0, SMCR = 0, DIER = 1, SR = 0, EGR = 0, CCMR1 = 0, CCMR2 = 0, CCER = 0, CNT = 54834720, PSC = 83, ARR = 100000000, RCR = 0, CCR1 = 0, CCR2 = 0, CCR3 = 0, CCR4 = 0, BDTR = 0, DCR = 0, DMAR = 5, OR = 0} NOTE: in the above example I have the ARR set to 100000000 but in my real code I set it to 0xFFFFFFFF as I just want to get an interrupt when the timer counter overflows. Same issue in both cases: tim5_isrs is always twice the uif_ints count. Here is the interrupt handler I am using:static
void
tim5_isr
(
void
)
{
uint32_t
sr
;
/* Count ♯ of interrupts */
++tim5_isrs
;
sr
=
TIM5
->
SR
;
if
(
sr
&
TIM_SR_UIF
)
{
++
uif_ints
;
}
/* Clear the interrupt sources */
TIM5
->
SR
&=
~
sr
;
}
Thanks in advance to anyone that can help. #stm32f407 #timer2015-08-05 11:15 AM
ARM-CortexM gotcha #1... Put
/* Clear the interrupt sources */
TIM5
->
SR
&=
~
sr
;
at the beginning of the ISR. JW2015-08-05 11:29 AM
Thanks Jan. I appreciate the quick response although I have to say I don't understand why it would make a difference although I am no cortex-M expert. I do a similar thing when using an external GPIO interrupt and I don't get multiple GPIO interrupts. Do you know off the top of your head where this is discussed in the cortex-M documentation?
Will2015-08-05 12:09 PM
2015-08-05 01:24 PM
Thanks Clive! I just passed over the rc_w0 in the description of the SR register. Always like to save some code/cycles. :)
Will2015-08-06 02:09 AM
The reason is that these chips are not microcontrollers but SoC, stitched together more or less loosely from a processor core, peripherals, and an interconnection mesh (data and signalling).
Particularly, while the write of word which clears the interrupt passes from processor through the buses (mainly the AHB/APB bridge) to the timer, and then while the timer's cleared output signal reaches NVIC (there may/probably will be a resynchronizer in the path as they are in different clock domain), the processor starts to exit the ISR, and as due to the tail-chaining feature it starts to check for new interrupts quite early, it still sees the timer interrupt active, so it kicks in again. I missed the |= but that can't escape Clive's eyes - the issue is not just the extra clocks spared, but the possibility to inadvertently clear bits you don't intended to - you'd read 0 and after the or write 0 back, but the flag might've been changed by hardware meantime (not issue in your simplistic case but in cases several interrupt sources are enabled). JW