📄 arm_core_s.s
字号:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Copyright (c) 2006 by RockOS.
;; All rights reserved.
;;
;; This software is supported by Rock Software Workroom.
;;
;; Any bugs please contact the author with e-mail or QQ:
;; E-mail : baobaoba520@yahoo.com.cn
;; QQ : 59681888
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;File name : arm_core.s
;;Description : the BSP core code for all ARM cpu.
;; :
;; :
;; :
;; :
;;Auther : sunxinqiu
;;History :
;; 2006-3-15 first release.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include 44b.inc
;; vairable for task stack init.
IMPORT taskDeleteSelf
;; variables for task switch
IMPORT g_runningTask
IMPORT g_runningTcb
IMPORT g_newTask
IMPORT g_newTcb
;; Hook for task switch
IMPORT OSSwTaskHook
AREA ||.text||, CODE, READONLY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function : unsigned int getMemStartAddr(void)
;;Params : N/A
;; :
;; :
;; :
;;Return : N/A
;;Description : get the heap memory start address which the OS can use.
;; :
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT getMemStartAddr
getMemStartAddr
ldr r0, =|Image$$ZI$$Limit|
mov pc, lr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function : unsigned int getMemEndAddr(void)
;;Params : N/A
;; :
;; :
;; :
;;Return : N/A
;;Description : get the heap memory end address which the OS can use.
;; :
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT getMemEndAddr
getMemEndAddr
ldr r0, =_ISR_STARTADDRESS
mov pc, lr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function : void * taskStackInit(void * pStack,
;; : int stackSize,
;; : TASK_ENTRY pEntryFunc,
;; : void * pData)
;;Params : pStack - the task's stack start address.
;; : stackSize - the task's stack size, by bytes.
;; : pEntryFunc - the task's main entry point.
;; : pData - param for pEntryFunc.
;; :
;;Return : The initializaed SP for this task.
;;Descript : This function is called once only when task is created. RockOS
;; : can't know whether the stack is growth from low address or from
;; : high address to low address, so I let this work done by BSP.
;; : Defaultly, the LR(R14) register is set to function taskDeleteSelf(),
;; : it is used to delete the task if the task entry function terminates.
;; The init stack frame is as below:
;; | |
;; | Free space |
;; |--------------|<-- sp
;; | CPSR |
;; |--------------|
;; | |
;; | r0~r12 |
;; | |
;; |--------------|
;; | LR |
;; |--------------|
;; | PC |
;; |--------------|<-- end of stack.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT taskStackInit
taskStackInit
;; r0 - the pStack (stack start address).
;; r1 - size of stack (in bytes).
;; r2 - the task entry point.
;; r3 - param for the task entry point.
stmfd sp!, {r4-r12}
add r4, r0, r1 ;; r4 is now the task's stack top position.
bic r4, r4, #0x03 ;; align the r4 register(task stack pointer)
;; clear the stack to all 0xFE
mov r6, r0
ldr r5, =0xFEFEFEFE
1 str r5, [r6]
cmp r6, r4
addcc r6, r6, #4
bcc %b1
;; the task's entry pointer
stmfd r4!, {r2} ;; will be popped to PC
;; once the task's entry function returns, delete the task
ldr r2, =taskDeleteSelf ;; will be popped to LR
stmfd r4!, {r2}
;; param for the task's entry point should be stored in r0
mov r0, r3 ;; the param for taskEntry()
mov r1, r4 ;; r1 now saves the task's stack top
ldr r2, =0x22222222 ;; save {r5-r12} in task's stack
ldr r3, =0x33333333
ldr r4, =0x44444444
ldr r5, =0x55555555
ldr r6, =0x66666666
ldr r7, =0x77777777
ldr r8, =0x88888888
ldr r9, =0x99999999
ldr r10,=0xaaaaaaaa
ldr r11,=0xbbbbbbbb
ldr r12,=0xcccccccc
stmfd r1!,{r2-r12}
ldr r2, =0x11111111
stmfd r1!, {r0, r2} ;; r0 and r1 in task's stack
;; the task's CPSR, all tasks are running in SVC mode.
mov r0, #(SVC_MODE|FIQ_DISABLED) ;; will be popped to CPSR
stmfd r1!, {r0}
;; return the task stack's top
mov r0, r1
ldmfd sp!,{r4-r12}
mov pc, lr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function : void OSRunTask(void)
;;Params : N/A
;; :
;; :
;; :
;;Return : N/A
;;Description : start the first ready task when system starting.
;; : global variable g_runningTask and g_runningTcb must be set
;; : properly before calling this function.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT OSRunTask
OSRunTask
;; load task's stack.
ldr r0, =g_runningTcb
ldr r0, [r0]
ldr sp, [r0]
ldmfd sp!, {r0} ;; pop cpsr for the task
msr spsr_cxsf, r0
ldmfd sp!, {r0-r12, lr, pc}^ ;; run the task
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function : void OSSwTask (void);
;;Params : N/A
;; :
;;Return : N/A
;;Descript : This function is called by RockOS scheduler to switch task from
;; : one to another. These global variable should be set properly
;; : before calling this function:
;; : g_runningTask - the running task's handle.
;; : g_runningTCB - the running task's TCB.
;; : g_newTask - the new task's handle
;; : g_newTCB - the new task's TCB.
;; :
;; To switch from one task to another, the tasks' stack frame are:
;; | | | |
;; | Free space | | Free space |
;; |------------|<-- sp(after SW out) |------------|<-- sp(before SW in)
;; | CPSR | | CPSR |
;; |------------| |------------|
;; | | | |
;; | r0~r12 | | r0~r12 |
;; | | | |
;; |------------| |------------|
;; | LR | | LR |
;; |------------| |------------|
;; | PC | | PC |
;; |------------|<-- sp(befor SW out) |------------|<-- sp(after SW in)
;; | | | |
;; | app data | | app data |
;; | | | |
;; |------------| |------------|
;; old task's stack frame new task's stack frame
;; : Note that the register PC appears twicely, it is used to keep
;; : consist with the task switch procedure in interrupt.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT OSSwTask
OSSwTask
;; save the old task's all registers and PSR in its stack.
;; the sp is still pointer to the old task's stack now.
stmfd sp!, {lr} ;; pc for old task
stmfd sp!, {r0-r12, lr} ;; r0--r12, lr for old task
mrs r0, cpsr ;; cpsr for task
stmfd sp!, {r0}
bl OSSwTaskHook ;; OSSwTaskHook();
ldr r4, =g_runningTcb ;; g_runningTcb->pSP = sp
ldr r4, [r4]
str sp, [r4]
ldr r0, =g_newTask ;; g_runningTask = g_newTask;
ldr r0, [r0]
ldr r5, =g_runningTask
str r0, [r5]
ldr r1, =g_newTcb ;; g_runningTcb = g_newTcb;
ldr r1, [r1]
ldr r4, =g_runningTcb
str r1, [r4]
;; restore the new task's all registers and PSR from its stack
ldr r4, [r4]
ldr sp, [r4]
ldmfd sp!, {r0} ;; cpsr for the new task
msr spsr_cxsf, r0
ldmfd sp!, {r0-r12, lr, pc}^ ;; all other registers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;Function : void OSIntSwTask (void);
;;Params : N/A
;; :
;;Return : N/A
;;Descript : This function is called by OSLeaveIsr() to switch task from
;; : one to another. These global variables should be set properly
;; : before calling this function:
;; : g_runningTask - the running task's handle.
;; : g_runningTCB - the running task's TCB.
;; : g_newTask - the new task's handle
;; : g_newTCB - the new task's TCB.
;; : for the task stack frame, see OSSwTask() for more.
;; :
;; : note that the current task's context (which to be switched out)
;; : has been saved in its own stack when entering the ISR, so
;; : we only need load the new task's context directly here.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXPORT OSIntSwTask
OSIntSwTask
bl OSSwTaskHook ;; OSSwTaskHook();
ldr r0, =g_newTask ;; g_runningTask = g_newTask;
ldr r0, [r0]
ldr r1, =g_runningTask
str r0, [r1]
ldr r0, =g_newTcb ;; g_runningTcb = g_newTcb;
ldr r0, [r0]
ldr r1, =g_runningTcb
str r0, [r1]
;; load the new task directly.
ldr r0, =g_runningTcb
ldr r0, [r0]
ldr sp, [r0]
ldmfd sp!, {r0} ;; cpsr for the new task
msr spsr_cxsf, r0
ldmfd sp!, {r0-r12, lr, pc}^ ;; all other registers
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -