⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtos_asm.s

📁 一个以ARM9为平台小型操作系统的设计源码
💻 S
字号:
;****************************************************************************************
; 文件名: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
											   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -