Introduction: When discussing the ARM porting process, I think we should first understand the working mode of the CPU in each case, the particularity of the registers, and the general process of interrupt processing.
In the process of transplanting uc/os-II, there is a general irq interrupt processing function, the implementation process of which is as follows:
OS_CPU_IRQ_ISR
STMFD SP!, {R1-R3} ; We will use R1-R3 as temporary registers
MOV R1, SP
ADD SP, SP, #12 ;Adjust IRQ stack pointer
SUB R2, LR, #4 ;Adjust PC for return address to task
MRS R3, SPSR ; Copy SPSR (Task CPSR)
MSR CPSR_cxsf, #SVCMODE|NOINT ;Change to SVC mode
; SAVE TASK''S CONTEXT ONTO OLD TASK''S STACK
STMFD SP!, {R2} ; Push task''s PC
STMFD SP!, {R4-R12, LR} ; Push task''s LR,R12-R4
LDMFD R1!, {R4-R6} ; Load Task''s R1-R3 from IRQ stack
STMFD SP!, {R4-R6} ; Push Task''s R1-R3 to SVC stack
STMFD SP!, {R0} ; Push Task''s R0 to SVC stack
STMFD SP!, {R3} ; Push task''s CPSR
LDR R0,=OSIntNesting ;OSIntNesting++
LDRB R1,[R0]
ADD R1,R1,#1
STRB R1,[R0]
CMP R1,#1 ;if(OSIntNesting==1){
BNE %F1
LDR R4,=OSTCBCur ;OSTCBHighRdy->OSTCBStkPtr=SP;
LDR R5,[R4]
STR SP,[R5] ;}
1 MSR CPSR_c,#IRQMODE|NOINT ;Change to IRQ mode to use IRQ stack to handle interrupt
LDR R0, =INTOFFSET
LDR R0, [R0]
LDR R1, IRQIsrVect
MOV LR, PC ; Save LR before jump to the C function we need return back
LDR PC, [R1, R0, LSL #2] ; Call OS_CPU_IRQ_ISR_handler();
MSR CPSR_c,#SVCMODE|NOINT ;Change to SVC mode
BL OSIntExit ;Call OSIntExit
LDMFD SP!,{R4} ;POP the task''s CPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC}^ ;POP new Task''s context
IRQIsrVect DCD HandleEINT0
This function is a general processing form of irq interrupt. I will briefly analyze and discuss the code in it.
First of all, I need to briefly analyze the tasks we should complete during interrupt processing. First, the CPU will automatically complete some operations, including closing the interrupt, saving the return address, switching modes, etc. We programmers need to complete some register saving work and jump to the specific processing function, and finally complete the return control.
It should be noted that the UC/OS-II tasks in this article are all running in SVC mode, not SYS mode. The registers saved in the task stack are also the corresponding values in this mode.
I explain the code according to the comment numbers:
2. STMFD SP!, {R1-R3}; is mainly used to push several registers onto the stack. Why do we do this? Because we will use these registers next. Why do we need this? This is because the current CPU is working in irq mode, so the SP here is not the SP pointer in SVC mode. However, in the process of porting UC/OS-II, each task is usually operated in SVC mode, and the registers need to be saved. After the interrupt occurs, all registers and CPSR values need to be saved, and the current SP is not the task stack. At this time, except for the values of SP and R14, other registers have not changed. However, since these registers will be used later, they need to be pushed onto the stack.
3. MOV R1, SP; Save the value of R14_irq to R1. The purpose of saving SP is to access the stack space in IRQ mode through this value to access the data.
4. ADD SP, SP, #12; Adjust the stack pointer SP_irq in IRQ mode and point this pointer to the beginning of the IRQ stack to facilitate the next interrupt processing operation.
5. SUB R2, LR, #4; This operation is mainly to adjust the return address and understand the meaning of the exception return address. The return address at this time is actually the return address of the task, which is the value that needs to be loaded into the PC in the future.
6. MRS R3, SPSR; Because an IRQ interrupt occurs, the CPU enters the IRQ mode, and the SPSR_irq at this time saves the CPSR status in the SVC mode. The status register saved in the task stack happens to be the status register in the SVC mode, so the status register in the SVC mode needs to be read out first, and then saved in the task stack, so R3 is used to save the CPSR value.
7. MSR CPSR_cxsf, #SVCMODE|NOINT; Because the stack space of the task is in SVC mode, it is necessary to first switch the CPU state to SVC mode and then perform the task context switching operation.
9. STMFD SP!, {R2}; At this time, SP refers to R13_svc in SVC mode. After the interrupt occurs, the SP in SVC mode does not change. After returning, the value still exists and still points to the top of the task stack. According to the distribution of the task stack space, the PC value needs to be saved first, then R14-R0, the value of CPSR, and finally the SP is saved to the task. This distribution state is consistent with the distribution of the stack initialization process. The adjusted return address is just saved in R2, so the PC value needs to be pushed onto the stack.
10. STMFD SP!, {R4-R12, LR}; Because the values of R4-R12 and R14 are not destroyed in the previous series of operations, the stack push operation can be performed directly to save R4-R12 and LR in the task stack.
The next few lines of code are the key points: they implement the problem of accessing the stack space in other modes.
11. LDMFD R1!, {R4-R6}; means loading some data from address R1 to R4-R6. The values of these three registers have been pushed into the stack. Modifying them will not cause errors. Therefore, these three registers are actually used as intermediate addresses. The order of loading satisfies that high addresses correspond to high-numbered register values. I have emphasized R1 as the reference address used to access the IRQ mode stack space. From this address upward, the values of the R1-R3 registers pushed into the stack are saved respectively, that is, the values of the interrupted task R1-R3.
12. STMFD SP!, {R4-R6}; that is, the stack push operation on task registers R1-R3 is completed.
13. STMFD SP!, {R0}; The previous code does not modify the value of R0, so the value is still the value of R0 of the task, so it also needs to be pushed to the stack. The above few lines of code complete the save operation of all registers R0-R15 of the task. The next step is to save the CPSR.
14. STMFD SP!, {R3}; The current R3 actually stores the value in the SPCR_irq mentioned above, that is, the value of the status register in SVC mode. Therefore, it can be considered that the status register of the task has been saved.
16-19. The next operation should be to save the value of SP to the task stack space, but there is a global variable OSIntNesting in UC/OS-II, which indicates the number of interrupt nesting, so this value needs to be increased by 1.
21. The next operation is to determine whether it is in interrupt nesting, that is, to compare the global variable. If the value is 1, it is considered that only one interrupt has occurred. If it is not equal to 1, it is considered that the interrupt is nested.
CMP R1,#1 ;if(OSIntNesting==1){
22. BNE %F1; If it is in interrupt nesting, it will jump directly to the following interrupt processing function
23-25,
LDR R4,=OSTCBCur ;OSTCBHighRdy->OSTCBStkPtr=SP;
LDR R5,[R4]
STR SP,[R5]
This means that there is only one interrupt, not in the interrupt nesting. At this time, the value of SP needs to be saved to the task control block. The above operation completes the task scenario saving operation, and the next operation should be the real interrupt handling function.
27.1 MSR CPSR_c, #IRQMODE|NOINT; actually completes the CPU mode switching operation and enters the IRQ mode.
The actual processing that follows is just like the interrupt handling process discussed in the previous two articles.
29-30,
LDR R0, =INTOFFSET
LDR R0, [R0]
Getting the value of INTOFFSET is actually getting the offset, which is essentially the interrupt number that generates the interrupt. Through this register, the vector position of the interrupt in the secondary vector table can be quickly determined. The vector table stores the function address of the corresponding interrupt handling function.
32. LDR R1, IRQIsrVect
43. IRQIsrVect DCD HandleEINT0
These two sentences explain my previous analysis. IRQIsrVect is actually a label, which stores HandleEINT0. HandleEINT0 is the entry address of our IRQ interrupt vector (as explained in the previous article), which means that HandleEINT0 is the starting address of the secondary vector table. Therefore, HandleEINT0 is actually saved in R1 at this time.
33. MOV LR, PC; completes a simple saving process, which essentially saves the return address of the function call.
34. LDR PC, [R1, R0, LSL #2]; The meaning of this code is to load the content at address R1+R0*4 into PC, that is, to implement the function jump, that is, the function call process. Among them, R1=HandleEINT0, and R0 happens to be an offset. The space of each pointer is 4 bytes, so the address R1+R0*4 is exactly the vector corresponding to the interrupt number. It stores the address of the corresponding interrupt function. Therefore, PC stores the entry address of the calling function. That is, the function call process is implemented.
35. MSR CPSR_c, #SVCMODE|NOINT; The premise of executing this code is that the called function has been executed, and the related stack push and pop operations have also been completed, and restored to the state before the call. At this time, the CPU mode needs to be switched to SVC mode.
36. BL OSIntExit; This operation completes the interrupt switching. If it is not in the interrupt nesting, the highest priority task will be executed. After entering the highest priority task, it will not return. This is the characteristic of the task in UC/OS-II, and the subsequent code will not be executed. This is particularly important to note. However, if the task is in the interrupt nesting, then OSIntExit only reduces the number of interrupt nesting and does not complete other operations. Then it is necessary to restore the previously interrupted task, that is, it is necessary to complete the pop-up operation of the task stack.
39-41,
LDMFD SP!,{R4} ;POP the task''s CPSR
MSR SPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC}^
Previous article:Design of an intelligent logistics management system based on ARM11 and RFID technology
Next article:Analysis of ARM technology middleware technology
Recommended ReadingLatest update time:2024-11-22 03:37
- Popular Resources
- Popular amplifiers
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- Europe's three largest chip giants re-examine their supply chains
- Breaking through the intelligent competition, Changan Automobile opens the "God's perspective"
- The world's first fully digital chassis, looking forward to the debut of the U7 PHEV and EV versions
- Design of automotive LIN communication simulator based on Renesas MCU
- When will solid-state batteries become popular?
- Adding solid-state batteries, CATL wants to continue to be the "King of Ning"
- The agency predicts that my country's public electric vehicle charging piles will reach 3.6 million this year, accounting for nearly 70% of the world
- U.S. senators urge NHTSA to issue new vehicle safety rules
- Giants step up investment, accelerating the application of solid-state batteries
- Guangzhou Auto Show: End-to-end competition accelerates, autonomous driving fully impacts luxury...
- 100% Earn E-Coins or Red Packets: Tektronix will help you solve USB development and testing problems. Download, complain/share experiences to win good gifts
- Newbie help, about Error initializing emulator: No USB FET was found solution
- 【NXP Rapid IoT Review】 NO5. Development Kit Hardware Module Review
- [Old post ups and downs 3] Customize u8, uint8_t?
- Linux self-study notes (I) Please criticize and correct me, and learn together
- How to prevent copying of FPGA code running on the board
- Characteristics that PCB should have during the design and manufacturing process
- Connectors and Connector Care
- Application of MSP430F5xxx in the highway toll collection system (ETC)
- pyboardCN V2 Issue 1