📄 os_cup_a.s
字号:
;******************************************************************************
;
; os_cpu_a.s
;
; Architecture specific code for AT91M40800
;
; eking
; 2004-06-01
;
;
; change log
; -----------
; 01e,20040713,eking Define LINK_SAVE PSR_SAVE in os_cpu_c.c, fixed run in FLASH error bug.
; 01d,20040712,eking Modify OSIntCtxSw fixed stack error bug.
; 01c,20040710,eking Modify OSTickISR according AT91 interrupt handle flow.
; 01b,20040610,eking Modify ARMDisableInt and ARMEnableInt, we do it by push and pop CPSR.
; 01a,20040601,eking created from S3C44B0 ucosii.
;
;********************************************************************************************************
; uC/OS-II
; The Real-Time Kernel
;
; (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
; All Rights Reserved
;
;
; Architecture Specific code
; LARGE MEMORY MODEL
;
; ARM Compatible Target
;
; File : OS_CPU_A.S
; By : Jean J. Labrosse
;********************************************************************************************************
;********************************************************************************************
AREA |subr|, CODE, READONLY
INCLUDE at91m40800.inc
;********************************************************************************************
;
; 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 cpsr
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:
; The whole function is executed in CRITICAL state. See OSSched().
;
; 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
EXPORT OSIntCtxSw
EXPORT OS_TASK_SW
IMPORT OSPrioCur
IMPORT OSPrioHighRdy
IMPORT OSTCBCur
IMPORT OSTaskSwHook
IMPORT OSTCBHighRdy
OSIntCtxSw
;- Push working register in SVC stack
stmfd sp!, {r4,r14}
;- Disable Interrupt and switch back in IRQ mode
mrs r4, CPSR
bic r4, r4, #ARM_MODE_SVC
orr r4, r4, #I_BIT:OR:ARM_MODE_IRQ
msr CPSR_c, r4
;- Mark the End of Interrupt on the AIC
ldr r4, =AT91C_BASE_AIC
str r4, [r4, #AIC_EOICR]
;- Pop IRQ stack
ldmia sp!, {r4, r14}
ldmia sp!, {r14}
orr r4, r4, #I_BIT
msr CPSR_cxsf, r4
;- Now in SVC mode, pop working register
ldmia sp!, {r4, r14}
b __OSCtxSw
OS_TASK_SW
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
LDR r4, =OSTCBCur ; Get current task TCB address
LDR r5, [r4]
STR sp, [r5] ; store sp in preempted tasks s TCB
IMPORT OSTaskSwHook
__OSCtxSw
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:
; 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
;
;********************************************************************************************
EXPORT OSTickISR
IMPORT OSIntEnter
IMPORT OSTimeTick
IMPORT OSIntExit
IMPORT LINK_SAVE
IMPORT PSR_SAVE
IMPORT R4_SAVE
OSTickISR
;- Adjust and save LR_irq in IRQ stack and LINK_SAVE
sub lr, lr, #4
stmfd sp!, {r4, lr}
;- Write in the IVR to support Protect Mode
;- No effect in Normal Mode
;- De-assert the NIRQ and clear the source in Protect Mode
ldr r4, =AT91C_BASE_AIC
str r4, [r4, #AIC_IVR]
ldr r4, =LINK_SAVE
str lr, [r4] ; LINK_SAVE = lr_irq
;- Save SPSR in IRQ stack and PSR_SAVE
mrs lr, spsr
stmfd sp!, {lr}
str lr, [r4, #4] ; PSR_SAVE = spsr_irq
;read the interrupt status reg to clear it
ldr r4,=AT91C_BASE_TC0 ; load tc0 base address <- eking ->
ldr r4,[r4, #0x020] ; read from status register offse
ldr r4, [sp, #(1*4)] ;get value of r4
;- Switch to previous mode with interrupt disabled???这里中断如果禁止,那什么时候打开呢???
;orr lr, lr, #I_BIT ; Mask irq for context switching before////这里应该不要关中断
msr cpsr_cxsf, lr ; returning back from irq mode.
stmfd sp!, {lr}
stmfd sp!, {r0-r12, lr}
ldr r4, =LINK_SAVE
ldr lr, [r4, #0]
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 OSIntExit
__jump
;- Disable Interrupt and switch back in IRQ mode
mrs r4, CPSR
bic r4, r4, #ARM_MODE_SVC
orr r4, r4, #I_BIT:OR:ARM_MODE_IRQ
msr CPSR_c, r4
;- Mark the End of Interrupt on the AIC
ldr r4, =AT91C_BASE_AIC
str r4, [r4, #AIC_EOICR]
;- Pop IRQ stack
ldmfd sp!, {r4, r14}
ldmfd sp!, {r14}
orr r4, r4, #I_BIT
msr CPSR_cxsf, r4
;- Now in SVC mode
ldmfd sp!, {r4}
msr CPSR_cxsf, r4
ldmfd sp!, {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
mrs r0, cpsr
stmfd sp!, {r0} ; push current PSR
orr r0, r0, #I_BIT
msr cpsr_c, r0 ; disable IRQ Int s
bx lr
EXPORT ARMEnableInt
ARMEnableInt
ldmfd sp!, {r0} ; pop current PSR
msr cpsr_c, r0 ; restore original cpsr
bx lr
;---------------------------------------------------------------------
; function : dump stack
; Only for debug
;---------------------------------------------------------------------
EXPORT DmpStk
DmpStk
LDR r0, =Dump_Pool
MOV r1, sp
MOV r2, sp
ADD r2, r2, #64
DmpLoop
LDR r3, [r1]
STR r3, [r0]
ADD r0, r0, #4
ADD r1, r1, #4
CMP r1, r2
BNE DmpLoop
MOV pc, lr
ALIGN
Dump_Pool DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
DCD 0
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -