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

Keil programming for interrupts

Hi everyone,

I dont know what should I do to let the keil compiler know refer to which function when interrupt occur. I know interrupt functions are followed with _irq prefix but there may be several of these functions!

Parents
  • Dear Westonsupermare,

    Thanks, I am using LPC2138.
    I see in a example program for usart0 interrupt handlers like below. I dont know where in this function compiler understands USART0 interrupt calls this function:

    void UART0Handler (void) __irq
    {
        BYTE IIRValue, LSRValue;
        BYTE Dummy;
    
        IENABLE;                            /* handles nested interrupt */
        IIRValue = U0IIR;
    
        IIRValue >>= 1;                       /* skip pending bit in IIR */
        IIRValue &= 0x07;                       /* check bit 1~3, interrupt identification */
        if ( IIRValue == IIR_RLS )          /* Receive Line Status */
        {
            LSRValue = U0LSR;
            /* Receive Line Status */
            if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
            {
                /* There are errors or break interrupt */
                /* Read LSR will clear the interrupt */
                UART0Status = LSRValue;
                Dummy = U0RBR;              /* Dummy read on RX to clear
                                            interrupt, then bail out */
                IDISABLE;
                VICVectAddr = 0;            /* Acknowledge Interrupt */
                return;
            }
            if ( LSRValue & LSR_RDR )   /* Receive Data Ready */
            {
                /* If no error on RLS, normal ready, save into the data buffer. */
                /* Note: read RBR will clear the interrupt */
                UART0Buffer[UART0Count] = U0RBR;
                UART0Count++;
                if ( UART0Count == BUFSIZE )
                {
                    UART0Count = 0;         /* buffer overflow */
                }
            }
        }
        else if ( IIRValue == IIR_RDA )     /* Receive Data Available */
        {
            /* Receive Data Available */
            UART0Buffer[UART0Count] = U0RBR;
            UART0Count++;
            if ( UART0Count == BUFSIZE )
            {
                UART0Count = 0;             /* buffer overflow */
            }
        }
        else if ( IIRValue == IIR_CTI )     /* Character timeout indicator */
        {
            /* Character Time-out indicator */
            UART0Status |= 0x100;           /* Bit 9 as the CTI error */
        }
        else if ( IIRValue == IIR_THRE )    /* THRE, transmit holding register empty */
        {
            /* THRE interrupt */
            LSRValue = U0LSR;               /* Check status in the LSR to see if
                                            valid data in U0THR or not */
            if ( LSRValue & LSR_THRE )
            {
                UART0TxEmpty = 1;
            }
            else
            {
                UART0TxEmpty = 0;
            }
        }
    
        IDISABLE;
        VICVectAddr = 0;            /* Acknowledge Interrupt */
    }
    

Reply
  • Dear Westonsupermare,

    Thanks, I am using LPC2138.
    I see in a example program for usart0 interrupt handlers like below. I dont know where in this function compiler understands USART0 interrupt calls this function:

    void UART0Handler (void) __irq
    {
        BYTE IIRValue, LSRValue;
        BYTE Dummy;
    
        IENABLE;                            /* handles nested interrupt */
        IIRValue = U0IIR;
    
        IIRValue >>= 1;                       /* skip pending bit in IIR */
        IIRValue &= 0x07;                       /* check bit 1~3, interrupt identification */
        if ( IIRValue == IIR_RLS )          /* Receive Line Status */
        {
            LSRValue = U0LSR;
            /* Receive Line Status */
            if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
            {
                /* There are errors or break interrupt */
                /* Read LSR will clear the interrupt */
                UART0Status = LSRValue;
                Dummy = U0RBR;              /* Dummy read on RX to clear
                                            interrupt, then bail out */
                IDISABLE;
                VICVectAddr = 0;            /* Acknowledge Interrupt */
                return;
            }
            if ( LSRValue & LSR_RDR )   /* Receive Data Ready */
            {
                /* If no error on RLS, normal ready, save into the data buffer. */
                /* Note: read RBR will clear the interrupt */
                UART0Buffer[UART0Count] = U0RBR;
                UART0Count++;
                if ( UART0Count == BUFSIZE )
                {
                    UART0Count = 0;         /* buffer overflow */
                }
            }
        }
        else if ( IIRValue == IIR_RDA )     /* Receive Data Available */
        {
            /* Receive Data Available */
            UART0Buffer[UART0Count] = U0RBR;
            UART0Count++;
            if ( UART0Count == BUFSIZE )
            {
                UART0Count = 0;             /* buffer overflow */
            }
        }
        else if ( IIRValue == IIR_CTI )     /* Character timeout indicator */
        {
            /* Character Time-out indicator */
            UART0Status |= 0x100;           /* Bit 9 as the CTI error */
        }
        else if ( IIRValue == IIR_THRE )    /* THRE, transmit holding register empty */
        {
            /* THRE interrupt */
            LSRValue = U0LSR;               /* Check status in the LSR to see if
                                            valid data in U0THR or not */
            if ( LSRValue & LSR_THRE )
            {
                UART0TxEmpty = 1;
            }
            else
            {
                UART0TxEmpty = 0;
            }
        }
    
        IDISABLE;
        VICVectAddr = 0;            /* Acknowledge Interrupt */
    }
    

Children
  • So an ARM7 with an NXP/LPC Vectored Interrupt Controller (VIC).

    The jump via the VIC is likely in startup.s and when you configure the VIC you put the address of your IRQ Handler into the slot/vector set aside for the UART0.

  • For Example:

    /******************************************************************************
    ** Function name:               install_irq
    **
    ** Descriptions:                Install interrupt handler
    ** parameters:                  Interrupt number, interrupt handler address,
    **                                              interrupt priority
    ** Returned value:              true or false, return false if IntNum is out of range
    **
    ******************************************************************************/
    DWORD install_irq( DWORD IntNumber, void *HandlerAddr, DWORD Priority )
    {
        DWORD *vect_addr;
        DWORD *vect_prio;
    
        VICIntEnClr = 1 << IntNumber; /* Disable Interrupt */
        if ( IntNumber >= VIC_SIZE )
        {
                    return ( FALSE );
        }
        else
        {
                    /* find first un-assigned VIC address for the handler */
                    vect_addr = (DWORD *)(VIC_BASE_ADDR + VECT_ADDR_INDEX + IntNumber*4);
                    vect_prio = (DWORD *)(VIC_BASE_ADDR + VECT_PRIO_INDEX + IntNumber*4);
                    *vect_addr = (DWORD)HandlerAddr;        /* set interrupt vector */
                    *vect_prio = Priority;
                    VICIntEnable = 1 << IntNumber;    /* Enable Interrupt */
                    return( TRUE );
        }
    
    /******************************************************************************
    ** Function name:               init_timer
    **
    ** Descriptions:                Initialize timer, set timer interval, reset timer,
    **                                              install timer interrupt handler
    **
    ** parameters:                  timer number and timer interval
    ** Returned value:              true or false, if the interrupt handler can't be
    **                                              installed, return false.
    **
    ******************************************************************************/
    DWORD init_timer ( BYTE timer_num, DWORD TimerInterval )
    {
      if ( timer_num == 0 )
      {
            timer0_counter = 0;
            T0MR0 = TimerInterval;
            T0MCR = 3;                              /* Interrupt and Reset on MR0 */
    #if FIQ
            /* FIQ is always installed. */
            VICIntSelect |= (0x1<<4);
            VICIntEnable = (0x1<<4);
            return (TRUE);
    #else
            if ( install_irq( TIMER0_INT, (void *)Timer0Handler, HIGHEST_PRIORITY ) == FALSE )
            {
              return (FALSE);
            }
            else
            {
              return (TRUE);
            }
    #endif
      }
      else if ( timer_num == 1 )
      {
            timer1_counter = 0;
            T1MR0 = TimerInterval;
            T1MCR = 3;                              /* Interrupt and Reset on MR1 */
    #if FIQ
            VICIntSelect |= (0x1<<5);
            VICIntEnable = (0x1<<5);
            return (TRUE);
    #else
            if ( install_irq( TIMER1_INT, (void *)Timer1Handler, HIGHEST_PRIORITY ) == FALSE )
            {
              return (FALSE);
            }
            else
            {
              return (TRUE);
            }
    #endif
      }
      return (FALSE);
    }
    

  • The same source code bundle where you did find this UART ISR did also contain the source code to initialize the UART - and that code did contain a source code line that used the name of the ISR function. That's the line that associate the UART ISR with that specific UART.

    It's always a good idea to not just cut some lines from example programs but to actually try and run the examples and to use the processor datasheet/user manual and lookup the description of how different parts of the processor works until you understand exactly what the source code deoes.

  • Dear all friends,

    Thanks for your helpful advises. Yes I see that the function USARTInit() installs my usart function 'UART0Handler' in the VIC table by following code:

     if ( install_irq( UART0_INT, (void *)UART0Handler ) == FALSE )
        {
            return (FALSE);
        }