Take ucos as an example to explain in detail. Ucos is divided into task-level task switching and interrupt-level task switching.
Ucos's entire user program and operating system program run in one mode (SVC mode), so task-level task switching can be done without switching the chip's operating mode.
The reason for task-level process switching is that the task itself explicitly calls the process switching function.
For example, when a task with a relatively high priority is created, the task switching function must be called explicitly. Also, when the OSTimeDly() function is called in the task code itself, a task switch will also occur. Of course, before the switch, task scheduling is generally performed first, and I will not go into details about the scheduling algorithm here.
The specific process of switching:
OS_TASK_SW
STMFD sp!, {lr}; save pc.
//Save the scene to save the next instruction. The next instruction stores the return instruction address in lr.
STMFD sp!, {lr} ; save lr//save the value of lr
STMFD sp!, {r0-r12} ; save registers //Save the value of general registers
MRS r4, CPSR; The cpsr register can only be read and written using mrs and msr. As mentioned earlier, the entire code runs in system mode and has the permission to read the cpsr register.
STMFD sp!, {r4} ; save current CPSR //Save the value of CPSR
MRS r4, SPSR
STMFD sp!, {r4} ; save SPSR //Save the value of SPSR
So far, we have saved the program's running environment to the task stack of the current mode.
; OSPrioCur = OSPrioHighRdy
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
The above code copies the highest priority to the current priority
; Get current task TCB address
LDR r4, addr_OSTCBCur
LDR r5, [r4]; extract the first address in the tcb structure. That is, OSTCBStkPtr
STR sp, [r5] ; store sp in preempted tasks's TCB//Save the sp pointer to the content pointed to by OSTCBStkPtr
So far, all the relevant information of the current task has been saved in the tcb of the current task.
; Get highest priority task TCB address
LDR r6, addr_OSTCBHighRdy assigns the pointer to the highest priority task tcb to r6
LDR r6, [r6] Assign the first address of the highest priority TCB to r6 (the address of the task stack pointer)
LDR sp, [r6] ; get new task's stack pointer Assign the new task's stack pointer content to sp
; OSTCBCur = OSTCBHighRdy
STR r6, [r4] ; set new current task TCB addres //Assign the highest priority task control block to the task control block of the current task
; restore task's mode regsiters
LDMFD sp!, {r4}
MSR SPSR_cxsf, r4
LDMFD sp!, {r4}
MSR CPSR_cxsf, r4
//Restore the contents of SPSR and CPSR
; return in new task context
LDMFD sp!, {r0-r12, lr, pc}
//Restore r0~r12, lr, pc values. Of course, the program will jump to the new task execution.
Find the task control block of the highest priority task. Since the first data field of the task control block is the task stack pointer,
That is, the offset is 0. Take out the task stack of the task and restore the information about the task saved in it to all current registers. At this point, the task switch is completed.
The whole process is to use instructions to force the current process to switch to another process.
It should be noted that interrupts have been disabled before calling the task switching function. That is, the I and F bits of the saved CPSR are 1.
Well, let's talk about interrupt-level task switching. That is, in the interrupt service program, if a higher priority process ready to run is found, the interrupt service program will not return to the original process after execution, but return to another higher priority process.
; post FIQ Context switcher. This is called from OSIntExit when a hooked ISR
; wants to return in the context of another task. We load the new tasks context
; (from OSPrioHighRdy) and do the return from interrupt.
;
; Get pointer to stack where ISR_FiqHandler saved interrupted context
; ISR entry only saves first seven regs and LR.
;
;add r7, sp, #24 ; save pointer to register file, we must adjust this pointer to the position that just Enter Interrupt
LDR sp, =IRQStack ;IRQ_STACK ;test to del it
sub r7, sp, #4 ;r7 is the position that just Enter Interrupt; After entering the mid-segment operation mode, the stack has saved the pc and other related registers of the interrupted task, and r7 now saves the first address of the stack. (Because ARM uses a decreasing full stack)
; Change ARM CPU to SVC mode for stack operations.
; This gets the CPU off the interrupt stack and back to the
; interrupted task's stack, which is the one we want to alter.
;
mrs r1, SPSR; get suspended PSR
orr r1, r1, #0xC0; disable IRQ, FIQ.
msr CPSR_cxsf, r1 ; switch mode (shold be SVC_MODE)
Change the CPU to system operation mode. The purpose is to save the various register states saved in interrupt mode to the task control block of the interrupted task (mainly to save the program running state to the stack in SVC mode)
; PSR, SP, LR regs are now restored to the interrupted SVC_MODE.
; now set up the task's stack frame as OS_TASK_SW does...
;ldr r0, [r7, #52] ; get IRQ's LR (tasks PC) from IRQ stack //r0-r12
ldr r0, [r7] ; get IRQ's LR (tasks PC) from IRQ stack
sub r0, r0, #4 ; Actual PC address is (saved_LR - 4) When the interrupt occurs, the address of the next two instructions saved to PC is related to the 2-stage pipeline of arm9.
STMFD sp!, {r0} ; save task PC
STMFD sp!, {lr} ; save LR
sub lr, r7, #52 ;//we save the r0-r12 when we enter IRQ.
; mov lr, r7 ; save FIQ stack ptr in LR (going to nuke r7)
ldmfd lr!, {r0-r12} ; get saved registers from FIQ stack
STMFD sp!, {r0-r12} ; save registers on task stack // Save r0~r12 saved when the interrupt occurs to the stack in SVC mode
; save PSR and PSR for task on task's stack
MRS r4, CPSR
bic r4, r4, #0xC0 ; leave interrupt bits in enabled mode
STMFD sp!, {r4} ; save task's current PSR //The saved CPSR is interrupt-enabled
MRS r4, SPSR
STMFD sp!, {r4} ; SPSR too
So far, the values of the relevant registers of the interrupted task saved in interrupt mode have been saved to the stack in SVC mode.
The following switching process is the same as task switching at the task level.
; OSPrioCur = OSPrioHighRdy // change the current process
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; Get preempted tasks's TCB
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
So far, the current task execution environment has been saved in the current task control block.
; Get new task TCB address
LDR r6, addr_OSTCBHighRdy
LDR r6, [r6]
LDR sp, [r6] ; get new task's stack pointer
; OSTCBCur = OSTCBHighRdy
STR r6, [r4] ; set new current task TCB address
LDMFD sp!, {r4}
MSR SPSR_cxsf, r4
LDMFD sp!, {r4}
BIC r4, r4, #0xC0; we must exit to new task with ints enabled//The I and F bits of the CPSR saved during task-level task switching disable interrupts, and now we enable interrupts when restoring.
MSR CPSR_cxsf, r4
LDMFD sp!, {r0-r12, lr, pc}
At this point, the interrupt-level task switching is completed.
The only difference from task-level task switching is that there is a mode change during the process switching.
This has been explained clearly before. We should save the execution environment of the task to the task stack of the current task, and when the interrupt-level task switch is released, we are in interrupt mode, so we should switch the running mode and then save the relevant content.
After analysis, we can see that the CPSR saved when generating tasks and switching tasks is interrupt-disabled, and when the delayed task is restored, it is restored through the interrupt service routine, and the interrupt is turned on before restoration. The CPSR of the task saved during interrupt switching is interrupt-enabled, and the restoration is completed through task-level switching. In our example, only the idle task is forced to seize the CPU by the interrupt switching function.
What is the relationship between process switching and mode switching?
From the above description, we can also see that mode conversion does not necessarily cause process switching. Mode is a change of execution environment for different situations on CPU hardware. Process switching is the purposeful scheduling of processes by the operating system to optimize the use of CPU in time.
The concepts of mode transition and process switching have now been described and illustrated using the UCOS operating system as an example.
As for how the operating system manages processes, you can see that UCOS has mastered the simplest management related to tasks. The so-called process management means first knowing all the relevant information of the process and changing these attributes at a reasonable time and opportunity.
So far, we have roughly analyzed how a real-time operating system runs.
We have analyzed what a process is. A process is a flow of instructions that can run normally on the CPU. It is a whole. We already know how to manage them as a whole, but sometimes we may need to communicate between processes.
Regarding these contents, ucos provides semaphores, message mailboxes, event group flags, etc.
These contents are relatively easy to understand, so we will not analyze them one by one. We have already mastered the core things, and these should be easy to understand.
Previous article:STM32F302 drives LCD1602
Next article:Overall analysis of the running process of ucos on s3c2410 -- overall running environment and tool description
Recommended ReadingLatest update time:2024-11-16 12:50
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- DSP5402 development board schematic diagram
- Please tell me the setting function of deep sleep
- Driver transplantation of pedometer bracelet based on F103 and X-NUCLEO-IKS01A3
- [Jihai APM32E103VET6S Development Board] Review 1. Unboxing
- Using LM339 to generate triangle wave
- Are there any homemade downloaders such as st-link and j-link?
- [2022 Digi-Key Innovation Design Competition] Project Sharing Post 2: Porting Emwin5.28 on the stm32f7 official development board
- PWM+RC Circuit Analysis
- Using BTool and CC2640R2 LaunchPad as Downloader
- EEWORLD University-How to use TI GaN in high-efficiency power factor correction (PFC)?