📄 os_cpu_a.s
字号:
;//********************************************************************************************************
;// uC/OS-II
;// The Real-Time Kernel
;//
;// (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
;// All Rights Reserved
;//
;//
;// ARM Specific code
;//
;//
;// File : OS_CPU_A.ASM
;// By : Jean J. Labrosse
;//********************************************************************************************************
AREA |SUBR|,CODE,READONLY
EXPORT OSTickISR
EXPORT OSStartHighRdy
EXPORT OS_TASK_SW
EXPORT OSIntCtxSw
IMPORT OSIntExit
IMPORT OSIntEnter
IMPORT OSTimeTick
IMPORT OSTaskSwHook
IMPORT OSIntNesting
IMPORT OSPrioHighRdy
IMPORT OSPrioCur
IMPORT OSRunning
IMPORT OSTCBCur
IMPORT OSTCBHighRdy
IMPORT I_ISPC
IMPORT BIT_TIMER0
IMPORT SYSMODE
IMPORT SVCMODE
IMPORT IRQMODE
;//*********************************************************************************************************
;// START MULTITASKING
;// void OSStartHighRdy(void)
;//
;// The stack frame is assumed to look as follows:
;//
;// OSTCBHighRdy->OSTCBStkPtr --> PC (Low memory)
;// LR
;// R12
;// R11
;// R10
;// R9
;// R8
;// R7
;// R6
;// R5
;// R4
;// R3
;// R2
;// R1
;// R0 (unsigned int)pdata
;// CPSR (High memory)
;// Note : OSStartHighRdy() MUST:
;// a) Call OSTaskSwHook() then,
;// b) Set OSRunning to TRUE,
;// c) Switch to the highest priority task.
;//*********************************************************************************************************
OSStartHighRdy
MSR CPSR_c,#SYSMODE ;//enter system mode, and disable interrupt
BL OSTaskSwHook
LDR R6,=OSTCBHighRdy
LDR R6,[R6]
LDR R4,[R6] ;//now R4=OSTCBHighRdy->OSTCBStkPtr
TaskStart
LDR R7,=OSRunning ;//OSRunning = TRUE
MOV R8,#1
STRB R8,[R7]
ADD SP,R4,#56 ;//restore LR of task
LDR LR,[SP]
MSR CPSR_c,#SVCMODE ;//Switch to SVC mode , and ready to start the highest priority task
MOV SP,R4 ;//SP = OSTCBHighRdy->OSTCBStkPtr;
LDMFD SP!,{R4}
MSR SPSR_cxsf,R4
LDMFD SP!,{R0-R12,LR,PC}^ ;//start task
;//*********************************************************************************************************
;// PERFORM A CONTEXT SWITCH (From task level)
;// void OSCtxSw(void)
;//
;// Note(s): 1) Upon entry,
;// OSTCBCur points to the OS_TCB of the task to suspend
;// OSTCBHighRdy points to the OS_TCB of the task to resume
;//
;// 2) now,system has already entered into SVC mode, and the contexts of task to be suspend have stored in
;// SVC stack,the SVC stack frame looks as follows:
;// notes:SPSR_SVC=CPSR_task;
;//
;// LR (High memory)
;// R12
;// R3
;// R2
;// R1
;// SP_svc--> R0 (unsigned int)pdata (Low memory)
;//
;//
;// 3) The stack frame of the task to resume looks as follows:
;//
;// PC (High memory)
;// LR
;// R12
;// R11
;// R10
;// R9
;// R8
;// R7
;// R6
;// R5
;// R4
;// R3
;// R2
;// R1
;// R0 (unsigned int)pdata
;// OSTCBHighRdy->OSTCBStkPtr --> CPSR (Low memory)
;//*********************************************************************************************************
OS_TASK_SW
;//Store the context of the task to suspend
LDR R2,[SP,#20] ;//get PC
LDR R12,[SP,#16] ;//get R12
MRS R0,CPSR
MSR CPSR_c,#SYSMODE
MOV R1,LR
STMFD SP!,{R1-R2} ;//store PC,LR,R12-R4
STMFD SP!,{R4-R12}
MSR CPSR_c,R0 ;//Return previous mode
LDMFD SP!,{R4-R7}
MRS R3,SPSR
ADD SP,SP,#8 ;//pop PC and R12
MSR CPSR_c,#SYSMODE
STMFD SP!,{R4-R7} ;//store PC,LR,R3-R0
STMFD SP!,{R3} ;//Store CPSR
LDR R1,=OSTCBCur ;//OSTCBCur->OSTCBStkPtr = Stack pointer
LDR R1,[R1]
STR SP,[R1]
;//Now all of the contexts of task to suspend have stored in task stack
BL OSTaskSwHook
LDR R4,=OSTCBHighRdy ;//OSTCBCur=OSTCBHighRdy
LDR R4,[R4]
LDR R6,=OSTCBCur
STR R4,[R6]
LDR R4,[R4] ;//now R4=OSTCBHighRdy->OSTCBStkPtr
LDR R7,=OSPrioHighRdy ;//OSPrioCur=OSPrioHighRdy
LDRB R7,[R7] ;//note: OSPrioHighRdy and OSPrioCur are stored with 8bits
LDR R8,=OSPrioCur
STRB R7,[R8]
B TaskStart
;//*********************************************************************************************************
;// PERFORM A CONTEXT SWITCH (From an ISR)
;// void OSIntCtxSw(void)
;//
;// Note(s): 1) Upon entry,
;// OSTCBCur points to the OS_TCB of the task to suspend
;// OSTCBHighRdy points to the OS_TCB of the task to resume
;//
;// 2) The contexts of each register in IRQ mode looks as follows:
;//
;// LR (the return address of task to suspend, i.e. PC) (High memory)
;// R12
;// R3
;// R2
;// R1
;// R0 (unsigned int)pdata (Low memory)
;//
;//
;// The CPSR value of task to suspend store in SPSR_irq
;// The return address of OSIntExit() store in LR(R14_irq)
;//
;// 3) The stack frame of the task to resume looks as follows:
;//
;// PC
;// LR (High memory)
;// R12
;// R11
;// R10
;// R9
;// R8
;// R7
;// R6
;// R5
;// R4
;// R3
;// R2
;// R1
;// R0 (unsigned int)pdata
;//OSTCBHighRdy->OSTCBStkPtr --> CPSR (Low memory)
;//*********************************************************************************************************
OSIntCtxSw
B OS_TASK_SW
;//*********************************************************************************************************
;// the following C-like pseudo-code describe the operation being performed in the code below
;//
;// void OSTickISR(void)
;// {
;// Store the value of register;
;// Call OSIntEnter(), or OSIntNesting+1;
;// Call OSTimeTick();
;// Call OSIntExit();
;// Restore the value of register;
;// RIT;
;// }
;//
;//Notes:Call OSIntEnter() or OSIntNesting+1,Call OSIntExit(),Restore the value of register,and RIT are handled
;//in file InitTarget.s, So Call OSTimeTick() is the only work to do in OSTickISR().
;//*********************************************************************************************************
OSTickISR
;//end of interrupt, and clear the pending bit of interrupt
;//the following code is Closely linked to the real CPU
LDR R0,=I_ISPC ;//I_ISPC
LDR R1,=BIT_TIMER0 ;//Clear the pending bit of the timer0
STR R1,[R0]
BL OSTimeTick
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -