I have a small test program where the only interrupt I've enabled is the periodic interval timer, and it's been configured to generate 1-msec interrupts.
The system peripheral interrupt service routine...
1) toggles an I/O pin to show it's been serviced 2) if the PIT interrupt is active, then 2a) reads the PIVR register to clear the interrupt, 2b) toggles a (2nd) different I/O pin
The main loop toggles a (3rd) different I/O pin.
------------------------------------------------------
The problems are:
A) Even though the I/O pin associated with the periodic interval timer (PIT) is toggling every 1-msec like it should, the other I/O pin in the system peripheral interrupt service routine that shows when the system peripheral ISR has been serviced toggles virtually continuosly (every 4 or 5 usec's with a 25 MHz MCK).
B) The 3rd I/O pin that's supposed to toggle forever in the main loop never toggles.
I've tried trapping all the system peripheral interrupt sources I can find documented in the datasheet, but none of them (other than the PIT) appear to be active.
Question 1 = Can anyone point me to a place in the AT91SAM7S datasheet that clearly defines what all the system peripheral interrupt sources are? I ask this because of the datasheet text that says things like "the system peripheral interrupts, such as the periodic interval timer, debug UART, etc.". It's the "etc." that's throwing me off. I've been unable to locate any definitive text in the datasheet that says "these are all the possible sources of system peripheral interrupts".
Question 2 = Are there any system peripheral interrupts that are enabled by default, i.e., by the generic SAM7.s code generated by the KEIL tools when a new project is generated?
Question 3 = Can anyone tell me how to clear *all* possible sources of system peripheral interrupts (before globally enabling interrupts), so that I can make sure the only one that's been enabled is the single PIT interrupt that I explicitly enabled?
Thanks, Dave.
Here's my system peripheral ISR code, minus all the #define's to keep this post shorter. As you can see, I tried putting infinite loops in all the unexpected interrupt handlers. When I run the code, it doesn't stop on any of the infinite loop spots in the ISR. Are there any other system peripheral traps I should cover in this ISR...? My system peripheral ISR keeps triggering in an infinite loop, but I can't figure out what the cause of the infinite re-triggering is. I've only *explicitly* enabled the PIT and debug UART TX READY interrupts, and they're working fine. TP3 toggles at a 1 KHz rate, and char's get dumped out the debug UART properly, with TP4 changing state once/transmitted char.
But... TP2 toggles every 9 or 10 usec's (my ISR is longer now), but when stepping through the ISR with the debugger no interrupt condition appears to be active (well, other than the PIT and debug UART TX READY ones)!!
HELP... please.
------------------------------------------------------ NOTE: I tried saving this file several different ways using a variety of editors, but I can't get my carriage returns to work in this forum... sigh. Sorry for the ugliness of the below code. ------------------------------------------------------
void sys_isr (void) __irq __atr // system peripherals interrupt service routine { char c; static char* pString = s; unsigned int dummy;
if(PIOA_ODSR & TP2) { PIOA_CODR = TP2; } else { PIOA_SODR = TP2; }
// periodic interval timer interrupt
if((PIT_MR & PITIEN) && (PIT_SR & PITS))
{ dummy = PIT_PIVR; // clear interrupt
++tClock; // increment 1-msec system clock
if(PIOA_ODSR & TP3) { PIOA_CODR = TP3; } else { PIOA_SODR = TP3; } }
// debug UART receiver ready interrupt
if((DBGU_IMR & DBGU_BIT_RXREADY) && (DBGU_SR & DBGU_BIT_RXREADY))
{ c = (char)DBGU_RHR; }
// service debug UART transmitter ready interrupt
if((DBGU_IMR & DBGU_BIT_TXREADY) && (DBGU_SR & DBGU_BIT_TXREADY))
{ DBGU_THR = (unsigned int)*pString;
++pString;
if(*pString == 0)
{ pString = s; }
if(PIOA_ODSR & TP4)
{ PIOA_CODR = TP4; } else { PIOA_SODR = TP4; } }
// service unexpected debug UART interrupts
if((DBGU_IMR & DBGU_BIT_COMMRX) && (DBGU_IMR & DBGU_BIT_COMMRX))
{ for(;;); }
if((DBGU_IMR & DBGU_BIT_COMMTX) && (DBGU_IMR & DBGU_BIT_COMMTX))
if((DBGU_IMR & DBGU_BIT_RXBUFF) && (DBGU_IMR & DBGU_BIT_RXBUFF))
if((DBGU_IMR & DBGU_BIT_TXBUFE) && (DBGU_IMR & DBGU_BIT_TXBUFE))
if((DBGU_IMR & DBGU_BIT_PARE) && (DBGU_IMR & DBGU_BIT_PARE))
if((DBGU_IMR & DBGU_BIT_FRAME) && (DBGU_IMR & DBGU_BIT_FRAME))
if((DBGU_IMR & DBGU_BIT_OVRE) && (DBGU_IMR & DBGU_BIT_OVRE))
if((DBGU_IMR & DBGU_BIT_ENDTX) && (DBGU_IMR & DBGU_BIT_ENDTX))
if((DBGU_IMR & DBGU_BIT_ENDRX) && (DBGU_IMR & DBGU_BIT_ENDRX))
// service unexpected real time timer interrupt
if(RTT_SR & (RTT_BIT_ALARM | RTT_BIT_INCREMENT))
{ DISABLE_INTERRUPTS; RTT_MR = 0; dummy = RTT_SR; ENABLE_INTERRUPTS; }
// service unexpected watchdog timer interrupt
if(WDT_SR & (WDT_BIT_UNDERFLOW | WDT_BIT_ERROR))
// service unexpected power management controller faults
if((PMC_SR & 0xD) != 0xD)
AIC_EOICR = 0; }
EEKS... just noticed a horrid cut/paste/edit error in the traps for my unexpected debug UART interrupts. Tested the same thing twice... that the interrupt was enabled, but not that it ever occurred. I'll fix that, but that just showed that none of those interrupts were ever enabled. So... those still couldn't be the cause of the ISR continuosly retriggering.
Sorry... Dave (embarrassed).
Okay... problem solved. Sorry to have to admit it was due to cockpit error.
Problem was caused when, somehow, as I cut/pasted/hacked code from a working SAM7S32 based project to my SAM7S256 based project I inadvertently changed the type of system peripheral interrupt from "HIGH LEVEL" to "POSITIVE EDGE". Not sure of all the ramifications, but when I changed it back to "HIGH LEVEL" my bad symptoms went away.
I'm not exactly sure how the interrupt H/W in the chip works, but my current best guess is that when the system peripheral interrupt was entered (when configured for "POSITIVE EDGE"), it registered that the interrupting condition was still active and generated another pending interrupt. So... when the ISR was exited, the INT was already pending again (even though the source of the interrupt was not), and the system entered a sort of catch-22 infinite loop.
If this is how the chip works, that seems pretty odd to me. Of course, that's only my opinion. The bottom line is I've got to study the datasheet much closer to see exactly how the different interrupt modes work, to figure out how my code got so lost in this infinite loop with the system peripheral interrupt in the first place.
Sigh... life goes on.
Dave.