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

ISR Handling problem in LPC2378

Hi,

Please help

I have written a c code for LPC2378 microcontroller, inorder to set a timer0 and generate an interrupt whenever the timer overflow occurs and the interrupt is mapped to VIC timer0 vector address 4. The problem is while watching the timer and vector register values.............the overflow is happening finely, the interrupt is generated and notified to the VIC by changing the VIC vector address where the PC has to take control but the pc is not changed to that location to execute the subroutine. Please help me.

Please find my attached code.

#include <stdio.h>
#include <LPC23xx.H> /* LPC23xx definitions */
__irq void T0_IRQHandler (void);
int main (void)
{ /* Enable and setup timer interrupt, start timer */
T0MR0 = 10;
T0MCR = 3; /* Interrupt and Reset on MR0 */
T0TCR = 1; /* Timer0 Enable */
T0PR = 10; /* Timer0 Enable */
VICVectAddr4 = (unsigned long)T0_IRQHandler;/* Set Interrupt Vector */
VICVectCntl4 = 15; /* use it for Timer0 Interrupt priority is 5*/
VICIntEnable = (1 << 4); /* Enable Timer0 Interrupt */
while(1)
{ }
}

/* Import function for turning LEDs on or off */
/* Timer0 IRQ: Executed periodically */

__irq void T0_IRQHandler (void)
{ static int clk_cntr;
clk_cntr++;
if (clk_cntr >= 1000)
{ clk_cntr = 0; /* Activate flag every 1 second */
} T0IR = 1; /* Clear interrupt flag */
VICVectAddr = 0; /* Acknowledge Interrupt */
}

  • Check the contents of your Startup file - particularly any reference to the VICAddress register. The location is different from that used in the LPC21xx/LPC22xx MCUs. Was VIVVectAddr: 0xFFFF F030; now VICAddress: 0xFFFF FF00

    For more details see the NXP Application note: AN10576 Migration to the LPC2300/LPC2400 family.

    --
    Regards,
    Chris Burrows
    Armaide v2.0: LPC2xxx Oberon-07 Development System
    www.cfbsoftware.com/armaide

  • VICVectCntl4 = 15; /* use it for Timer0 Interrupt priority is 5*/
    

    I guess the above is incorrect.

    From LPC23xx.h

    /* The name convention below is from previous LPC2000 family MCUs, in LPC23xx/24xx,
    these registers are known as "VICVectPriority(x)". */
    #define VICVectCntl0   (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x200))
    #define VICVectCntl1   (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x204))
    #define VICVectCntl2   (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x208))
    #define VICVectCntl3   (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x20C))
    #define VICVectCntl4   (*(volatile unsigned long *)(VIC_BASE_ADDR + 0x210))
    

  • Strictly, yes. However, although these have been renamed to indicate their current use more accurately the addresses remain unchanged. i.e. VICVectCntl0-15 == VICVectPriority0-15 so it should still work.

    The comment is not quite right however. It should say:

    ...priority is 15*/

    or better still, use the proper register name and remove the comment as it is then just stating the obvious ;-)

  • Hi Chris,

    I think You are right. it should still work.

    So, maybe the problem is caused by Mohana Ganesh didn't initialize the VIC?

    Step 1. Initialize the VIC
    Step 2. Disable Timer0 Interrupt
    Step 3. Set and Enable Timer0 Interrupt

  • T0MR0 = 10;
    


    10 is very very small, I think.

    (This thread is too difficult to me.)

  • I agree - 10 is way too small. The system may be being swamped by interrupts. My LPC2378 interrupt example written in Oberon-07 works OK and in that I have set T1MR0 := 100000. The relevant code snippets (using Timer1) are:

    Initialisation:
    
      (* Timer match value *)
      SYSTEM.PUT(LPC.T1MR0, 100000);
      (* MR0 Interrupt (MR0I: {0}) and Reset (MR0R: {1}) on match *)
      SYSTEM.PUT(LPC.T1MCR, {0, 1});
    
    
    Module IRQTimer:
    
    PROCEDURE TimerHandler[4]; (* 4 for IRQ or FIQ *)
    BEGIN
      INC(timeVal);
      (* Clear the MR0 interrupt *)
      SYSTEM.PUT(LPC.T1IR, {0});
      (* Update the VIC priority hardware *)
      SYSTEM.PUT(LPC.VICVectAddr, 0)
    END TimerHandler;
    
    
    Client Module:
    
    PROCEDURE Wait();
    VAR
      i: INTEGER;
    BEGIN
      i := IRQTimer.timeVal;
      WHILE ABS(IRQTimer.timeVal - i) < 100 DO END
    END Wait;
    
    

    Chris Burrows
    CFB Software
    Armaide v2.0: LPC2xxx Oberon-07 Development System
    www.cfbsoftware.com/armaide

  • Hi John,

    1. I have initialized the vector address for timer0 to the irq subroutine.
    2. I have given the vector priority for timer0 interrupt as 5.
    3. Then I enabled the Timer0 interrupt.
    4. Then i initialized my timer0 for 10 counts in timer0 match register and to generate an interrupt whenever an interrupt occurs.
    All the initialization i have verified in all the register settings corresponding to the instruction execution. The interrupt is generated. Vic recieves the interrupt and transfer the Timer0 vector address to VICVectorAddr.

    Please tell me in what way the program execution is carried out after this address transfer.

    Also I have checked startup code.

    In the user mode both the FIQ and IRQ's are disabled by setting the CPSR register IRQ and FIQ bit by 1.

    Is there any startup code modification that i have to do to make it work.

  • In the startup code You need to have the following instruction located at the IRQ Vector (0x0000 0018):

      LDR     PC, [PC, #-0x0120]
    

    Then when the IRQ interrupt occurs the PC is loaded with the value that is in VICVectorAddr from where execution continues.

    NOTE: If you have MEMMAP set to User RAM mode, the instruction should be located at the memory mapped interrupt location 0x4000 0018

  • Hi Mohana,

    I would suggest you to download the below Example Code, and give it a try.

    www.standardics.nxp.com/.../code.bundle.lpc23xx.lpc24xx.uvision.zip

    After you extract this zip-file, you can find an example for Timer.

    The path should be:
    [somewhere]\code.bundle.lpc23xx.lpc24xx.uvision\LPC23xx_24xxSampleSoftware.r6\Keil\Timer

    It also needs:
    [somewhere]\code.bundle.lpc23xx.lpc24xx.uvision\LPC23xx_24xxSampleSoftware.r6\Keil\Common

  • Hi Mohana,

    For your own codes, as Chris Burrows said, you should do two things first:

    1.
    In the startup code You need to have the following instruction located at the IRQ Vector (0x0000 0018):

      LDR     PC, [PC, #-0x0120]
    

    2.
    10 is way too small. The system may be being swamped by interrupts. My LPC2378 interrupt example written in Oberon-07 works OK and in that I have set T1MR0 := 100000.

      T0MR0 = 100000;
    

  • Hi Mohana,

    About your case, there are a lot of things I don't understand.

    The problem is while watching the timer and vector register values
    the overflow is happening finely, the interrupt is generated
    and notified to the VIC by changing the VIC vector address
    where the PC has to take control but the pc is not changed
    to that location to execute the subroutine.

    In the user mode both the FIQ and IRQ's are disabled
    by setting the CPSR register IRQ and FIQ bit by 1.

    1. If YOU DISABLED IRQ and FIQ, why Timer0 ISR should work for You?

    2. What does "the overflow is happening finely" mean?

    3. How did you know "the interrupt is generated and notified"? What did you check?

    4. "but the pc is not changed to that location", then, where was the PC pointing to?

    5. You should check the Timer Example from NXP to see what is:

        Step 1. Initialize the VIC
        Step 2. Disable Timer0 Interrupt
        Step 3. Set and Enable Timer0 Interrupt
    

    6. "I have given the vector priority for timer0 interrupt as 5." Both Chris Burrows and me don't think so.

    7. You should consider why "T0MR0 = 10;" is too small; and why the steps are necessary.

        Step 1. Initialize the VIC
        Step 2. Disable Timer0 Interrupt
        Step 3. Set and Enable Timer0 Interrupt
    

    7.1 What is your CCLK/PCLK?
    7.2 Were there other Interrupts triggered?
    7.3 What if you are changing Timer0 Interrupt, and Timer0 Interrupt is triggered?


  • In the user mode both the FIQ and IRQ's are disabled
    by setting the CPSR register IRQ and FIQ bit by 1.

    1. If YOU DISABLED IRQ and FIQ, why Timer0 ISR should work for You?

    [ Insider's Guide NXP LPC2300/2400 ]
    On entry to the IRQ Mode, the I bit in the CPSR is set, causing the IRQ interrupt line to be disabled.