




已阅读5页,还剩6页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C/OS-II实时嵌入式操作系统在AVR mega系列MCU上的移植摘要:本文以AVR mega系列单片机为平台详细介绍了源代码公开的实时嵌入式操作系统C/OS-II的内核代码及移植方法,并对系统的相关性能进行了测试,为在8位单片机上进行嵌入式系统开发提供了参考。关键词:C/OS-II; AVR mega; 移植; 系统测试1 简介随着技术的发展,在近几年中,嵌入式系统的设计及应用对人们生活产生了很大的影响,并将逐渐改变人们未来的生活方式。在特定的操作系统之上开发应用程序,可以使得开发人员忽略掉很多底层硬件细节,使得应用程序调试更方便,易于维护,同时开发周期也缩短,降低了开发成本,因而嵌入式实时操作系统深得开发人员的青睐。C/OS-II是一种专门为微处理器设计的抢占式实时多任务操作系统,具有源代码公开、可移植性、可裁减、稳定性和可靠性高等特点。其内核主要提供进程管理、时间管理、内存管理等服务,系统最多支持56个任务,每个任务均有自己单独的优先级。由于其内核为抢占式,所以总是运行优先级最高的任务。系统提供了丰富的API函数,便于实现进程间的通信及进程状态的转化。由于C/OS-II是为嵌入式应用编写的通用软件,故在具体应用时需根据不同单片机的特点进行移植,其大部分代码是用标准C语言所写,只有与处理器相关的一部分代码用汇编语言写成,因而具有很强的移植性,能在多数8位、16位、32位单片机及数字信号处理器上实现运行。AVR mega系列单片机是基于AVR RISC的,低功耗的8位单片机,内部有32个通用寄存器。通过在一个时钟周期内执行一条指令,运行速度可以达到1MIPS/MHz的性能。AVR单片机内核有丰富的指令集,通过32个通用寄存器直接与逻辑运算单元相连接,允许在一个时钟周期内一条单一的指令访问两个独立的寄存器。这样的结构使得代码的执行效率比传统的复杂指令集的微处理器快近10倍。AVR mega128是mega系列里功能最强大、资源最丰富的一款单片机,有128k的在系统可编程flash,4k字节的SRAM和EEPROM,为系统的移植提供了一个良好的平台。要实现C/OS-II在AVR mega 系列MCU上的移植,需要有AVR系列单片机的编译器,这里采用的是GNU推出的AVR-GCC编译器。2 移植工作概要移植工作主要包括以下几个内容: 用#define设置一个常数的值(OS_CPU.H); 声明9个数据类型(OS_CPU.H); 用#define声明三个宏(OS_CPU.H); 用C语言编写六个函数(OS_CPU_C.C); 编写四个汇编语言函数(OS_CPU_A.ASM).要移植C/OS-II,必须编写OS_CPU.H、OS_CPU_A.ASM、OS_CPU_C.C三个文件。这三个文件与芯片的硬件特性有关,它们主要提供任务切换与时钟的功能。C/OS-II其他内核代码均用C语言写成,它们为系统提供任务管理、进程间通信、时间管理以及内存管理等功能。C/OS-II软、硬件体系结构如下图所示:图1 C/OS-II软件、硬件体系结构INCLUDES.H是一个头文件,在所有后缀为.C的文件开始都包含INCLUDES.H文件,其主要包含CFG.H、OS_CPU.H、UCOS_II.H三个文件。对于不同类型的处理器,还需要改写INCLUDES.H文件,增加自己的头文件,但必须加在文件末尾。OS_CFG.H主要包含的是一些二值常量,通过对这些常量置1或0,可以方便的对内核进行裁减,这是C/OS-II较为突出的一个优点。3 移植代码分析3.1 OS_CPU.H文件OS_CUP.H包括用#define定义的与处理器有关的常量,宏和类型定义。大体结构如下:typedef unsigned char BOOLEAN;typedef unsigned char INT8U; /无符号8位数/typedef signed char INT8S; /带符号8位数/typedef unsigned int INT16U; /无符号16位数/typedef signed int INT16S; /带符号16位数/typedef unsigned long INT32U; /无符号32位数/typedef signed long INT32S; /带符号32位数/typedef float FP32; /单精度浮点数/typedef unsigned char OS_STK; /堆栈入口宽度为8位/#define OS_STK_GROWTH 1 /堆栈由高地址向低地址增长/#define OS_ENTER_CRITICAL() asm volatile (cli)/禁止中断/#define OS_EXIT_CRITICAL() asm volatile (sei)/允许中断/#define OS_TASK_SW() OSCtxSw() /任务级的切换函数/(1)数据类型由于不同的处理器有不同的字长,C/OS-II的移植需要重新定义一系列的数据结构以确保其可移植性。用户还需通过OS_STK声明正确的C数据类型将任务堆栈的数据类型通知C/OS-II。在AVR mega系列中堆栈是按8位字长进行操作的,所以堆栈数据类型OS_STK被声明为8位。所有的任务堆栈都必须用OS_STK来声明数据类型。(2)代码临界区C/OS-II在进入系统临界代码区之前需关中断,退出临界区后再开中断,则C/OS-II能够保护临界区代码免受多任务或中断服务例程的破坏。在AVR mega系列单片机中,通过设置状态寄存器SREG中的中断屏蔽位来实现。C/OS-II中的宏OS_ENTER_CRITICAL()定义将状态寄存器中的中断屏蔽位清除,以屏蔽所有的中断;OS_EXIT_CRITICAL()定义将状态寄存器的中断屏蔽位置位以允许所有的中断。(3)堆栈方向AVR mega系列微处理器的堆栈是由高地址向低地址递减的,所以OS_STK_GROWTH必须设置为1。(4) OS_TASK_SW()函数的定义在C/OS-II中,OS_TASK_SW()用来实现任务切换。在进行宏定义时直接定义为OSCtxSw()函数,即任务级切换函数。3.2 OS_CPU_A.ASM文件3.2.1相关函数移植C/OS-II时需要改写OS_CPU_A.ASM中的四个汇编语言函数: OSStartHighRdy() OSCtxSw() OSIntCtxSw() OSTickISR()3.2.2函数介绍(1) OSStartHighRdy()函数该函数由OSStart()函数调用,功能是运行优先级最高的就绪态任务。在调用OSStart()函数之前,用户必须调用OSInit(),并且至少已经创建了一个任务。当调用OSStart()函数时,获得了指向就绪任务中最高优先级任务的OS_TCB的地址指针OSTCBHighRdy,并把这个指针赋值给OSTCBCur。OSStartHighRdy()通过OSTCBHighRdy,就可以从任务的控制块中获得堆栈指针。由于OSTaskCreate()函数创建任务时堆栈初始化为模拟一次中断发生的结构,于是当弹出所有保存的寄存器后,运行RET命令就可以切换到了新任务。OSStartHighRdy()函数的汇编代码及相关介绍如下:CALL OSTaskSwHook /调用用户自己定义的函数/LDS R16,OSRunning /设置标识系统开始运行的变量/INC R16STS OSRunning,R16LDS R30,OSTCBHighRdy / Z指针指向最高优先级任务的OS_TCB /LDS R31,OSTCBHighRdy+1LD R28,Z+out SPL,R28LD R29,Z+out SPH,R29 /从OS_TCB中获取堆栈指针/POPRS /恢复所有的寄存器/RET /任务开始执行/(2) OSCtxSw()函数OSCtxSw()是一个任务级任务切换函数,其只在任务中被调用,区别于中断程序中调用的切换函数OSIntCtxSw();在C/OS-II中,如果任务调用某个函数,而该函数的执行结果可能会造成系统任务重新调度,例如试图唤醒了一个优先级更高的任务,则需进行任务切换。由于AVR mega128不支持软中断指令,移植时于OS_CPU.H文件直接定义了OSCtxSw()函数。OSCtxSw()函数的汇编代码及相关介绍如下:PUSHRS /保存当前环境/LDS R30,OSTCBCurLDS R31,OSTCBCur+1 / Z指针指向当前任务的OS_TCB /in r28,SPLST Z+,R28in r29,SPHST Z+,R29 /保存堆栈指针到OS_TCB中/CALL OSTaskSwHook /调用用户自己定义的函数/LDS R16,OSPrioHighRdy / OSPrioCur = OSPrioHighRdy /STS OSPrioCur,R16LDS R30,OSTCBHighRdyLDS R31,OSTCBHighRdy / z指针指向高优先级任务的OS_TCB/STS OSTCBCur,R30STS OSTCBCur+1,R31 / OSTCBCur = OSTCBHighRdy /LD R28,Z+out SPL,R28LD R29,Z+out SPH,R29 /获得堆栈指针/POPRS /更新寄存器内容/RET /任务切换/(3) OSIntCtxSw()函数在C/OS-II中,由于中断的发生可能引起任务切换,故在中断服务程序的最后会调用OSIntExit()函数检查任务就绪状态。如果要进行任务切换,将调用OSIntCtxSw()函数,因而OSIntCtxSw()又称为中断级的任务切换函数。由于在调用OSIntCtxSw()之前已经发生了中断,OSIntCtxSw()默认寄存器已经保存在被中断任务的堆栈中了。OSIntCtxSw()的代码大部分和OSCtxSw()函数相同,不同之处在于: 由于中断已经发生,寄存器入栈的工作已经完成,在此不需要再保存寄存器的内容; 在中断服务子程序中调用OSIntExit()时,将返回地址推入了堆栈。OSIntExit()中的进入临界函数OS_ENTER_CRITICAL()可能会将CPU的状态字也推入了堆栈,这取决于中断是怎么关掉的。同时OSIntCtxSw()的返回地址也会被推入堆栈中。当任务挂起时,栈结构应该与C/OS-II所规定的完全一致。所以当任务挂起时,OSIntCtxSw()需要对栈指针进行调整,即调整的栈结构要保证所有挂起的任务的栈结构看起来是一样的。调整的方法很简单,只要将堆栈指针加一个固定的值就可以了。(4) OSTickISR()函数在C/OS-II中,当调用OSStart()启动多任务环境后,时钟中断非常重要。在时钟中断中处理所有与定时器相关的工作,如任务的延时、等待操作等。在时钟中断中将查询处于等待状态的任务,判断是否延时结束,以重新进行任务调度。OSTickISR()采用C/OS-II中的其他中断服务程序原型,移植时采用了AVR mega128的8位定时器0的溢出中断来产生时钟节拍,溢出时间为10ms,并在OSTickISR()中重新装载定时器的起始值。OSTickISR()函数汇编代码及相关介绍如下:OSTickISR:SEI /重新开中断/PUSHRS /保存所有寄存器/LDS R16,OSIntNesting / C/OS-II中断服务程序原型/INC R16STS OSIntNesting,R16CALL OSTimeTick /调用时钟节拍处理函数/CALL OSIntExit / C/OS-II中断服务程序原型/LDI R16,256-(11059200/50/1024)OUT TCNT0,R16 /重载定时器,定时10ms /POPRS /恢复寄存器的值/RET /中断返回/3.3 OS_CPU_C.C文件C/OS-II的移植需要用户在OS_CPU_C.C中定义6个函数,而实际上需要定义的只有OSStkInit()一个函数,其他5个函数需要声明,但不一定有实际内容。这五个函数是用户自己定义的。使用时需要将OS_CFG.H里的OS_CPU_HOOKS_EN定义为1,设置为零表示不使用这些函数。在移植代码中并不要求使用这几个函数,故只定义其位空函数。这5个函数分别为: OSTaskCreateHook()函数 OSTaskDelHook ()函数 OSTaskSwHook ()函数 OSTaskStatHook ()函数 OSTimeTickHook ()函数OSTaskStkInit()函数由任务创建函数OSTaskCreate()或OSTaskCreateExt()调用,用来初始化任务的堆栈。初始状态的堆栈模拟发生一次中断后的堆栈结构。按照中断后的进栈次序预留各个寄存器的存储空间,而中断返回地址指向任务代码的起始地址。由于AVR mega128的堆栈是8位宽的,OSTaskStkInit()将创建一个指向以字节为单位的内存区域的指针,同时要求堆栈指针指向空堆栈的顶端。堆栈初始化工作结束后,OSTaskStkInit()返回新的堆栈指针,OSTaskCreate()或OSTaskCreateExt()将这个堆栈指针保存到任务的OS_TCB上。这里要注意的是,堆栈中的SREG初始化为0x80,即使得任务启动后允许中断的发生;如果设置为0x00,则任务启动后将禁止中断。如果选择任务启动后允许中断发生,则所有的任务运行期间中断都允许;同样,如果选择任务启动后禁止中断,则所有的任务都禁止中断发生,而不能有所选择。如果某个任务选择启动后禁止中断,那么其他的任务在运行的时候需要重新开启中断。同时还需要修改OSTaskIdle()和OSTaskStat()函数,在运行时开启中断。如果以上任何环节出现问题,系统就会崩溃。所以在初始化任务堆栈时设置状态寄存器SREG为0x80,即允许任务启动后中断。4 系统测试随着嵌入式产品的广泛应用,嵌入式系统的研究也在不断发展,出现了很多的实时系统。比如实时系统VxWorks,RT-Linux等。但这些操作系统主要在32位处理器上使用,并且需要较高的成本。而由于8位单片机本身资源的限制,以前很少有在8位机上运行的操作系统,随着8位机功能和资源的增加,渐渐出现了不少使用在8位单片机上的实时系统,比如在AVR单片机上的AVRX,NUT/OS等。这些操作系统主要用汇编语言写成,相对来讲代码效率较高,但也有他本身的限制,即作为一种专用的操作系统而言,它们很难移植到其他平台上和在其他场合使用。C/OS-II作为一个用C语言编写成的操作系统,已被广泛的移植到各种平台上。同时因为其用C语言所写,性能比汇编语言编写的操作系统稍差,故在移植工作完成后,对系统进行了测试。一个实时进程在系统中变成可运行到进程实际开始它的执行,是有一定的延迟时间的,即分配时间。这段时间与内核密切相关。为了测试这段时间,这里只建立了一个任务,该任务在等待一个信号量,收到信号量后对一个计数值进行简单的加1,而给任务发信号量的过程采用定时器2的比较匹配中断完成。AVR单片机的定时器有比较匹配中断模式,当定时器计数与预设值相等时,可以再次从0开始计数。比较匹配中断的程序采用C/OS-II的中断服务程序原型,并且在中断程序中给任务发信号量,而且定义一个变量记录中断发生的次数。如果在所设定的比较时间里,任务程序中的计数值和中断程序中的计数值相等,表明任务在该时间内能满足分配时间。通过不断缩小比较匹配的时间发现,当时间减小到24微秒时,任务已经没有运行了,任务中的计数值为0,表明任务没来得及运行又被比较匹配中断程序占用了处理器。而当大于24微秒时,运行了六千次任务调度,可以完成。对于处理速度相对高档CPU而言已是较慢的8位单片机而言,24微秒能满足应用的需要。在实时系统中,实时系统的实时性表现在系统对外部事件的响应能力上。系统通过中断来响应外部事件的发生,并且用户的中断服务中做的事要尽量的少,把大部分工作留给任务去做,只是通过信号量或者消息队列机制来通知任务运行。因而任务对外部事件的响应时间就是一个重要的性能指标,这里对这段时间进行了测试。程序中建立了一个任务,等待在一个信号量上。mega128的定时器2设置为比
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025布草洗涤与客户体验中心建设合同
- 2025版外墙粉刷与外墙防霉防藻合同
- 2025年度企业财务风险预警系统研发聘用合同范本
- 河北省赤城县2025年上半年事业单位公开遴选试题含答案分析
- 2025多股东企业股权变更及简单转让合同
- 2025年特色小镇拆迁房产权交易合同
- 河北省安新县2025年上半年事业单位公开遴选试题含答案分析
- 海南省屯昌县2025年上半年事业单位公开遴选试题含答案分析
- 2025版文化创意产业资产托管与运营合同
- 2025年度全民健身中心体育馆场地租赁服务合同
- 交通事故处理交通事故委托书
- 劳动与技术小学开学第一课
- 新诊断心房颤动的护理查房
- 辽宁盘锦中医师承确有专长人员考核考试题含答案2024年
- 《WPS AI智能办公应用大全》全套教学课件
- 新疆疫苗管理办法
- 生产策划管理办法
- 2025年重庆出租车资格证区域考试题库区域考试
- 低氯血症护理查房
- 虫害外包服务商管理制度
- 医疗废物监督管理课件
评论
0/150
提交评论