ARM7 LPC2103 interrupt processing method

Publisher:Changsheng520Latest update time:2019-01-16 Source: eefocusKeywords:arm7  LPC2103  interrupt Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The Vectored Interrupt Controller (VIC) has 32 interrupt request inputs that can be programmed into three categories: FIQ, Vectored IRQ, and Non-Vectored IRQ. The programmable allocation mechanism means that the interrupt priorities of different peripherals can be dynamically allocated and adjusted.


Fast interrupt request (FIQ) requires the highest priority. If more than one request is assigned to FIQ, VIC will OR the interrupt requests and generate a FIQ signal to the ARM processor. This is possible when only one interrupt is assigned to FIQ.


The shortest FIQ wait time, because the FIQ service routine simply starts the device processing. However, if more than one interrupt is assigned to the FIQ level, the FIQ service routine reads a word from the VIC to identify which FIQ interrupt source generated the interrupt request.


 Vectored IRQ has medium priority. This level can assign 16 of the 32 requests. Any of the 32 requests can be assigned to any of the 16 vectored IRQ slots, with slot0 having the highest priority and slot15 having the lowest priority.


  Non-vectored IRQs have the lowest priority. The VIC "ORs" all vectored and non-vectored IRQs to generate an IRQ signal to the ARM processor. The IRQ service routine can be immediately started by reading a register of the VIC and jumps to the corresponding address. If any of the vectored IRQs makes a request, the VIC provides the address of the highest priority requesting IRQ service routine, otherwise it provides the address of the default routine. This default routine is shared by all non-vectored IRQs. The default routine can read another VIC register to determine which IRQ is activated.




1. Vector Interrupt


1.1 The first method is that each interrupt can directly jump to the corresponding interrupt processing function


1.1.1 Startup Code

        ARM

__vector:

        ;;

        ldr   pc,[pc,#+24]              ;; Reset

        ldr   pc,[pc,#+24]              ;; Undefined instructions

        B   .                           ;; Software interrupt (SWI/SVC)

        ldr   pc,[pc,#+24]              ;; Prefetch abort

        ldr   pc,[pc,#+24]              ;; Data abort

__vector_0x14:

        DC32  0                         ;; RESERVED

        ldr   pc,[pc,#-0xFF0]           ;; IRQ

        ldr   pc,[pc,#+24]              ;; FIQ


        DC32  __iar_program_start       ;; Reset

        DC32  undef_handler             ;; Undefined instructions

        DC32  0                         ;; Software interrupt (SWI/SVC)

        DC32  prefetch_handler          ;; Prefetch abort

        DC32  data_handler              ;; Data abort

        DC32  0                         ;; RESERVED

        DC32  0                         ;; IRQ

        DC32  fiq_handler               ;; FIQ

    The FIQ here is easy to understand, but why does the IRQ here need PC-0XFF0?


     Combined with the three-stage pipeline of ARM7, this problem should be very simple. When the program jumps to 0X18 to execute instructions, PC should be 0x18+8=0x20.

     Then 0x20-0xff0=0xfffff030, where 0XFFFFF030 is exactly the address of VICVectAddr, which means that through a simple ARM instruction,

     Implemented IRQ program jump


1.1.2 Initialization, taking serial port interrupt as an example

Set IRQ slot 0 (the highest priority among vector interrupts) as the serial port interrupt, and assign the interrupt handler IRQ_UART_0 to VICVectAddr0

void Init_uart0()

{

    U0LCR = 0x83; //Enable access to the divisor register, 8-bit character length     

    U0DLM = 0x00; // 6 at 115200 and 0x006c at 9600

    U0DLL = 0x6c; 

    U0LCR = 0x03; //Disable access to divisor register       

    U0IER = 0x03; // Allow receive data available interrupt [bit 0] and transmit buffer empty interrupt [bit 1] 

    //The following is the interrupt setting set to interrupt channel 0

    VICIntSelect = 0x00000000;

    VICVectCntl0 = 0x26; //5th position 1: vector enable, [4:0] interrupt source number

    VICVectAddr0 = (unsigned long)&IRQ_UART_0;

    //jtk When a vector interrupt occurs, the processor automatically assigns VICVectAddrN to VICVectAddr

    VICIntEnable = 0x00000040;   

    BRUSH0 |= 0x00000005;

}


1.1.3 Interrupt Handling Function

__irq __arm void IRQ_UART_0(void)

{

    …………

    VICVectAddr = 0x00;

}




1.2 The second method is to jump to a processing function first and then jump to the corresponding interrupt processing function


1.2.1 Startup Code


        ARM

__vector:  

        ;jtk absolute jump, jump to the corresponding exception handler, PC always points to the address of the next two instructions of the current instruction, that is, the value of PC is the address value of the current instruction plus 8 bytes

        ;jtk So LDR PC, [PC,#24] jumps to 24+8=32 bytes later

        ldr pc,[pc,#+24] ;; Reset jtk Jump to __iar_program_start

        ldr   pc,[pc,#+24]              ;; Undefined instructions

        B   .                           ;; Software interrupt (SWI/SVC)

        ldr   pc,[pc,#+24]              ;; Prefetch abort

        ldr   pc,[pc,#+24]              ;; Data abort

__vector_0x14

        DC32  0                         ;; RESERVED

        ldr   pc,[pc,#+24]              ;; IRQ

        ldr   pc,[pc,#+24]              ;; FIQ

;jtk The interrupt vector above jumps here. If it is defined in C language,

; If the following labels have corresponding processing procedures in C language, then once an interrupt occurs, it will jump to the corresponding interrupt function

        DC32  __iar_program_start       ;; Reset

        DC32  undef_handler             ;; Undefined instructions

        DC32  0                         ;; Software interrupt (SWI/SVC)

        DC32  prefetch_handler          ;; Prefetch abort

        DC32  data_handler              ;; Data abort

        DC32  0                         ;; RESERVED

        DC32 irq_handler ;; IRQ jumps to the irq_handler function

        DC32  fiq_handler               ;; FIQ


        

void Init_key()

{

    PINSEL1_bit.P0_16 = 1; //Pin P0.16 is selected as external interrupt function


    EXTWAKE=0X00; //jtk is not used for wake-up. When it is 1, the processor wakes up from power-down mode.

    EXTMODE =0x00; //jtk is level activated when 0, and edge activated when 1

    EXTPOLAR=0x00; //jtk is valid when it is low level or falling edge


    VICIntSelect_bit.EINT0 =0; //The 14th bit of the jtk interrupt selection register can be 0.

    //5th position 1: vector enable, [4:0] interrupt source number

    VICVectCntl9 = 0x20|14; //Set IRQ slot 9 to vector interrupt (bit 5 is 1 to enable vector interrupt, 0 is non-vector interrupt)

    VICVectAddr9 = (unsigned int)KEY_IRQ; //When set as vector interrupt, the interrupt function address is given to VICVectAddrN  

    VICDefVectAddr = (unsigned long)KEY_IRQ; //When set to non-vector interrupt, the interrupt function address is given to VICDefVectAddr 

    //When an IRQ service routine reads the vector address register VICVectAddr and no IRQ slot responds, it returns the address of VICDefVectAddr

    //So when there is no IRQ slot response, the address of VICDefVectAddr is read, and this becomes the program for handling non-vectored interrupts

    //KEY_IRQ; //interrupt function address 


    EXTINT=0X01; //jtk clears the EXTINT register by writing 1 to it

    VICIntEnable_bit.EINT0 = 1; //Interrupt enable register table shows that the interrupt source number of ext0 is 14, and the 14th bit is 1.

}


 __irq __arm void irq_handler (void) //Public interrupt handling function, check whether VICVectAddr is empty

{

    void (*interrupt_function)();

    unsigned int vector;


    vector = VICVectAddr;     // Get interrupt vector.

//jtk If it is used as a vector interrupt, you can assign VICVectAddrN to vector or assign VICVectAddr to vector.

//jtk When a vector interrupt occurs, the processor automatically assigns VICVectAddrN to VICVectAddr

    interrupt_function = (void(*)())vector;

    if(interrupt_function !=NULL){

       interrupt_function();  // Call vectored interrupt function.

    }else{

        VICVectAddr = 0;      // Clear interrupt in VIC.

    }

}




2. Non-vectored interrupts


        ARM

__vector:  

        ;jtk absolute jump, jump to the corresponding exception handler, PC always points to the address of the next two instructions of the current instruction, that is, the value of PC is the address value of the current instruction plus 8 bytes

        ;jtk So LDR PC, [PC,#24] jumps to 24+8=32 bytes later

        ldr pc,[pc,#+24] ;; Reset jtk Jump to __iar_program_start

        ldr   pc,[pc,#+24]              ;; Undefined instructions

        B   .                           ;; Software interrupt (SWI/SVC)

        ldr   pc,[pc,#+24]              ;; Prefetch abort

        ldr   pc,[pc,#+24]              ;; Data abort

__vector_0x14

        DC32  0                         ;; RESERVED

        ldr   pc,[pc,#+24]              ;; IRQ

        ldr   pc,[pc,#+24]              ;; FIQ

;jtk The interrupt vector above jumps here. If it is defined in C language,

; If the following labels have corresponding processing procedures in C language, then once an interrupt occurs, it will jump to the corresponding interrupt function

        DC32  __iar_program_start       ;; Reset

        DC32  undef_handler             ;; Undefined instructions

        DC32  0                         ;; Software interrupt (SWI/SVC)

        DC32  prefetch_handler          ;; Prefetch abort

        DC32  data_handler              ;; Data abort

        DC32  0                         ;; RESERVED

        DC32 irq_handler ;; IRQ jumps to the irq_handler function

        DC32  fiq_handler               ;; FIQ


 2.1.2 Initialization

void Init_key()

{

    PINSEL1_bit.P0_16 = 1; //Pin P0.16 is selected as external interrupt function


    EXTWAKE=0X00; //jtk is not used for wake-up. When it is 1, the processor wakes up from power-down mode.

    EXTMODE =0x00; //jtk is level activated when 0, and edge activated when 1

    EXTPOLAR=0x00; //jtk is valid when it is low level or falling edge


    VICIntSelect_bit.EINT0 =0; //The 14th bit of the jtk interrupt selection register can be 0.

    //5th position 1: vector enable, [4:0] interrupt source number

    VICDefVectAddr = (unsigned long)KEY_IRQ; //When set to non-vector interrupt, the interrupt function address is given to VICDefVectAddr

    //When an IRQ service routine reads the vector address register VICVectAddr and no IRQ slot responds, it returns the address of VICDefVectAddr

    //So when there is no IRQ slot response, the address of VICDefVectAddr is read, and this becomes the program for handling non-vectored interrupts

    //KEY_IRQ; //interrupt function address 


    EXTINT=0X01; //jtk clears the EXTINT register by writing 1 to it

    VICIntEnable_bit.EINT0 = 1; //Interrupt enable register table shows that the interrupt source number of ext0 is 14, and the 14th bit is 1.

}


2.1.3 Public interrupt handling function

 __irq __arm void irq_handler (void) //Public interrupt handling function, check whether VICVectAddr is empty

{

    void (*interrupt_function)();

    unsigned int vector;


/*********jtk When there is only one interrupt source, you can handle it like this*****************************/

    vector = VICVectAddr;     // Get interrupt vector.

//jtk If it is used as a non-vector interrupt, you can assign VICDefVectAddr to vector or assign VICVectAddr to vector.

//jtk Because when a non-vector interrupt occurs, the processor automatically assigns VICDefVectAddr to VICVectAddr

    interrupt_function = (void(*)())vector;

    if(interrupt_function !=NULL){

       interrupt_function();  // Call vectored interrupt function.

    }else{

        VICVectAddr = 0;      // Clear interrupt in VIC.

    }


/*********jtk When there is only one interrupt source, you can handle it like this*****************************/



//jtk When there are multiple interrupts, you can read the VICIRQStatus register to determine which interrupt occurred and jump to the corresponding processing function

}


2.1.4 Interrupt Handling Function


void KEY_IRQ(void)

{  

  EXTINT=0X01; //jtk clears the EXTINT register by writing 1 to it

  …………

 VICVectAddr = 0; //When the interrupt program ends, write "0" to the vector address register



3. FIQ Interrupt


You can set the corresponding interrupt to FIQ by setting VICIntSelect

When multiple FIQ interrupts are set, you can determine which interrupt is which by reading the VICFIQStatus register. The processing method is similar to that of non-vectored interrupts.




4. If there are both vector interrupts and non-vector interrupts in the interrupt, the processing function of the vector interrupt is placed in the corresponding VICVectAddrN, and the non-vector interrupt is placed in VICDefVectAddr. Then, different non-vector interrupts can be distinguished in the function corresponding to VICDefVectAddr.

--------------------- 

Author: swjtk 

Source: CSDN 

Original text: https://blog.csdn.net/DICKJTK/article/details/8606893 

Copyright Statement: This article is an original article by the blogger. Please attach the blog link when reprinting!


Keywords:arm7  LPC2103  interrupt Reference address:ARM7 LPC2103 interrupt processing method

Previous article:Simple Analysis of ARM Interrupt Vector Table
Next article:Example programs for 10 software filtering methods for microcontrollers

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号