嵌入式实时操作系统详细设计说明书Word文件下载.docx
《嵌入式实时操作系统详细设计说明书Word文件下载.docx》由会员分享,可在线阅读,更多相关《嵌入式实时操作系统详细设计说明书Word文件下载.docx(33页珍藏版)》请在冰点文库上搜索。
3MyRtos详细设计及编码实现7
3.1MyRtos内核结构概述7
3.1.1临界区7
3.1.2任务及其任务控制块7
3.1.3任务调度8
3.1.4空闲任务9
3.2任务管理9
3.2.1建立任务10
3.2.2任务堆栈13
3.2.3改变任务的优先级14
3.2.4挂起任务15
3.2.5恢复任务17
3.2.6任务休眠19
3.3互斥信号量20
3.3.1创建一个互斥信号量20
3.3.2等待一个互斥信号量21
3.3.3释放一个互斥信号量22
总结25
致谢26
参考文献27
详细设计说明书
(ProceduralDesignSpecification)
1绪论
嵌入式系统简介
嵌入式系统本身是一个相对模糊的定义。
目前嵌入式系统已经渗透到我们生活中的每个角落,工业、服务业、消费电子……,而恰恰由于这种范围的扩大,使得“嵌入式系统”更加难于明确定义。
举个简单例子:
一个手持的mp3是否可以叫做是嵌入式系统呢?
答案肯定是“是”。
另外一个PC104的微型工业控制计算机你会认为它是嵌入式系统吗?
当然,也是,工业控制是嵌入式系统技术的一个典型应用领域。
然而比较两者,你也许会发现二者几乎完全不同,除了其中都嵌入有微处理器。
那是否可以说嵌入着微处理器的设备就是嵌入式系统?
那鼠标中也有单片机,能叫嵌入式系统嘛?
那到底什么是嵌入式系统?
莫非嵌入式系统只是一个难以定义的抽象概念?
(1)嵌入式系统定义
根据IEEE(国际电机工程师协会)的定义,嵌入式系统是“控制、监视或者辅助装置、机器和设备运行的装置”(原文为devicesusedtocontrol,monitor,orassisttheoperationofequipment,machineryorplants)。
这主要是从应用上加以定义的,从中可以看出嵌入式系统是软件和硬件的综合体,还可以涵盖机械等附属装置。
不过上述定义并不能充分体现出嵌入式系统的精髓,目前国内一个普遍被认同的定义是:
以应用为中心、以计算机技术为基础、软件硬件可裁剪、适应应用系统对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。
(2)嵌入式系统的特点(与通用PC相比较)
专用性----这是与传统PC最大的区别。
嵌入式系统是面向用户,面向产品,面向应用的。
它只有和具体的应用相结合才能体现出自己的优势。
高实时性----这是嵌入式系统的基本条件。
嵌入性----嵌入式系统是与具体的环境相结合的,与被控对象紧密连接的。
智能性----操作使用人性化、仪表化。
一般很少有人直接参与。
(3)嵌入式系统组成
嵌入式系统主要有两部分组成:
嵌入式微处理器等相关硬件和嵌入式操作系统等嵌入式软件。
嵌入式处理器
嵌入式处理器的体系架构可分为三种形式:
(1)IP(IntellectualProperty)级架构
也就是片上系统SoC(SystemonChip)形式,即是依设备功能的需求,将不同的IP单元,集成在一块总片中,它包含有处理器功能,I/O接口功能及嵌入式软件功能。
(2)芯片级架构
依应用系统要求,选用相应的微处理器,如MCU、MPU、DSP、RISC等芯片,并将RAM、ROM(EPROM/EEPROM/Fash)及I/O接口芯片等组成相应的嵌入式系统,相应的系统软件、应用软件是以固件形式固化在ROM中,这是目前常用的嵌入式系统的架构方式。
MCU、MPU属于单片机系列,这是大家熟知的。
DSP(DigitaSignalProcessor)数字信号处理器,它具有数字信号处理能力强,特别适合于声音、图像等多媒体信息系统,但是其常规处理能力不强、寻址范围有限、I/O功能弱及开发平台问题,较少单独作为嵌入式系统的处理器,而是与嵌入式处理器相结合,构成更强大的功能。
RISC(ReducedInstructionSetComputer)型处理器具有结构简单、处理速度快和处理功能强等优点,因此,新型的嵌入式系统大多数采用RISC处理器,主流架构由ARM架构处理器、Intel的8051处理器、Microchip的PIC处理器和ZiOG的Z80处理器。
目前典型的代表是ARM架构处理器,世界上许多公司均基于ARM架构开发出相应的微处理器芯片,如:
ATME公司:
AT91系列MCU(采用ARM7TDMI内核)。
Intel公司:
SA-1110微处理器MPU(采用StrongARM核)。
Cirros公司:
EP及CL-PS系列掌上型计算机产品的MPU(采用ARM720T核)。
inkupSystems公司:
L720互联网处理器(采用ARM720T核)。
Sharp公司:
H77790掌上型产品中的MPU(采用ARM7TD内核)。
其它如Hyundai公司、OKI公司、Rohm公司、Samsung公司,Netsiicom公司等,其产品中均采用ARM内核。
另外一种新型的微架构处理器是Inte公司的Xscale,它是新一代为无线掌上型应用产品开发的嵌入式处理器,是PCA开发式平台架构中应用于子系统与通信子系统中的嵌入式处理器。
(3)X86处理器嵌入到应用系统中
这样可充分利用PC机的通用性和便利性,采用嵌入式操作系统,并且将操作系统和应用软件均固化在固态电子盘中,以缩小体积,增加可靠性。
典型的产品有研祥公司的嵌入式CPU卡及威盛公司的C3CPU卡。
嵌入式实时操作系统(RTOS)
嵌入式实时操作系统(EmbeddedRealTimeOS,简称RTOS)是嵌入式系统应用开发的核心软件,是嵌入式系统的灵魂,就像我们日常所用计算机桌面系统中,微软公司的Windows操作系统一样重要。
市场上有很多著名的商业化嵌入式操作系统,如VxWorks、PamOS、WindowsCE、嵌入式Linux和μC/OS-II等上千种RTOS。
风河VxWorks是非常出色的设备软件操作系统平台,适用于从手持电子设备到大型网络设施的各种设备。
它以其良好的可靠性和卓越的实时性被广泛的应用在通信、军事、航空、航天等高精尖技术及实时性要求很高的领域中,如卫星通信、军事演习等。
它是目前嵌入式系统领域中使用最广泛、市场占有率最高的系统。
它支持多种处理器,如x86,i960,StrongARM,ARM等。
PalmOS是由Palm公司自行开发,在掌上计算机和PDA市场上占有很大的市场份额。
开放的操作系统应用程序接口(API),开发商可以根据需要自行开发所需的应用程序。
WindowsCE是微软开发的一个嵌入式操作系统,专门用于手持设备和信息家电,它的模块化设计允许他对从掌上计算机到专用的工业控制的用户电子设备进行定制。
它的特点是发展掌上型Windows系统,有文件兼容性高、功能多样化的特点,可以看作是Windows95的简化版。
Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。
Linux继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。
它以高效性和灵活性著称。
但是,由于Linux是全球各地的成千上万的程序员设计和实现的,因此开发散乱也是它的一大弱点。
μC/OS-II是源代码公开的实时嵌入式操作系统,主要有以下特点:
(1)可移植性(Portable)强,μC/OS-II绝大部分源码使用ANSIC编写的,而与微处理器硬件相关的那部分使用会编写的。
(2)可固化,可裁减,可确定性。
(3)μC/OS-II完全是占先式(Preemptive)的实时内核。
(4)实时多任务,不支持时间片轮转调度法。
(5)任务栈,μC/OS-II每个任务都有自己的任务栈
(6)系统服务,μC/OS-II提供了很多的系统服务,例如信号量、互斥信号量、消息邮箱、消息队列等
MyRtos的介绍
现在,市场上有那么多的嵌入式操作系统,从简单到复杂,应有尽有。
比如μC/OS-II就是一个简单易学的RTOS,而且他又是开放源代码的,免费用于个人学习的。
但是,他也还有一个最大的弱点,就是不支持时间片轮转调度算法,这样带来的另一个弱点就是任务的数量是有限。
通过对μC/OS-II的研究,最终实现一个小型的嵌入式操作系统,取名为MyRtos。
MyRtos的主要特点:
(1)可移植性强(Portable),MyRtos绝大部分使用ANSIC编写,而而与微处理器硬件相关的那部分利用了μC/OS-II的函数层,所以MyRtos和μC/OS-II一样有很强的可移植性的
⑵可固化,可裁减,可确定性。
⑶MyRtos是占先式(Preemptive)和时间片轮转共存的实时内核。
⑷实时多任务,支持时间片轮转调度法,任务数可以不确定
(5)任务栈,MyRtos每个任务都有自己的任务栈
(6)系统服务,MyRtos提供了系统服务,例如互斥信号量。
2硬件体系结构和软件平台
硬件体系结构
硬件平台采用的是EasyARM2138开发板,他是广州周立功公司设计的EasyARM系列开发套件之一,下面简单介绍一下EasyARM2138。
EasyARM2138采用了PHILIPS公司基于ARM7TDMI-S核、单电源供电、QFP64封装的LPC2138,LPC2138具有32kB的片内静态RAM和512kB的片内Fash程序存储器,支持JTAG仿真调试、ISP编程等功能,
EasyARM2138开发板上还提供了一些键盘、ED、蜂鸣器等常用功能部件,还具有RS232接口电路、I2C存储器电路。
另外,灵活的跳线组合(开发板内使用的所有I/O均可断开连接),还有用户I/O接口,极大地方便了用户进行32位ARM嵌入式系统的开发实验。
开发的小型嵌入式操作系统(MyRtos),代码量不是很大,对于拥有32kB的片内静态RAM和512kB的片内Flash程序存储器的PC2138来说是绰绰有余,再加上开发板还支持JTAG仿真测试,ISP编程,这样使得开发效率大幅度提高。
另外开发板上还提供了一些键盘、LED、蜂鸣器等常用功能部件,还具有RS232接口电路、I2C存储器电路。
这样更有利于通过小的试验才测试一下程序的正确性,通过这两点所以选择了EasyARM2138开发板。
软件平台
在软件平台的选择上,现在有很多的嵌入式开发软件平台,比如ARM公司的ADS系列的软件,还有IAR公司的IAREmbeddedWorkbenchforARMEvauation,,RealView公司的MDK等软件。
最后选择了陈老师推荐的MDK软件平台,选用的是MDK3.5。
MyRtos内核结构概述
临界区
和其它内核一样,MyRtos为了处理临界段代码需要关中断,处理完毕后再开中断。
这使得MyRtos能够避免同时有其它任务或中断服务进入临界段代码。
关中断的时间是实时内核开发商应提供的最重要的指标之一,因为这个指标影响用户系统对实时事件的响应性。
MyRtos努力使关中断时间降至最短,但就使用MyRtos而言,关中断的时间很大程度上取决于微处理器的架构以及编译器所生成的代码质量。
微处理器一般都有关中断/开中断指令,用户使用的C语言编译器必须有某种机制能够在C中直接实现关中断/开中断地操作。
某些C编译器允许在用户的C源代码中插入汇编语言的语句。
这使得插入微处理器指令来关中断/开中断很容易实现。
而有的编译器把从C语言中关中断/开中断放在语言的扩展部分。
MyRtos定义两个宏(macros)来关中断和开中断,以便避开不同C编译器厂商选择不同的方法来处理关中断和开中断。
MyRtos中的这两个宏调用分别是:
OS_ENTER_CRITICA()和OS_EXIT_CRITICA()。
因为这两个宏的定义取决于所用的微处理器。
任务及其任务控制块
一个任务通常是一个无限的循环。
一个任务看起来像其它C的函数一样,有函数返回类型,有形式参数变量,返回任务编号tid。
MyRtos可以管理的任务数取决于cpu资源的大小,任务之间的优先级可以相等,也可以不相等。
一旦任务建立了,任务控制块os_tcb将被赋值。
任务控制块是一个数据结构,当任务的CPU使用权被剥夺时,MyRtos用它来保存该任务的状态。
当任务重新得到CPU使用权时,任务控制块能确保任务从当时被中断的那一点丝毫不差地继续执行。
os_tcb全部驻留在RAM中。
程序清单3.1ms_tcb
typedefstructms_tcb{
OS_STK*MSTCBStkPtr;
/*指向当前任务堆栈栈顶的指针*/
INT32UMSTCBStkSize;
/*存有栈中可容纳的指针元数目*/
INT16UMSTCBId;
/*用于存储任务的识别码(ID)*/
structms_tcb*MSTCBNext;
/*用于任务控制块OS_TCB双向链表的前链表接*/
structms_tcb*MSTCBPrev;
/*用于任务控制块OS_TCB双向链表的后链接*/
INT16UMSTCBDly;
/*用于把任务延时若干时钟节拍或把任务挂起一段时间*/
INT8UMSTCBStat;
/*任务的状态字*/
INT8UMSTCBPrio;
/*任务的优先级*/
char*name;
/*函数的名字*/
#ifMS_TASK_DEL_EN>
0
BOOLEANMSTCBDelReq;
//用于表示该任务是否需删除,只有OS_TASK_DEL_EN=1时,
//个变元才会出现
#endif
structms_tcb*MSTSnext;
/*当进程为同一个优先级的时候,形成一个链表*/
structos_tcb*MSTSprev;
INT8UMSTCBInitTick;
/*任务初始化的时间片*/
INT8UMSTCBRemainigTick;
/*任务剩余的时间片*/
}
MS_TCB;
任务调度
MyRtos总是运行进入就绪态任务中优先级最高的那一个。
确定哪个任务优先级最高,下面该哪个任务运行了的工作是由调度器(Scheduer)完成的。
任务的调度是由函数MS_Sched()完成的。
程序清单3.2调度函数
voidMS_Sched(void)
{
OS_ENTER_CRITICAL();
if((MSIntNesting==0)&
&
(MSLockNesting==0))
{
/*如果调用来自中断服务子程序或由于至少调用了一次给任务调度上锁函数,任务调度函数将退出*/
MSPrioHighRdy=HighestPrio();
if(MSPrioHighRdy!
=MSPrioCur){
/*检查此任务是否是当前正在运行的任务以避免不必要的麻烦*/
MSTCBHighRdy=MSTCBPrioTbl[MPrioHighRdy];
/*MTCBHighRdy指向优先级最高的任务控制块*/
MCtxSwCtr++;
/*统计计数器加1,以跟踪任务切换次数*/
MS_TASK_SW();
/*使用此宏调用完成实际上的任务切换*/
}
OS_EXIT_CRITICAL();
}
MyRtos任务调度所花的时间是常数,与应用程序中建立的任务数无关。
如程序清单中条件语句的条件不满足,任务调度函数MS_Sched()将退出,不做任务调度。
这个条件是:
如果在中断服务子程序中调用MS_Sched(),此时中断嵌套层数MSIntNesting>
0,或者由于用户至少调用了一次给任务调度上锁函数MSSchedLock(),使MSLockNesting>
0。
如果不是在中断服务子程序调用OS_Sched(),并且任务调度是允许的,即没有上锁,则任务调度函数将找出那个进入就绪态且优先级最高的任务。
一旦找到那个优先级最高的任务,OS_Sched()检验这个优先级最高的任务是不是当前正在运行的任务,以此来避免不必要的任务调度。
为实现任务切换,MSTCBHighRdy必须指向优先级最高的那个任务控制块MS_TCB,任务切换很简单,由以下两步完成,将被挂起任务的微处理器寄存器推入堆栈,然后将较高优先级的任务的寄存器值从栈中恢复到寄存器中。
在MyRtos中,就绪任务的栈结构总是看起来跟刚刚发生过中断一样,所有微处理器的寄存器都保存在栈中。
换句话说,MyRtos运行就绪态的任务所要做的一切,只是恢复所有的CPU寄存器并运行中断返回指令。
为了做任务切换,运行MS_TASK_SW(),人为模仿了一次中断。
空闲任务
程序清单3.3空闲任务
voidMS_TaskIdle(void*pdata)
pdata=pdata;
/*为了防止编译器发出警告*/
while
(1){
/*空闲的任务不停地为一个叫名为MSIdleCtr的计数器加一*/
MSIdleCtr++;
MSTaskIdleHook();
/*调用MSTaskIdleHook(),可以写入用户的任何代码*/
上面的代码就是系统的空闲任务MS_TaskIdle(),MyRtos总是建立一个空闲任务,这个任务在没有其它任务进入就绪态时投入运行。
这个空闲任务永远设为最低优先级,即MS_LOWEST_PRI0。
空闲任务MS_TaskIdle()什么也不做,只是在不停地给一个32位的名叫MSIdeCtr的计数器加1,注意空闲任务不可能被应用软件删除。
任务管理
任务可以是一个无限的循环。
任务看起来与任何C函数一样,具有一个返回类型和一个参数,任务的返回类型被定义成int型。
建立任务
想让MyRtos管理用户的任务,用户必须要先建立任务。
用户可以通过传递任务地址和其它参数到以下这个函数来建立任务:
taskCreate()。
任务可以在多任务调度开始前建立,也可以在其它任务的执行过程中被建立。
在开始多任务调度(即调用MSStart())前,用户必须建立至少一个任务。
任务不能由中断服务程序(ISR)来建立。
taskCreate()的代码如下。
从中可以知道,taskCreate()需要4个参数:
name是任务名称,entryPtr是任务函数入口,stack_size是任务栈大小,priority是分配给任务的优先级。
程序清单3.4建立任务
INT8StaskCreate(char*name,void(*entryPtr)(void*pd),void*pdata,OS_STK*ptos,INT8Uprio,INT8UTSlen)
OS_STK*psp;
/*创建一个任务堆栈指针*/
INT8Uerr;
/*判断是否创建任务块成功*/
if(prio>
MS_LOWEST_PRIO)
{
/*确保优先级在有效的范围内*/
return(ERROR);
/*返回错误信息,优先级大于MS_LOWEST_PRIO*/
OS_ENTER_CRITICAL();
psp=(OS_STK*)MSTaskStkInit(entryPtr,pdata,ptos,0);
/*初始化任务栈,返回新的栈顶指针*/
err=MS_TCBInit(name,prio,psp,64,TSlen);
/*初始化任务块,成功返回MS_NO_ERR*/
OS_EXIT_CRITICAL();
if(err==OK)
{
/*MS_NO_ERR表示调用成功*/
OS_ENTER_CRITICAL();
MSTaskCtr++;
/*任务计数器加一*/
if(MSRunning==TRUE)
/*如果此函数是在执行某任务过程中调用的,则判断优先级*/
MS_Sched();
/*任务切换*/
return(OK);
returntid;
else{
/*任务初始化失败*/
MSTCBPrioTbl[prio]=(MS_TCB*)0;
/*如果任务控制块初始化失败,则放弃该任务的优先级*/
MSTCBIdTbl[tid]=(MS_TCB*)0;
return(err);
/*返回任务创建是否成功*/
taskCreate()一开始先检测分配给任务的优先级是否有效。
任务的优先级必须在0到MS_LOWEST_PRIO之间。
然后,taskCreate()调用MSTaskStkInit(),它负责建立任务的堆栈。
该函数是与处理器的硬件体系相关的函数。
MSTaskStkInit()函数返回新的堆栈栈顶(psp),并被保存在任务的ms_tcb中。
MyRtos支持的处理器的堆栈既可以从上(高地址)往下(低地址)递减也可以从下往上递增。
用户在调用taskCreate()的时候必须知道堆栈是递增的还是递减的,因为用户必须得把堆栈的栈顶传递给taskCreate(),而栈顶可能是堆栈的最高地址(堆栈从上往下递减),也可能是最低地址(堆栈从下往上长)。
一旦MSTaskStkInit()函数完成了建立堆栈的任务,taskCreate()就调用MS_TCBInit()。
MS_TCBInit()的代码3.5所示
程序清单3.5初始化任务控制块
INT8SMS_TCBInit(char*name,INT8Uprio,OS_STK*ptos,INT32Ustk_size,INT8UTSlen)
MS_TCB*ptcb;
ptcb=MSTCBFreeList;
/*得到一个空的任务控制块*/
if(ptcb!
=(OS_TCB*)0){
MSTCBFreeList=ptcb->
OSTCBNext;
/*指向控制块*/
ptcb->
MSTCBStkPtr=ptos;
/*此MS_TCB被初始化*/
MSTCBPrio=prio;
/*保存此块的优先级*/
MSTCBStat=MS_STAT_SUSPEND;