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

LPC2xxx - fast interrupt FIQ GCC/GNU

Dear all,

I try to get the fast interrupt to run by using the GNU toolchain.
In C source I defined a function with the extension __attribute__ ((interrupt("FIQ"))) as the fast interrupt service routine.
Currently the program stucks at the dummy handler of the "startup.s" and I don't know how to bring the handler and the service routine together to run.

Thank you,
Best regards,
Detlef Weidner

  • Hi Detlef,

    I use the LPC2129 and GNU Toolchain too. My application needs a Timer Interrupt with highest priority, it works very fine with FIQ. The ISR is called "Timer1ISR" for example.

    First of all, you have to change the startup code (startup.s) to put your specified ISR-Address to the FIQ-Vector (FIQ_Handler: B Timer1ISR) and you have to make this symbol public for other files and maybe the linker (.global Timer1ISR).

    Please have a look on the following code snippet to see the 2 changes in comparison
    to the original startup.s:


    from startup.s:

    .........................
    
    # Starupt Code must be linked first at Address at which it expects to run.
    
            .text
            .arm
            .global Timer1ISR  /* FIQ ISR in my application */
            .global _startup
            .func   _startup
    _startup:
    
    
    # Exception Vectors
    #  Mapped to Address 0.
    #  Absolute addressing mode must be used.
    #  Dummy Handlers are implemented as infinite loops which can be modified.
    
    Vectors:        LDR     PC, Reset_Addr
                    LDR     PC, Undef_Addr
                    LDR     PC, SWI_Addr
                    LDR     PC, PAbt_Addr
                    LDR     PC, DAbt_Addr
                    NOP                        /* Reserved Vector */
    #               LDR     PC, IRQ_Addr
                    LDR     PC, [PC, #-0x0FF0] /* Vector from VIC */
                    LDR     PC, FIQ_Addr
    
    Reset_Addr:     .word   Reset_Handler
    Undef_Addr:     .word   Undef_Handler
    SWI_Addr:       .word   SWI_Handler
    PAbt_Addr:      .word   PAbt_Handler
    DAbt_Addr:      .word   DAbt_Handler
                    .word   0                  /* Reserved Address */
    IRQ_Addr:       .word   IRQ_Handler
    FIQ_Addr:       .word   FIQ_Handler
    
    Undef_Handler:  B       Undef_Handler
    SWI_Handler:    B       SWI_Handler
    PAbt_Handler:   B       PAbt_Handler
    DAbt_Handler:   B       DAbt_Handler
    IRQ_Handler:    B       IRQ_Handler
    FIQ_Handler:    B       Timer1ISR          /* FIQ ISR Address */
    
    
    # Reset Handler
    
    Reset_Handler:            /* Programm starts here after RESET */
    
    .........................
    


    In a second step you have to define the ISR in your Header file (.h).

    In my case it is not necessary to use the VIC, there is no definition of a

    VICVectAddr or VICVectCtrl in Initialization and no VICVectAddr dummy write at the

    End of the ISR.

    Here is the ISR definition, the ISR and the ISR Init-File to see how it all works together:


    //-----------------------------------------------------
    
    
    // Interrupt Service Routines
    void Timer1ISR (void) __attribute__ ((interrupt("FIQ")));
    
    
    //-----------------------------------------------------
    
    
    void Timer1ISR (
      void
      )
    {
      ++gTimerTick;                // global Timer Tick 1 ms
      T1IR = 1;                    // Clear interrupt flag
    } // VICVectAddr dummy write not needed in this case
    
    
    //-----------------------------------------------------
    
    
    void init_timer1 (
      void
      )
    {                              // the pclk is 15 MHz
      PCONP        |= (0x01 << 2); // power up Timer1 Peripheral
      T1TCR         = 2;           // T1TC, T1PC Reset on next pclk
      T1MR0         = 14999;       // 1 ms = 15.000-1 counts
      T1MCR         = 3;           // Interrupt and Reset on MR0
      VICIntSelect |= (0x01 << 5); // Timer1 Interrupt is FIQ Type
      VICIntEnable  = (0x01 << 5); // Enable Timer1 Interrupt
      gTimerTick    = 0;           // clear interrupt counter
      T1TCR         = 1;           // Timer1 Enable
    }
    
    //-----------------------------------------------------
    


    With best regards

    Dietmar Wengler