AT91SAM7x256 & USART0 interrupt
Hi all,
I'm having a hard time to get the USART0 interrupt working.
Maybe some kind soul could have a look at what I've got here ...
I am using an OLIMEX board with an AT91SAM7X256 on it.
Main routine calls my usart0_init(). After that I can send data
and also receive it (if I do that manually).
The interrupt which should be started does not seem to work.
At least, my ISR routine (below) is never called.
What am I missing?
Thanks,
Christoph
//--------------------------------------------------------------------
void usart0_init(void)
{
volatile int dummy;
PIOA_PDR = BIT0 | BIT1; // Disable PIO control, enable peripheral control of the pin.
PIOA_ASR = BIT0 | BIT1; // Assigns the I/O line to the peripheral A function.
PIOA_BSR = 0; // do NOT assign it to peripheral B function.
PMC_PCER = (1 << US0_ID); // enable power for USART0 clock
US0_CR = US0_CR_RSTRX | US0_CR_RSTTX | US0_CR_RXDIS | US0_CR_TXDIS; //Reset and disable receiver and transmitter
US0_MR = US0_NBSTOP_1 | US0_PAR_NO | US0_ASYNC | US0_CHRL_8 | US0_CLKS_MCK | US0_MODE_NORMAL; //Set the USART mode
US0_IER = 0x00; // enable NO interrupt
US0_IDR = (U32) -1; // Disable all interrupts
US0_BRGR = ctl_at91sam7_get_mck_frequency(OSCILLATOR_CLOCK_FREQUENCY) / (16 * BAUDRATE); //set baud rate divisor register
US0_RTOR = 0; // receiver time-out disabled
US0_TTGR = 0; // transmitter timeguard disabled
AIC_IDCR = (1 << US0_ID); // Disable USART0 interrupt in AIC
ctl_set_isr(US0_ID, 3, CTL_ISR_TRIGGER_HIGH_LEVEL, receiveISR_US0, 0); // set ISR,
AIC_IECR = (1 << US0_ID); // Enable the USART0 interrupt in AIC
US0_CR = US0_CR_TXEN | US0_CR_RXEN; // Enable usart - enable RX receiver and TX transmitter
US0_PTCR = US0_PTCR_TXTEN | US0_PTCR_RXTEN; // Enable the RX and TX PDC transfer requests
US0_IER = US0_IER_RXRDY; // Enable RXRDY usart0 receive interrupt
US0_IDR = ~US0_IER_RXRDY; // disable all interrupts except RXRDY
ctl_unmask_isr(US0_ID);
}
// ----------------------------------------------------------------------
static void receiveISR_US0(void) // actual ISR routine
{
usart0_CSR = US0_CSR;
if(usart0_CSR & US0_RXRDY)
{
usart0_read_buffer(); // call routine to read and handle received character
}
// AIC_EOICR = 0xFFFFFFFF;
}
-
Hi Christoph.
I'm wondering why the line that enables USART0 in DMA transfer mode. The rest of the code looks like you you plan to use non DMA mode, were each received byte invokes the receive ISR. If this is the case then I think the line:
US0_PTCR = US0_PTCR_TXTEN | US0_PTCR_RXTEN; // Enable the RX and TX PDC transfer requests
should be removed.
If I'm worng, applogies for wasting your time.
Regards,
John
-
Thanks for Your answer, John!
Mr. Lynch (with whose tutorial I have been trying all this) has provided one interrupt- and one DMA-centered variant.
I must have slipped there.
But still: it doesn't work.
In debugging mode US_CSR shows me lots of 'ticks' like 'RXRDY', 'TXRDY', 'ENDRX', 'ENDTX' and so on.
Should that somehow be cleared beforehand? US_IMR shows a tick at RXRDY. Anything else I could look up in the registers?
Regards,
Christoph
-
Hi Christoph.Apologies for the late reply. I had to re-build a test project using US0 to check on the settings of the various interrupt related flags.I don't see any obvious errors in your code. You seem to have all the major initialisation steps in place.In debug looking at the following registers:AIC register. The entry for AIC_SVR6 should be set to non 0. This is the vector to your ISR handler which is set by the call to ctl_set_isr(...AIC_IMR should have a tick for US0AIC_IPR; if the entry for US0 is 1 then the AIC has detected an interrupt from US0 but has not yet processed it. If your code is working as intended this flag will generally be seen at 0.A likely cause for it being stuck at 1 is that global interrupts are disabled. See below.AIC_IMR; the entry for US0 should be a 1.US0_IMR should have the RXRDY flag set.The CPU Current mode register cpsr should have the I flag at 0. This is the global interrupt flag. If it is 1 then all interrupts (expect fast interrupts) are disabled.If you see this at 1 then its likely that something is missing in your initialisation code that should have globally enable interrupts.If you let me have an email address I will send you my relevant source files.Regards,John
Hi Christoph.
Apologies for the late reply. I had to re-build a test project using US0 to check on the settings of the various interrupt related flags.I don't see any obvious errors in your code. You seem to have all the major initialisation steps in place.
In debug looking at the following registers:
AIC register. The entry for AIC_SVR6 should be set to non 0. This is the vector to your ISR handler which is set by the call to ctl_set_isr(...
AIC_IMR should have a tick for US0
AIC_IPR; if the entry for US0 is 1 then the AIC has detected an interrupt from US0 but has not yet processed it. If your code is working as intended this flag will generally be seen at 0.A likely cause for it being stuck at 1 is that global interrupts are disabled. See below.
AIC_IMR; the entry for US0 should be a 1.
US0_IMR should have the RXRDY flag set.
The CPU Current mode register cpsr should have the I flag at 0. This is the global interrupt flag. If it is 1 then all interrupts (expect fast interrupts) are disabled. If you see this at 1 then its likely that something is missing in your initialisation code that should have globally enable interrupts.
If you let me have an email address I will send you my relevant source files.
Regards,John -
Now, I sincerely wish I could say something like "this will never happen to me again: to forget enabling interrupts" but I remember vaguely haven't had a rather similar problem with the AVRs before :)
Anyway, I've seen my first US0_RXRDY interrupt so it seems to work now.
Thanks a lot, John!
Regards,
Christoph
(topic closed, I think ...)
Please sign in to leave a comment.
Comments
7 comments