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.
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:
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
}