This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Unable to use two IRQs at a time.

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;