📄 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 = 0x08
IrqV = 0x18
FiqV = 0x1C
NoInt = 0x80
SVC32Mode = 0x13
IRQ32Mode = 0x12
FIQ32Mode = 0x11
SYS32Mode = 0x1f
I_BIT = 0x80
OSEnterSWI = 0x00
/* AREA |subr|, CODE, READONLY */
/* ; Improper use of locations within a READONLY area */
SavedIRQ: .word 0x0
SavedFIQ: .word 0x0
SavedSWI: .word 0x0
.global SavedSPSR
addr_SavedSPSR: .word SavedSPSR
.global SavedR14
addr_SavedR14: .word SavedR14
/* ; External symbols we need the addresses of */
.global OSTCBCur
addr_OSTCBCur: .word OSTCBCur
.global OSTCBHighRdy
addr_OSTCBHighRdy: .word OSTCBHighRdy
.global OSPrioCur
addr_OSPrioCur: .word OSPrioCur
.global OSPrioHighRdy
addr_OSPrioHighRdy: .word OSPrioHighRdy
.global OSRunning
addr_OSRunning: .word OSRunning
.global 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 | IRQ32Mode
msr cpsr, r0
nop
nop
nop
/* ;- Restore SPSR_irq and r0 from IRQ stack */
ldmia sp!, {r0, r14}
msr spsr, 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.
;
*/
.global ARMDisableInt
ARMDisableInt:
MRS r12, cpsr
ORR r12, r12, #NoInt
MSR cpsr, r12
MOV pc, lr
.global 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.
*/
.global swi_irq
.global 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;
;
*/
.global _debug_led
.global _DispHex32
.global OSStartHighRdy
TempSave:
.word 0x4321cdef
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 */
/* ldmfd sp!, {r0} ;pc
mov pc, r0
*/
/*
;-----------------------------------------;-----------------------------------------
; from swi_irq.s
;-----------------------------------------;-----------------------------------------
; AREA WANGYFLED, CODE, READONLY
; INCLUDE Include/arm.inc
;I_BIT = 0x80
; INCLUDE Include/pio.inc
; INCLUDE Include/aic.inc
*/
AIC_BASE = 0xFFFFF000
/*
@ -----------------------------------------
@ - Advanced Interrupt Controller Structure
@ -----------------------------------------
*/
AIC_SMR = 0 @ Source Mode Register
AIC_SVR = AIC_SMR + 32*4 @ Source Vector Register
AIC_IVR = AIC_SVR + 32*4 @ Interrupt Vector Register
AIC_FVR = AIC_IVR + 4 @ Fast Interrupt Vector Register
AIC_ISR = AIC_FVR + 4 @ Interrupt Status Register
AIC_IPR = AIC_ISR + 4 @ Interrupt Pending Register
AIC_IMR = AIC_IPR + 4 @ Interrupt Mask Register
AIC_CISR = AIC_IMR + 4 @ Core Interrupt Status Register
AIC_IECR = AIC_CISR + 3*4 @ Interrupt Enable Command Register
AIC_IDCR = AIC_IECR + 4 @ Interrupt Disable Command Register
AIC_ICCR = AIC_IDCR + 4 @ Interrupt Clear Command Register
AIC_ISCR = AIC_ICCR + 4 @ Interrupt Set Command Register
AIC_EOICR = AIC_ISCR + 4 @ End Of Interrupt Command Register
/* ; INCLUDE Include/irq.mac */
MY_TCB_BASE = 0xFFFE0000
.global need_to_swap_context
addr_n_t_s_c:
.word need_to_swap_context
.global timer_irq
/* ; .global IRQContextSwap */
.global IrqStart
.global OSTimeTick
.global IrqFinish
/*
; ------------------------- List of Imported resources -------------------------
; Timer Counter Handler Table
*/
.global TCHandlerTable
/* ; ------------------------- List of Internal resources ------------------------- */
MyPtTCBBase:
.word MY_TCB_BASE
/*
;------------------------------------------------------------------------------
;- 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
;------------------------------------------------------------------------------
*/
.global 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, 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 | IRQ32Mode
msr cpsr, r0
/* ;- Restore SPSR_irq and r0 from IRQ stack */
ldmia sp!, {r0, r14}
msr spsr, 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 + -