;/*
;*********************************************************************************************************
;* uC/OS-II
;* The Real-Time Kernel
;*
;*
;* (c) Copyright 2006, Micrium, Weston, FL
;* All Rights Reserved
;*
;* ARM 7 Port
;*
;* File : OS_CPU_A.S
;* Version : V2.86
;* By : Jean J. Labrosse
;*
;* For : ARMv4
;* Mode : ARM
;* Toolchain : RealView Development Suite
;* RealView Microcontroller Development Kit (MDK)
;* ARM Developer Suite (ADS)
;* Keil uVision
;*********************************************************************************************************
;*/
;/*
;*********************************************************************************************************
; External references
;*********************************************************************************************************
;*/
EXTERN OSRunning
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXTERN OSTaskSwHook
;/*
;*********************************************************************************************************
; Functions declared in this file
;*********************************************************************************************************
;*/
EXPORT OS_CPU_SR_Save
EXPORT OS_CPU_SR_Restore
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
;/*
;*********************************************************************************************************
; Config
;*********************************************************************************************************
;*/
OS_TASK_SW_HOOK EQU0
ASM_KEILRV EQU1
;/*
;*********************************************************************************************************
; ARM Core Mode and Status Bits
;*********************************************************************************************************
;*/
ARM_MODE_USER EQU 0x10
ARM_MODE_FIQ EQU 0x11
ARM_MODE_IRQ EQU 0x12
ARM_MODE_SVC EQU 0x13
ARM_MODE_ABORT EQU 0x17
ARM_MODE_UNDEF EQU 0x1B
ARM_MODE_SYS EQU 0x1F
I_BIT EQU 0x80
F_BIT EQU 0x40
T_BIT EQU 0x20
;/*
;*********************************************************************************************************
; CRITICAL SECTION METHOD 3 FUNCTIONS
; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void);
; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OS_CPU_SR_Save
MRS R0,CPSR ;// Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1,R0,#(I_BIT | F_BIT)
MSR CPSR_c,R1
BX LR ;// return the original CPSR contents in R0
OS_CPU_SR_Restore
MSR CPSR_c,R0
BX LR
;/*
;*********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OSStartHighRdy
IF (OS_TASK_SW_HOOK >= 1)
BL OS_TaskSwHook ;// OSTaskSwHook();
ENDIF
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_SYS);// Switch to SYS mode with IRQ and FIQ disabled
LDR R4, OS_Running ;// OSRunning = TRUE
MOV R5, #1
STRB R5, [R4]
;// SWITCH TO HIGHEST PRIORITY TASK
LDR R4, OS_TCBHighRdy ;// Get highest priority task TCB address
LDR R6, [R4] ;// get stack pointer
B OSCtxSw2
;/*
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OSCtxSw
;// SAVE CURRENT TASK'S CONTEXT
STMFD SP!, {LR} ;// Push return address
STMFD SP!, {R0-R12, LR} ;// Push registers
MRS R4, CPSR ;// Push current CPSR
STMFD SP!, {R4}
OSCtxSw1
LDR R4, OS_TCBCur ;// OSTCBCur->OSTCBStkPtr = SP;
LDR R5, [R4]
STR SP, [R5]
IF (OS_TASK_SW_HOOK >= 1)
BL OS_TaskSwHook ;// OSTaskSwHook();
ENDIF
LDR R4, OS_PrioCur ;// OSPrioCur = OSPrioHighRdy
LDR R5, OS_PrioHighRdy
LDRB R6, [R5]
STRB R6, [R4]
LDR R4, OS_TCBCur ;// OSTCBCur = OSTCBHighRdy;
LDR R6, OS_TCBHighRdy
LDR R6, [R6]
STR R6, [R4]
OSCtxSw2
LDR R4, [R6] ;// R4(SP) = OSTCBHighRdy->OSTCBStkPtr;
ADD SP, R4, #16*4 ;// Adjust SYS stack pointer
LDR LR, [SP, #-2*4] ;// get new task's register LR_sys
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_UNDEF);// Switch to UNDEF mode
MOV SP, R4
;// RESTORE NEW TASK'S CONTEXT
LDMFD SP!, {R4} ;// Pop new task's CPSR
MSR SPSR_cxsf, R4 ;// has SPSR only at UNDEF mode
LDMFD SP!, {R0-R12,LR,PC}^ ;// pop new task's context
;/*
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OSIntCtxSw
LDR R2, [SP, #4*5] ;// 获取PC
LDR R12, [SP, #4*4] ;// 获取R12
MRS R0, CPSR ;// 等下还要回到IRQ模式
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_SYS);// 切换到SYS系统模式
MOV R1, LR
STMFD SP!, {R1-R2} ;// 保存LR,PC
STMFD SP!, {R4-R12} ;// 保存R4-R12
MSR CPSR_c, R0 ;// 切换回IRQ模式
LDMFD SP!, {R4-R7} ;// 获取R0-R3
ADD SP, SP, #4*2 ;// 出栈R12,PC
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_SYS);// 切换到SYS系统模式
STMFD SP!, {R4-R7} ;// 保存R0-R3
STMFD SP!, {R3} ;// 保存CPSR
B OSCtxSw1
;/*
;*********************************************************************************************************
; POINTERS TO VARIABLES
;*********************************************************************************************************
;*/
IF (OS_TASK_SW_HOOK >= 1)
OS_TaskSwHook
DCD OSTaskSwHook
ENDIF
OS_IntExit
DCD OSIntExit
OS_IntNesting
DCD OSIntNesting
OS_PrioCur
DCD OSPrioCur
OS_PrioHighRdy
DCD OSPrioHighRdy
OS_Running
DCD OSRunning
OS_TCBCur
DCD OSTCBCur
OS_TCBHighRdy
DCD OSTCBHighRdy
END
;/*
;*********************************************************************************************************
; END OF FILE
;*********************************************************************************************************
;*/
;*********************************************************************************************************
;* uC/OS-II
;* The Real-Time Kernel
;*
;*
;* (c) Copyright 2006, Micrium, Weston, FL
;* All Rights Reserved
;*
;* ARM 7 Port
;*
;* File : OS_CPU_A.S
;* Version : V2.86
;* By : Jean J. Labrosse
;*
;* For : ARMv4
;* Mode : ARM
;* Toolchain : RealView Development Suite
;* RealView Microcontroller Development Kit (MDK)
;* ARM Developer Suite (ADS)
;* Keil uVision
;*********************************************************************************************************
;*/
;/*
;*********************************************************************************************************
; External references
;*********************************************************************************************************
;*/
EXTERN OSRunning
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXTERN OSTaskSwHook
;/*
;*********************************************************************************************************
; Functions declared in this file
;*********************************************************************************************************
;*/
EXPORT OS_CPU_SR_Save
EXPORT OS_CPU_SR_Restore
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
;/*
;*********************************************************************************************************
; Config
;*********************************************************************************************************
;*/
OS_TASK_SW_HOOK EQU0
ASM_KEILRV EQU1
;/*
;*********************************************************************************************************
; ARM Core Mode and Status Bits
;*********************************************************************************************************
;*/
ARM_MODE_USER EQU 0x10
ARM_MODE_FIQ EQU 0x11
ARM_MODE_IRQ EQU 0x12
ARM_MODE_SVC EQU 0x13
ARM_MODE_ABORT EQU 0x17
ARM_MODE_UNDEF EQU 0x1B
ARM_MODE_SYS EQU 0x1F
I_BIT EQU 0x80
F_BIT EQU 0x40
T_BIT EQU 0x20
;/*
;*********************************************************************************************************
; CRITICAL SECTION METHOD 3 FUNCTIONS
; Prototypes : OS_CPU_SR OS_CPU_SR_Save(void);
; void OS_CPU_SR_Restore(OS_CPU_SR cpu_sr);
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OS_CPU_SR_Save
MRS R0,CPSR ;// Set IRQ and FIQ bits in CPSR to disable all interrupts
ORR R1,R0,#(I_BIT | F_BIT)
MSR CPSR_c,R1
BX LR ;// return the original CPSR contents in R0
OS_CPU_SR_Restore
MSR CPSR_c,R0
BX LR
;/*
;*********************************************************************************************************
; START MULTITASKING
; void OSStartHighRdy(void)
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OSStartHighRdy
IF (OS_TASK_SW_HOOK >= 1)
BL OS_TaskSwHook ;// OSTaskSwHook();
ENDIF
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_SYS);// Switch to SYS mode with IRQ and FIQ disabled
LDR R4, OS_Running ;// OSRunning = TRUE
MOV R5, #1
STRB R5, [R4]
;// SWITCH TO HIGHEST PRIORITY TASK
LDR R4, OS_TCBHighRdy ;// Get highest priority task TCB address
LDR R6, [R4] ;// get stack pointer
B OSCtxSw2
;/*
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From task level) - OSCtxSw()
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OSCtxSw
;// SAVE CURRENT TASK'S CONTEXT
STMFD SP!, {LR} ;// Push return address
STMFD SP!, {R0-R12, LR} ;// Push registers
MRS R4, CPSR ;// Push current CPSR
STMFD SP!, {R4}
OSCtxSw1
LDR R4, OS_TCBCur ;// OSTCBCur->OSTCBStkPtr = SP;
LDR R5, [R4]
STR SP, [R5]
IF (OS_TASK_SW_HOOK >= 1)
BL OS_TaskSwHook ;// OSTaskSwHook();
ENDIF
LDR R4, OS_PrioCur ;// OSPrioCur = OSPrioHighRdy
LDR R5, OS_PrioHighRdy
LDRB R6, [R5]
STRB R6, [R4]
LDR R4, OS_TCBCur ;// OSTCBCur = OSTCBHighRdy;
LDR R6, OS_TCBHighRdy
LDR R6, [R6]
STR R6, [R4]
OSCtxSw2
LDR R4, [R6] ;// R4(SP) = OSTCBHighRdy->OSTCBStkPtr;
ADD SP, R4, #16*4 ;// Adjust SYS stack pointer
LDR LR, [SP, #-2*4] ;// get new task's register LR_sys
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_UNDEF);// Switch to UNDEF mode
MOV SP, R4
;// RESTORE NEW TASK'S CONTEXT
LDMFD SP!, {R4} ;// Pop new task's CPSR
MSR SPSR_cxsf, R4 ;// has SPSR only at UNDEF mode
LDMFD SP!, {R0-R12,LR,PC}^ ;// pop new task's context
;/*
;*********************************************************************************************************
; PERFORM A CONTEXT SWITCH (From interrupt level) - OSIntCtxSw()
;*********************************************************************************************************
;*/
IF (ASM_KEILRV > 0)
PRESERVE8
AREA |.text|, CODE, READONLY
CODE32
ELSE
RSEG CODE:CODE:NOROOT(2)
CODE32
ENDIF
OSIntCtxSw
LDR R2, [SP, #4*5] ;// 获取PC
LDR R12, [SP, #4*4] ;// 获取R12
MRS R0, CPSR ;// 等下还要回到IRQ模式
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_SYS);// 切换到SYS系统模式
MOV R1, LR
STMFD SP!, {R1-R2} ;// 保存LR,PC
STMFD SP!, {R4-R12} ;// 保存R4-R12
MSR CPSR_c, R0 ;// 切换回IRQ模式
LDMFD SP!, {R4-R7} ;// 获取R0-R3
ADD SP, SP, #4*2 ;// 出栈R12,PC
MSR CPSR_c, #(I_BIT | F_BIT | ARM_MODE_SYS);// 切换到SYS系统模式
STMFD SP!, {R4-R7} ;// 保存R0-R3
STMFD SP!, {R3} ;// 保存CPSR
B OSCtxSw1
;/*
;*********************************************************************************************************
; POINTERS TO VARIABLES
;*********************************************************************************************************
;*/
IF (OS_TASK_SW_HOOK >= 1)
OS_TaskSwHook
DCD OSTaskSwHook
ENDIF
OS_IntExit
DCD OSIntExit
OS_IntNesting
DCD OSIntNesting
OS_PrioCur
DCD OSPrioCur
OS_PrioHighRdy
DCD OSPrioHighRdy
OS_Running
DCD OSRunning
OS_TCBCur
DCD OSTCBCur
OS_TCBHighRdy
DCD OSTCBHighRdy
END
;/*
;*********************************************************************************************************
; END OF FILE
;*********************************************************************************************************
;*/