Transplantation of UCOS-II on lpc2210 -- OS _cpu_a.s
CPU: Philips ARM7 lpc2210
OS: uC/OS-II 2.52
IDE: ADS 1.2
Porting an operating system to a CPU architecture requires the following:
1. Have a deep understanding of the target architecture-arm Architecture Reference Manual
2. Have a deep understanding of the operating system principle -- embedded real-time operating system uC/OS-II
3. Have a deep understanding of the compilers used-the analyticdb compiler and connector Manual
4. Have a good understanding of the operating system to be transplanted-embedded real-time operating system uC/OS-II
5. Have a certain understanding of the specific chip used-the chip data manual
Write OS _cpu_a.s
; **************************************** **************************************** ************************/
; Defines the size of the system mode Stack
Svc_stack_le1_equ 32
Noint equ 0x80
; Define the pattern bit
Usr32mode equ 0x10
Svc32mode equ 0x13
Sys32mode equ 0x1f
Irq32mode equ 0x12
Fiq32mode equ 0x11
T_bit is used to detect whether the CPU is in the thumb state before an exception
T_bit equ 0x20
Code32
Area | subr |, code, readonly
Import ostcbcur; pointer to the current task TCB
Import ostcbhighrdy; pointer to the TCB task to be run
Import ospriocur; priority of the current task
Import ospriohighrdy; priority of the task to be run
Import ostaskswhook; hook function for Task Switching
Import osrunning; uC/OS-II run flag
Import osentersum; Guanzhong disconnection counter (Guanzhong disconnection semaphore)
Import swi_exception; Soft Interrupt exception handling program
Export _ osstarthighrdy
Export osintctxsw; entry for stopping and exiting, see irq_handler in startup. S.
Export softwareinterrupt; Soft Interrupt entry
; /*************************************** **************************************** **************************
; ** Function name: softwareinterrupt
; ** Function Description: software interruption. It is used to provide some system services. For more information about the functions, see OS _cpu_c.c.
; ** Input: Depends on the Function
; ** Output: Depends on the Function
; ** Global variable: None
; ** Call module: swi_exception
;**
; **************************************** **************************************** ************************/
Software interruption
Softwareinterrupt
LDR sp, stacksvc; reset the stack pointer
Stmfd SP !, {R0-R3, R12, LR}; parameter, IP (R12), LR into Stack. (These are the stack structures for the current processor Mode)
MoV R1, SP; R1 stores the stack pointer of the parameter storage location, essentially the current stack pointer
Mrs R3, spsr
Tst R3, # t_bit; whether the status is thumb before interruption, test Bit t
Ldrneh r0, [LR, #-2]; yes: SWI number in the thumb status is obtained, and H is semi-loaded.
Bicne r0, R0, #0xff00; SWI is 24 bits in 32 bits and 8 bits in thumb state
Ldreq r0, [LR, #-4]; NO: SWI number in arm status is obtained.
Biceq r0, R0, #0xff000000; SWI is a 24-bit immediate number
; R0 = SWI, R1 points to the parameter storage location
CMP r0, #1; compared with 1
Ldrlo PC, = osintctxsw; if it is smaller than 1, it will be zero, so it is to switch to the task switching function osintctxsw
Ldreq PC, =__ osstarthighrdy; SWI 0x01 is the first task switch
BL swi_exception; jump to Soft Interrupt Service Program
Ldmfd SP !, {R0-R3, R12, PC} ^; parameter, IP (R12), LR out Stack
Stacksvc DCD (svcstackspace + svc_stack_legth * 4-4)
; /*************************************** **************************************** **************************
; ** Function name: osintctxsw
; ** Function Description: entry for stopping AND EXITING
; ** Input: R3: Status Register CPSR of the current task (that is, the value of spsr)
; ** R4-R12: R4-R11 of the current task
; ** Current processor mode stack structure (out-of-stack order): R0-R3, R12, PC (current task)
; ** Output: None
; ** Global variables: ospriocur, ospriohighrdy, ospriocur, ospriohighrdy
; ** Call module: None
;**
; **************************************** **************************************** ************************/
; | ____________________ | <--- Bottom of the stack
; |
; | Other data of the task into the stack |
; | ____________________ |
; | PC |
; | ____________________ | <--- Start of the task environment
; | LR |
; | ____________________ |
; | R12 |
; | ____________________ |
; | R11 |
; | ____________________ |
; | R10 |
; | ____________________ |
; | R9 |
; | ____________________ |
; | R8 |
; | ____________________ |
; | R7 |
; | ____________________ |
; | R6 |
; | ____________________ |
; | R5 |
; | ____________________ |
; | R4 |
; | ____________________ |
; | R3 |
; | ____________________ |
; | R2 |
; | ____________________ |
; | R1 |
; | ____________________ |
; | R0 |
; | ____________________ |
; | CPSR |
; | ____________________ |
; | Osentersum | <---- sp
; | ____________________ |
; |
; | Idle space |
; | ____________________ |
; |
;
; Figure A Job stack structure
; | ____________________ | <--- Bottom of the stack
; |
; | Other data of the task into the stack |
; | ____________________ |
; | LR |
; | ____________________ | <--- Start of the task environment
; | R12 |
; | ____________________ |
; | R3 |
; | ____________________ |
; | R2 |
; | ____________________ |
; | R1 |
; | ____________________ |
; | R0 | <---- sp
; | ____________________ |
; |
; | Idle space |
; | ____________________ |
; |
Figure B stack structure when osintctxsw is called
Osintctxsw
The following figure shows how to save the task environment.
LDR R2, [Sp, #20]; get PC, that is, LR
LDR R12, [Sp, #16]; obtain R12
Mrs r0, CPSR
MSR cpsr_c, # (noint | sys32mode); disconnected and set to System Mode
MoV R1, LR
Stmfd SP !, {R1-R2}; save LR, PC
Stmfd SP !, {R4-R12}; save R4-R12
MSR cpsr_c, R0
Ldmfd SP !, {R4-R7}; get R0-R3
Add SP, SP, #8; outbound stack R12, PC
MSR cpsr_c, # (noint | sys32mode)
Stmfd SP !, {R4-R7}; save R0-R3
LDR R1, = osentersum; get osentersum
LDR R2, [R1]
Stmfd SP !, {R2, R3}; save CPSR, osentersum.
The task environment is saved.
; Save the current task stack pointer to the TCB of the current task
LDR R1, = ostcbcur
LDR R1, [R1]
STR sp, [R1]
BL ostaskswhook; call the hook function
; Ospriocur <= ospriohighrdy
; The current task is set to the highest priority
LDR R4, = ospriocur
LDR R5, = ospriohighrdy
Ldrb R6, [R5]
Strb R6, [R4]
; Ostcbcur <= ostcbhighrdy
The task control block is set to the TCB of the highest priority task.
LDR R6, = ostcbhighrdy
LDR R6, [R6]
LDR R4, = ostcbcur
STR R6, [R4]
Osintctxsw_1
; Get the new Task Stack pointer
LDR R4, [R6]
Add SP, R4, #68; 17 registers CPSR, osentersum, R0-R12, LR, SP
Ldr lr, [Sp, #-8]
MSR cpsr_c, # (noint | svc32mode); enter Management Mode
MoV sp, R4; Set Stack pointer
Ldmfd SP !, {R4, R5}; CPSR, osentersum
; Restore the osentersum of the new task
LDR R3, = osentersum
STR R4, [R3]
MSR spsr_cxsf, R5; resume CPSR
Ldmfd SP !, {R0-R12, LR, PC} ^; run new task
; /*************************************** **************************************** **************************
; ** Function name: _ osstarthighrdy
; ** Function Description: run the first task with osstarthighrdy at UC/OS-II startup,
; ** Osstarthighrdy will call _ osstarthighrdy
; ** Input: None
; ** Output: None
; ** Global variables: osrunning, ostcbcur, ostcbhighrdy, osentersum
; ** Call module: ostaskswhook
;**
; **************************************** **************************************** ************************/
_ Osstarthighrdy
MSR cpsr_c, # (noint | sys32mode)
Tell uC/OS-II that it is running
LDR R4, = osrunning
MoV R5, #1
Strb R5, [R4]
BL ostaskswhook; call the hook function
LDR R6, = ostcbhighrdy
LDR R6, [R6]
B osintctxsw_1
Area swistacks, Data, noinit
;, Align = 2
Svcstackspace space svc_stack_legth * 4; management mode stack space
End
; /*************************************** **************************************** **************************
; ** End of File
; **************************************** **************************************** ************************/