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.
Unable to use two IRQs at a time. maybe reading the instructions would help you clearly were unable to read those for posting code
Sorry for the pervious post. Actually the code is quite big that's why there is the problem. I am rewriting the interrupt initialization routines. If there is a problem in that then please indicate.
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 } //after call to this function I wrote U0IER=(1<<RBR); 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 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 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; } }
Unable to use two IRQs at a time. obviously you can't use ISRs you do not have
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;