00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "asm_linkage.h"
00012
00013 .extern OSTCBCur @ current task control block pointer
00014 .extern OSTCBHighRdy @ next task control block pointer
00015 .extern OSPrioCur @ current task id
00016 .extern OSPrioHighRdy @ next task id
00017 .extern OSIntNesting @ nested interrupt counter
00018 .extern OSRunning @ operation system running flag
00019
00020 .globl OSStartHighRdy @ Os starts to run highest priority task
00021 .globl OSCtxSw @ Os task level context switch
00022 .globl OSIntCtxSw @ Os interrupt level context switch
00023 .globl OS_ENTER_CRITICAL @ Enter os critical section
00024 .globl OS_EXIT_CRITICAL @ Exit os critical section
00025
00026 .equ USERMODE,0x10
00027 .equ FIQMODE,0x11
00028 .equ IRQMODE,0x12
00029 .equ SVCMODE,0x13
00030 .equ ABORTMODE,0x17
00031 .equ UNDEFMODE,0x1b
00032 .equ SYSTEMMODE,0x1f
00033 .equ MODEMASK,0x1f
00034 .equ NOINT,0x80
00035 .equ NOFIQ,0x40
00036
00037
00038 ENTRY(OS_CPU_A)
00039 OS_ENTER_CRITICAL:
00040 stmfd sp!,{r0,lr}
00041 mrs r0,cpsr
00042 orr r0,r0,#(1<<7) @ set i_bit in cpsr...disable irq
00043 msr cpsr_cxsf,r0
00044 ldmfd sp!,{r0,pc}
00045
00046 OS_EXIT_CRITICAL:
00047 stmfd sp!,{r0,lr}
00048 mrs r0,cpsr
00049 bic r0,r0,#(1<<7) @ clr i_bit in cpsr...disable irq
00050 msr cpsr_cxsf,r0
00051 ldmfd sp!,{r0,pc}
00052
00053 OSStartHighRdy: @ load first task to run
00054 ldr r0,=OSRunning @ Set OSRunning=1
00055 mov r1,#1
00056 strb r1,[r0]
00057 ldr r1,=OSTCBCur @ OSTCBCur=**ptos
00058 ldr r1,[r1] @ get *ptos into r1
00059 ldr sp,[r1,#0] @ get task stack pointer into sp
00060 ldmfd sp!,{r0} @ pop CPSR(r1),
00061 msr cpsr_cxsf,r0
00062 ldmfd sp!,{r0-r12,lr,pc} @ pop R12-R0,LR,PC.
00063
00064 OSCtxSw: @ task level context switch
00065 stmfd sp!,{lr} @ push PC into system stack
00066 stmfd sp!,{lr} @ push LR into stsyem stack
00067 L_TaskSwitchOff:
00068 stmfd sp!,{r0-r12} @ push R12-R0.
00069 mrs r0,cpsr
00070 stmfd sp!,{r0} @ pushCPSR.
00071 ldr r0,=OSTCBCur
00072 ldr r0,[r0]
00073 str sp,[r0] @ OSTCBCur=SP. sp is stack pointer of task go switching off
00074
00075 ldr r0,=OSPrioCur @ OSPrioCur = OSPrioHighRdy.
00076 ldr r1,=OSPrioHighRdy
00077 ldrb r1,[r1]
00078 strb r1,[r0]
00079
00080 ldr r0,=OSTCBCur @ OSTCBCur = OSTCBHighRdy.
00081 ldr r1,=OSTCBHighRdy
00082 ldr r1,[r1]
00083 str r1,[r0]
00084
00085 L_TaskSwitchOn:
00086 ldr sp,[r1,#0] @ get task stack pointer
00087 ldmfd sp!,{r0} @ pop CPSR.
00088 msr cpsr_cxsf,r0
00089 ldmfd sp!,{r0-r12,lr,pc} @ R12-R0,LR,PC.
00090
00091 OSIntCtxSw: @ interrupt level context switch
00092 stmfd sp!,{r0} @ push r0 to irq stack
00093
00094 mov r0,lr @ keep irq mode lr in r0
00095 msr cpsr_c,#(NOINT | SYSTEMMODE) @ enter system mode
00096 stmfd sp!,{r0} @ push irq lr...pc where irq occurs
00097 stmfd sp!,{lr} @ push system original lr
00098
00099 msr cpsr_c,#(NOINT | IRQMODE) @ back to irq mode
00100 ldmfd sp!,{r0} @ pop back r0
00101 ldr lr,=L_IntSwitchOff
00102 stmfd sp!,{lr}
00103 ldmfd sp!,{pc}^ @ ^..leave irq mode...copy cpsr_irq to cpsr...return to previous mode before enter irq...see s3c2440spec.p3-46
00104 @ previous mode should be system mode or supervisor mode
00105 L_IntSwitchOff: @ operate in system mode now
00106 stmfd sp!,{r0-r12} @ push R12-R0.
00107 mrs r0,cpsr
00108 stmfd sp!,{r0} @ push CPSR,...last byte for task stack backup
00109
00110 ldr r0,=OSTCBCur
00111 ldr r0,[r0]
00112 str sp,[r0] @ update stack pointer to os_tcb
00113
00114 ldr r0,=OSPrioCur @ OSPrioCur=OSPrioHighRdy.
00115 ldr r1,=OSPrioHighRdy
00116 ldrb r1,[r1]
00117 strb r1,[r0]
00118
00119 ldr r0,=OSTCBCur @ OSTCBCur=OSTCBHighRdy.
00120 ldr r1,=OSTCBHighRdy
00121 ldr r1,[r1]
00122 str r1,[r0]
00123
00124 L_IntSwitchOn:
00125 ldr sp,[r1,#0] @ get task stack pointer from os_tcb
00126 ldmfd sp!,{r0} @ pop CPSR
00127 msr cpsr_cxsf,r0
00128 ldmfd sp!,{r0-r12,lr,pc} @ R12-R0,LR,PC.
00129