osintctxsw分析

OS_CPU_a.s:

;定义系统模式堆栈的大小

SVC_STACK_LEGTH EQU 32

 

NoInt EQU 0x80

 

USR32Mode EQU 0x10

SVC32Mode EQU 0x13

SYS32Mode EQU 0x1f

IRQ32Mode EQU 0x12

FIQ32Mode EQU 0x11

 

;T_bit用于检测进入异常前cpu是否处于THUMB状态

T_bit EQU 0x20

 

CODE32

 

AREA |subr|, CODE, READONLY

 

IMPORT OSTCBCur ;指向当前任务TCB的指针

IMPORT OSTCBHighRdy ;指向将要运行的任务TCB的指针

IMPORT OSPrioCur ;当前任务的优先级

IMPORT OSPrioHighRdy ;将要运行的任务的优先级

IMPORT OSTaskSwHook ;任务切换的钩子函数

IMPORT OSRunning ;uC/OS-II运行标志

 

IMPORT OsEnterSum ;关中断计数器(关中断信号量)

IMPORT SWI_Exception ;软中断异常处理程序

 

EXPORT __OSStartHighRdy

EXPORT OSIntCtxSw ;中断退出时的入口,参见startup.s中的IRQ_Handler

EXPORT SoftwareInterrupt ;软中断入口

 

;软件中断

//CPU发现有软中断信号出现时,CPUPC马上指到软中断服务地址处【见Startup.s】,然后通过跳转到下面这段软中断处理程序,进入后,首先要设置好管理模式下的堆栈,保存好用户任务的几个寄存器,其它寄存器系统会自动保存,然后取出SWI号。

SoftwareInterrupt

LDR SP, StackSvc ; 重新设置堆栈指针

STMFD SP!, {R0-R3, R12, LR} //为什么只保存这几个寄存器,见上面的解释

MOV R1, SP ; R1指向参数存储位置

 

MRS R3, SPSR //保存管理模式的状态寄存器

TST R3, #T_bit ; 中断前是否是Thumb状态

LDRNEH R0, [LR,#-2] ; : 取得Thumb状态SWI

BICNE R0, R0, #0xff00

LDREQ R0, [LR,#-4] ; : 取得arm状态SWI

BICEQ R0, R0, #0xFF000000

; r0 = SWI号,R1指向参数存储位置

CMP R0, #1

LDRLO PC, =OSIntCtxSw

LDREQ PC, =__OSStartHighRdy ; SWI 0x01为第一次任务切换

 

BL SWI_Exception

 

LDMFD SP!, {R0-R3, R12, PC}^

 

StackSvc DCD (SvcStackSpace + SVC_STACK_LEGTH * 4 - 4)

 

OSIntCtxSw

;下面为保存任务环境

LDR R2, [SP, #20] ;获取PC//其实他就是管理模式下的LR寄存器的值,也就是用户任务的PC值,为什么是SP+20,因为该栈是满栈递减,保存了R0-R3, R12, LR,所以LR的值为[SP+#20]

LDR R12, [SP, #16] ;获取R12

MRS R0, CPSR //用通用寄存器R0保存该管理模式下的CPSR

 

MSR CPSR_c, #(NoInt | SYS32Mode)//切换到系统模式

MOV R1, LR //把用户的LR保存在通用寄存器R1

STMFD SP!, {R1-R2} ;保存LR,PC//把系统模式的LR,PC压入用户任务的栈中

STMFD SP!, {R4-R12} ;保存R4-R12//把系统模式的R4-R12压入用户栈中

 

MSR CPSR_c, R0 //重新回到管理模式

LDMFD SP!, {R4-R7} ;获取R0-R3//实际上把用户的R0~R3放到管理模式下的R4-R7

ADD SP, SP, #8 ;出栈R12,PC//这两个已经保存了,所以SP要往上8个字节

 

MSR CPSR_c, #(NoInt | SYS32Mode//系统模式

STMFD SP!, {R4-R7} ;保存R0-R3//因为管理模式的R4-R11和系统模式的R4-R11是一样的,保存在用户任务的栈中

LDR R1, =OsEnterSum ;获取OsEnterSum

LDR R2, [R1]

STMFD SP!, {R2, R3} ;保存CPSR,OsEnterSum

 

;保存当前任务堆栈指针到当前任务的TCB

LDR R1, =OSTCBCur

LDR R1, [R1]

STR SP, [R1]

 

BL OSTaskSwHook ;调用钩子函数

;OSPrioCur <= OSPrioHighRdy

LDR R4, =OSPrioCur

LDR R5, =OSPrioHighRdy

LDRB R6, [R5]

STRB R6, [R4]   ;r4内为最高任务的优先级

;OSTCBCur <= OSTCBHighRdy

LDR R6, =OSTCBHighRdy

LDR R6, [R6]

LDR R4, =OSTCBCur 

STR R6, [R4] ;ostcbcur指向将要运行的任务

OSIntCtxSw_1

;获取新任务堆栈指针

LDR R4, [R6]

ADD SP, R4, #68 ;先调整堆栈 因为等会从管理模式下直接恢复到系统模式下开始

                 运行任务,无法修改指针了。 

LDR LR, [SP, #-8]

MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式

MOV SP, R4 ;设置堆栈指针(是没修改过的指针,即保存了上下文的指针)

 

LDMFD SP!, {R4, R5} ;CPSR,OsEnterSum

;恢复新任务的OsEnterSum

LDR R3, =OsEnterSum

STR R4, [R3]

 

MSR SPSR_cxsf, R5 ;恢复CPSR

LDMFD SP!, {R0-R12, LR, PC }^ ;运行新任务

 

 

__OSStartHighRdy

MSR CPSR_c, #(NoInt | SYS32Mode)

;告诉uC/OS-II自身已经运行

LDR R4, =OSRunning

MOV R5, #1

STRB R5, [R4]

 

BL OSTaskSwHook ;调用钩子函数

 

LDR R6, =OSTCBHighRdy

LDR R6, [R6]

B OSIntCtxSw_1

 

AREA SWIStacks, DATA, NOINIT,ALIGN=2

SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;管理模式堆栈空间

 

END

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值