找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3613|回复: 1
打印 上一主题 下一主题
收起左侧

UCOS移植代码之LAMMY分析--OS_CPU_a.s

[复制链接]
跳转到指定楼层
楼主
ID:72519 发表于 2015-1-23 20:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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发现有软中断信号出现时,CPU的PC马上指到软中断服务地址处【见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]
;OSTCBCur <= OSTCBHighRdy
LDR R6, =OSTCBHighRdy
LDR R6, [R6]
LDR R4, =OSTCBCur
STR R6, [R4]
OSIntCtxSw_1
;获取新任务堆栈指针
LDR R4, [R6]
ADD SP, R4, #68 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP
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


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:68804 发表于 2015-2-9 15:05 | 只看该作者
学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表