📄 os_cpu_a.s
字号:
;********************************************************************************************************
; uC/OS-II
; The Real-Time Kernel
;
; (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
; All Rights Reserved
;
; File : OS_CPU_A.ASM
; By : Jean J. Labrosse
;********************************************************************************************************
;********************************************************************************************************
; ARM Port
;
; Target : ARM (Includes ARM7, ARM9)
; Ported by : Michael Anburaj
; URL : http://geocities.com/michaelanburaj/ Email : michaelanburaj@hotmail.com
;
;********************************************************************************************************
AREA UCOS_ARM, CODE, READONLY
;*********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;
; Note : OSStartHighRdy() MUST:
; a) Call OSTaskSwHook() then,
; b) Set OSRunning to TRUE,
; c) Switch to the highest priority task.
;*********************************************************************************************************
IMPORT OSTaskSwHook
IMPORT OSRunning
IMPORT OSTCBHighRdy
EXPORT OSStartHighRdy
OSStartHighRdy
bl OSTaskSwHook ; Call user defined task switch hook
ldr r4,=OSRunning ; Indicate that multitasking has started
mov r5,#1
strb r5,[r4]
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 psr
msr CPSR_cxsf,r4
ldmfd sp!,{r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level)
; void OSCtxSw(void)
;
; Note(s): Upon entry,
; OSTCBCur points to the OS_TCB of the task to suspend
; OSTCBHighRdy points to the OS_TCB of the task to resume
;
;*********************************************************************************************************
IMPORT OSTCBCur
IMPORT OSTaskSwHook
IMPORT OSTCBHighRdy
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
EXPORT OSCtxSw
OSCtxSw
; Special optimised code below:
stmfd sp!,{lr} ; push pc (lr should be pushed in place of PC)
stmfd sp!,{r0-r12,lr} ; push lr & register file
mrs r4,cpsr
stmfd sp!,{r4} ; push current psr
; OSPrioCur = OSPrioHighRdy
ldr r4,=OSPrioCur
ldr r5,=OSPrioHighRdy
ldrb r6,[r5]
strb r6,[r4]
; Get current task TCB address
ldr r4,=OSTCBCur
ldr r5,[r4]
str sp,[r5] ; store sp in preempted tasks's TCB
bl OSTaskSwHook ; call Task Switch Hook
; Get highest priority task TCB address
ldr r6,=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} ; pop new task's psr
msr CPSR_cxsf,r4
ldmfd sp!,{r0-r12,lr,pc} ; pop new task's 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 OSTaskSwHook
OSIntCtxSw
BL OSTaskSwHook
LDR r4, =OSTCBHighRdy
LDR r4, [r4]
LDR r5, =OSTCBCur
STR r4, [r5] ; OSTCBCur = OSTCBHighRdy
LDR r6, =OSPrioHighRdy
LDRB r6, [r6]
LDR r5, =OSPrioCur
STRB r6, [r5] ; OSPrioCur = OSPrioHighRdy
LDR sp, [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: OSTickISR ;
; Purpose: Timer0 Interrupt Sever ;
; Processing: Call OSTimeTick ;
; Parameters: void ;
; Outputs: None ;
; Returns: void ;
; Notes: ;
;*********************************************************************************************************
EXPORT OSTickISR
IMPORT OSIntEnter
IMPORT OSTimeTick
IMPORT tick_hook
IMPORT OSIntExit
IMPORT printa
IMPORT printb
IMPORT printc
LINK_SAVE DCD 0
PSR_SAVE DCD 0
OSTickISR
STMFD sp!, {r4}
LDR r4, =LINK_SAVE
STR lr, [r4] ; LINK_SAVE = lr_irq
MRS lr, spsr
STR lr, [r4, #4] ; PSR_SAVE = spsr_irq
LDMFD sp!, {r4}
ORR lr, lr, #0x80 ; Mask irq for context switching before
MSR cpsr_cxsf, lr ; returning back from irq mode.
SUB sp, sp, #4 ; Space for PC
STMFD sp!, {r0-r12, lr}
LDR r4, =LINK_SAVE
LDR lr, [r4, #0]
SUB lr, lr, #4 ; lr = LINK_SAVE - 4,
STR lr, [sp, #(14*4)] ; the return address for pc.
LDR r4, [r4, #4] ; r4 = PSR_SAVE,
STMFD sp!, {r4} ; CPSR of the task
LDR r4, =OSTCBCur
LDR r4, [r4]
STR sp, [r4] ; OSTCBCur -> stkptr = sp
BL OSIntEnter
BL OSTimeTick
BL tick_hook ; here do_IRQ is used to clear some virtual-hardware flags
BL OSIntExit
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: RTL8019ISR ;
; Purpose: EINT1 Interrupt Sever ;
; Processing: Call RTL8019ISR ;
; Parameters: void ;
; Outputs: None ;
; Returns: void ;
; Notes: ;
;*********************************************************************************************************
EXPORT RTL8019ISR
IMPORT rtl_hook
IMPORT OSIntEnter
IMPORT OSIntExit
IMPORT rtl8019_print
LINK_SAVE2 DCD 0
PSR_SAVE2 DCD 0
RTL8019ISR
STMFD sp!, {r4}
LDR r4, =LINK_SAVE2
STR lr, [r4] ; LINK_SAVE = lr_irq
MRS lr, spsr
STR lr, [r4, #4] ; PSR_SAVE = spsr_irq
LDMFD sp!, {r4}
ORR lr, lr, #0x80 ; Mask irq for context switching before
MSR cpsr_cxsf, lr ; returning back from irq mode.
SUB sp, sp, #4 ; Space for PC
STMFD sp!, {r0-r12, lr}
LDR r4, =LINK_SAVE2
LDR lr, [r4, #0]
SUB lr, lr, #4 ; lr = LINK_SAVE - 4,
STR lr, [sp, #(14*4)] ; the return address for pc.
LDR r4, [r4, #4] ; r4 = PSR_SAVE,
STMFD sp!, {r4} ; CPSR of the task
LDR r4, =OSTCBCur
LDR r4, [r4]
STR sp, [r4] ; OSTCBCur -> stkptr = sp
BL OSIntEnter
BL rtl_hook
BL rtl8019_print
BL OSIntExit
LDMFD sp!, {r4} ; pop new task cpsr
MSR cpsr_cxsf, r4
LDMFD sp!, {r0-r12,lr,pc} ; pop new task r0-r12,lr & pc
;*********************************************************************************************************
; 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}
MRS r0, CPSR
ORR r0, r0, #0xC0
MSR cpsr_cxsf, r0 ; disable IRQ Int s
LDMIA sp!, {r0}
MOV pc, lr
EXPORT ARMEnableInt
ARMEnableInt
STMDB sp!, {r0}
MRS r0, CPSR
BIC r0, r0, #0xC0
MSR CPSR_cxsf, r0
LDMIA sp!, {r0}
MOV pc, lr
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -