# Timer2 period match interrupt on dsPIC33F not working

I'm trying to get the Timer2 period match interrupt on my dsPIC33FJ128GP802 working. I want it to interrupt after ~480 cycles. I'm using MPLAB C30.

I have, to initialize the timer and interrupt:

// Initialize Timer2, which is used for output timing.
T2CONbits.TON = 1;
T2CONbits.TSIDL = 0;
T2CONbits.TCKPS = 0;
T2CONbits.TCS = 0;
T2CONbits.T32 = 0;
// Initialize Timer2 interrupt with a slightly
// higher priority.
IPC1bits.T2IP = 5;
IFS0bits.T2IF = 0;
IEC0bits.T2IE = 0;


(the timer interrupt is initially disabled)

I have already got pin change interrupts working with a priority of 4. I want the Timer2 interrupt to have a higher priority.

And to set up the interrupt I have this:

T2CONbits.TON = 1;
TMR2 = 0;
timer2_osd = 480 + vid_hoffset;
PR2 = timer2_osd;
IEC0bits.T2IE = 1;


I also have an ISR,

void _MY_ISR _T2Interrupt()
{
IFS0bits.T2IF = 0;
return;
}


However I find the processor just resets and will not run with this enabled. It will work with a busy loop checking the timer, but that wastes cycles.

Can anyone see where I've gone wrong?

• I assume _MY_ISR is defined as __attribute__((interrupt)) or similar? – tcrosley Nov 18 '10 at 18:57
• @tcrosley: correct – Thomas O Nov 18 '10 at 19:10
• If the processor is resetting only with your interrupt routine enabled, this is often a stack problem. You don't need the explicit return instruction, but it should be optimized out. In any case, you might want to look at the disassembly code (View -> Disassembly Listing) for the interrupt routine and post it. – tcrosley Nov 18 '10 at 19:26
• @tcrosley I've discovered it only crashes if I uncomment the PR2 statement. The code already has one interrupt which works perfectly, could it still be a stack issue? – Thomas O Nov 18 '10 at 19:30
• If the period register is 0, it probably never matches and so it never triggers the interrupt. With PR2 line uncommented, can you trigger on a breakpoint set inside the interrupt routine? – tcrosley Nov 18 '10 at 19:42

I just looked at the code I wrote a while ago to set up timer 2 for a periodic interrupt of 1 ms for a PIC24F (essentially same timer hardware as dsPIC33F), and it looks like so:

#define CPU_CLK_RATE 32000000L
#define PERIPH_CLOCK_RATE (CPU_CLK_RATE/2L)

#define TIMER_2_RATE 1000L
#define TIMER_2_PRE  64L        // clock rate is (32000000/2)/64 = 250 KHz
#define TIMER_2_MATCH (PERIPH_CLOCK_RATE/(TIMER_2_RATE * TIMER_2_PRE))

T2CON = 0; // set control register to defaults

T2CONbits.TSIDL = 1;  // discontinue when idle
T2CONbits.TCKPS1 = 1; // prescaler of 64
T2CONbits.TCKPS0 = 0; // prescaler of 64
T2CONbits.T32 = 0;    // 16 bit timer
T2CONbits.TCS = 0;    // FOSC/2 (32Mhz/2)
TMR2 = 0-TIMER_2_MATCH*19;  // 20 millisecond delay before starting
PR2 = TIMER_2_MATCH;

SetPriorityIntT2(TIMER2_INTERRUPT_PRIORITY); // set to very high priority
EnableIntT2; // enable interrupts

T2CONbits.TON = 1


Very similar to yours, except I pre-initialized TMR2 so there would be a delay before the first interrupt. Don't know if that would help in your case or not, but you might try it.

The datasheet seems to suggest you should clear TON, initialize the timer, then set TON. Many example sequences end with setting TON, they don't start with it.

Many devices latch working values out of their configuration registers when they're enabled... so you should always disable, configure, then enable. Be very careful when changing registers on a running peripheral.

I'm also not clear on how the interrupt code gets tied to the timer2 interrupt event. What's _MY_ISR?

• _MY_ISR is defined as __attribute__((interrupt, shadow, auto_psv)) – Thomas O Nov 18 '10 at 19:13
• I tried disabling the timer before config and then reenabling it but it doesn't work, and has the same problem (resetting I suspect.) – Thomas O Nov 18 '10 at 19:13
• @Thomas, since you are not accessing data in the auto_psv space in your interrupt routine, you can use no_auto_psv instead of auto_psv. – tcrosley Nov 18 '10 at 19:30
• @tcrosley: thanks for the suggestion but no luck... – Thomas O Nov 18 '10 at 19:33
• Perhaps it's my ignorance of that specific environment, but how does that interrupt routine get mapped to the timer2 overflow event? Usually there some vector table offset number, a name of the interrupt to tie to, etc. – darron Nov 18 '10 at 19:59