I really wanted to solve this myself and feel like I'm getting the hang of my AT91SAM9261. But I'm clearly not.
I am writing some simple-as-possible code to do two things: trap an interrupt for (a) the PIT, and (b) when receive a character over the DBGU.
Below is the code.
Code:
__irq __arm void AT91F_SysHandler(void)
{
volatile int StStatus;
// Read the system timer status register
if(AT91F_PITGetStatus(AT91C_BASE_PITC))
{
AT91F_PITGetPIVR(AT91C_BASE_PITC);
tick++;
}
if (AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY)
{
// handle DBGU rx
tick++;
}
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);
}
void main(void)
{
// Clear AIC stack
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_AIC->AIC_EOICR; // clear the AIC stack (???)
AT91C_BASE_AIC->AIC_DCR = 1; // put the AIC in protect mode (so debug reads don't trigger action)
// set up the PIT
AT91C_BASE_PITC->PITC_PIMR = (SYS_TMR_PER/10)? ((SYS_TMR_PER/10) * (Fmclk/1000000) + 8) >> 4 : 0; // +8 to avoid %10 and /10
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITIEN; // enable the PIT interrupt
tick = 0;
// set up the AIC
AT91C_BASE_AIC->AIC_IDCR = (0x1 << AT91C_ID_SYS) ; // disable the system interrupt
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (unsigned int) AT91F_SysHandler ; // point the vector to the function
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE | AT91C_AIC_PRIOR_HIGHEST ; // set mode, priority
AT91C_BASE_AIC->AIC_ICCR = (0x1 << AT91C_ID_SYS) ; // clear the system interrupt
AT91C_BASE_AIC->AIC_IECR = 0x1 << (AT91C_ID_SYS) ; // enable the system interrupt
// set up the DBGU
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS ; // Reset receiver and transmitter
AT91C_BASE_DBGU->DBGU_BRGR = calculate_baudrate(Fmclk, AT91C_BAUDRATE_115200);
AT91C_BASE_DBGU->DBGU_MR = AT91C_US_ASYNC_MODE ; // define the USART mode
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN; // enables the transmitter and receiver
AT91C_BASE_DBGU->DBGU_IER = AT91C_US_RXRDY; // RX Ready interrupt
AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_SYS;
__enable_interrupt();
while(1){};
}
I put breakpoints in both branches of the AT91F_SysHandler function, and it seems that my PIT is working fine, but I can't trigger the AT91C_US_RXRDY branch by sending a character in to the DBGU port. Zilch.
I'm pretty sure that I have the hardware, connection, and port settings correct because I have some other code that sends a character out to my terminal, and I receive it fine at 115200. I've tried the send functions of a couple of different port tools, so I don't think the problem is there.
By the way when I do get a PIT interrupt, I look at my DBGU_CSR registers to see if anything looks funny, and I see:
RXRDY=0
TXRDY=1
ENDRX=1
ENDTX=1
OVRE=0
FRAME=0
PARE=0
TXEMPTY=1
TXBUFE=1
RXBUFF=1
RX=1
TX=1
Nothing jumps out at me as wrong, but maybe someone smarter sees something.
Anyway I have been spending WAY too much time on this and am an utter failure. You will make me a very, very happy man if you spot the problem in my code. You will be a hero of mythic proportions.