UCOS在LPC上的移植
一、一、OS_CPU_A.ASM文件的编写
1、 1、 SoftwareInterrupt的编写
当发生软件中断时,程序通过异常向量表跳转到软中断的汇编与C接口程序SoftwareInterrupt处,下图为SoftwareInterrupt的流程图。
程序:
SoftwareInterrupt
LDR SP, StackSvc ; 重新设置堆栈指针,堆栈指向的是SVC模式下的堆栈
STMFD SP!,{R0-R3,R12,LR}
STMFD SP!, {R0-R3, R12, LR} ;此时R0-R3, R12,在svc和用户模式下都是同一物理地址,lr为svc下的寄存器,保存着中断返回地址
MOV R1, SP ; R1指向参数存储位置(svc下的堆栈指针地址)
这个不知道用在哪??
MRS R3, SPSR ;R3中放SWI前的CPSR(即被中断的任务的cpsr),在切换函数中用到
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}^;
LDMFD SP!, {R0-R3, R12, PC}^ R12处的上一堆栈指针(&R12+4)存放的为LR,所以就把LR装入PC
分析:因为执行任务切换时(执行新任务)堆栈指针会指向用户的堆栈,这样下一次进入管理模式(在osintctxsw中就会用到管理模式)就会破坏用户堆栈,从而导致程序执行不正确。所以程序在一开始设置堆栈指针。软中断指令使处理器进入管理模式,而用户程序处于系统/用户模式,其它异常也有自己的处理器模式,都有各自的堆栈指针,不会因为给堆栈指针赋值而破坏其它处理器模式的堆栈而影响其它程序的执行。返回的地址已经存储在连接寄存器LR中而不是存储在堆栈中。由于进人管理模式自动关中断,所以这段程序不会被其它程序同时调用,设置的堆栈指针指向的位置肯定是空闲位置,后一次调用不会影响前一次调用。这样就可以保证“LDR SP, StackSvc”进行正确的堆栈指针设置。
因为ARM处理器核具有两个指令集,在执行Thumb指令的状态时不是所有寄存器都可见(参考ARM的相关资料),而且任务又可能不在特权模式(不能改变CPSR)。为了兼容任意一种模式,本移植使用软中断指令SWI使处理器进入管理模式和ARM指令状态,并使用功能0实现OS_TASK_SW()的功能,
附: (1)LR没有入栈:
从SWI和Undef异常返回时使用:
movs pc, LR;
从FIQ、IRQ和预取终止返回时使用:
SUBS PC, LR,#4;
从数据异常返回时使用:
SUBS PC, LR,#8
(2)LR有入栈:
在使用上述指令异常返回时,如果LR之前被压栈的话使用LDM “∧”,达到同样效果。 例如:
LDMFD SP!, {PC}∧
2 、OSIntCtxSw的编写:
在μC/OS-Ⅱ中,任务切换只是简单的将处理器寄存器保存到将被挂起的任务的堆栈中,并且将更高优先级的任务从堆栈中恢复出来。处于就绪状态的任务的堆栈结构看起来就像刚发生过中断并将所有的寄存器保存到堆栈中的情形一样。换句话说,μC/OS-Ⅱ要运行处于就绪状态的任务必须要做的事就是将所有处理器寄存器从任务堆栈中恢复出来,并且执行中断的返回。
在μC/OS-Ⅱ中,用户级任务调度时会调用宏(或者函数)OS_TASK_SW(),它是在μC/OS-Ⅱ从低优先级任务切换到最高优先级任务时被调用的,μC/OS-Ⅱ建议OS_TASK_SW()通过某种途径最终调用函数OSCtxSw()。函数OSCtxSw()是与系统相关的,μC/OS-Ⅱ提供的OSCtxSw()函数原型如下:
OSCtxSw()原型的程序清单
void OSCtxSw(void)
{
保存处理器寄存器;
将当前任务的堆栈指针保存到当前任务的OS_TCB中;
OSTCBCur->OSTCBStkPtr = Stack pointer;
调用用户定义的OSTaskSwHook();
OSTCBCur = OSTCBHighRdy;
OSPrioCur = OSPrioHighRdy;
得到需要恢复的任务的堆栈指针;
Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
将所有处理器寄存器从新任务的堆栈中恢复出来;
执行中断返回指令;
}
下面将各部分分解来分析:
在进入OSIntCtxSw 前,当前处理器堆栈模式(SVC)为:SP指向R0
(1) (1)保存处理器寄存器:
OSIntCtxSw ;下面为保存任务环境
LDR R2, [SP, #20] LDR R2, [SP, #20] ;
;获取PC ,此时SP指向的是SVC的任务堆栈;SP+20=LR,即把中断返回地址给PC, 这里的PC是当前任务的PC , 跟下面需要恢复的新任务的PC(程序37)是不一样的 ……………………………………………………………………………………………(1)
获取PC ,此时SP指向的是SVC
钱
LDR R12, [SP, #16] ;获取R12 …………………………………………(2)
MRS R0, CPSR ;用来存储模式切换 ………………………… (3)
MSR CPSR_c, #(NoInt | SYS32Mode) ;系统模式…………………………………(4)
***注***自己的理解:
1. Ucos的任务运行在用户模式或是系统模式下,也就意味着所有任务的堆栈位于为用户模式开辟的堆栈区中(系统模式和用户模式拥有相同的堆栈区)。
2. 当进行任务切换时,ARM都会自动进入相应的处理器模式,如任务级调度进入管理模式,中断级调度进入IRQ模式,而每个处理器模式拥有不同的堆栈区。
3. 任务切换需要保存被中断中止任务的上下文,将寄存器内容压入自己的任务堆栈,而任务堆栈位于用户模式堆栈区,所以必须先将ARM处理器模式由管理模式或是IRQ模式切换到系统模式,才能正确完成上下文切换。
MOV R1,LR ……………………………………………………… (5)
STMFD SP!,{R1,R2};
STMFD SP!, {R1-R2} ; 保存LR,PC到任务堆栈下;ARM 7中模式R0-R12公用,
所以转到SYS,R1,R2还是不变 …………………………(6)
STMFD SP!, {R4-R12} ;保存R4-R12到任务堆栈下 …………………(7)
MSR CPSR_c, R0 ; ……………………………………………… (8)
LDMFD SP!, {R4-R7} ;获取R0-R3,在SVC的堆栈中R3存放着SPSR值 ………… (9)
ADD SP, SP, #8 ;
ADD SP, SP, #8 ; 出栈R12,PC,在堆栈中剩余的数据(R12、PC)已经没有用处,所以
要进行调整;清理软中断堆栈,复原到任务切换前的样子…… (10)
MSR CPSR_c, #(NoInt | SYS32Mode) ;系统模式……………………………(11)
STMFD SP!, {R4-R7} ;把获取的R0-R3参数保存到任务堆栈中………(12)
LDR R1, =OsEnterSum ;获取OsEnterSum单元地址(CPU寄存器下的地址)… (13)
LDR R2, [R1] ;…………………………………… (14)
STMFD SP!, {R2, R3} ;保存CPSR,OsEnterSum 到任务堆栈 ………………………(15)
至此,处理器寄存器已保存完毕。
(2)将当前任务的堆栈指针保存到当前任务的OS_TCB中;
OSTCBCur->OSTCBStkPtr = Stack pointer
OSTCBCur:当前任务的OS_TCB任务块指针
.OSTCBStkPtr:指向当前任务堆栈栈顶的指针
栈顶:堆栈中刚存入有效数据的那一个单元地址
代码如下:
;保存当前任务堆栈指针到当前任务的TCB
LDR R1, =OSTCBCur ;取 & OSTCBCur 单元地址 …………………(16)
LDR R1, [R1] LDR R1, [R1] ;
STR SP, [R1] 取 OSTCBCur指向的内容,OS_TCB本身就是一个数据结构 ,因此OSTCBCu指向的内容即为该任务块的 第一个元素OSTCBStkPtr …………………………………………………………………………………(17)
STR SP, [R1] ;OSTCBCur->OSTCBStkPtr = Stack pointer…………………………(18)
(3)调用用户定义的OSTaskSwHook():
(3)调用用户定义的OSTaskSwHook():这样可直接访问OSTCBCur和OSTCBHighRdy这2个全局变量。OSTCBCur指向将被切换出去的任务控制块;而OSTCBHighRdy指向新任务的任务控制块
OSTCBCur = OSTCBHighRdy;任务控制块更新
OSPrioCur = OSPrioHighRdy; 任务优先级更新
代码如下:
BL OSTaskSwHook ;调用子函数 …………………………………………(19)
LDR R4, =OSPrioCur ; ………………………………………(20)
LDR R5, =OSPrioHighRdy ; 优先级更新 ………………… (21)
LDRB R6, [R5] ;……………………………………………………………… (22)
STRB R6, [R4] ;……………………………………………………………… (23)
任务控制块更新:
LDR R6, =OSTCBHighRdy ;取& =OSTCBHighRdy单元地址…………………………………… (24)
OSTCBHighRdy 指向的是新任务控制块的第一个元素
LDR R6, [R6] ;取OSTCBHighRd的值 ………… (25)
LDR R4, =OSTCBCur ; …………………………………………(26)
STR R6, [R4] ;把OSTCBHighRdy指向的内容复制给 OSTCBCur …………(27)
此时,任务块已更新,OSTCBHighRdy已复制到OSTCBCur,即OSTCBCur已指向新任务控制块的第一个元素(栈顶指针)。
(4)得到需要恢复的任务的堆栈指针;
Stack pointer = OSTCBHighRdy->OSTCBStkPtr;
将所有处理器寄存器从新任务的堆栈中恢复出来;
执行中断返回指令;
代码分析:从标号OSIntCtxSw_1处开始至程序的最后,是将所有处理器寄存器从新任务的堆栈中恢复出来。处理器执行这段代码时处于ARM状态,但用户任务可能处于Thumb状态。而由ARM的相关资料可知,程序不可以直接改变程序状态寄存器的CPSR的T位来改变处理器的状态。但“LDMFD SP!, {R0-R12, LR, PC }^ ” 异常返回指令是可以使用的(具体参见ARM的多寄存器加载指令),所以在恢复寄存器时,必须使处理器处于某种异常模式。由于FIQ模式和IRQ模式对应中断,SP指针不能随意改变,而未定义模式和中止模式以后可能会用到,所以本移植选择为管理模式。
OSIntCtxSw_1
;获取新任务堆栈指针,[R6] 的值为指针:指向的是新任务的栈顶指针,而新任务的栈顶指针指向哪?因为在堆栈初始化后(OSTaskStkInit()函数),堆栈指针已经指向任务堆栈的最低地址单元(OsEnterSum)
LDR R4, [R6] ;[R6] :新任务的栈顶指针;指针指向的内容为(& OsEnterSum )…(28)
ADD SP, R4, #68 ADD SP, R4, #68; 堆栈指向(PC+4 )处,这就是新任务CPU寄存器的SP值(R13),为入其他数据做堆栈指针调整 …………………………………………(29)
LDR LR, [SP, #-8] ;把任务堆栈的LR给CPU寄存器R14 ……………………(30)
MSR CPSR_c, #(NoInt | SVC32Mode) ;进入管理模式 ……………………………………(31)
MOV SP, R4 ;设置堆栈指针,SP为R13_SVC下的,SP指向(& OsEnterSum )……(32)
LDMFD SP!, {R4, R5} ;取任务下的CPSR,OsEnterSum 到CPU寄存器R5,R4……… (33)
LDR R3, =OsEnterSum ;取CPU寄存器下的地址单元 ………………………………(34)
STR R4, [R3] ;恢复新任务的OsEnterSum……………………………… (35)
MSR SPSR_cxsf, R5 ;恢复CPSR ,异常下的SPSR返回后给新任务的CPSR…………(36)
LDMFD SP!, {R0-R12, LR, PC LDMFD SP!, {R0-R12, LR, PC }^ ;异常返回,这里的PC在堆栈初始化时已经设置好了,运行新 任 务…………………………………………………………………………………………………………………(37)
转载于:https://www.cnblogs.com/gmh915/archive/2009/09/30/1577029.html
UCOS在LPC上的移植相关推荐
- 关于ucos在lpc上移植
关于ucos在lpc上移植: 主要有四个文件,传统的有三个文件:os_cpu_c.c,os_cpu_a.s,os_cpu.h 还有一个是IRQ.inc Os_cpu.h:这个文件相对来说还是很简单的, ...
- uCOS-II在51单片机上的移植
uCOS-II在51单片机上的移植 约定:文中所写的硬件堆栈或系统堆栈是指51单片机SP指针所指向的堆栈空间,而用户堆栈或任务堆栈是指用来保存任务状态为每个任务分配的堆栈空间. 前一段时间一直在学习U ...
- 移植c语言算法到arm上,μCOS-II移植到ARM处理器上的几个要点
原标题:μCOS-II移植到ARM处理器上的几个要点 本文主要介绍μCOS-II移植到ARM处理器上的几个要点,如下所示: uCOS II在ARM处理器上移植过程中的中断处理 uCOS II是一个源码 ...
- VxWorks在EasyARM2200和SmartARM2200上的移植zz
发信人: gdtyy (gdtyy), 信区: Embedded 标 题: VxWorks在EasyARM2200和SmartARM2200上的移植 发信站: 水木社区 (Mon Jun 25 23 ...
- RTOS 在 stm32f407 探索者上的移植(一)
RTOS是什么 先看他们的定义.非实时操作系统指 操作系统无法保证 最高优先级任务开始执行 的最后时限. 软实时操作系统指 操作系统只能保证在xx时间内开始执行最高优先级的用户代码,但无法保证用户软件 ...
- 在arm linux mini2440上移植ntp服务,RTEMS 4.9.5 在 QEMU MINI2440 上的移植发布啦……
(本文原创,转载请注明出处,谢谢) 这两天抽了个空,在rickleaf移植的 qemu mini2440 的rtems 4.9.5 bsp 上做了一些修改: 1.原来mini2440的 bsp是基于 ...
- OpenCV在ARM上的移植
OpenCV在ARM上的移植 与X86 Linux类似,请参考: Linux 下编译安装OpenCV 本文在此基础上进行进一步操作. 网络上很多移植编译的方法比较老,多数针对OpenCV 1.0,而且 ...
- u-boot-2009.08在2440上的移植详解(三)
一.移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-b ...
- 文件系统应用笔记之一:FatFS在STM32F4上的移植
在实现如U盘文件读写,SD卡的文件读写等工作时,我们往往需要一个文件系统来支持我们的工作.特别在一些MCU应用中,文件系统的加入能明显改善系统交互的友好性.在这一篇中,我们就来讨论FatFS文件系 ...
最新文章
- 《OpenMP编译原理及实现技术》摘录
- ​利用卷积神经网络学习脑电地形图表示进行分类
- html段落加边框,Word2010怎样为段落加上边框
- python-基础知识
- Android开发(七)——判断网络状态
- 活动报名 | PaddlePaddle Hackathon飞桨黑客马拉松邀你参加
- 动态顺序图可视化控件
- python 序列类型函数_序列类型可用的内置函数
- multiset实现ALV树
- istio 防故障流量控制
- 普通话/汉语的语音识别:DFSMN-CTC-SMBR模型
- 【PyTorch】pkg_resources
- jquery选择器可以利用后代和直系后代选择器连续选择元素
- 安卓开发用什么语言?一次违反常规的安卓大厂面试经历,含BATJM大厂
- MTK芯片平台,MT6737烧录工具资料(SP_Flash_Tool_exe_Windows_v5.1712.00.000)
- Promsql语法用法
- 全国电子设计大赛 物品清单分析2013年
- macOS系统升级(vmware虚拟机安装)
- 计算机基础知识教案 技能高考,高考实用类文本阅读知识复习教案
- 2019,先定个小目标
热门文章
- 手把手教你:如何让Windows恋上Linux bash
- 大型系统OA--技术
- android 删除文件
- 开启和关闭(禁用)IE8加速器功能的办法
- 昌平房价已降至6500元每一平米
- C语言 浮点数从0递增至1.0的过程
- Python 网易新闻热点新闻爬虫
- InsecureRequestWarning: Unverified HTTPS request is being made to host(requests证书警告)
- Eclipse IDE for Enterprise Java Developers和JDK8与apache-tomcat-8下载地址
- rabbitMQ简单使用