Created
February 11, 2012 12:58
-
-
Save iskl/1799297 to your computer and use it in GitHub Desktop.
ARM9上运行的微型操作系统(汇编)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;**************************************************************************************** | |
; 文件名:RTOS_ASM.S | |
; 功能: ARM9上运行的微型操作系统(汇编) | |
; 备注: 汇编主要完成维护任务堆栈和存取堆栈指针SP的操作 | |
; | |
; By Lisuwei | |
; | |
;***************************************************************************************/ | |
AREA ARM_OS_ASM, CODE, READONLY | |
;******************************************************************************************************** | |
; 引用的外部标号 | |
;******************************************************************************************************** | |
IMPORT p_OSTCBCur | |
IMPORT p_OSTCBHighRdy | |
IMPORT Int_Return_Addr_Save | |
IMPORT OSIntCtxSwFlag | |
IMPORT C_IRQHandler | |
IMPORT OSIntExit | |
;******************************************************************************************************** | |
; 系统第一个运行的任务出栈 | |
;******************************************************************************************************** | |
EXPORT OSStartHighRdy ; 输出的标号 | |
OSStartHighRdy | |
ldr r4,=p_OSTCBHighRdy ; 取出最高优先级就绪任务的PCB的地址 | |
ldr r4,[r4] ; 取得任务的栈顶指针(因为TaskCtrBlock地址亦即OSTCBStkPtr的地址) | |
ldr sp,[r4] ; 任务的栈顶指针赋给SP | |
b POP_ALL ; 根据设定的栈结构顺序出栈 | |
;******************************************************************************************************** | |
; 根据设定的栈结构顺序入栈 | |
;******************************************************************************************************** | |
EXPORT OS_TASK_SW | |
OS_TASK_SW_INT ; 中断级任务切换,中断服务时使用另外的堆栈,所以要回到管理模式中才进行任务切换 | |
sub sp,sp,#4 ; 为PC保留位置 | |
stmfd sp!,{r0-r12,lr} ; r0-r12,lr入栈 | |
ldr r0,=Int_Return_Addr_Save; 取出进入中断之前保存的PC | |
ldr r0,[r0] ; Int_Return_Addr_Save -> r0 | |
add sp,sp,#56 ; 调整SP | |
stmfd sp,{r0} ; r0(PC)入栈 | |
sub sp,sp,#56 ; 调整SP回到栈顶 | |
b PUAH_PSR | |
OS_TASK_SW ; 任务级的任务切换 | |
stmfd sp!,{lr} ; PC 入栈 | |
stmfd sp!,{r0-r12,lr} ; r0-r12,lr入栈 | |
PUAH_PSR | |
mrs r4,cpsr | |
stmfd sp!,{r4} ; cpsr入栈 | |
SaveSPToCurTcb ; 保存当前任务的堆顶指针到它的TCB. TCB[OSPrioCur].OSTCBStkPtr = SP; | |
ldr r4,=p_OSTCBCur ; 取出当前任务的PCB地址 | |
ldr r5,[r4] ; | |
str sp,[r5] ; 保存当前任务的堆顶指针到它的TCB(因为TaskCtrBlock地址亦即OSTCBStkPtr的地址) | |
GetHigTcbSP ; 取出更高优先级任务的堆顶指针到SP ,SP = TCB[OSPrioCur].OSTCBStkPtr | |
ldr r6,=p_OSTCBHighRdy ; 取出更高优先级就绪任务的PCB的地址 | |
ldr r6,[r6] | |
ldr sp,[r6] ; 取出更高优先级任务的堆顶指针到SP | |
b POP_ALL ; 根据设定的栈结构顺序出栈 | |
;******************************************************************************************************** | |
; 根据设定的栈结构顺序出栈 | |
;******************************************************************************************************** | |
POP_ALL | |
ldmfd sp!,{r4} ; psr出栈 | |
msr CPSR_cxsf,r4 | |
ldmfd sp!,{r0-r12,lr,pc} ; r0-r12,lr,pc出栈 | |
;******************************************************************************************************** | |
; 中断服务入口程序 | |
;******************************************************************************************************** | |
EXPORT ASM_IRQHandler | |
ASM_IRQHandler ; 中断入口地址,在中断向量表初始化时被设置 | |
sub lr,lr,#4 ; 计算中断返回地址 | |
stmfd sp!,{r0-r3,r12,lr} ; 保护现场,此时处于中断模式下,sp指向中断模式下的堆栈.不能进行任务切换(各任务堆栈处在管理模式堆栈). | |
; R4-R11装的是局部变量,在进行函数跳转时,编译器它会自动保护它们, | |
; 即C语言函数返回时,寄存器R4-R11、SP不会改变,无需人为保护 | |
bl C_IRQHandler ; 调用c语言的中断处理程序 | |
bl OSIntExit ; 判断中断后是否有更高优先级的任务进入就绪而需要进行任务切换 | |
ldr r0,=OSIntCtxSwFlag ; if(OSIntCtxSwFlag == 1) OSIntCtxSw() | |
ldr r1,[r0] | |
cmp r1,#1 | |
beq OSIntCtxSw ; 有更高优先级的任务进入了就绪状态,则跳转到OSIntCtxSw进行中断级的任务切换 | |
ldmfd sp!,{r0-r3,r12,pc}^ ; 不进行任务切换,出栈返回被中断的任务。寄存器出栈同时将spsr_irq的值复制到CPSR,实现模式切换 | |
;******************************************************************************************************** | |
; 中断后需任务切换时的跳转程序。若中断后需任务切换,则中断结束后不返回先前的任务,而去执行中断级任务切换 | |
; 函数OS_TASK_SW_INT。因为中断返回地址保存了在中断模式的堆栈中(中断时先保存在中断模式的lr中,之后压栈), | |
; 这里把它用一个变量保存下来,待后任务切换时再把它取出压入先前任务的堆栈中(管理模式下)。 | |
; | |
;******************************************************************************************************** | |
OSIntCtxSw ; 把中断的返回地址保存到Int_Return_Addr_Save变量中 | |
ldr r0,=OSIntCtxSwFlag | |
mov r1,#0 | |
str r1,[r0] ; OSIntCtxSwFlag = 0 | |
add sp,sp,#20 ; 调整SP,使之指向之前入栈的lr(中断模式下的lr保存的是中断返回地址), | |
ldr r0,[sp] ; lr -> r0 | |
ldr r1,=Int_Return_Addr_Save; &Int_Return_Addr_Save -> r1 | |
str r0,[r1] ; lr -> Int_Return_Addr_Save | |
ldr r0,=OS_TASK_SW_INT | |
str r0,[sp] ; OS_TASK_SW -> lr | |
sub sp,sp,#20 ; 调整SP回到栈顶 | |
ldmfd sp!,{r0-r3,r12,pc}^ ; 退出中断后跳到OS_TASK_SW而不返回中断前运行的程序 | |
;******************************************************************************************************** | |
; 进入临界代码区 | |
;******************************************************************************************************** | |
NOINT EQU 0xc0 | |
EXPORT OSCPUSaveSR | |
OSCPUSaveSR | |
mrs r0,CPSR ; 保存当前中断状态,参阅汇编子程序调用ATPCS规则,r0保存传递的参数 | |
orr r1,r0,#NOINT ; 关闭所有中断 | |
msr CPSR_c,r1 | |
mov pc,lr | |
;******************************************************************************************************** | |
; 退出临界代码区 | |
;******************************************************************************************************** | |
EXPORT OSCPURestoreSR | |
OSCPURestoreSR | |
msr CPSR_c,r0 ; 恢复原来的中断状态 | |
mov pc,lr | |
END | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment