第八章 嵌入式操作系统软件设计(下:UCOS分析,参考资料)_第1页
第八章 嵌入式操作系统软件设计(下:UCOS分析,参考资料)_第2页
第八章 嵌入式操作系统软件设计(下:UCOS分析,参考资料)_第3页
第八章 嵌入式操作系统软件设计(下:UCOS分析,参考资料)_第4页
第八章 嵌入式操作系统软件设计(下:UCOS分析,参考资料)_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

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

文档简介

1、第八章 C/OS,嵌入式操作系统( C/OS )软件设计,一、嵌入式操作系统的移植 二、SDT工具的使用,移植的概念和目的 C/OS-II的移植 软件移植,一、嵌入式操作系统的移植,移植的概念和目的,移植:程序或应用软件从一个系统平台移动另一个系统平台,其功能、结构、执行结果保持不变。 OS移植:使一个实时内核能够在某个微处理器或微控制器上运行。 移植的目的: 1、硬件平台的升级 2、实现软件重用 3、实现软件/硬件并行设计,移植的要求: 移植对象具有硬件无关性 移植对象具有系统无关性 移植对象采用标准语言编程,C/OS-II的移植,C/OS -II的软硬件体系结构 C/OS -II的移植需要

2、满足的要求 C/OS -II移植的主要工作,C/OS II的软硬件体系结构,C/OS-II目录结构与代码组织 可从C/OS-II网站www.ucos-II.com下载;,SOFTWAREuCOS-II 与C/OS-II 相关的文件都放在这个目录下。,SOFTWAREuCOS-IISOURCE 这个目录里包括与处理器类型无关的源代码。 这些代码完全可移植到其它架构的处理器上。,SOFTWAREuCOS-IIARM 这个目录下包括依赖于处理器类型的代码。,C/OS -II移植需要满足的要求,处理器的C编译器可以产生可重入代码; 处理器支持中断,并且能产生定时中断(通常为10100Hz); 用C语言

3、就可以开/关中断; 处理器需要能够容纳一定数据的硬件堆栈; 处理器需要有能够在CPU寄存器与内存和堆栈交换数据的指令。,开/关中断: 在C/OS -II中,可以通过: OS_ENTER_CRITICAL () OS_EXIT_CRITICAL() 宏来控制系统关闭或者打开中断。这需要处理器的支持。 在ARM7TDMI的处理器上,可以设置相应的寄存器来关闭或者打开系统的所有中断。,处理器支持中断并能产生定时中断: C/OS -II是通过处理器产生的定时器的中断来实现多任务之间的调度的。ARM7TDMI的处理器上可以产生定时器中断。 本系统工作在60MHz的主频下,定时器的中断的频率为1000Hz

4、。也就是系统的响应时间为1ms。,处理器支持硬件中断: C/OS -II进行任务调度的时候,会把当前任务的CPU寄存器存放到此任务的堆栈中,然后,再从另一个任务的堆栈中恢复原来的工作寄存器,继续运行另一个任务。所以,寄存器的入栈和出栈是C/OS -II多任务调度的基础。 ARM7处理器中有专门的指令处理堆栈,可以灵活的使用堆栈。,开发工具: 针对所使用的CPU的标准C交叉编译器 C编译器支持汇编语言程序 C编译器还须提供一种机制,能在C语言中开中断和关中断。,C/OS -II移植的主要工作,移植工作包括以下几个内容: 用#define设置一个常量的值(OS_CPU.h) 声明10个数据类型(O

5、S_CPU.h),数据类型与CPU与编译器有关 用#define声明三个宏(OS_CPU.h) 编写四个汇编语言函数(OS_CPU_A.asm) 编写六个C语言函数(OS_CPU_C.c) 可以从C/OS II网站:www.ucos-II.com中查找一些移植实例。 编写与处理器相关的代码 测试移植代码,与处理器相关的代码有: OS_CPU.H OS_CPU_A.ASM OS_CPU_C.C,OS_CPU.H包含了用define语句定义的、与处 理器相关的常数、宏以及类型。 OS_CPU.H中定义了与编译器相关的数据类型,比如:INT8U、INT8S等。 与 ARM处理器相关的代码,使用 OS

6、_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL() 宏开启关闭中断 设施堆栈的增长方向 :堆栈由高地址向低地址增长,用C语言编写十个操作系统相关的函数(OS_CPU_C.C) OSTaskStkInit() OSTaskCreatHook() OSTaskDelHook() OSTaskSwHook() OSTaskIdleHook() OSTaskStatHook() OSTimeTickHook() OSInitHookBegin() OSInitHookEnd() OSTCBInitHook(),其中唯一必要的函数是OSTaskStkInit(),其他9个函数必

7、须声明,但不一定要包含任何代码。 C/OS -II中每个任务都有自己的任务堆栈,在任务创建初期由初始化OSTaskStkInit()初始化。初始化堆栈的目的就是模拟一次中断。任务堆栈中保存了任务代码的起始地址和一些CPU寄存器(初值是无关紧要的),这样一旦条件满足,就可以执行该任务了。,用汇编语言编写四个与处理器相关的函 数(OS_CPU.ASM) OSStartHighRdy() OSCtxSw() OSIntCtxSw() OSTickISR(),在每个硬件时钟到来后,C/OS -II会在中断服务例程中调用OSIntCtxSw()进行任务调度;另外,当某个任务因等待资源而被挂起时,没有必要

8、等到自己的时间片全都用完,可以自己主动放弃CPU,这可以通过调用一个任务级的任务调度函数OSCtxSw()来实现。 其中相对复杂的是OSIntCtxSw()。由于OSTickISR()调用了OSIntExit(),OSIntExit()又再次调用了OSIntCtxSw(),如果进行任务切换,那么两次调用都不会返回,而不同的C编译器、不同的编译选项处理C调用时对堆栈的使用也不尽相同。因此OSIntCtxSw()是编译器相关的。,测试移植代码,确保C编译器、汇编编译器及链接器正常工作 验证OSTaskStkInit()和OSStartHighRdy()函数 验证OSCtxSw()函数 验证OSIn

9、tCtxSw()和OSTickISR()函数,向嵌入式平台移植软件,大部分嵌入式开发人员选用的软件开发模式是先在PC机上编写软件,再进行软件的移植工作。在PC机上编写软件时,要注意软件的可移植性。 1、选用具有较高移植性的编程语言(如C语言) 2、尽量少调用操作系统函数 3、注意屏蔽不同硬件平台带来的字节顺序、字节对齐等问题。,字节顺序,字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序。小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处。基于X86平台的PC机是小端字节序

10、的,而有的嵌入式平台则是大端字节序的。因而对int、uint16、uint32等多于1字节类型的数据,在这些嵌入式平台上应该变换其存储顺序。 通常我们认为,在空中传输的字节的顺序即网络字节序为标准顺序,考虑到与协议的一致以及与同类其它平台产品的互通,在程序中发数据包时,将主机字节序转换为网络字节序,收数据包处将网络字节序转换为主机字节序。,字节对齐,有的嵌入式处理器的寻址方式决定了在内存中占2字节的int16、uint16等类型数据只能存放在偶数内存地址处,占4字节的int32 、uint32 等类型数据只能存放在4的整数倍的内存地址处;占8字节的类型数据只能存放在8的整数倍的内存地址处;而在

11、内存中只占1字节的类型数据可以存放在任意地址处。 由于这些限制,在这些平台上编程时有很大的不同。首先,结构体成员之间会有空洞,比如这样一个结构:typedef struct test char a; uint16 b;TEST,结构TEST在单字节对齐的平台上占内存三个字节,而在以上所述的嵌入式平台上有可能占三个或四个字节,视成员a的存储地址而定。当a存储地址为偶数时,该结构占四个字节,在a与b之间存在一个字节的空洞。对于通信双方都是对结构成员操作的,这种情况不会出错,但如果有一方是逐字节读取内容的(通信协议大都如此),就会错误地读到其它字节的内容。其次,若对内存中数据以强制类型转换的方式读取

12、,字节对齐的不同会引起数据读取的错误。因为假如指针指在基数内存地址处,我们想取得占内存两个字节的数据存放在uint16型的变量中,强制类型转换的结果是取得了该指针所指地址与前一地址处的数据,并没有按照我们的愿望取该指针所指地址与后一地址处的数据,这样就导致了数据读取的错误。,代码优化的问题,嵌入式系统对应用软件的质量要求更高,因而在嵌入式开发中尤其须注意对代码进行优化,尽可能地提高代码的效率,减少代码的大小。虽然现代C和C+编译器都提供了一定程度的代码优化,但大部分由编译器执行的优化技术仅涉及执行速度和代码大小的平衡,不可能使程序既快又小,因而必须在编写嵌入式软件时采取必要的措施。,(1)提高

13、代码的效率,switch-case 语句。在程序中经常会使用switch- case语句,每一个由机器语言实现的测试和跳转仅仅是为了决定下一步要做什么,就浪费了处理器时间。为了提高速度,可以把具体的情况按照它们发生的相对频率排序。即把最可能发生的情况放在第一,最不可能发生的情况放在最后,这样会减少平均的代码执行时间。 全局变量。使用全局变量比向函数传递参数更加有效率,这样做去除了函数调用前参数入栈和函数完成后参数出栈的需要。当然,使用全局变量会对程序有一些负作用。,(2)减小代码的大小,嵌入式系统编程应避免使用标准库例程, 因为很多大的库例程设法处理所有可能的 情况,所以占用了庞大的内存空间,因而 应尽可能地减少使用标准库例程。,(3)避免内存泄漏,用户内存空间(堆)为RAM中全局数据和任务堆 栈空间都分配后的剩余空间,为了使程序能有足 够的内存运行,必须在申请的内存不用后及时地 将其释放,以确保再次申请时能有空间。如果程 序中存在内存泄漏(即申请内存后没有及时释放) 的情况,程序最终会因为没有足够的内存空间而 无法运行。,通过案例说明编程模型:指示灯控制程序。 创建2个任务,任务1是让灯亮,任务2让灯灭 /任务1定义 /任务2定

温馨提示

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

评论

0/150

提交评论