PDA

View Full Version : Timer Interrupt issue


zboot
04-10-07, 11:18 PM
I've been coding for the lpc2131 using WinARM.

I setup timer0 as a free running timer. I use the two match registers to generate interrupts on the compare match event. I do not reset the timer counter, I just increment the match registers by the amount needed to generate another interrupt in the future.

Now, here comes the tricky part. When I only enable one interrupt (ie only generate interrupts on either a compare match of T0MR0 or T0MR1), the code executes ok. But, when I allow both to generate interrupts, one interrupt will stop working for a while, then it will start working and the other will stop. There is sometimes a few seconds when both will work as expected.

Here is the code:

#include "timer.h"
#include "type.h"
#include "irq.h"
#include "LPC213x.h"
#include "iofun.h"

volatile long timeval;

void Timer0ISR(void) __irq;

/* Timer Counter 0 Interrupt executes each 10ms @ 60 MHz CPU Clock */
void Timer0ISR (void) __irq
{
volatile BYTE iFlag;

iFlag = T0IR;

if (iFlag & 0x01)
{
++timeval; // increment ms counter
T0MR0 = T0MR0 + TMR_1_MS - 1; // next interrupt in 1ms
T0IR |= 0x01; // clear interrupt flag
}

if (iFlag & 0x02)
{
//AD0CR |= (1 << 24); // start A2D conversion
T0MR1 = T0MR1 + TMR_1_MS*40 - 1; // next interrupt in 40ms
IOPIN1 ^= YEL_LED_PIN; // toggle LED pin
T0IR |= 0x02; // clear interrupt flag
}

VICVectAddr = 0; // Acknowledge Interrupt
}


// at 15Mhz - 15000 counts per ms
/* Setup the Timer Counter 0 Interrupt */
void init_timer (void)
{
timeval = 0;
T0TCR = 0x02; // reset timer and prescale count
T0PR = 0x0000; // divide by 1 (prescaler = 1 - 1)
T0MR0 = TMR_1_MS - 1; // interrupt in 1ms
T0MR1 = TMR_1_MS*40 - 1; // interrupt in 40ms
//T0MCR = (1 << 0) | (1 << 3); // interrupt on match of MR[0..1]
T0MCR = 8;
VICVectAddr0 = (unsigned long)Timer0ISR; // set interrupt vector in 0
VICVectCntl0 = TIMER0_INT | IRQ_SLOT_EN; // use it for Timer 0 Interrupt
VICIntEnable |= (1 << 4); // Enable Timer0 Interrupt
T0TCR = 0x01; // Timer0 Enable (reset cleared)
}

zboot
04-11-07, 10:37 AM
Just a couple things in the code, this line is uncommented when both match interrupts are enabled and the uncommented T0MCR setting is removed.

//T0MCR = (1 << 0) | (1 << 3); // interrupt on match of MR[0..1]

I've narrowed down what's happening to the following: It seems that the compare match events are happening really close to each other - on the 40th time that the 1ms match event occurs, the 40ms event may be occuring within the ISR. In fact, if I wrote my code correctly, the 40th 1ms match event and the first 40ms match event would occur at the exact same time.

Is it possible that while in the ISR, the T0IR register is not updated by the interrupt hardware and thus the processor misses that event until the timer-counter wraps around (which at the PCLK freq takes about 4.8 minutes)?

zboot
04-11-07, 11:47 AM
I've found the solution though I'd still like to understand the problem.

If I stagger the 40ms interrupt by 0.5ms, it never interferes with the 1ms interrupt - they never trigger at the same time and the 40ms interrupt never triggers during an ISR of the 1ms or vice versa.

This is annoying because it means if I want more match interrupts on the same timer, I'd have to stagger all of them to be safe. . .

mckenney
04-11-07, 07:43 PM
T0IR |= 0x02; // clear interrupt flag
Don't clear the IR this way -- you'll introduce a race which will produce
exactly the symptom you describe. What you want to do instead is:
T0IR = 0x02; // clear interrupt flag
though typically you can get away with just:
T0IR = iFlag; // Clear all
at the end of your ISR.

zboot
04-12-07, 07:32 PM
I'll give that a shot.

Can you explain why one method would generate race conditions while the other would not?

zboot
04-12-07, 08:06 PM
Hi,

This is going to come after my prev post. I would have edited that one. . but apparently my posts to this forum are being pipelined. . . really slowly. . .

Anyway, I implemented your suggestion and I still get the same problem - or perhaps a different one because now, both ISRs are missed instead of just one.

zboot
04-12-07, 08:45 PM
Sorry about all this. . .

turns out in my haste to try your suggestion, I'd accidentally deleted the line of code that enabled timer0.

This is great - this simplifies some of the work I have to do (I'm in crunch mode for the Trinity Firefighting competition. . . I've really only got friday afternoon-evening and saturday morning left to get from parts and separate components lying around and bits and pieces of code here and there to a fully working competition ready robot! :-)

mckenney
04-13-07, 08:08 PM
Can you explain why one method would generate race conditions while the other would not?
See page 173 of the User Manual. Doing a Read-Modify-Write of the IR may
clear bits that you don't intend (viz. those that came on since you fetched
the IR).

Good luck in the contest.

mckenney
04-13-07, 08:14 PM
apparently my posts to this forum are being pipelined. . . really slowly. . .
I'd never dream of criticizing the webmaster, but I won't disagree that the
(many-)hour latency makes interaction a bit, um, clumsy.

Dave
04-16-07, 11:35 AM
Essentially it is a matter of having a bit of latency in post appearance, or having a deluge of ads posted for Viagra, other drugs, cheap software, or other such messages.

Sadly the days of quick posts left with the arrival of these ads, but NMItech is doing pretty good at getting valid messages verifed as soon as he can.

zboot
04-16-07, 03:44 PM
I thought it might be a limiter on new users where your posts are screened for spam until its established you're a legit user.