嵌入式技术简介和应用_第1页
嵌入式技术简介和应用_第2页
嵌入式技术简介和应用_第3页
嵌入式技术简介和应用_第4页
嵌入式技术简介和应用_第5页
已阅读5页,还剩66页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 嵌入式技术简介和应用移植C/OS-II到ARM7 6C H A P T E R第6章 目录1. C/OS-II简介2.移植规划3.移植C/OS-II4.移植代码应用到LPC2000第6章 目录1. C/OS-II简介2.移植规划3.移植C/OS-II4.移植代码应用到LPC20006.1 C/OS-II简介概述 C/OS-II是源码公开的著名实时内核,可用于各类8位、16位和32位单片机或DSP。从C/OS算起,该内核已有10多年应用史,在诸多领域得到广泛应用。 C/OS-II是一个完整的、可移植、可固化、可剪裁的占先式实时多任务内核。C/OS-II使用ANSI C语言编写,包含一小部分汇编

2、代码,使之可以供不同架构的微处理器使用。至今,从8位到64位,C/OS-II已在超过40种不同架构的微处理器上运行。C/OS-II特点提供源代码:购买作者撰写的嵌入式实时操作系统C/OS-II一书即可获得版本的所有源代码,购买此书的其它版本可以获得相应版本的全部源代码。可移植性(portable):C/OS-II的源代码绝大部分是使用移植性很强的ANSI C写的,将与微处理器硬件相关的汇编语言使用量压缩到最低的限度,以使C/OS-II便于移植到其它微处理器上。目前,C/OS-II已经被移植到多种不同架构的微处理器上。可固化(ROMmable):只要具备合适的软硬件工具,就可以将C/OS-II嵌

3、入到产品中成为产品的一部分。可剪裁(scalable):C/OS-II使用条件编译实现可剪裁,用户程序可以只编译自己需要的(C/OS-II的)功能,而不编译不要需要的功能,以减少C/OS-II对代码空间和数据空间的占用。可剥夺(preemptive):C/OS-II是完全可剥夺型的实时内核,C/OS-II总是运行就绪条件下优先级最高的任务。C/OS-II特点多任务:C/OS-II可以管理64个任务,然而,C/OS-II的作者建议用户保留8个给C/OS-II。这样,留给用户的应用程序最多可有56个任务。可确定性:绝大多数C/OS-II的函数调用和服务的执行时间具有确定性,也就是说,用户总是能知道

4、C/OS-II的函数调用与服务执行了多长时间。任务栈:C/OS-II的每个任务都有自己单独的栈,使用C/OS-II的占空间校验函数,可确定每个任务到底需要多少栈空间。系统服务:C/OS-II提供很多系统服务,例如信号量、互斥信号量、时间标志、消息邮箱、消息队列、块大小固定的内存的申请与释放及时间管理函数等。中断管理:中断可以使正在执行的任务暂时挂起,如果优先级更高的任务被中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达255层。 C/OS-II特点稳定性与可靠性:C/OS-II是C/OS的升级版,C/OS自1992年以来已经有数百个商业应用。C/OS-II与C/OS的内

5、核是一样的,只是提供了更多的功能。2000年7月,C/OS-II在一个航空项目中得到了美国联邦航空管理局对商用飞机的、符合RTCA DO 178B标准的认证。这表明,该操作系统的质量得到了认证,可以在任何应用中使用。作者及其著作第6章 目录1. C/OS-II简介2.移植规划3.移植C/OS-II4.移植代码应用到LPC20006.2 移植规划概述 所谓“移植”,就是使一个实时内核能在其它的微处理器或微控制器上运行。尽管大部分C/OS-II的代码是用C语言编写的,但是 在编写与处理器硬件相关的代码时还是不得不使用汇编语言。移植的主要工作就是编写这些与处理器硬件相关的代码。 在移植前针对所使用的

6、微处理器进行规划,主要有以下几个方面的考虑:编译器的选择、任务模式的选择和支持的指令集。C/OS-II移植应用程序(用户代码)C/OS-II(与处理器无关代码)OS_CORE.cOS_FLAG.c. C/OS-II配置(与应用无关)OS_CFG.HINCLUDES.H C/OS-II移植(与处理器相关代码)CPU定时器 硬件软件C/OS-II硬件软件体系结构用于产生系统时钟移植时需要编写的代码6.2 移植规划编译器的选择 针对ARM处理器核的C语言编译器有很多,如SDT、ADS、IAR、TASKING和GCC等。目前国内最流行的是ADS、SDT和GCC。SDT和ADS均为ARM公司开发,ADS

7、为SDT的升级版,以后ARM公司不再支持SDT,所以不会选择SDT。GCC虽然支持广泛,很多开发套件使用它作为编译器,但是与ADS比较其编译效率较低,这对充分发挥芯片性能很不利,所以最终使用ADS编译程序和调试。6.2 移植规划任务模式的取舍 ARM7处理器核具有用户、系统、管理、中止、未定义、中断和快中断七种模式,其中除用户模式外其它均为特权模式。其中管理、中止、未定义、中断和快中断模式与相应异常相联系,任务使用这些模式不太适合。而系统模式除了是特权模式外,其它与用户模式一样,因而可选为任务使用的模式只有用户模式和系统模式。为了尽量减少任务代码错误对整个程序的影响,缺省的任务模式定为用户模式

8、,可选为系统模式,同时提供接口使任务可以在这两种模式间切换。6.2 移植规划支持的指令集 带T变量的ARM7处理器核具有两个指令集:标准32位ARM指令集和16位Thumb指令集,两种指令集有不同的应用范围。为了最大限度地支持芯片的特性,任务应当可以使用任意一个指令集并可以自由切换,而且不同的任务应当可以使用不同的指令集,这次移植的代码已经实现了这一点。 第6章 目录1. C/OS-II简介2.移植规划3.移植C/OS-II4.移植代码应用到LPC20006.3 移植C/OS-II概述 要移植一个操作系统到一个特定的CPU体系结构上并不是一件很容易的事情,它对移植者有以下要求:1 对目标体系结

9、构要有很深了解;2 对OS原理要有较深入的了解;3 对所使用的编译器要有较深入的了解;4 对需要移植的操作系统要有相当的了解;5 对具体使用的芯片也要一定的了解。 要移植一个操作系统到一个特定的CPU体系结构上并不是一件很容易的事情,它对移植者有以下要求:1 对目标体系结构要有很深了解;2 对OS原理要有较深入的了解;3 对所使用的编译器要有较深入的了解;4 对需要移植的操作系统要有相当的了解;5 对具体使用的芯片也要一定的了解。概述 要移植一个操作系统到一个特定的CPU体系结构上并不是一件很容易的事情,它对移植者有以下要求:1 对目标体系结构要有很深了解;2 对OS原理要有较深入的了解;3

10、对所使用的编译器要有较深入的了解;4 对需要移植的操作系统要有相当的了解;5 对具体使用的芯片也要一定的了解。参考ARM公司的ARM体系结构文档参考嵌入式实时操作系统C/OS-II 一书参考ADS软件自带的编译器和连接器手册参考嵌入式实时操作系统C/OS-II 一书参考具体芯片的数据手册和使用手册因为第4点的影响是全局性的,它决定移植代码的框架和功能。所以重点介绍第4点。概述 根据C/OS-II的要求,移植C/OS-II到一个的体系结构上需要提供2个或3个文件: (C语言头文件) (C程序源文件) (汇编程序源文件) 其中在某些情况下不需要。不需要的必须满足以下苛刻条件,而同时满足这些条件的微

11、控制器几乎没有: 1.可以直接使用C语言开关中断; 2.可以直接使用C语言编写中断服务程序; 3.可以直接使用C语言操作堆栈指针; 4.可以直接使用C语言保存CPU的所有寄存器。 移植需要编写的文件概述移植内容类型所属文件描述BOOLEAN、INT8U、INT8S、数据类型OS_CPU.H与编译器无关的数据类型OS_STK数据类型OS_CPU.H堆栈的数据类型OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()宏OS_CPU.H开关中断的代码OS_STK_GROWTH常量OS_CPU.H定义堆栈的增长方向OS_TASK_SW函数OS_CPU.H任务切换时执行的代码OST

12、askStkInit()函数OS_CPU_C.C任务堆栈初始化函数OSInitHookBegin()、OSInitHookEnd()、函数OS_CPU_C.CC/OS-II在执行某些操作时调用的用户函数,一般为空OSStartHighRdy()函数*OS_CPU_A.ASM进入多任务环境时运行优先级最高的任务, OSIntCtxSw()函数*OS_CPU_A.ASM中断退出时的任务切换函数OSTickISR()中断服务程序*OS_CPU_A.ASM时钟节拍中断服务程序实际上,还有一个文件很重要,它就是,它定义了一个汇编宏,它是C/OS-II for ARM7通用的中断服务程序的汇编与C函数接口

13、代码。时钟节拍中断服务程序也没有移植,因为其与芯片和应用都强烈相关,需要用户自己编写,不过可以通过简化用户代码的编写。 移植代码包括的内容关于头文件和 C/OS-II要求所有.C文件的都要包含都文件,这样使得用户项目中的每个.C文件不用分别去考虑它实际上需要哪些头文件。使用的缺点是它可能会包含一些实际不相关的头文件,这意味着每个文件的编译时间可能会增加,但却增强了代码的可移植性。 在本移植中另外增加了一个头文件,我们要求所有用户程序必须包含,在中包含和特定的头文件和配置项。而C/OS-II的系统文件依然只是包含,即C/OS-II的系统文件完全不必改动。所有的配置改变包括头文件的增减均在中进行,

14、而定下来后不必改动(C/OS-II的系统文件需要包含的东西是固定的)。这样,C/OS-II的系统文件需要编译的次数大大减少,编译时间随之减少。 congfig.hUCOS内核文件Includes.h用户程序编写 COS-II不使用C语言中的short、int、long等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性。代之以移植性强的整数数据类型,这样,既直观又可移植,不过这就成了必须移植的代码。根据ADS编译器的特性,这些代码如程序清单所示。typedefunsigned char BOOLEAN; typedefunsigned char INT8U;typedefsigned

15、char INT8S;typedefunsigned short INT16U;typedefsigned short INT16S;typedefunsigned int INT32U;typedefsigned int INT32S;typedeffloat FP32;typedefdouble FP64;typedefINT32U OS_STK;不依赖于编译的数据类型编写COS-II运行时,处理器可能处于的状态如下图所示:使用软中断SWI作底层接口Thumb指令集ARM指令集用户模式系统模式用户任务使用的处理器模式ARM7内核具有的指令集ARM指令用户模式ARM指令系统模式Thumb指令

16、系统模式Thumb指令用户模式编写 为了使底层接口函数与处理器状态无关,同时在任务调用相应的函数不需要知道函数位置,本移植使用软中断指令SWI作为底层接口,使用不同的功能号区分不同的函数。软中断功能号分配如下表所示,未列出的为保留功能。 使用软中断SWI作底层接口功能号接口函数简介0 x00void OS_TASK_SW(void)任务级任务切换函数0 x01_OSStartHighRdy(void)运行优先级最高的任务,由OSStartHighRdy产生0 x02void OS_ENTER_CRITICAL(void)关中断0 x03Void OS_EXIT_CRITICAL(void)开中

17、断0 x80Void ChangeToSYSMode(void)任务切换到系统模式0 x81Void ChangeToUSRMode(void)任务切换到用户模式0 x82Void TaskIsARM(INT8U prio)任务代码是ARM代码0 x83Void TaskIsTHUMB(INT8U prio)任务代码是THUMB代码编写 用软中断作为操作系统的底层接口就需要在C语言中使用SWI指令。在ADS中,有一个关键字_swi,用它声明一个不存在的函数,则调用这个函数就在调用这个函数的地方插入一条SWI指令,并且可以指定功能号。同时,这个函数也可以有参数和返回值,其传递规则与一般函数一样。

18、 使用软中断SWI作底层接口/* 任务级任务切换函数 */_swi(0 x00) void OS_TASK_SW(void); /* 运行优先级最高的任务 */_swi(0 x01) void _OSStartHighRdy(void); /* 关中断 */_swi(0 x02) void OS_ENTER_CRITICAL(void); /* 开中断 */_swi(0 x03) void OS_EXIT_CRITICAL(void); /* 任务切换到系统模式 */_swi(0 x80) void ChangeToSYSMode(void); /* 任务切换到用户模式 */_swi(0 x8

19、1) void ChangeToUSRMode(void); /* 任务代码是ARM代码 */_swi(0 x82) void TaskIsARM(INT8U prio);/* 任务代码是THUMB代码 */_swi(0 x83) void TaskIsTHUMB(INT8U prio);程序中调用软中断时使用的函数名软件中断号该调用不返回参数编写COS-II使用结构常量OS_STK_GROWTH中指定堆栈的生长方式:置OS_STK_GROWTH为0表示堆栈从下往上长。置OS_STK_GROWTH为1表示堆栈从上往下长。虽然ARM处理器核对于两种方式均支持,但ADS的C语言编译器仅支持一种方式

20、,即从上往下长,并且必须是满递减堆栈,所以OS_STK_GROWTH的值为1。#define OS_STK_GROWTH 1 堆栈生长方式编写 该函数用于初始化任务堆栈,使任务的堆栈看起来就像刚发生中断一样。即任务被执行时,就像从中断返回一样。 在编写此函数之前,必须先确定任务的堆栈结构。而任务的堆栈结构是与CPU的体系结构、编译器有密切的关联。本移植的堆栈结构如下图所示。 OSTaskStkInit( )任务入栈的其它数据LRR12R11R10R9R8. 栈底 任务环境开始 SPPCR2R1R0OSEnterSum空闲空间编写OSTaskStkInit( )OS_STK *OSTaskStk

21、Init (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) OS_STK *stk; opt = opt; stk = ptos; *stk = (OS_STK) task; *-stk = (OS_STK) task; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = (unsigned

22、int) pdata; *-stk = (USER_USING_MODE|0 x00); *-stk = 0; return (stk); 入栈的数据任务入栈的其它数据LRR12R11R10R9R8. 栈底 任务环境开始 SPPCR2R1R0OSEnterSum空闲空间编写OSTaskStkInit( )OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt) OS_STK *stk; opt = opt; stk = ptos; *stk = (OS_STK) task; *-s

23、tk = (OS_STK) task; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = 0; *-stk = (unsigned int) pdata; *-stk = (USER_USING_MODE|0 x00); *-stk = 0; return (stk);该数据比较特别,它用于保存该任务关中断的次数,它在调用OS_ENTER_CRITICAL( )时加1,在调用OS_EXIT

24、_CRITICAL( )时减1。这样每个任务都可以独立控制本任务的中断允许状态,而不会影响其它任务的中断允许状态。因此关中断和开中断就可以嵌套。 编写软件中断异常服务程序 操作系统与硬件相关的底层函数使用软件中断作为接口,如下表所示。移植代码中一个重要的工作就是为这些软件中断编写服务程序。功能号接口函数简介0 x00void OS_TASK_SW(void)任务级任务切换函数0 x01_OSStartHighRdy(void)运行优先级最高的任务,由OSStartHighRdy产生0 x02void OS_ENTER_CRITICAL(void)关中断0 x03Void OS_EXIT_CRI

25、TICAL(void)开中断0 x80Void ChangeToSYSMode(void)任务切换到系统模式0 x81Void ChangeToUSRMode(void)任务切换到用户模式0 x82Void TaskIsARM(INT8U prio)任务代码是ARM代码0 x83Void TaskIsTHUMB(INT8U prio)任务代码是THUMB代码编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是AR

26、M代码0 x83任务代码是THUMB代码功能号接口函数简介0 x00void OS_TASK_SW(void)任务级任务切换函数0 x01_OSStartHighRdy(void)运行优先级最高的任务,由OSStartHighRdy产生0 x02void OS_ENTER_CRITICAL(void)关中断0 x03Void OS_EXIT_CRITICAL(void)开中断0 x80Void ChangeToSYSMode(void)任务切换到系统模式0 x81Void ChangeToUSRMode(void)任务切换到用户模式0 x82Void TaskIsARM(INT8U prio)

27、任务代码是ARM代码0 x83Void TaskIsTHUMB(INT8U prio)任务代码是THUMB代码void SWI_Exception(int SWI_Num, int *Regs) OS_TCB *ptcb; switch(SWI_Num) case 0 x02: / 关中断 . case 0 x03: / 开中断 . case 0 x80: / 任务切换到系统模式 . case 0 x81: / 任务切换到用户模式 . case 0 x82: / 任务代码是ARM代码 . case 0 x83: / 任务代码是Thumb代码 . default: 这两个软件中断使用汇编代码完成

28、编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码 C/OS-II的启动多任务环境的函数叫做OSStart(),用户在调用OSStart()之前,必须已经建立了一个或更多任务。OSStart()最终调用函数OSStartHighRdy()运行多任务启动前优先级最高的任务。 void OSStartHighRdy(void) _OSStartHighRdy(); 该函数

29、在Os_cpu_a.s文件中实现。编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码关中断和开中断是为了保护临界段代码。这些代码与处理器有关,是需要移植的代码。在ARM处理器核中关中断和开中断时通过改变程序状态寄存器CPSR中的相应控制位实现。由于使用了软件中断,程序状态寄存器CPSR保存到程序状态保存寄存器SPSR中,软件中断退出时会将SPSR恢复到CPSR中,所以

30、程序只要改变程序状态保存寄存器SPSR中的相应的控制位就可以了。 编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码void SWI_Exception(int SWI_Num, int *Regs) . case 0 x02: / 关中断 _asm MRS R0,SPSR ORR R0,R0,#NoInt MSR SPSR_c,R0 OsEnterSum+; bre

31、ak; case 0 x03: / 开中断 if (-OsEnterSum = 0) _asm MRS R0,SPSR BIC R0,R0,#NoInt MSR SPSR_c,R0 break; .每关闭一次中断,中断关闭计数器加1每调用一次开中断函数,该计数器减1,为0时允许打开中断关闭中断打开中断编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码 它们可以在任何情

32、况下使用。它们改变程序状态保留寄存器SPSR的相应位段,而程序状态保留寄存器会在软件中断退出时复制到程序状态寄存器CPSR,任务的处理器模式就改变了。 编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码void SWI_Exception(int SWI_Num, int *Regs) . case 0 x80: / 任务切换到系统模式 _asm MRS R0,SPS

33、R BIC R0,R0,#0 x1f ORR R0,R0,#SYS32Mode MSR SPSR_c,R0 break; case 0 x81: / 任务切换到用户模式 _asm MRS R0,SPSR BIC R0,R0,#0 x1f ORR R0,R0,#USR32Mode MSR SPSR_c,R0 break; .使用内嵌汇编将处理器模式切换到用户模式使用内嵌汇编将处理器模式切换到系统模式编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任

34、务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码 任务可以使用ARM的两种指令集的任意一种运行,但是任务建立时默认的只是一种指令集。如果任务使用的第一条指令与默认的指令集不同,则程序运行错误。所以增加两个函数TaskIsARM()和TaskIsTHUMB()用于改变任务建立时默认的指令集。 它们都有唯一的参数:需要改变的任务的优先级,值得注意的是,这两个函数必须在相应的任务建立后但还没有运行时调用。 编写软件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0

35、x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码 . case 0 x82: / 任务代码是ARM代码 if (Regs0 OSTCBStkPtr1 &= (1 5); break; case 0 x83: / 任务代码是Thumb代码 if (Regs0 OSTCBStkPtr1 |= (1 5); break; .被设置的任务号一定不能大于最低优先级任务获取指定任务的任务控制块的地址修改任务堆栈中CPSR的值,在任务重新运行时,切换到ARM指令方式修改任务堆栈中CPSR的值,在任务重新运行时,切换到Thumb指令方式编写软

36、件中断异常服务程序功能号简介0 x00任务级任务切换函数0 x01运行优先级最高的任务,由OSStartHighRdy产生0 x02关中断0 x03开中断0 x80任务切换到系统模式0 x81任务切换到用户模式0 x82任务代码是ARM代码0 x83任务代码是THUMB代码注意: 这两个函数必须在相应的任务建立后但还没有运行时调用。 如果在低优先级的任务中创建高优先级的任务就十分危险了。此时,解决的方法有三种:(1)高优先级任务使用默认的指令集;(2)改变函数OSTaskCreateHook()使任务默认不是处于就绪状态,建立任务后调用函数OSTaskResume()来使任务进入就绪状态;(3

37、)建立任务时禁止任务切换,调用函数TaskIsARM()或TaskIsTHUMB()后再允许任务切换。编写 在文件中还有许多钩子函数,它们在某个特定的系统动作时被调用,允许执行函数中的用户代码。这些函数默认是空函数,用户根据实际情况添加相关代码。它们分别如下表所示。Hook( )函数函数名被执行条件OSInitHookBegin( )在开始执行OSInit( )函数时被执行OSInitHookEnd( )在OSInit()函数结束时被执行OSTaskCreateHook( )在任务建立时被调用OSTaskDelHook( )在任务删除时被调用OSTaskSwHook( )在进行任务切换时被调用

38、OSTaskStatHook( )被统计任务调用,每秒执行一次OSTCBInitHook( )在建立所有的TCB后,由OSTCBInit函数调用OSTimeTickHook( )每个时钟节拍产生后被调用OSTaskIdleHook( )由空闲任务调用7.3 移植C/OS-II编写 在文件中有软件中断的汇编接口程序、任务切换程序、OS启动时运行就绪最高优先级任务的程序。编写 在调用软中断之后,处理器切换到ARM指令和管理模式下工作。在执行软件中断服务函数之前,要提取中断号和其它入口参数,这些通过软件中断接口程序完成。软件中断汇编接口SoftwareInterrupt LDR SP, StackS

39、vc STMFD SP!, R0-R3, R12, LR MOV R1, SP MRS R3, SPSR TST R3, #T_bit LDRNEH R0, LR,#-2 BICNE R0, R0, #0 xff00 LDREQ R0, LR,#-4 BICEQ R0, R0, #0 xFF000000 CMP R0, #1 LDRLO PC, =OSIntCtxSw LDREQ PC, =_OSStartHighRdy BL SWI_Exception LDMFD SP!, R0-R3, R12, PC 保护被中断的现场将要用到的寄存器压栈判断中断前的指令集类型从产生软件中断的指令中提取中断

40、号ARMThumb根据不同的中断号执行不同的程序返回被中断的任务中断号执行程序0进行任务切换1启动多任务环境,运行就绪的最高优先级任务其它软件中断服务函数编写 COS-II是抢占式实时操作系统,得到运行的始终是就绪条件下最高优先级的任务。当处于运行状态的任务因为某种脱离就绪态,或者有其它更高优先级的任务进入就绪态,那么操作系统内核就要运行别的就绪任务,这时需要进行任务切换。任务切换可能发生的情况有两种: 1.当前运行的任务主动交出CPU控制权,通常发生在等待某个事件或是调用系统延时。调用函数OS_TASK_SW( ); 2.发生中断,使更高优先级的任务进入就绪状态,内核剥夺当前任务的运行资格。

41、即发生在中断退出时。调用函数OSIntCtxSw( )。任务切换代码编写 虽然OS_TASK_SW( )和OSIntCtxSw( )的执行条件不同,但是它们的功能相同,只要稍作处理就可以它们共用一段任务切换代码。这些处理就是保证在执行任务切换前两者的任务现场是一致的。共同执行的任务切换代码是“OSIntCtxSw” 其中OS_TASK_SW( )是通过软件中断0完成的,通过前面的分析,可以知道执行任务切换时的现场环境如下所示,同时R3中保存着SPSR,它是任务中断前CPSR的备份。任务切换代码任务入栈的其它数据LRR12R3R2R1R0空闲空间 栈底 任务环境开始 SP编写OSIntCtxSw

42、保存当前任务的寄存器组及其它修改当前任务的TCB堆栈指针用将要运行任务的优先级和TCB指针更新OSPrioHighRdy和OSTCBCur恢复新任务的寄存器组及其它运行新任务流程图编写OSIntCtxSw保存当前任务的寄存器组及其它修改当前任务的TCB堆栈指针用将要运行任务的优先级和TCB指针更新OSPrioHighRdy和OSTCBCur恢复新任务的寄存器组及其它运行新任务流程图OSIntCtxSw ;下面为保存任务环境 LDR R2, SP, #20 ;获取PC LDR R12, SP, #16 ;获取R12 MRS R0, CPSR ;保存LR,PC及R4-R12 MSR CPSR_c,

43、 #(NoInt | SYS32Mode) MOV R1, LR STMFD SP!, R1-R2 STMFD SP!, R4-R12 ;获取R0-R3,并出栈R12和PC寄存器 MSR CPSR_c, R0 LDMFD SP!, R4-R7 ADD SP, SP, #8 ;保存R0-R3 MSR CPSR_c, #(NoInt | SYS32Mode) STMFD SP!, R4-R7 ;获取OsEnterSum,并保存CPSR,OsEnterSum LDR R1, =OsEnterSum LDR R2, R1 STMFD SP!, R2, R3 .PCLRR12R11R10R9R7R5R4

44、R3R2R1R0R6R8CPSROSEnterSum切换至系统模式获取任务运行时的各寄存器并将它们压栈恢复之前的模式读出压栈的数据任务环境保存结束后的栈结构编写OSIntCtxSw修改当前任务的TCB堆栈指针用将要运行任务的优先级和TCB指针更新OSPrioHighRdy和OSTCBCur保存当前任务的寄存器组及其它恢复新任务的寄存器组及其它运行新任务OSIntCtxSw . ;保存当前任务堆栈指针到当前任务的TCB LDR R1, =OSTCBCur LDR R1, R1 STR SP, R1 BL STaskSwHook ;调用钩子函数 ;OSPrioCur = OSPrioHighRdy

45、 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用即将运行任务的TCB指针更新OSTCBCur变量用即将运行任务的优先级更新OSPrioCur变量编写OSIntCtxSw恢复新任务的寄存器组及其它运行新任务保存当前任务的寄存器组及其它修改当前任务的TCB堆栈指针用将要运行任务的优先级和TCB指针更新OSPrioH

46、ighRdy和OSTCBCurOSIntCtxSw .OSIntCtxSw_1 ;从R6指向TCB中获取新任务堆栈指针 LDR R4, R6 ;调整堆栈指针 ;17寄存器CPSR,OsEnterSum,R0-R12,LR,SP ADD SP, R4, #68 LDR LR, SP, #-8 ;进入管理模式,恢复任务的各寄存器和变量 MSR CPSR_c, #(NoInt | SVC32Mode) MOV SP, R4 ;设置堆栈指针 ;获取CPSR和OsEnterSum LDMFD SP!, R4, R5 ;恢复新任务的OsEnterSum LDR R3, =OsEnterSum STR R4

47、, R3 ;恢复CPSR MSR SPSR_cxsf, R5 ;运行新任务 LDMFD SP!, R0-R12, LR, PC 编写OSIntCtxSw恢复新任务的各寄存器运行新任务这段代码还被_OSStartHighRdy函数调用,用于启动最高优先级的就绪任务_OSStartHighRdy MSR CPSR_c, #(NoInt | SYS32Mode) ;告诉uC/OS-II自身已经运行 LDR R4, =OSRunning MOV R5, #1 STRB R5, R4 ;调用钩子函数 BL OSTaskSwHook LDR R6, =OSTCBHighRdy ;取得新任务的TCB指针 L

48、DR R6, R6 B OSIntCtxSw_1 编写OSStartHighRdy C/OS-II的多任务环境由函数OSStart( ) 启动。用户在调用该函数之前,必须已经建立了一个或更多任务。OSStart()最终调用函数OSStartHighRdy( )运行多任务启动前优先级最高的任务,而它最终是调用_OSStartHighRdy实现的,其代码如下所示:Os_cpu_a.s文件编写通过前面的分析,我们可以画出下面这张结构图:中断退出时任务切换xxx_Handler任务级任务切换OS_TASK_SW()启动多任务OSStartHighRdy()OSIntCtxSw_OSStartHighR

49、dyOSIntCtxSw_16.3 移植C/OS-II关于中断及时钟节拍 在本移植中,IRQ是受C/OS-II管理的中断,而对于FIQ不做处理,这是为了提高FIQ的响应速度。由于各种ARM芯片的中断系统不一样,各个用户的目标板也不一样,对于中断和时钟节拍是需要进一步移植的代码。为此编写了一个汇编宏,它是C/OS-II for ARM7通用的中断服务程序的汇编与C函数接口代码。 注:在不受管理的中断服务程序中不能调用任何系统函数。关于中断及时钟节拍流程图保存当前任务的寄存器组中断嵌套数加1切换到系统模式执行中断服务程序关中断执行OSIntExit( )切换到IRQ模式判断是否需要进行任务切换切换

50、任务或返回关于中断及时钟节拍流程图保存当前任务的寄存器组中断嵌套数加1切换到系统模式执行中断服务程序关中断执行OSIntExit( )切换到IRQ模式判断是否需要进行任务切换切换任务或返回 MACRO$IRQ_Label HANDLER $IRQ_Exception_Function EXPORT $IRQ_Label ; 输出的标号 IMPORT $IRQ_Exception_Function ; 引用的外部标号$IRQ_Label SUB LR, LR, #4 ; 计算返回地址 STMFD SP!, R0-R3, R12, LR ; 保存任务环境 MRS R3, SPSR ; 保存状态 ;

51、 保存用户状态的R3,SP,LR,不能回写 STMFD SP, R3, SP, LR LDR R2, =OSIntNesting LDRB R1, R2 ADD R1, R1, #1 STRB R1, R2 SUB SP, SP, #4*3 ; 切换到系统模式 MSR CPSR_c, #(NoInt | SYS32Mode) CMP R1, #1 LDREQ SP, =StackUsr .关于中断及时钟节拍中断嵌套层数加1切换到系统模式,如果是第一次中断还要设置堆栈指针压栈保存被中断任务的运行环境关于中断及时钟节拍流程图保存当前任务的寄存器组中断嵌套数加1切换到系统模式执行中断服务程序关中断执

52、行OSIntExit( )切换到IRQ模式判断是否需要进行任务切换切换任务或返回中断服务程序(ISR)在ISR中可以打开中断实现中断嵌套 MACRO$IRQ_Label HANDLER $IRQ_Exception_Function EXPORT $IRQ_Label ; 输出的标号 IMPORT $IRQ_Exception_Function ; 引用的外部标号$IRQ_Label . BL $IRQ_Exception_Function ; 切换到系统模式 MSR CPSR_c, #(NoInt | SYS32Mode) ; OsEnterSum,使OSIntExit退出时中断关闭 LDR

53、 R2, =OsEnterSum MOV R1, #1 STR R1, R2 BL OSIntExit ; 因为中断服务程序要退出,所以OsEnterSum=0 LDR R2, =OsEnterSum MOV R1, #0 STR R1, R2 ; 切换回irq模式,并恢复用户状态的R3,SP,LR MSR CPSR_c, #(NoInt | IRQ32Mode) LDMFD SP, R3, SP, LR ; 注意不能回写 .关于中断及时钟节拍关闭中断执行中断服务程序(ISR)使OSEnterSum为1,防止在OSIntExit函数中打开中断通知系统,中断退出使OSEnterSum为0,运行中

54、断打开恢复任务的R3、SP和LR关于中断及时钟节拍流程图保存当前任务的寄存器组中断嵌套数加1切换到系统模式执行中断服务程序关中断执行OSIntExit( )切换到IRQ模式判断是否需要进行任务切换切换任务或返回 MACRO$IRQ_Label HANDLER $IRQ_Exception_Function EXPORT $IRQ_Label ; 输出的标号 IMPORT $IRQ_Exception_Function ; 引用的外部标号$IRQ_Label . LDR R0, =OSTCBHighRdy LDR R0, R0 LDR R1, =OSTCBCur LDR R1, R1 CMP R

55、0, R1 ADD SP, SP, #4*3 MSR SPSR_cxsf, R3 ; 不进行任务切换 LDMEQFD SP!, R0-R3, R12, PC ; 进行任务切换 LDR PC, =OSIntCtxSw MEND关于中断及时钟节拍比较当前任务是否为就绪的最高优先级任务,如果不是则进行切换设置堆栈指针和恢复SPSR进行任务切换或者恢复执行被中断任务关于中断及时钟节拍流程图保存当前任务的寄存器组中断嵌套数加1切换到系统模式执行中断服务程序关中断执行OSIntExit( )切换到IRQ模式判断是否需要进行任务切换切换任务或返回中断服务程序(ISR)在ISR中可以打开中断实现中断嵌套voi

56、d ISR(void) OS_ENTER_CRITICAL()或直接给变量OsEnterSum赋1; 清除中断源; 通知中断控制器中断结束: 开中断: OS_EXIT_CRITICAL(); 用户处理程序;中断服务程序的编写 因为中断发生时肯定是允许中断的,所以如果用户在清除中断源之前调用C/OS-II的系统服务函数就很可能会造成芯片的中断系统工作异常而使程序工作异常。因此在函数开始处关闭中断,或者直接给变量OSEnterSum赋1。如果用户程序没有这种情况,则不需要这个操作。在执行OS_EXIT_CRITICAL( )后,中断重新打开,如果在接下来的用户处理程序中发生中断,就可以实现中断嵌套

57、。第6章 目录1. C/OS-II简介2.移植规划3.移植C/OS-II4.移植代码应用到LPC20006.4 移植代码应用到LPC2000概述项目中应用移植代码时,还要做一些工作,因为:1各种基于ARM7处理器核的芯片的硬件结构不尽相同,所以需要编写部分启动代码。另外中断服务程序的编写方法也各不相同;2.因为各个项目对资源的要求不一样,所以尽管使用同一系列的芯片,其时钟节拍中断也可能使用不同的中断实现。 6.4 移植代码应用到LPC2000概述将C/OS-II移植到LPC2000时,需要完成的工作主要有以下几个部分: 编写或获取启动代码; 挂接SWI软件中断; 中断及时钟节拍中断; 编写应用

58、程序。注:其中“启动代码”已经在第5章中讲述。Reset LDR PC,ResetAddr LDR PC,UndefinedAddr LDR PC,SWI_Addr LDR PC,PrefetchAddr LDR PC,DataAbortAddr DCD 0 xb9205f80 LDR PC,PC, #-0 xff0 LDR PC,FIQ_AddrResetAddr DCD ResetInitUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortDataAbortAddr DCD DataAbortnouse DCD 0IRQ_Addr DCD IRQ_HandlerFIQ_Addr DCD FIQ_Handler挂接SWI软件中断 将软中断异常处理程序挂接到内核是通过修改启动代码中的异常向量表实现, 代码如下所示:发生软件中断时跳转到软件中断服务函数 因为中断发生时肯

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论