📄 os_cpu_a.s
字号:
;********************************************************************/
AREA |subr|, CODE, READONLY
;/***********************************************************************
;
; Function: OSStartHighRdy
;
; Purpose:
; To start the task with the highest priority during OS startup
;
; Processing:
; See uC/OS-II Task Level Context Switch flow chart
;
; Parameters: void
;
; Outputs: None
;
; Returns: void
;
; Notes:
; Called once during OSStart()
;
;*********************************************************************/
EXPORT OSStartHighRdy
IMPORT OSTaskSwHook
IMPORT OSTCBHighRdy
IMPORT OSRunning
OSStartHighRdy
BL OSTaskSwHook ; Call user-defined hook function
LDR r4,=OSRunning ; Indicate that multitasking has started
MOV r5, #1
STRB r5, [r4] ; OSRunning = true
LDR r4, =OSTCBHighRdy ; Get highest priority task TCB address
LDR r4, [r4] ; get stack pointer
LDR sp, [r4] ; switch to the new stack
LDMFD sp!, {r4} ; pop new task s spsr_cxsf
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task s psr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12,lr,pc} ; pop new task s r0-r12,lr & pc
;/***********************************************************************
;
; Function: OS_TASK_SW
;
; Purpose:
; To perform a context switch from the Task Level.
;
; Processing:
; See uC/OS-II Task Level Context Switch flow chart
;
; Parameters: void
;
; Outputs: None
;
; Returns: void
;
; Notes:
; On entry, OSTCBCur and OSPrioCur hold the current TCB and priority
; and OSTCBHighRdy and OSPrioHighRdy contain the same for the task
; to be switched to.
;
; The following code assumes that the virtual memory is directly
; mapped into physical memory. If this is not true, the cache must
; be flushed at context switch to avoid address aliasing.
;
;*********************************************************************/
EXPORT OSCtxSw
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSTCBCur
IMPORT OSTaskSwHook
IMPORT OSTCBHighRdy
OSCtxSw
STMFD sp!, {lr} ; push pc (lr is actually be pushed in place of PC)
STMFD sp!, {r0-r12,lr} ; push lr & register file
MRS r4, cpsr
STMFD sp!, {r4} ; push current psr
MRS r4, spsr
STMFD sp!, {r4} ; push current spsr_cxsf
_OSCtxSw
LDR r4, =OSPrioCur ; OSPrioCur = OSPrioHighRdy
LDR r5, =OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
LDR r4, =OSTCBCur ; Get current task TCB address
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks s TCB
BL OSTaskSwHook ; call Task Switch Hook
LDR r6, =OSTCBHighRdy ; Get highest priority task TCB address
LDR r6, [r6]
LDR sp, [r6] ; get new task s stack pointer
STR r6, [r4] ; set new current task TCB address
LDMFD sp!, {r4} ; pop new task spsr_cxsf
MSR spsr_cxsf, r4
LDMFD sp!, {r4} ; pop new task cpsr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12,lr,pc} ; pop new task r0-r12,lr & pc
;***********************************************************************
;
; Function: OSIntCtxSw
;
; Purpose:
; To perform a context switch from the interrupt level.
;
; Processing:
; See uC/OS-II Interrupt Level Context Switch flow chart
;
; Parameters: void
;
; Outputs: None
;
; Returns: void
;
; Notes:
; Sets up the stacks and registers to call the task level
; context switch
;
;*********************************************************************/
EXPORT OSIntCtxSw
IMPORT OSIntCtxSwFlag
OSIntCtxSw
LDR r0, =OSIntCtxSwFlag ; OSIntCtxSwFlag = true
MOV r1, #1
STR r1, [r0]
MOV pc, lr ; return
;/***********************************************************************
;
;yangye 2003-2-14
;changed this function name from OSTickISR to OSISR(it is not a TICK isr)
; Function: OSISR
;
; Purpose:
; The IRQ interrupt handler
;
; Processing:
; Saves context
; Calls the IRQ dispatcher
; Checks if context switch necessary
; If not, restores context and returns from interrupt
; If switch required, branches without link to IRQContextSwap
; which performs context switch if interrupts not nested
; and returns from interrupt to new context
;
; Parameters: void
;
; Outputs: None
;
; Returns: void
;
; Notes:
; (1) here we use OSIntCtxSwFlag to indicate a request for int-level
; context switch
; (2) _IntCtxSw is used to perform a real switch operation
;
;*********************************************************************/
SAVED_LR_SVC DCD 0x00000000 ; some variables for temparal use
SAVED_LR_IRQ DCD 0x00000000
SAVED_SPSR DCD 0x00000000
SAVED_LR DCD 0x00000000
SRCPND EQU 0x4a000000 ;Interrupt request status
INTPND EQU 0x4a000010 ;Interrupt request status
BIT_TIMER4 EQU (0x1<<14)
BIT_TIMER0 EQU (0x1<<10)
EXPORT OSTickISR
IMPORT OSIntEnter
IMPORT OSTimeTick
IMPORT OSIntExit
IMPORT OSIntCtxSwFlag
OSTickISR
STMFD sp!, {r0-r12, lr} ; push r0-r12 register file and lr( pc return address )
ldr r0,=SRCPND
ldr r1,=BIT_TIMER4
;ldr r1,=BIT_TIMER0
str r1,[r0]
ldr r0,=INTPND
str r1,[r0]
BL OSIntEnter
BL OSTimeTick
BL OSIntExit
B OSIntReturn
EXPORT OSIntReturn
OSIntReturn
LDR r0, =OSIntCtxSwFlag ; check if OSIntCtxFlag is marked as true
LDR r1, [r0]
CMP r1, #1
BEQ _IntCtxSw ; if OSIntCtxFlag = true, then jump to _IntCtxSw
LDMIA sp!,{r0-r12, lr}
SUBS pc,lr, #4
_IntCtxSw
MOV r1, #0 ; clear OSIntCtxSwFlag = flase
STR r1, [r0]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LDMIA sp!,{r0-r12, lr}
SUBS lr,lr, #4
STR lr, SAVED_LR ;STR lr, [pc, #SAVED_LR-.-8]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Change Supervisor mode
;!!!r12 register don't preserved. (r12 that PC of task)
MRS lr, SPSR
AND lr, lr, #0xFFFFFF00
ORR lr, lr, #0xD3
MSR CPSR_cxsf, lr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Now Supervisor mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
STR r12, [sp, #-8] ; saved r12
LDR r12, SAVED_LR ;LDR r12, [pc, #SAVED_LR-.-8]
STMFD sp!, {r12} ; r12 that PC of task
SUB sp, sp, #4 ; inclease stack point
LDMIA sp!, {r12} ; restore r12
STMFD sp!, {lr} ; save lr
STMFD sp!, {r0-r12} ; save register file and ret address
MRS r4, CPSR
AND r4, r4, #0xFFFFFF00
ORR r4, r4, #0x53
STMFD sp!, {r4} ; push current psr
STMFD sp!, {r4} ; push spsr_cxsf
B _OSCtxSw ; jump to _OSCtxSw
;/***********************************************************************
;
; Functions: ARMDisableInt
; ARMEnableInt
;
; Purpose:
; Disable and enable IRQ and FIQ preserving current CPU mode.
;
; Processing:
; Push the cpsr onto the stack
; Disable IRQ and FIQ interrupts
; Return
;
; Parameters: void
;
; Outputs: None
;
; Returns: void
;
; Notes:
; (1) Can be called from SVC mode to protect Critical Sections.
; (2) Do not use these calls at interrupt level.
; (3) Used in pairs within the same function level;
; (4) Will restore interrupt state when called; i.e., if interrupts
; are disabled when DisableInt is called, interrupts will still
; still be disabled when the matching EnableInt is called.
; (5) Uses the method described by Labrosse as "Method 2".
;
;*********************************************************************/
EXPORT ARMDisableInt
ARMDisableInt
STMDB sp!, {r0-r1,lr}
MRS r0, cpsr
and r1,r0,#3
CMP r1, #2
BEQ __IntUDIS
ORR r0, r0, #0xC0
__IntUDIS
MSR CPSR_cxsf, r0 ; disable IRQ Int s
LDMIA sp!, {r0-r1,pc}
;------------------------------------------------------------------------
EXPORT ARMEnableInt
ARMEnableInt
STMDB sp!, {r0-r1,lr}
MRS r0, cpsr
and r1,r0,#3
CMP r1, #2
BEQ __IntUEN
BIC r0, r0, #0x80
__IntUEN
MSR CPSR_cxsf, r0 ; enable IRQ Int s
LDMIA sp!, {r0-r1,pc}
;------------------------------------------------------------------------
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -