Analysis of OS_CPU_IRQ_ISR transplantation process in UCOS-II

Publisher:明理厚德Latest update time:2021-07-05 Source: eefocusKeywords:UCOS-II Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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}^

[1] [2]
Keywords:UCOS-II Reference address:Analysis of OS_CPU_IRQ_ISR transplantation process in UCOS-II

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

Technical Analysis of RTOS Based on uC/OS-II and MSP430 MCU
As an important application of embedded information products, the use and design of single-chip microcomputers are facing new challenges. On the one hand, people have higher and higher requirements for embedded products, and stable, reliable, feature-rich, high-quality and low-cost information products will be
[Microcontroller]
Technical Analysis of RTOS Based on uC/OS-II and MSP430 MCU
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号