cancel
Showing results for 
Search instead for 
Did you mean: 

Max frequency of TIM2 periodic interrupt?

czajnik
Associate II
Posted on October 09, 2008 at 14:37

Max frequency of TIM2 periodic interrupt?

13 REPLIES 13
czajnik
Associate II
Posted on May 17, 2011 at 12:47

Hi!

I need to sample a single input in software with 125kHz frequency (software implementation of serial protocol). However, experimenting with TIM2 timer I can't get about 110kHz at most. The timer is configured like this:

Code:

timeBaseInitParams.TIM_Period = TIMEBASE_PERIOD - 1;

timeBaseInitParams.TIM_Prescaler = 0;

timeBaseInitParams.TIM_ClockDivision = TIM_CKD_DIV1;

timeBaseInitParams.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &timeBaseInitParams);

I need TIMEBASE_PERIOD og 288. PCLK1 in my setup is 36MHz. Unfortunately, everything is fine for TIMEBASE_PERIOD down to about 330, i.e. I get the expected frequency. If I try to lower it to 300 or less, the actual frequency no longer corresponds to what I calculate, it's much lower.

Is there something I can possibly do wrong? Or is it a known limitation of the architecture? Any help appreciated.

lanchon
Associate III
Posted on May 17, 2011 at 12:47

it sounds like your interrupt service routine isn't having enough time to complete between timer interrupts when you increase the frequency.

(if you want to test: reset the timer int pending flag when you enter the ISR. after processing and before leaving the ISR, read the timer int pending flag. if it's set, a second timer event was triggered while you were still processing the first.)

possible solutions:

-optimize the ISR (including turning on compiler optimizations).

-or interrupt only when a transition occurs:

a)simpler: configure the pin so that an int is triggered on both (or alternate) edges. read a timer value in the ISR to know the approximate transition time of the signal.

b)better: configure the pin as input capture. in the ISR read the captured value to know the exact transition time of the signal.

czajnik
Associate II
Posted on May 17, 2011 at 12:47

Quote:

On 06-10-2008 at 09:12, Anonymous wrote:

it sounds like your interrupt service routine isn't having enough time to complete between timer interrupts when you increase the frequency.

Sounds unlikely, given the fact that CPU is running at 72MHz (which gives ~700 cycles between timer ticks), and the interrupt handler now contains only a few instructions to toggle the GPIO pin (I use oscilloscope to measure this).

But perhaps I overlooked something obvious, I started fighting with this issue yesterday evening.

Perhaps to early to bother people on the discussion forum, yet I wanted to check for any limitations that are obvious for others and not necessarily for me ;)

Quote:

(if you want to test: reset the timer int pending flag when you enter the ISR. after processing and before leaving the ISR, read the timer int pending flag. if it's set, a second timer event was triggered while you were still processing the first.)

Sure, that's the next logical thing to try, however I assumed the test ISR is short enough, see above. I'll give it a try later today.

Quote:

possible solutions:

-optimize the ISR (including turning on compiler optimizations).

Yep, gonna try it as well, at the moment I'm compiling with -g -O0. Still I believe my ISR executes in a few dozens of cycles. It just turns the pin high and then low, the pulse is about 1us wide (measured with the oscilloscope).

Quote:

-or interrupt only when a transition occurs:

a)simpler: configure the pin so that an int is triggered on both (or alternate) edges. read a timer value in the ISR to know the approximate transition time of the signal.

b)better: configure the pin as input capture. in the ISR read the captured value to know the exact transition time of the signal.

I've seen software UART application note somewhere on the net, based on this approach. However I wanted to start with a simpler solution, which seemed perfectly feasible given STM32 capabilities.

Best Regards,

Przemek

czajnik
Associate II
Posted on May 17, 2011 at 12:47

Quote:

On 06-10-2008 at 09:12, Anonymous wrote:

it sounds like your interrupt service routine isn't having enough time to complete between timer interrupts when you increase the frequency.

I had a little time to measure the time spent in the ISR (ok, in its test version, in my real application it's going to be a bit bigger) - it is about 80-90 CPU cycles now.

So I don't think it's a matter of ISR time. And actually, if the situation was as you described, I would see that ISR re-enters again immediately after returning - that's not the case.

lanchon
Associate III
Posted on May 17, 2011 at 12:47

let me ask the obvious: you did remember to configure the clock at 72MHz, right? I can't think of anything but the ISR taking too long. what's your idle loop? I mean, what are you interrupting?

lanchon
Associate III
Posted on May 17, 2011 at 12:47

> So I don't think it's a matter of ISR time. And actually, if the situation was as you described, I would see that ISR re-enters again immediately after returning - that's not the case.

I don't remember the detailed semantics of the interrupt pending bits, but assuming simple semantics what you say might not be true. if you clear the pending bit towards the end of the ISR you might be clearing the second int; what you'd get is a jittery mixture of T and 2T periods. the same would happen if the ISR invocation is delayed, which is why I asked what you were interrupting. are you using other interrupts? (also there's an issue that could cause double ISR invocations doubling the ''actual'' service time; but you'd see that with the scope or somehow, right?)

czajnik
Associate II
Posted on May 17, 2011 at 12:47

Quote:

On 07-10-2008 at 11:18, Anonymous wrote:

let me ask the obvious: you did remember to configure the clock at 72MHz, right? I can't think of anything but the ISR taking too long. what's your idle loop? I mean, what are you interrupting?

Yes, I have hope to have clocks configured properly :)

Look here:

http://pwegrzyn.pastebin.com/f1d48ca0e

Perhaps I overlooked something, let me know if you see something wrong here.

Perhaps I should try to use TIM1 or TIM8, as those timers are driven by PCLK2.

I'm interrupting a silly while(1) {} loop, for tests I've also disabled other interrupts.

czajnik
Associate II
Posted on May 17, 2011 at 12:47

Quote:

I don't remember the detailed semantics of the interrupt pending bits, but assuming simple semantics what you say might not be true. if you clear the pending bit towards the end of the ISR you might be clearing the second int; what you'd get is a jittery mixture of T and 2T periods. the same would happen if the ISR invocation is delayed, which is why I asked what you were interrupting. are you using other interrupts? (also there's an issue that could cause double ISR invocations doubling the ''actual'' service time; but you'd see that with the scope or somehow, right?)

You are right, I'm clearing the pending bit at the end (I didn't remember this piece of code correctly). Actually I'm going to try moving the pending bit clearing towards the beginning of ISR. It should be reasserted during the ISR then, and ISR should re-enter.

lanchon
Associate III
Posted on May 17, 2011 at 12:47

clearing the bit at the end of the ISR can cause lost ints, but it could also cause double triggering of the ISR for each (non-lost) int event. this could happen because the pending bit clearing operation (a memory write) can be delayed and complete out of order with respect to the return from interrupt instruction. the end result is that the ISR ends before the pending bit is cleared, and thus it's immediately retriggered. to avoid this effect, after clearing the pending bit you should read back that same register. this will stall the processor until after the write finishes.