cancel
Showing results for 
Search instead for 
Did you mean: 

TIM3 interrupt occasionally fires too early

richm
Associate II
Posted on May 20, 2013 at 19:28

I am using TIM3 as an event timer to trigger external ADC conversions. I am having an issue where the timer interrupt fires too early and causes an out of range conversion result from the ADC. I notice that when the interrupt is enabled, the TIM3 isr immediately fires followed by another one approximately 9ms later. After that, the isr fires correctly (66ms) for a period of time until i get spurious interrupts that, again, fire at the 9ms interval. The spurious interrupts occur anywhere from every few minutes to every few hours...

Using Keil Microvision 4.6 on a STM32F103ZE. Using the Standard peripheral driver 3.5.0. Code is as follows...

/* Enable the TIM3 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_Init(&NVIC_InitStructure);
/* TIM3 Peripheral Configuration */
TIM_DeInit(TIM3);
TIM_TimeBaseStructure.TIM_Period = 2666;
TIM_TimeBaseStructure.TIM_Prescaler = 719;
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_SetCounter(TIM3,0x0000);//clear counter reg 
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//enable isr
TIM_Cmd(TIM3, ENABLE);//enable the counter

Here is the ISR...

void TIM3_IRQHandler(void){
static int iTicks240Milliseconds = 0;
static int iTicks10Seconds = 0;
TIM_ClearITPendingBit(TIM3, (TIM_IT_Update|TIM_IT_CC1|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4));
b30Milliseconds = TRUE;
if(iTicks240Milliseconds++ >= 6){
b240Milliseconds = TRUE;
iTicks240Milliseconds = 0;
}
if(iTicks10Seconds++ > 333){
bInitComplete = TRUE;//allow relays, analog out...etc to function
}
}

Any ideas what might be going on? thanks
9 REPLIES 9
Posted on May 20, 2013 at 19:50

I could see you getting an initial interrupt, which you could likely address by enabling the timer, then clearing and enabling the Update interrupt.

You might want to qualify the interrupt you're receiving, and leave the other alone. ie don't shotgun clear ALL possible sources.

The period should be 2666-1 for 26.66ms, the compare here is for N-1, not N

I haven't observed STM32 glitching in the manner you suggest, so you should perhaps look at what other code is doing, things like dwelling in while() loops in other interrupts.

Sending pulses to an external ADC might be better achieved by using PWM mode to generate a pulse on a timer pin. The internal ADC can also be paced using a TIM unit to start the conversion, which is later caught by DMA, or ADC EOC interrupt.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
richm
Associate II
Posted on May 20, 2013 at 23:20

I have been shutting down other interrupt sources with no change in behavior...I am only enabling the ''update event'' interrupt for TIM3.  The status register always indicates 0x001F (both for correct and early isrs).  I realize that there are other ways an update event can occur (during initialization...counter register rollover...etc).  In theory, the counter register should never rollover since my ARR reg is below this threshold and I am up-counting...odd

Posted on May 21, 2013 at 09:54

> I am using TIM3 as an event timer to trigger external ADC conversions. 

How do you do that?

> I notice that when the interrupt is enabled, the TIM3 isr immediately fires followed by another one approximately 24.9ms later. 

> After that, the isr fires correctly (26.66ms) for a period of time until i get spurious interrupts that, again, fire at the 24.9ms interval. 

How do you observe that?

Please post a minimal but complete compilable example producing the problem.

JW

richm
Associate II
Posted on May 24, 2013 at 00:48

>How do you do that?

I am using a Delta-Sigma ADC.  The ADC requires a PWM to configure it's conversion time.  Currently I have the conversion time set to around 25.5 ms.  I use the TIM3 isr to set a flag for background code to trigger a conversion cycle every ~26.6ms.  So every time the isr sets the flag, background clears the flag and clocks in the new conversion request using the SPI2 peripheral (while simultaneously clocking out the previous result).

>How do you observe that?

I set a breakpoint in my conversion result code that detects an out of range condition.  I have my oscilloscope monitoring the chip select line for the ADC.  When an out of range condition occurs, the code hits the breakpoint and I can see the early chip select assertion on the scope

>Please post a minimal but complete compilable example producing the problem.

I attempted to strip down the application to just the PWM, SPI driver, and TIM3 isr...this version seems to work without fail, so probably not much use.  I have added another chunk of stuff back in that does fail...seems to be related to either printf, or the UART1 peripheral

I will try to post this code but the ST site keeps deleting my posts :(

richm
Associate II
Posted on May 24, 2013 at 01:03

One more note on the initial TIM3 initial glitches I mentioned in my first post.  These initial glitches are indeed caused by a call to printf at the conclusion of my initialization (right after the timer3 is turned on).  Removing this call eliminates the initial 2 glitches right after init is complete.  I then removed the entire UART1 init from the code but this doesn't  stop the early TIM3 interrupts later in operation however...fyi

Posted on May 24, 2013 at 12:23

There is way too much going on in between the interrupt and the signal you observe, for the interrupt to be accused.

Why not putting a pin toggle into the interrupt service routine and watch that on the scope/LA, too?

JW
Posted on May 24, 2013 at 12:37

Whenever printf/scanf come up as causing issues you want to look at the stack allocation. In Keil this is done in startup_stm32f4xx.s, and usually quite small. To modify you need to take a local copy of the .s file, and remove the read-only attribute.

Not saying this is the issue here, but not much to work with. You could put a fill pattern on the stack and evaluate the depth.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
richm
Associate II
Posted on May 24, 2013 at 16:42

>Whenever printf/scanf come up as causing issues you want to look at the stack allocation. 

My thoughts exactly...however I have an 8k stack size...probably wouldn't hurt to fill with pattern and check the depth however

Danish1
Lead II
Posted on May 25, 2013 at 11:25

Looking at your code, it seems that the interrupt does not immediately cause your event to happen. It looks as though your interrupt sets a flag that will eventually lead to your event happening.

Am I right in thinking that

b240Milliseconds

is simply a variable that your code somehow monitors (either explicitly in your event loop, or by way of an RTOS thread that waits on it)? What might be happening is that your interrupt is consistently called at your intended time interval. But your code might be slow in responding to the flag that you set in the interrupt one time, so when it responds promptly the next time you see the interval between your responses being too short. Why might that be? It could be that the processor is doing something else that is deemed to be high-priority e.g. servicing a different interrupt. Or doing something that takes a long time before it goes round again to see if your flag was set (slow event loop). Or you have a low-priority task that is using a resource that is needed for your high-priority handler. For example while one printf is running, it is possible that all other printfs will have to wait. Where you have something that is time-critical, quick, and will not block, do it in the interrupt. Hope this helps, Danish