Hi,
I was trying to use the timer interrupt on the
prototype development
board on RCM3000. I found that my code is resetting
again and again.
The code snippet is as follows:
#nodebug
#define
FAST_INTERRUPT 0
interrupt_vector timera_intvec timer_isr
main()
{
WrPortI(PGFR,&PGFRShadow,0);
WrPortI(PGCR,&PGCRShadow,0);
WrPortI(PGDR,&PGDRShadow,0xFF);
WrPortI(PGDDR,&PGDDRShadow,0xFF);
//timer
WrPortI(TACR,&TACRShadow,0x01);
WrPortI(TAPR,&TAPRShadow,0x01);
WrPortI(TACSR,&TACSRShadow,0x03);
WrPortI(TAT1R,&TAT1RShadow,0xFF);
while(1);
}
nodebug root interrupt void timer_isr()
{
WrPortI(PGDR,&PGDRShadow,0x00);
WrPortI(TAT1R,&TAT1RShadow,0xFF);
}
Is there anything wrong in this piece of code? All the ISR is doing
is
setting the LED on the prototype board.
Thanks in advance
-SVJ[Robert] There are a number of problems. First, timer A1 is
not recommended for C--assembly only because you only have 512 clocks within
which it may work, and a good portion of those are spent pushing and popping the
complete register set. Timer A1 IRQ's should be in strict assembly
and should not push very much on the stack; push af, hl, and possibly
de.
The second problem is that you must clear the source of the interrupt;
the Rabbit won't do that for you when the interrupt is entered. A
read of TACSR will clear the interrupt.
Here is your modified code--
interrupt_vector timera_intvec
timer_isr
main()
{
WrPortI(PGFR,&PGFRShadow,0);
WrPortI(PGCR,&PGCRShadow,0);
WrPortI(PGDR,&PGDRShadow,0xFF);
WrPortI(PGDDR,&PGDDRShadow,0xFF);
//timer
WrPortI(TACR,&TACRShadow,0x81); // <--Modified
to allow A7 to be clocked off A1
WrPortI(TAPR,&TAPRShadow,0x01);
WrPortI(TACSR,&TACSRShadow,0x81); // <--Modified to only get
an IRQ from timer A7 instead of A1
WrPortI(TAT1R,&TAT1RShadow,0xFF);
WrPortI(TAT7R,
&TAT7RShadow, Divisor); // <--On most boards (22Mhz), this is the
number of 1/43200'ths of a second you want between IRQ's
while(1);
}
nodebug root interrupt void
timer_isr()
{ auto int InterruptCause; //
Integers produce better code than char's in an IRQ
InterruptCause=RdPortI(TACSR); // This line is a necessity; without it, the IRQ
will be re-entered the moment the function exits.
if (InterruptCause
& 0x80) { // Check the cause of the IRQ
WrPortI(PGDR,&PGDRShadow,0x00);
// WrPortI(TAT1R,&TAT1RShadow,0xFF);
// Only on timer B do you rewrite these registers
}
}