Has:
I enabled the debug protect mode like this:
pAIC->AIC_DCR = AT91C_AIC_DCR_PROT; // Enables debug protect mode
I see you already discovered what I just talked about in another comment.
Has:
The AIC_DCR register now reads 0x01. Without any other changes made, pressing the IRQ0 button now changes three AIC registers. The AIC_IVR now matches the AIC_SVR[30] with a value of 0x3b4. The IPR and IMR registers match as they did before. The AIC_CISR status register now reads 0x02 indicating the IRQ line is active. Obviously the debug protect mode is needed to view the changes to the AIC registers.
Ah yes, it is. Reading the IVR without it changed the state of the AIC. I expected the debugger to set that for you, though, and it apparently didn’t.
Has:
I added the following lines to clear the stack:
for (i=0; i < 8; i++)
{
AT91C_BASE_AIC->AIC_EOICR = 0;
}
This didn't seem to change anything, but I'll leave it anyways. The AIC_FFSR register reads 0x00 so I don't think I need to do anything with the FF.
I have gotten the impression that this (the 8 writes) needs to be done, and I do it anyway because of the aforementioned bootloader issue in my particular project.
Regarding FF, it looks like you’re good. So long as you only ever start your application directly after a peripheral reset or you only ever have one particular line (or none) set to FF. In other words, if you can count on it always being 0x00. I set it to 0 in my startup code because I cannot count on it in my environment.
Has:
Just to make sure, the dummy write to the IVR register happens after the program starts executing the interrupt routine correct?
Yeah. I have mine immediately after the read of IVR (I’m not doing that shortcut where you put the magic instruction in the exception table; if you are, you could just do it early in the handler). I’m not using a debugger, but it is there to keep me from getting bitten if I start using one.
Has:
I’m getting closer, but the code still stays in the while loop forever waiting for the interrupt to fire. Any other suggestions?
Here’s the default handler code:
// Set up the default interrupts handler vectors
AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler;
AT91C_BASE_AIC->AIC_SVR[30] = (int) AT91F_Default_IRQ_handler;
AT91C_BASE_AIC->AIC_SPU = (int) AT91F_Spurious_handler;
The irq0_handler.c only contains a line of code that turns on an LED and is a breakpoint. This is only for testing, I know there needs to be more there, I'm just mentioning it in case there's a problem there.
irq0_handler.c defines AT91F_Default_IRQ_handler, right? That is the function that just turns on an LED? Do you not have a write to AIC_ICCR in there? You need one for edge triggered interrupts. Without it, you’ll keep executing the interrupt and not spend much if any time in your main loop. Of course, for that to become a problem, we have to get you invoking the routine.
That the bit in AIC_CISR gets set tells me that the AIC is at least trying to dispatch the interrupt. Well, that and AIC_DCR being set correctly now if not before. So the IRQ line in the ARM core should be getting asserted. You’ve already stated that the I bit in the CPSR is clear, so it should be throwing an IRQ exception. How are you handling the IRQ exception?
What happens on your system when you throw an unhandled exception? If the board were rebooting or spinning, would you know?