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

📄 cpu_a.s

📁 瑞星微公司RK27XX系列芯片的SDK开发包
💻 S
字号:
	;移植,huangsl。
;********************************************************************************************************/
		INCLUDE ../boot/CONDEFINE.s
		
;定义系统模式堆栈的大小

    CODE32

    AREA    |OSIRQ|, CODE, READONLY		;OSSCHEDE

;import here , 080301,huangsl,下面的变量 必须放到 SRAM,以避免 CACHE问题.

            IMPORT  OSTCBCur                    ;指向当前任务TCB的指针
            IMPORT  OSTCBHighRdy                ;指向将要运行的任务TCB的指针
            IMPORT  OSPrioCur                   ;当前任务的优先级
            IMPORT  OSPrioHighRdy               ;将要运行的任务的优先级
            IMPORT  OSRunning                   ;uC/OS-II运行标志
;						IMPORT	OSIntNesting
						
						IMPORT	OSIntEnter
            IMPORT 	IrqCHandler               	;IRQ C语言中断处理函数
						IMPORT 	OSIntExit 
						
						IF {FALSE}
						IMPORT	OSTaskStackCheck
						ENDIF 
;export here
            EXPORT OSCtxSw 
            EXPORT  OSStartHighRdy            
            EXPORT  OSIntCtxSw                  ;中断退出时的入口,参见startup.s中的IRQ_Handler
        ;    EXPORT  SoftwareInterrupt           ;软中断入口
						EXPORT	OSIrqIsr
						
						EXPORT OSDisableInt 
						EXPORT OSEnableInt 
						
;/*********************************************************************************************************
;** 函数名称: OSIrqIsr
;** 功能描述: IRQ 中断服务程序
;** 输 入:   依功能而定
;** 输 出 :  依功能而定
;** 全局变量: 无
;具体功能可以通过 C函数实现.
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
OSIrqIsr
	
	IF	:DEF: ARMULATE
	;|   LR |
	;| SPSR |
	STR	   R0 , [SP,#-4]
	LDR	   R0 , [SP]
	LDR	   LR , [SP,#4]
	MSR	   SPSR_cxsf, R0
	LDR    R0 , [SP,#-4]
	ADD	   SP , SP , #8			   ; adjust sp.
	ENDIF
	
	SUB     LR, LR, #4                             ;计算返回地址
	
        STMFD   SP!, {R0-R3, R12, LR}        					;保存任务环境,因为可能在调用 C 语言处理函数时会改变
        MRS     R3, SPSR                               ;保存状态
        STMFD   SP!, {R3}															;防止中断嵌透时丢失

				IF {FALSE}
        LDR     R2,  =OSIntNesting                  ;OSIntNesting++
        LDRB    R1, [R2]
        ADD     R1, R1, #1
        STRB    R1, [R2]
        ELSE
        BL			OSIntEnter
        ENDIF
        
        BL      IrqCHandler                       	;调用C语言的中断处理程序
 ;MSR写状态寄存器指令使得CPSR[7:0]=0b10010010
 ;作用为关IRQ中断
 				MSR CPSR_c, #IRQMODE|NOINT									;关中断
 				
        BL      OSIntExit                                  ;调用OSIntExit(该函数需要修改,内部不能调用 OSIntCtxSw)
 
 ;比较OSTCBHighRdy和OSTCBCur
 ;作用为判断在退出中断处理之后是否进行任务切换
        LDR     R0, =OSTCBHighRdy
        LDR     R0, [R0]
        LDR     R1, =OSTCBCur
        LDR     R1, [R1] 
        CMP     R0, R1    
        
        LDMFD   SP!, {R3}   
        MSR     SPSR_cxsf, R3                              ;SPSR[31:0]=R3

        LDMEQFD SP!, {R0-R3, R12, PC}^          ;不进行任务切换则恢复任务环境
        LDR     PC, =OSIntCtxSw


OSCtxSw 
				STMFD 	sp!, {lr} 					; OSCtxSw是被调用的,lr的值就是调用前的PC值,入栈 
				STMFD 	sp!, {r0-r12,lr} 		; 将lr和其他寄存器入栈 
				MRS 		r4, cpsr 						;通过MRS指令将cpsr入栈 
				STMFD 	sp!, {r4} 					; 被挂起的当前任务的寄存器保存完毕,下面接着保存该 
																		;任务的堆栈指针,以便下次恢复时,可以找到其堆栈指针,便可恢复其寄存器 
																		
				LDR r4, =OSTCBCur 					; 得到当前TCB块的地址,传给r4 
				LDR r5, [r4] 								; 将OSTCBCur中的值传给r5,注意OSTCBCur存的是指针 
				STR sp, [r5] 								; 将当前任务的sp传到OSTCBCur存的指针中去 
				
				;进行任务切换
				B			OSIntCtxSw_0
;/*********************************************************************************************************
;** 函数名称: OSIntCtxSw
;** 功能描述: 中断退出时的入口
;** 输 入:   R3    :当前任务的状态寄存器CPSR(即SPSR的值)
;**           R4-R12:当前任务的R4-R11
;**           当前处理器模式的堆栈结构(出栈次序):R0-R3、R12、PC(当前任务的)
;** 输 出 :  无
;** 全局变量: OSPrioCur,OSPrioHighRdy,OSPrioCur,OSPrioHighRdy
;** 调用模块: 无
;** 
;任务切换退出中断
;080204,huangsl,任务切换时必须保证 R13 指向正确的堆栈,否则会 DATA ABORT.目前发现 FFT 运算会使用 R13 作为
;临时寄存器,此时中断发生 任务切换会 死机.
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
OSIntCtxSw
                                                    ;下面为保存任务环境
				;前 处于 IRQ 状态,并且 堆栈次序为  R0-R3、R12、PC,里面保存的时被中断的任务的 context.
				;首先出栈                                                  
        LDR     R2, [SP, #20]                       ;获取PC
        LDR     R12, [SP, #16]                      ;获取R12
        
        ;保存当前 CPSR(IRQ STATE)
        MRS     R0, CPSR
        
        ;切换到 SVC模式(任务运行模式)
        MSR     CPSR_c, #SVCMODE|NOINT			;局部修改 CPSR,该指令可能不支持
        MOV     R1, LR
        STMFD   SP!, {R1-R2}                        ;保存LR,PC
        STMFD   SP!, {R4-R12}                       ;保存R4-R12
				
			;下面保存 R0-R3,需要先出 IRQ STACK,然后保存到 SVC STACK.
        MSR     CPSR_cxfs, R0
        LDMFD   SP!, {R4-R7}                        ;获取R0-R3
        ADD     SP, SP, #8                          ;出栈R12,PC,即忽略这两个数据
        
        MSR     CPSR_c, #SVCMODE|NOINT							;局部修改 CPSR,该指令可能不支持
        STMFD   SP!, {R4-R7}                        ;保存R0-R3
        
        STMFD		SP!,{R3}														;保存CPSR
                                                    
                                                    ;保存当前任务堆栈指针到当前任务的TCB
        LDR     R1, =OSTCBCur
        LDR     R1, [R1]
        STR     SP, [R1]

        ;BL      OSTaskSwHook                        ;调用钩子函数
 
OSIntCtxSw_0                                                  ;OSPrioCur <= OSPrioHighRdy
        LDR     R4, =OSPrioCur
        LDR     R5, =OSPrioHighRdy
        LDRB    R6, [R5]
        STRB    R6, [R4]
                                                    ;OSTCBCur <= OSTCBHighRdy
        LDR     R6, =OSTCBHighRdy
        LDR     R6, [R6]
        LDR     R4, =OSTCBCur
        STR     R6, [R4]
				
OSIntCtxSw_1
        LDR 		sp, [r6] 											; 切换到新任务的堆栈 
        
        ;********测试堆栈数据***********
        IF {FALSE}
        MOV			R0,SP
        BL			OSTaskStackCheck
        ENDIF
        ;********测试堆栈数据结束***********
        
				LDMFD 	sp!, {r4} 									;从新任务堆栈中读取第一个参数(CPSR)到(r4) 
				
				MSR 		spsr_cxsf, r4 								;再传给cpsr,堆栈中的CPSR弹出到CPU的cpsr寄存器 
				LDMFD 	sp!, {r0-r12,lr,pc}^ 				;依次恢复该任务r0~r12,lr,pc,切换到该任务 
	
	;			MSR 		cpsr_cxsf, r4 								;直接传递给 CPSR,会导致开中断.
	;			LDMFD 	sp!, {r0-r12,lr,pc} 				;依次恢复该任务r0~r12,lr,pc,切换到该任务 
				                          
;/*********************************************************************************************************
;** 函数名称: __OSStartHighRdy
;** 功能描述: uC/OS-II启动时使用OSStartHighRdy运行第一个任务,
;**           OSStartHighRdy会调用__OSStartHighRdy
;** 输 入:   无
;** 输 出 :  无
;** 全局变量: OSRunning,OSTCBCur,OSTCBHighRdy,OsEnterSum
;** 调用模块: OSTaskSwHook
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/

OSStartHighRdy

 				;告诉uC/OS-II自身已经运行
        LDR     R4, =OSRunning
        MOV     R5, #1
        STRB    R5, [R4]

        ;BL      OSTaskSwHook                    ;调用钩子函数

        LDR     R6, =OSTCBHighRdy
        LDR     R6, [R6]
        B       OSIntCtxSw_1
        
        
OSDisableInt 
				MRS r0, cpsr 				;由于任务和内核都运行在svc模式下,因此可方便地操作cpsr 
			;	STMFD sp!, {r0} 		; 保存当前的cpsr 
				ORR r1, r0, #0xc0 		;屏蔽FIQ,IRQ中断 
				MSR cpsr_c, r1 			;回写cpsr,只屏蔽IRQ中断 
				MOV pc, lr 					;返回 
	
	
OSEnableInt 								;必须和 OSDisableInt 成对使用 
			;	LDMFD sp!, {r0} 		;弹出在 OSDisableInt 中被保存的cpsr 
				MSR cpsr_c, r0 			;恢复关中断前的cpsr 
				MOV pc, lr 					;返回     

    END
    
;/*********************************************************************************************************
;**                            End Of File
;********************************************************************************************************/

⌨️ 快捷键说明

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