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

📄 os_cpu_a.s

📁 ucos_ii在S3C2410上的移植
💻 S
字号:
;/*
;************************************************************************************************************
;*            			(c) Copyright ARM Limited 1999.  All rights reserved. 
;*
;*                              		ARM 专用代码
;*
;* 文件名称: os_cpu_a.s
;*
;* 文件说明: 该模块中的函数说明
;*
;*	void OSIntCtxSw						 中断中的任务切换
;*	void OSCtxSw						 任务切换
;*	void OSCPUSaveSR					 保存中断前的寄存器状态  
;*	void OSCPURestoreSR					 中断完成后,恢复中断前的状态 
;*	void OSStartHighRdy			 		 启动最高优先级任务 
;************************************************************************************************************
;*/

;/**********************************异常模式下的向量定义****************************************/

SwiV		EQU		0x08
IrqV		EQU		0x18
FiqV		EQU		0x1c
NoInt       EQU     0xc0
SVC32Mode	EQU		0x13
IRQ32Mode	EQU		0x12
FIQ32Mode	EQU		0x11

OSEnterSWI	EQU		0x00

        AREA	|subr|, CODE, READONLY
;/*
;*********************************************************************************************************
;                                          启动多任务
;                                       void OSStartHighRdy(void)
;
; 注释 : OSStartHighRdy() 函数必须:
;           a) 在 OSTaskSwHook() 之后调用,
;           b) 设定 OSRunning 为真,
;           c) 切换到最高优先级.
;*********************************************************************************************************
;*/               
        IMPORT  OSTCBCur       
        IMPORT  OSTaskSwHook
        IMPORT  OSRunning
        IMPORT  OSTCBHighRdy

        EXPORT  OSStartHighRdy

OSStartHighRdy                                                               ;// 寻找最高级任务开始

        bl OSTaskSwHook             				                         ;// 调用用户定义的任务钩子函数

        ldr r4,=OSRunning           				                                   ;//设定多任务开始标志
        mov r5,#1
        strb r5,[r4]
        
        ldr r4,=OSTCBCur
        ldr r5,=OSTCBHighRdy        				                       ;// 得到最高优先级任务的 TCB 地址

        ldr r5,[r5]                 				                                    ;// 得到任务堆栈指针
        ldr sp,[r5]  
        
        str r5,[r4]									                      ;// 把得到的TCB地址指针给当前的TCB
        
        ;// 切换到新任务
        ldmfd sp!,{r4}              				                                     ;// 弹出新任务的SPSR
        msr SPSR_cxsf,r4							                                   ;// 写入当前状态寄存器
        ldmfd sp!,{r4}              				                                     ;// 弹出新任务的 psr
        msr CPSR_cxsf,r4							                                   ;// 写入当前状态寄存器
        ldmfd sp!,{r0-r12,lr,pc}    				                          ;// 弹出新任务的 r0-r12,lr & pc
        
;/*
;***********************************************************************************************************
;                                        执行任务切换 (任务级)
;                                           void OSCtxSw(void)
;
; 注释 :    OSTCBCur       指向挂起的任务的OS_TCB 
;           OSTCBHighRdy   指向恢复的任务的OS_TCB
;
;************************************************************************************************************
;*/

        IMPORT  OSTCBCur
        IMPORT  OSTaskSwHook
        IMPORT  OSTCBHighRdy
        IMPORT  OSPrioCur
        IMPORT  OSPrioHighRdy

        EXPORT  OSCtxSw

OSCtxSw                                                                        ;// 任务切换
													
        stmfd sp!,{lr}              				                           ;// 压入PC (lr 应代替 PC被压入)
        stmfd sp!,{r0-r12,lr}       				                               ;// 压入 lr & register file
        mrs r4,cpsr
        stmfd sp!,{r4}              				                                              ;// 压入CPSR
        mrs r4,spsr
        stmfd sp!,{r4}              				                                             ;// 压入 spsr

        ;// OSPrioCur = OSPrioHighRdy
        ldr r4,=OSPrioCur
        ldr r5,=OSPrioHighRdy
        ldrb r6,[r5]
        strb r6,[r4]
        
        ;// 得到当前的TCB的地址
        ldr r4,=OSTCBCur
        ldr r5,[r4]
        str sp,[r5]                 				            ;// 在任务TCB中的存放当前任务控制块的栈底指针

        bl OSTaskSwHook             				                                   ;// 调用任务的钩子函数

        ;// 得到最高优先级TCB的地址
        ldr r6,=OSTCBHighRdy
        ldr r6,[r6]
        ldr sp,[r6]                 				                             ;// 得到新任务的堆栈栈底指针

        ;// OSTCBCur = OSTCBHighRdy
        str r6,[r4]                 				                                  ;// 设定新任务TCB的地址

        ldmfd sp!,{r4}              				                                    ;// 弹出新任务的 spsr
        msr SPSR_cxsf,r4
        ldmfd sp!,{r4}              				                                     ;// 弹出新任务的 psr
        msr CPSR_cxsf,r4
        ldmfd sp!,{r0-r12,lr,pc}    				                          ;// 弹出新任务的 r0-r12,lr & pc

;/*
;************************************************************************************************************
;                                       执行任务切换 (中断级)
;                                        void OSIntCtxSw(void)
;
; 注释 : 该函数针对中断服务子程序Handler仅设定标志为真。 
;
;************************************************************************************************************
;*/
        IMPORT  OSIntCtxSwFlag

        EXPORT  OSIntCtxSw

OSIntCtxSw

        ldr r0,=OSIntCtxSwFlag
        mov r1,#1
        str r1,[r0]
        mov pc,lr
        
;/*
;************************************************************************************************************
;                                            IRQ HANDLER
;
;        该段处理所有的 IRQs
;        注意: FIQ Handler 段应该近似此段编程
;
;************************************************************************************************************
;*/
        IMPORT  C_IRQHandler    					                                        ;//target.c中定义  
        IMPORT  OSIntEnter      					
        IMPORT  OSIntExit       					

        IMPORT  OSIntCtxSwFlag
        IMPORT  OSTCBCur
        IMPORT  OSTaskSwHook
        IMPORT  OSTCBHighRdy
        IMPORT  OSPrioCur
        IMPORT  OSPrioHighRdy

NOINT   EQU 	0xc0

        EXPORT  UCOS_IRQHandler

UCOS_IRQHandler

        stmfd sp!,{r0-r3,r12,lr}     ;// 保存CPU寄存器内容,进入IRQ后,CPSR 为1,禁止IRQ

        bl OSIntEnter                ;// 内核进入ISR函数
        bl C_IRQHandler
        bl OSIntExit                 ;// 内核退出ISR函数时,如果需要切换到更高优先级中去,该函数在OSIntCtxSw()中,
									 ;// 使OSIntCtxSwFlag为1。
        ldr r0,=OSIntCtxSwFlag
        ldr r1,[r0]
        cmp r1,#1
        beq _IntCtxSw                 ;// 判断是否在中断中发生任务切换?

        ldmfd sp!,{r0-r3,r12,lr}      ;// 否,则恢复CPU寄存器内容
        subs pc,lr,#4				  ;// 从IRQ中返回


_IntCtxSw							  ;// 是, 则发生中断级任务切换
        mov r1,#0
        str r1,[r0]					  ;// 清OSIntCtxSwFlag,使它为1

        ldmfd sp!,{r0-r3,r12,lr}	  ;//清IRQ中断堆栈
        stmfd sp!,{r0-r3}			  ;//将要使用R0,R1,R2,R3为暂时寄存器
        
        mov r1,sp					  ;// 保存IRQ的中断堆栈指针
        add sp,sp,#16				  ;// 回到IRQ的堆栈栈顶
        sub r2,lr,#4				  ;// 保存PC的返回地址
        mrs r3,spsr					  ;// 保存被中断的任务的SPSR
        
        orr r0,r3,#NOINT              ;//当返回到SVC或SYS模式下,禁止中断
        msr spsr_c,r0

        ldr r0,=.+8
        movs pc,r0                    ;//返回到SVC或SYS模式,禁止中断,即把spsr_c装入了cpsr中

        stmfd sp!,{r2}                ;//此时的SP为SVC或SYS的堆栈指针, 压入被中断的任务的 pc
        stmfd sp!,{r4-r12,lr}         ;// 压入被中断的任务的 lr,r12-r4
        
        mov r4,r1                     ;//保存IRQ的中断堆栈指针到R4                  				
        mov r5,r3					  ;//保存被中断的任务的SPSR到R5
        
        ldmfd r4!,{r0-r3}             ;//从IRQ的中断堆栈中弹出被中断的任务的 r3-r0 到CPU的寄存器中
        stmfd sp!,{r0-r3}             ;// 压入被中断的任务的 r3-r0 到SVC或SYS模式的堆栈中
        stmfd sp!,{r5}                ;// 压入被中断的任务的 Cpsr
        
        mrs r4,spsr
        stmfd sp!,{r4}                ;// 压入被中断的任务的 spsr 系统模式下,没有spsr
        
        ;// OSPrioCur = OSPrioHighRdy
        ldr r4,=OSPrioCur
        ldr r5,=OSPrioHighRdy
        ldrb r5,[r5]
        strb r5,[r4]
        
        ;// 得到当前的TCB的地址
        ldr r4,=OSTCBCur
        ldr r5,[r4]
        str sp,[r5]                 				               ;// 在任务TCB中的存放当前任务控制块的指针

        bl OSTaskSwHook             				                                  ;// 调用任务的钩子函数

        ;// 得到最高优先级TCB的地址
        ldr r6,=OSTCBHighRdy
        ldr r6,[r6]
        ldr sp,[r6]                 				                                 ;// 得到新任务的堆栈指针

        ;// OSTCBCur = OSTCBHighRdy
        str r6,[r4]                 				                                  ;// 设定新任务TCB的地址

        ldmfd sp!,{r4}              				                                    ;// 弹出新任务的 spsr
        msr SPSR_cxsf,r4
       
        ldmfd sp!,{r4}              				                                    ;// 弹出新任务的 cpsr
        msr CPSR_cxsf,r4

        ldmfd sp!,{r0-r12,lr,pc}    				                          ;// 弹出新任务的 r0-r12,lr & pc
;/*
;************************************************************************************************************
;                                   临界段代码的实现方式3
;
; 函数描述 : 通过预设定中断的状态来开关中断。在局部变量'cpu_sr'中保存中断标志,之后关闭中断。 'cpu_sr' 分配
;            给所有需要关中断的 uC/OS-II'的函数。通过把'cpu_sr' 复制到CPU的状态寄存器中来恢复关中断前的状态。
;
;            OS_CPU_SR OSCPUSaveSR()
; 输入参数 : 无
;
; 返回值   : OS_CPU_SR
;
;            OSCPURestoreSR(OS_CPU_SR cpu_sr)
; 输入参数 : OS_CPU_SR
;
; 返回值   : 无
;
; 注释     : 该函数使用如下
;
;            void Task (void *data)
;            {
;                    #if OS_CRITICAL_METHOD == 3 		// Allocate storage for CPU status register 
;                          OS_CPU_SR  cpu_sr;
;                    #endif
;                         :
;                         :
;                    OS_ENTER_CRITICAL();   // cpu_sr = OSCPUSaveSR(); 
;                         :
;                         :
;                    OS_EXIT_CRITICAL();    // OSCPURestoreSR(cpu_sr); 
;                         :
;                         :
;            }
;*********************************************************************************************************
;*/

        EXPORT  OSCPUSaveSR
        
OSCPUSaveSR
        mrs r0,CPSR
        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 + -