Hello Everyone, I am using ARM7 mcu (LPC2148 by NXP) to implement my project. In my code I am using UART0 Data received and Timer0 Match interrupts at a time. But the problem is that my controller enters a unpredictable state when I enable both the interrupts. If I enable either an UART0 data received interrupt only or timer0 match interrupt only then my code works fine; but when I enable both the interrupts, the code doesn't work. I think that it is a simple bug (similar to updating a register or something) but I am unable to fix it. Please help me.
This is my code....
#define T0_PRESCALAR 59 //This Value defines the divider of the PCLK //Here Address slot 0 is used for timer0 overflow interrupt. You have to use different slots for different types of interrupts #define TIMER0_ADDRESS_SLOT VICVectAddr0 #define TIMER0_CONTROL_SLOT VICVectCntl0 #define TIMER0_UNIQUE_ID 0x04 //This is 5 bit unique no to be allotted to the interrupt
void def_isr(void) __irq; #define DEFAULT_ISR_PTR (unsigned long)def_isr
#define STATUS 27 //P1.27
//PLL Macros #define PLLE 0 #define PLLC 1 #define PLOCK 10
//Timer0 Macros #define MR0I 0 #define MR0R 1 #define MR0S 2
#define T0_START 0x01
//Basic bitwise operations #define sbi(port, bit) (port) |= (1 << (bit)) #define cbi(port, bit) (port) &= ~(1 << (bit))
#define bit_is_set(pin,bit) (pin)&(1<<(bit)) #define bit_is_clear(pin,bit) !((pin)&(1<<(bit)))
//Macros for UART0 #define TX 0 #define RX 1 #define DLAB 7 #define WL0 0 #define WL1 1 #define RDR 0 #define RBR 0 #define THRE 5 #define TEMT 6
#include<LPC214x.h>
void init_ports(void);
void timer0overflow(void) __irq;
void enable_uart0int(void); void uart0DataReceived(void) __irq;
void clk_config(void);//will setup pll void delay(void);
//will initialize timer0 if enable_int==1 then interrupts will be initialized //overflow_fn_ptr is the pointer to the timer0 match irq. void init_timer0(unsigned char enable_int,unsigned long overflow_fn_ptr);
//Will start timer0 if 1 is passed and will stop timer0 if 0 is passed void start_timer0(unsigned char start); //will enable timer0 match interrupt void enable_timer0overflowint(unsigned long overflow_fn_ptr);
void uart0_init(void);//Will initialize UART0
volatile static unsigned char received_values[8],index; volatile unsigned char toggle=0;
int main(void) { unsigned char i; clk_config(); init_ports(); IO1SET=(1<<STATUS); delay(); init_timer0(1,(unsigned long)timer0overflow); T0MR0 = 19; //Enter Proper Match Value uart0_init(); enable_uart0int(); U0IER=(1<<RBR); start_timer0(1); delay(); IO1CLR=(1<<STATUS); while(1) { if(index==2) { if(received_values[0]=='M'&&received_values[1]=='S') { IO1SET=(1<<STATUS); delay(); IO1CLR=(1<<STATUS); delay(); } index=0; } delay(); } }
void def_isr(void) __irq { VICVectAddr = 0x00000000; //Dummy write to signal end of interrupt }
void timer0overflow(void) __irq { if(bit_is_set(T0IR,0))//Interrupt for match register 0 occourrs { sbi(T0IR,0); if(toggle) { IO1SET=(1<<STATUS); toggle=0; } else { IO1CLR=(1<<STATUS); toggle=1; } } VICVectAddr = 0x00000000; //Dummy write to signal end of interrupt// }
void uart0DataReceived(void) __irq { volatile int status = (U0IIR&0x0000000F);//status = (U0IIR&0x0000000E); volatile unsigned char value; if(status==4) { value = U0RBR; if(index<2) { received_values[index++]=value; } } else if(status==6)//This is written to clear the flags { value=U0LSR; } else if(status==0xC) { value=U0RBR; } VICVectAddr = 0x00000001; //Dummy write to signal end of interrupt }
void init_ports(void) { PINSEL0=0; PINSEL1=0; PINSEL2=0; IO1DIR=(1<<STATUS); }
void enable_uart0int(void) { cbi(VICIntSelect,6); VICDefVectAddr=(unsigned long)def_isr; VICVectAddr1=(unsigned long)uart0DataReceived; VICVectCntl1=0x00000026; VICIntEnable|=(1<<6);//Enable UART0 FIQ/IRQ }
void clk_config(void) { PLL0FEED=0xAA; PLL0FEED=0x55; PLL0CFG=4; //Multiply Crystal Speed 5 times it should be 4 for 5 PLL0CON=(1<<PLLE)|(1<<PLLC); while(!(PLL0STAT&(1<<PLOCK))); VPBDIV=0x01; //APB Bus speed same as CPU Speed }
void delay(void) { int i,j; for(i=0;i<100;i++) { for(j=0;j<10000;j++); } }
void init_timer0(unsigned char enable_int,unsigned long overflow_fn_ptr) { T0CTCR=0x00;//Select Timer Mode of Operation T0MCR |= (1<<MR0R); /*Reset Timer0 On Match (This Register is also to be used to enable interrupts)*/ T0EMR=0; /*This Register Decides whether you want to generate output on the PWM pins or not*/ T0PR=T0_PRESCALAR; /*This configuration is capable of just starting the timer0 of the MCU Configuration is still incomplete for generating interrupts. */ if(enable_int) { T0MCR|=(1<<MR0I); /*Locally Enable Timer0 Match with match register 0*/ enable_timer0overflowint(overflow_fn_ptr); } }
void enable_timer0overflowint(unsigned long overflow_fn_ptr) { cbi(VICIntSelect,4);//Timer0 Interrupt as IRQ is selected VICDefVectAddr=DEFAULT_ISR_PTR; TIMER0_ADDRESS_SLOT=overflow_fn_ptr; TIMER0_CONTROL_SLOT=(1<<5)|TIMER0_UNIQUE_ID; /*The lower 5 bits should be unique for different interrupts and the sixth bit is the interrupt enable bit*/ VICIntEnable|=(1<<4);//Enable Timer0 interrupt Globally }
void start_timer0(unsigned char start) { if(start) { T0TCR=T0_START; } else { T0TCR=0; } }
void uart0_init(void) { PINSEL0=0x00000005;//Selects P0.0 as TX & P0.1 as RX U0LCR=(1<<WL0)|(1<<WL1);//WL1 & WL2 8 bit data, no stop bits & parity sbi(U0LCR,DLAB); U0FDR=0x52; U0DLM=0x01; U0DLL=0x17; cbi(U0LCR,DLAB); }
Please Help.
I had defined the ISR. This is its definition.
void timer0overflow(void) __irq { if(bit_is_set(T0IR,0))//Interrupt for match register 0 occourrs { sbi(T0IR,0); if(toggle) { IO1SET=(1<<STATUS); toggle=0; } else { IO1CLR=(1<<STATUS); toggle=1; } } VICVectAddr = 0x00000000; //Dummy write to signal end of interrupt// } void uart0DataReceived(void) __irq { volatile int status = (U0IIR&0x0000000F); status = (U0IIR&0x0000000E); volatile unsigned char value; if(status==4) { value = U0RBR; if(index<2) { received_values[index++]=value; } } else if(status==6)//This is written to clear the flags if any { value=U0LSR; } else if(status==0xC) { value=U0RBR; } VICVectAddr = 0x00000001; //Dummy write to signal end of interrupt }
I had also provided the prototypes of these functions above the main() as
void timer0Overflow(void) __irq; void uart0datareceived(void) __irq;