 |
SparkFun Electronics MicroController Ideas and Support
|
| View previous topic :: View next topic |
| Author |
Message |
daa
Joined: 29 Jan 2008 Posts: 8
|
Posted: Mon Jul 07, 2008 1:42 pm Post subject: LPC2294 Uart interrupt problem |
|
|
Hello there,
I am having this strange problem where once an Interrrupt happens, interrupts are disabled forever. After the first occurance of the interrupt, even though interrupts are happening and the processor knows about it, because interrupts stays disabled in CPSR, it never goes back to the ISR. I DO NOT need to nest the interrupts. I actually prefer not to do that. I have found some example interrupt nesting code in assembly. I updated my crt.s file with those updates and that didn't help either.
Ok.. the basic thing I am trying to achieve is the following. I have a main loop that's being triggered by a timer interrupt. I have configured Timer1 to interrupt at every 10msec for this purpose. Then I am receiving data in Uart0. Uart0 raises an interrupt after it receives one byte of data. My plan was to send this byte out through Uart1. But for now I am just doing some dummy reads to clear the interrupt.
I have a very simple main loop where it toggles a bit to let me know if it's running. Now if I am not sending any data to the uart, the main loop is running smoothly which tells me that timer1 interrupt is happening periodically. But the moment I start sending data, I see that the timer1 interrupt has stopped working. After stepping through the code what I have noticed is that when it comes out of the Uart interrupt, for some reason it leaves the IRQ bit in the CPSR register disabled. How do I stop this from happening? I don't think I am doing anything special with Uart interrupt. It's working fine with the timer interrupt, then why does it mess up in case of timer interrupt.
| Code: |
void Uart0_ISR(void)
{
if(toggle) // toggle a bit
IOSET0 = 0x00000008;
else
IOCLR0 = 0x00000008;
toggle = ~toggle;
while(!(U0LSR & 0x01));
data = U0RBR; // dummy read
data = U0IIR; // dummy read
}
void Uart0_Driver_init(Uart0_Driver *this)//, FrequencyFormatter *FF_handle)
{
//this->rx_buffer = rx_buffer;
//this->rx_buffer_size = rx_buffer_size;
Uint8 q;
// set the pin
// PINSEL0 = PINSEL0 | PINSEL0_08_UART1_TX |
// PINSEL0_09_UART1_RX;
PINSEL0 = PINSEL0 | PINSEL0_00_UART0_TX |
PINSEL0_01_UART0_RX ;
// Set the line control registers
U0LCR = U0LCR_WORD_LENGTH_SELECT_8 |
U0LCR_1_STOP_BIT |
U0LCR_PARITY_DISABLE | // Parity = None.
U0LCR_BREAK_CONTROL_DISABLE |
U0LCR_DIVISOR_LATCH_ACCESS_ENABLE;
// Now set the baud rate.
U0DLL = (60000000/9600/16) & 0xFF; // should be 0x86 for 9600
U0DLM = ((60000000/9600/16)>>8) & 0xFF; // should be 0x01 for 9600
//Configure the FIFO first
U0FCR = U0FCR_FIFO_ENABLE |
U0FCR_RX_FIFO_RESET |
U0FCR_RX_TRIGGER_LEVEL_01;
//Disable the divisor latch access
U0LCR = U0LCR_WORD_LENGTH_SELECT_8 |
U0LCR_1_STOP_BIT |
U0LCR_PARITY_DISABLE | // Parity = None.
U0LCR_BREAK_CONTROL_DISABLE |
U0LCR_DIVISOR_LATCH_ACCESS_DISABLE;
q = U0RBR;
VICIntEnable = ENABLE_UART0_INTERRUPT;
VICVectCntl1 = THIS_VIRQ_IS_ENABLED |
UART0_INTERRUPT;
VICVectAddr1 = (unsigned long)Uart0_ISR;
// UART1 interrupt handling
U0IER = ENABLE_U0IER_RDA_INTERRUPT;
return;
}
|
Code for another ISR is as follows:
| Code: |
void mainLoopTimerInit(void)
{
// Configure for Timer 0 Match 0
PINSEL0 = PINSEL0 | PINSEL0_12_MAT_1_0;
// Timer Control Register
T1TCR = TCR_COUNTER_RESET;
// Match register values
T1MR0 = 600000;
// T0MR1 = 0;
// T0MR2 = 0;
// T0MR3 = 0;
// Match control register
T1MCR = MCR_INTERRUPT_MR0 |
MCR_RESET_MR0;
// Capture control register
//T1CCR = CCR_CAPTURE_ON_CAP0_FALLING_EDGE |
// CCR_CAPTURE_ON_CAP0_INTERRRUPT;
VICVectAddr2 = (unsigned long)timer_1_match_0_ISR;
VICVectCntl2 = THIS_VIRQ_IS_ENABLED |
TIMER1_INTERRUPT;
VICIntEnable = ENABLE_TIMER1_INTERRUPT;
T1TCR = TCR_COUNTER_ENABLE;
}
void __attribute__((interrupt("IRQ"))) timer_1_match_0_ISR(void)
{
main_loop_enable = 1;
T1IR = IR_RESET_MR0_INTERRUPT ; // Clear interrupt flag
VICVectAddr = 0; // Acknowledge Interrupt
}
|
|
|
| Back to top |
|
 |
jonloveslou
Joined: 20 Jul 2007 Posts: 13
|
Posted: Wed Jul 09, 2008 8:51 am Post subject: |
|
|
Don't you need
| Code: | | __attribute__((interrupt("IRQ"))) | and
in your Uart0_ISR as well? |
|
| Back to top |
|
 |
daa
Joined: 29 Jan 2008 Posts: 8
|
Posted: Tue Jul 15, 2008 4:06 pm Post subject: Fix |
|
|
A past post from somebody named Magnus helped me resolve this issue.
When compiler sees __attribute__ ((interrupt("IRQ"))) specifier, it adds appropriate to handle the entering and exiting the interrupt. It seemed like in my case, for some reason, the compiler wasn't generating the proper code. I removed this specifier and replaced it with __attribute__ ((naked)). If used this attribute, the compiler doesn't add code to handle entering the exiting the interrupt. I used the following code in my crt.s file for interrupt handing.
| Code: |
IRQHandler:
/* Adjust link register and save r0 and lr on IRQ stack */
sub lr, lr, #4
stmfd sp!, {r0, lr}
/*− SPSR needs to be saved on IRQ stack for nested interrupt */
mrs r14, SPSR
stmfd sp!, {r14}
/* Read the AIC Interrupt Vector register to clear the interrupt and fetch IRQ handler address */
ldr r14, =VICVECTADDR
ldr r0 , [r14]
/* Enable IRQ interrupts and switch to Supervisor mode */
msr CPSR_c, #ARM_MODE_SVC
/* Save scratch/used registers and LR in Supervisor Stack */
stmfd sp!, {r0-r12, r14}
/* Branch to the C language routine pointed by the AIC_IVR */
mov r14, pc
bx r0
/* Restore scratch/used registers and LR from Supervisor Stack */
ldmia sp!, {r0-r12,r14}
/* Disable IRQ interrupts and switch back to IRQ mode */
msr CPSR_c, #ARM_MODE_IRQ | I_BIT
/* Mark the End of Interrupt on the AIC */
ldr r14, =VICVECTADDR
str r14, [r14, #0]
/* Restore SPSR_irq and r0 from IRQ stack */
ldmia sp!, {r14}
msr SPSR_cxsf, r14
/* pop r0 and lr from IRQ stack and restore the SPSR_irq; this returns from IRQ interrupt */
ldmia sp!, {r0, pc}^
|
This took care of my problem. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|