;/****************************************Copyright (c)************************************************** ;** 中南民族大学 ;** 电子信息工程学院 ;** 2005级电子信息工程 ;** yangbin6b210@yahoo.com.cn ;** ;** ;**----------------------------------------文件信息------------------------------------------------------ ;**文 件 名: os_cpu_s.s ;**创 建 人: 杨斌 ;**最后修改日期: 2007年12月12日 ;**描 述: μCOS-II在S3C44B0X上的移植代码汇编代码部分,用ADS1.2编译 ;** ;**------------------------------------------------------------------------------------------------------ ;********************************************************************************************************/ NoInt EQU 0x80
SVC32Mode EQU 0x13 IRQ32Mode EQU 0x12 FIQ32Mode EQU 0x11 SYS32Mode EQU 0X1F
CODE32
AREA |subr|, CODE, READONLY IMPORT OSIntNesting IMPORT OSTCBCur IMPORT IsrIRQ IMPORT OSIntExit IMPORT OSTaskSwHook IMPORT OSTCBCur IMPORT OSTCBHighRdy IMPORT OSPrioCur IMPORT OSPrioHighRdy IMPORT IRQStack IMPORT OSRunning EXPORT OSIRQISR EXPORT OSIntCtxSw EXPORT OS_TASK_SW EXPORT OSStartHighRdy EXPORT OS_ENTER_CRITICAL EXPORT OS_EXIT_CRITICAL
;/********************************************************************************************************* ;** 函数名称: OSIRQISR ;** 功能描述: 中断进入和退出时的接口 ;** 输 入: 无 ;** ;** ;** 输 出 : 无 ;** 全局变量: OSIntNesting、OSTCBCur、IRQStack ;** 调用模块: 无 ;** ;** 作 者: 杨斌 ;** 日 期: 2007年12月12日 ;**------------------------------------------------------------------------------------------------------- ; 系统模式堆栈 IRQ模式堆栈 ; |PC | |LR |=断点处的将要执行的PC值 ; |LR | |R3 | ; |R12 | |R2 | ; |R11 | |R1 | ; |R10 | |R0 | ; |R9 | |LR |=系统模式的LR ; |R8 | |SP |=系统模式的SP ; |R7 | SP→|SPSR|=断点处的CPSR ; |R6 | ; |R5 | ; |R4 | ; |R3 | ; |R2 | ; |R1 | ; |R0 | ; |CPSR|←SP ;/********************************************************************************************************/ OSIRQISR SUB LR,LR,#4 ;调整返回地址 STMFD SP!,{R0-R3,LR} MRS R3,SPSR STMFD SP,{R3,SP,LR}^ ; 系统模式SP→|R0 | SUB SP,SP,#4*3 ; 系统模式SP→|SPSR| LDR R0,=OSIntNesting LDRB R1,[R0] ADD R1,R1,#1 STRB R1,[R0] ;OSIntNesting加1 MOV R2,LR MSR CPSR_c, #(NoInt | SYS32Mode) CMP R1,#1 BNE OSIRQ_NEXT ;若OSIntNesting为1,则保存当前任务的寄存器到当前任务的堆栈中 STMFD SP!,{R2} ;保存当前任务的PC, 系统模式SP→|PC | STMFD SP!,{LR} ;保存当前任务的LR, 系统模式SP→|LR | STMFD SP!,{R4-R12} ;保存当前任务的R4-R12, 系统模式SP→|R4 | STR R3,[SP,#-5*4] ;保存当前任务的CPSR MSR CPSR_c, #(NoInt | IRQ32Mode) ;进入IRQ模式 ADD SP,SP,#4*3 ; IRQ模式SP→ |R0 | LDMFD SP,{R0-R3} ;取出R0-R3 SUB SP,SP,#4*3 ; IRQ模式SP→ |SPSR| MSR CPSR_c, #(NoInt | SYS32Mode) ;进入系统模式 STMFD SP!,{R0-R3} ;保存R0-R3, 系统模式SP→|R0 | SUB SP,SP,#4 ;调整SP, 系统模式SP→|CPSR| LDR R0,=OSTCBCur LDR R0,[R0] STR SP,[R0] ;OSTCBCur->OSTCBStkPtr=SP OSIRQ_NEXT BL IsrIRQ ;调用IRQ中断服务函数,在此中断服务函数中必须清除中断挂起位 BL OSIntExit ;调用推出系统中断函数,在此函数中OSIntNesting减1,也有可能会切换到其他任务中 MSR CPSR_c, #(NoInt | IRQ32Mode) ;进入IRQ模式。 LDR R0,=OSIntNesting LDRB R0,[R0] CMP R0,#0 ;若OSIntNesting=0则表明这是第一层中断 BEQ OSIRQ_LEAVE LDMFD SP,{R0,SP,LR}^ ;程序运行到此处,此时处在嵌套中断中 MSR SPSR_cxsf,R0 ;恢复系统模式的SP,LR,IRQ模式SPSR ADD SP,SP,#4*3 ;调整IRQ模式SP, IRQ模式SP→ |R0 | LDMFD SP!,{R0-R3,PC}^ ;恢复R0-R3,PC,CPSR, IRQ模式SP→ |X |←上一层中断的堆栈顶部 OSIRQ_LEAVE LDR R0,=IRQStack ;程序运行到此处,表明这是第一层中断且不需要切换任务 LDR R0,[R0] MOV SP,R0 ; IRQ模式SP→ |X |←中断模式堆栈栈底 SUB SP,SP,#8*4 ; IRQ模式SP→ |SPSR| LDMFD SP,{R0,SP,LR}^ ;恢复系统模式的SP,LR, 系统模式SP→|X |←当前任务中断时的SP MSR SPSR_cxsf,R0 ;恢复IRQ模式SPSR ADD SP,SP,#4*3 ;调整IRQ模式SP, IRQ模式SP→ |R0 | MSR CPSR_c, #(NoInt | SYS32Mode) ;切换到系统模式, SUB SP,SP,#11*4 ;调整系统模式SP, 系统模式SP→|R4 | LDMFD SP,{R4-R12} ;恢复R4-R12 ADD SP,SP,#11*4 ;调整系统模式SP, 系统模式SP→|X |←当前任务中断时的SP MSR CPSR_c, #(NoInt | IRQ32Mode) ;切换到IRQ模式 LDMFD SP!,{R0-R3,PC}^ ;恢复R0-R3、CPSR并从中断返回到当前任务断点处 ;/********************************************************************************************************* ;** 函数名称: OSIntCtxSw ;** 功能描述: 中断级任务切换 ;** 输 入: IRQ模式堆栈结构(出栈次序):SPSR、SP(系统模式)、LR(系统模式)、R0-R3、LR ;** 当前任务(系统模式)堆栈结构:CPSR、R0-R12、LR、PC ;** ;** 输 出 : 无 ;** 全局变量: OSTCBHighRdy、OSTCBCur、OSPrioCur、OSPrioHighRdy、IRQStack ;** 调用模块: OSTaskSwHook ;** ;** 作 者: 杨斌 ;** 日 期: 2007年12月13日 ;**------------------------------------------------------------------------------------------------------- ;/********************************************************************************************************/ OSIntCtxSw BL OSTaskSwHook ;调用钩子函数OSTaskSwHook() MSR CPSR_c, #(NoInt | IRQ32Mode) LDR R0, =OSTCBHighRdy LDR R0, [R0] LDR R1, =OSTCBCur STR R0, [R1] ;OSTCBCur=OSTCBHighRdy LDR R0,=OSPrioCur LDR R1,=OSPrioHighRdy LDRB R1,[R1] STRB R1,[R0] ;OSPrioCur=OSPrioHighRdy LDR R0,=IRQStack LDR R0,[R0] SUB R0,R0,#4 ; MOV SP,R0 ;IRQ模式堆栈保留一个字 MSR CPSR_c, #(NoInt | SYS32Mode) ;进入系统模式 LDR R2, =OSTCBHighRdy LDR R2, [R2] LDR R2, [R2] ;取得新任务堆栈指针OSTCBHighRdy->OSTCBStkPtr并存入R2中 LDR R1,[R2] ;取得新任务的CPSR存入R1中 LDR R3,[R2,#15*4] ;取得新任务的PC存入R3中 STR R3,[R0] ;把新任务的PC存入IRQ模式的堆栈中 MSR CPSR_c, #(NoInt | IRQ32Mode) ;进入IRQ模式 MSR SPSR_cxsf,R1 ;把新任务的CPSR保存到IRQ模式的SPSR中 MSR CPSR_c, #(NoInt | SYS32Mode) ;进入系统模式 ADD R2,R2,#4 ;调整新任务堆栈指针 MOV SP,R2 ; 系统模式SP→|R0 | LDMFD SP!,{R0-R12,LR} ;恢复新任务的R0-R12,LR, 系统模式SP→|PC | ADD SP,SP,#4 ;调整系统模式堆栈指针 MSR CPSR_c, #(NoInt | IRQ32Mode) ;进入IRQ模式 LDMFD SP!,{PC}^ ;恢复新任务的CPSR、PC和IRQ模式SP
好像也没什么特别的,就是转换到系统模式,运行用户中断处理程序,运行完毕切换会中断模式. |