📄 os_cpu_a.s
字号:
;*
;* File: os_cpu_a.s
;*
;* (c) Copyright ARM Limited 1999. All rights reserved.
;*
;* ARM Specific code
;*
;*
;
; Functions defined in this module:
;
; void ARMDisableInt(void) /* disable interrupts when in SVC */
; void ARMEnableInt(void) /* enable interrupts when in SVC */
; void OS_TASK_SWAP(void) /* context switch */
; void OSStartHighRdy(void) /* start highest priority task */
SwiV EQU 0x08
IrqV EQU 0x18
FiqV EQU 0x1C
NoInt EQU 0x80
SVC32Mode EQU 0x13
IRQ32Mode EQU 0x12
FIQ32Mode EQU 0x11
SYS32Mode EQU 0x1f
I_BIT EQU 0x80
OSEnterSWI EQU 0x00
AREA |subr|, CODE, READONLY
; Improper use of locations within a READONLY area
SavedIRQ DCD 0x0
SavedFIQ DCD 0x0
SavedSWI DCD 0x0
IMPORT SavedSPSR
addr_SavedSPSR DCD SavedSPSR
IMPORT SavedR14
addr_SavedR14 DCD SavedR14
; External symbols we need the addresses of
IMPORT OSTCBCur
addr_OSTCBCur DCD OSTCBCur
IMPORT OSTCBHighRdy
addr_OSTCBHighRdy DCD OSTCBHighRdy
IMPORT OSPrioCur
addr_OSPrioCur DCD OSPrioCur
IMPORT OSPrioHighRdy
addr_OSPrioHighRdy DCD OSPrioHighRdy
IMPORT OSRunning
addr_OSRunning DCD OSRunning
EXPORT IRQContextSwap
IRQContextSwap
;- Restore scratch/used registers and LR from User Stack
ldmia sp!, { r0-r12, r14}
;- Disable Interrupt and switch back in IRQ mode
mrs r0, CPSR
bic r0, r0, #SVC32Mode
orr r0, r0, #I_BIT:OR:IRQ32Mode
msr CPSR_c, r0
nop
nop
nop
;- Restore SPSR_irq and r0 from IRQ stack
ldmia sp!, {r0, r14}
msr SPSR_cxsf, r14
;- Restore ajusted LR_irq from IRQ stack directly in the PC
nop
ldmia sp!, {r14}
subs pc,pc,#0
nop
nop
nop
; we are now executing in the interrupted mode with IRQs enabled
; BL OS_TASK_SW ; perform the context switch
STMFD sp!, {r0-r12, lr} ; save register file and ret address
MRS r4, CPSR
STMFD sp!, {r4} ; save current PSR
MRS r4, SPSR ; YYY+
STMFD sp!, {r4} ; YYY+ save SPSR
; OSPrioCur = OSPrioHighRdy
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; Get current task TCB address
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
; Get highest priority 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} ; YYY+
MSR SPSR, r4 ; YYY+
LDMFD sp!, {r4} ; YYY+
MSR CPSR, r4 ; YYY+
LDMFD sp!, {r0-r12,lr} ; YYY+
MOV pc, lr
; MOVS pc,lr
; void DisableInt(void)
; void EnableInt(void)
;
; Disable and enable IRQ and FIQ preserving current CPU mode.
;
EXPORT ARMDisableInt
ARMDisableInt
MRS r12, CPSR
ORR r12, r12, #NoInt
MSR CPSR, r12
MOV pc, lr
EXPORT ARMEnableInt
ARMEnableInt
MRS r12, CPSR
BIC r12, r12, #NoInt
MSR CPSR, r12
MOV pc, lr
; void OS_TASK_SW(void)
;
; Perform a context switch.
;
; 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.
IMPORT swi_irq
EXPORT OS_TASK_SW
OS_TASK_SW
STMFD sp!, {r0-r12, lr} ; save register file and ret address
MRS r4, CPSR
STMFD sp!, {r4} ; save current PSR
MRS r4, SPSR ; YYY+
STMFD sp!, {r4} ; YYY+ save SPSR
; OSPrioCur = OSPrioHighRdy
LDR r4, addr_OSPrioCur
LDR r5, addr_OSPrioHighRdy
LDRB r6, [r5]
STRB r6, [r4]
; Get current task TCB address
LDR r4, addr_OSTCBCur
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks's TCB
; Get highest priority 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} ; YYY+
MSR SPSR, r4 ; YYY+
LDMFD sp!, {r4} ; YYY+
MSR CPSR, r4 ; YYY+
LDMFD sp!, {r0-r12,lr} ; YYY+
MOV pc, lr
; void OSStartHighRdy(void)
;
; Start the task with the highest priority;
;
EXPORT OSStartHighRdy
OSStartHighRdy
;
LDR r4, addr_OSRunning
MOV r5, #1
STRB r5, [r4]
; Get current task TCB address
LDR r4, addr_OSTCBCur
; Get highest priority task TCB address
LDR r5, addr_OSTCBHighRdy
LDR r5, [r5] ; get stack pointer
LDR sp, [r5] ; switch to the new stack
STR r5, [r4] ; set new current task TCB address
LDMFD sp!, {r4} ; YYY
LDMFD sp!, {r4} ; get new state from top of the stack
MSR CPSR, r4 ; CPSR should be SVC32Mode
LDMFD sp!, {r0-r12, pc} ; start the new task
;-----------------------------------------;-----------------------------------------
; from swi_irq.s
;-----------------------------------------;-----------------------------------------
; AREA WANGYFLED, CODE, READONLY
; INCLUDE Include/arm.inc
;I_BIT EQU 0x80
; INCLUDE Include/pio.inc
; INCLUDE Include/aic.inc
AIC_BASE EQU 0xFFFFF000
;-----------------------------------------
;- Advanced Interrupt Controller Structure
;-----------------------------------------
^ 0
AIC_SMR # 32*4 ; Source Mode Register
AIC_SVR # 32*4 ; Source Vector Register
AIC_IVR # 4 ; Interrupt Vector Register
AIC_FVR # 4 ; Fast Interrupt Vector Register
AIC_ISR # 4 ; Interrupt Status Register
AIC_IPR # 4 ; Interrupt Pending Register
AIC_IMR # 4 ; Interrupt Mask Register
AIC_CISR # 4 ; Core Interrupt Status Register
# 4
# 4
AIC_IECR # 4 ; Interrupt Enable Command Register
AIC_IDCR # 4 ; Interrupt Disable Command Register
AIC_ICCR # 4 ; Interrupt Clear Command Register
AIC_ISCR # 4 ; Interrupt Set Command Register
AIC_EOICR # 4 ; End Of Interrupt Command Register
; INCLUDE Include/irq.mac
MY_TCB_BASE EQU 0xFFFE0000
IMPORT need_to_swap_context
addr_n_t_s_c DCD need_to_swap_context
IMPORT timer_irq
; IMPORT IRQContextSwap
IMPORT IrqStart
IMPORT OSTimeTick
IMPORT IrqFinish
; ------------------------- List of Imported resources -------------------------
; Timer Counter Handler Table
IMPORT TCHandlerTable
; ------------------------- List of Internal resources -------------------------
MyPtTCBBase
DCD MY_TCB_BASE
;SVC32Mode EQU 0x13
;IRQ32Mode EQU 0x12
;------------------------------------------------------------------------------
;- Function : interrupt_end
;- Treatments : End of Timer Counter interrupt.
;- Input Parameters : None
;- Output Parameters : Come back in the interrupted mode,
;- : restore PC and SPSR.
;- Registers lost : None
;- Called Functions : None
;- Called Macros : IRQ_EXIT
;------------------------------------------------------------------------------
EXPORT timer_2_isr
timer_2_isr
;- Adjust and save LR_irq mode in IRQ stack
sub r14, r14, #4
stmfd sp!, {r14}
;- Save SPSR and r0 in IRQ stack
mrs r14, SPSR
stmfd sp!, {r0, r14}
;- Enable Interrupt and Switch in SVC Mode
mrs r14, CPSR
bic r14, r14, #I_BIT
orr r14, r14, #SVC32Mode
msr CPSR_c, r14
;- Save scratch/used registers and LR in User Stack
stmfd sp!, { r0-r12, r14}
bl timer_irq
bl IrqStart
bl OSTimeTick
bl IrqFinish
;- Mark the End of Interrupt on the AIC
ldr r0, =AIC_BASE
str r0, [r0, #AIC_EOICR]
ldr r0, addr_n_t_s_c
ldrb r1, [r0]
cmp r1, #0
beq NoNeed
mov r1, #0
strb r1, [r0]
bl IRQContextSwap
NoNeed
;- Mark the End of Interrupt on the AIC
; ldr r0, =AIC_BASE
; str r0, [r0, #AIC_EOICR]
;- Restore scratch/used registers and LR from User Stack
ldmia sp!, { r0-r12, r14}
;- Disable Interrupt and switch back in IRQ mode
mrs r0, CPSR
bic r0, r0, #SVC32Mode
orr r0, r0, #I_BIT:OR:IRQ32Mode
msr CPSR_c, r0
;- Restore SPSR_irq and r0 from IRQ stack
ldmia sp!, {r0, r14}
msr SPSR_cxsf, r14
;- Restore ajusted LR_irq from IRQ stack directly in the PC
ldmia sp!, {pc}^
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -