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!
Previous article:Simple Analysis of ARM Interrupt Vector Table
Next article:Example programs for 10 software filtering methods for microcontrollers
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- Broadcom Wi-Fi 6E technology makes the Galaxy S21 Ultra shine
- Simulation Problems with Strobe Display
- dsp28335 phase shift full bridge easy to understand program
- Optimizing DSP Power Budget by Adjusting Voltage Regulators
- [Erha Image Recognition Artificial Intelligence Vision Sensor] Review 3: Firmware Upgrade via HUSKYLENS Uploader
- [Portable programmable meter] Ready to start soldering the board
- TMS320VC5509A development board hardware LED indicators and buttons
- EEWORLD University ---- Wide input DC-DC converters that meet low quiescent current requirements in industrial applications
- Is Python worth learning? Is it easy to learn?
- TMP112 read timing is incorrect, can produce results, 9 more clocks