__irq is an identifier used to indicate whether a function is an interrupt function. For different compilers, the position of __irq in the function name is different, for example:
In the ADS compiler: void __irq IRQ_Eint0(void);
In the Keil compiler: void IRQ_Eint0(void) __irq;
But its meaning is the same, it completes the task of identifying the function as an interrupt function. When the compiler compiles and calls this function, it first protects the function entry scene, then executes the interrupt function, and after the function is executed, restores the interrupt scene. This whole process does not require the user to rewrite the code to complete, and is automatically completed by the compiler. Therefore, this also brings problems to ARM systems that do not have the interrupt nesting function. If interrupt nesting occurs when using __irq, the scene protection will be chaotic. For interrupt nesting processing, you can write the interrupt entry scene protection code yourself, and do not use the __irq identifier. (Xiao Dai: How to write nested interrupts is not studied here for the time being.
The summary is as follows
: 1. If you do not want to write the interrupt entry site protection code yourself, and there is no interrupt nesting during use, use __irq to identify our interrupt function in the interrupt function, otherwise an error will occur;
2. If you want to use interrupt nesting in the program, for ARM without interrupt nesting function, you must write the interrupt entry field protection code yourself, and you cannot use __irq to identify your interrupt function, otherwise an error will occur.
In the ADS compiler, the __irq keyword
is used to declare an IRQ interrupt service routine. If you use __irq to declare a function, the function represents an IRQ interrupt service routine, and the compiler will automatically add interrupt context protection code to the function. For the same function, if the keyword "__irq" is removed, the compiler will not add context protection code, but will just treat it as a normal function.
Now everyone should have a certain understanding of the "__irq" keyword. So, do all IRQ interrupt service routines need to be declared using the "__irq" keyword? In fact, it depends on the method of obtaining the "interrupt service routine address":
if the interrupt site is not protected before executing the interrupt service function, then the interrupt service function must be declared using the "__irq" keyword. For example, when the instruction "LDR PC, [PC, #-0xff0]" is executed at 0x0000 0018, the corresponding interrupt service function must be declared using the "__irq" keyword; if the interrupt site has been protected before executing the interrupt service function, then the interrupt service function cannot be declared using the "__irq" keyword.
//==========================================
// NAME: main.c
// DESC: Internal timer 4LED light delay
//==============================================
#define U32 unsigned int
#define _ISR_STARTADDRESS 0x33ffff00
#define pISR_TIMER4 (*(unsigned *)(_ISR_STARTADDRESS+0x58))
#define rSRCPND (*(volatile unsigned *)0x4a000000) //Interrupt request status source pending register
#define rINTMSK (*(volatile unsigned *)0x4a000008) //Interrupt mask control interrupt mask register
#define rINTPND (*(volatile unsigned *)0x4a000010) //Interrupt request status interrupt pending register
#define rTCFG0 (*(volatile unsigned *)0x51000000) //Timer 0 configuration
#define rTCFG1 (*(volatile unsigned *)0x51000004) //Timer 1 configuration
#define rTCON (*(volatile unsigned *)0x51000008) //Timer control
#define rTCNTB4 (*(volatile unsigned *)0x5100003c) //Timer count buffer 4
#define rGPBCON (*(volatile unsigned *)0x56000010) //Port B control
#define rGPBDAT (*(volatile unsigned *)0x56000014) //Port B data
#define rGPBUP (*(volatile unsigned *)0x56000018) //Pull-up control B
void led_init(void)
{
//The onboard LED is GPB[5:8]
rGPBCON = (rGPBCON & ~(0xff<<10)) | (0x55<<10); //rGPBCON is 01, configured as output
rGPBUP = rGPBUP | (0xf<<5); //rGPBUP is 1, disable pull-up
rGPBDAT = rGPBDAT | (0xf<<5); //LED lights are all off
}
void led_display(unsigned char data)
{
//0x0 all off 0xf all on 0x01 0x02 0x04 0x80 each light is on
rGPBDAT = (rGPBDAT & ~(0xf<<5)) | ((~data) <<5);
}
void timer4_init(void)
{
rSRCPND = rSRCPND | (0x1<<14); //Clear timer 4 source request
rINTPND = rINTPND | (0x1<<14); //Clear timer 4 interrupt request
rINTMSK = rINTMSK & ~(0x1<<14); //Turn on timer 4 interrupt
//Timer configuration register 0
//Timer input clock frequency = PCLK / {prescaler value + 1} / {divider value}
//{prescaler value} = 0~255 {divider value} = 2, 4, 8, 16
//25KHz:50MHz/(250*8)=50MHz/(2000)
rTCFG0 = (rTCFG0 & ~(0xff<<8)) | (249<<8); // prescaler1:249
rTCFG1 = (rTCFG1 & ~(0xf<<16)) | (0x2<<16); //divider:8,0b0010
rTCNTB4 = 25000; //Let timer 4 interrupt once every 1 second 25000=1*25000
rTCON = (rTCON & ~(0x7<<20)) | (0x7<<20); //Automatically reload, manually update, start timer 4
rTCON = (rTCON & ~(0x2<<20)); //Turn off manual update
}
void __irq timer4_ISR(void)
{
static int count;
rSRCPND = rSRCPND | (0x1<<14);
rINTPND = rINTPND | (0x1<<14);
//The LED turns on every 0.5 seconds
if (count == 0)
{
led_display(0xf); //LED turns on
count = 1;
}
else if (count == 1)
{
led_display(0x0); //LED turns off
count = 0;
}
}
void Main(void)
{
led_init();
timer4_init();
pISR_TIMER4 = (U32)timer4_ISR;
while(1);
}
-------------------------------------
pISR_UNDEF=(unsigned)HaltUndef;
Any address can be regarded as a pointer to a variable. pISR_UNDEF is equivalent to a pointer variable. pISR_UNDEF=(unsigned)HaltUndef; is equivalent to storing the address of the function HaltUndef in this pointer variable. That is to say, the address of HaltUndef is stored in the address _ISR_STARTADDRESS+0x4. The purpose of this code is to assign a value to the interrupt function. When an interrupt occurs, the system will fetch the address of the interrupt function, that is, the address of HaltUndef, from the address defined by pISR_UNDEF and then execute it. It is equivalent to executing the HaltUndef function when an interrupt occurs.
Previous article:S3C2440 interrupt architecture: external interrupt experiment
Next article:ARM study notes 020: _asm_, CPSR, SPSR, position-independent code and other issues
- 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
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Research on A-type digital flaw detection system based on FPGA.pdf
- Phase loss detection of three-phase three-wire circuit
- What is the packaging of integrated circuits? What are the common types of packaging? What are their respective characteristics?
- GaN tube selection
- I downloaded a source code from the Internet. I don't know what software it was developed with. The file type is shown in the picture. Please help me take a look.
- How to choose MOS tube for low power motor
- 3D Printer Project—STM32F750 Startup Program (Part 2)
- Looking for a chip that can increase 12V to 12.6V/3A
- 【NUCLEO-F746ZG Motor】Based on SDK5.4.5-Project Build
- HDL Language Quick Guide