嵌入式操作系统uCOS课件_第1页
嵌入式操作系统uCOS课件_第2页
嵌入式操作系统uCOS课件_第3页
嵌入式操作系统uCOS课件_第4页
嵌入式操作系统uCOS课件_第5页
已阅读5页,还剩45页未读 继续免费阅读

付费下载

下载本文档

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

文档简介

嵌入式操作系统—uC/OS1What

isuC/OS?u:

Micro

C:controluC/OS:适合于小的、控制器的操作系统小巧公开源代码,详细的注解可剥夺实时内核可移植性强多任务确定性嵌入式操作系统—uC/OS2The

Story

of

uC/OS美国人Jean

Labrosse

1992年编写的商业软件的昂贵应用面覆盖了诸多领域,如照相机、医疗器械、音响设备、发动机控制、高速公路电话系统、自动提款机等www.uCOS-II.com嵌入式操作系统—uC/OS3μCOS不但提供了一个完整的嵌入式实时内核的源代码,而且对这些代码的细节作了详尽的解释,它不仅告诉读者这个实时内核是怎么写的,还解释了为什么要这样写。而商业上的实时操作系统软件不但价格昂贵(一般都在5千到2万美元的价位上),而且其中很多都是所谓黑盒子,即不提供源代码。l

源代码的绝大部分是用C语言写的,经过简单的编译,读者就能在PC机上运行,边读书、边实践。由于用汇编语言写的部分只有200行左右,该实时内核可以方便地移植到几乎所有的嵌入式应用类CPU上。移植范例的源代码可以从因特网上下载。l

从最老版本的实时内核μCOS,以及后来的μC/OS,到新版本的μC/OS-II,已经有多年的历史。许多行业上都有成功应用该实时源代码.实时内核移植.内核实时内核的实例,这些应用的实践是该内核实用性、无误性的最好证据。嵌入式操作系统—uC/OS4嵌入式操作系统—uC/OS5概要内核结构-任务以及调度机制任务间通信uC/OS的移植在PC机上运行uC/OS嵌入式操作系统—uC/OS6任务task典型的一个无限循环。void

mytask(void

*pdata){for

(;;)

{dosomething;waiting;dosomething;}}支持64个任务,每个任务一个特定的优先级。优先级越高,数字越小系统占用了两个任务,空闲任务和统计任务。嵌入式操作系统—uC/OS7任务优先级每个任务按其重要性被赋予一定的优先级。μC/OS-Ⅱ可以管理多达64个任务,但目前版本的μC/OS-Ⅱ有两个任务已经被系统占用了。作者保留了优先级为0、1、2、3、OS_LOWEST_PRIO-3、OS_LOWEST_PRI0-2,OS_LOWEST_PRI0-1以及OS_LOWEST_PRI0这8个任务以被将来使用。OS_LOWEST_PRI0是作为定义的常数在OS_CFG.H文件中用定义常数语句#defineconstant定义的。因此用户可以有多达56个应用任务。必须给每个任务赋以不同的优先级,优先级可以从0到OS_LOWEST_PR10-2。优先级号越低,任务的优先级越高。μC/OS-Ⅱ总是运行进入就绪态的优先级最高的任务。目前版本的μC/OS-Ⅱ中,任务的优先级号就是任务编号(ID)。优先级号(或任务的ID号)也被一些内核服务函数调用,如改变优先级函数OSTaskChangePrio(),以及任务删除函数OSTaskDel()。嵌入式操作系统—uC/OS8任务状态休眠态(dormant):指任务驻留在程序空间中,还没有交给内核管理。把任务交给内核是通过调用OSTaskCreate()或OSTaskCreatExt()实现的。就绪(Ready):当任务一旦建立,这个任务就处于就绪态准备运行。任务可以动态的被另一个程序建立,也可以在系统运行开始之前建立。如果一个任务是被另一个任务建立的,而这个任务的优先级高于建立它的那个任务,则这个刚刚建立的任务将立即得到

CPU的控制权。通过调用OSTaskDel()使任务返回到休眠态。就绪态的任务都放在就绪列表中。在任务调度时,指针

OSTCBHighRdy指向优先级最高的就绪任务,也就是立刻就要运行的任务。嵌入式操作系统—uC/OS9运行(Running):准备就绪的最高优先级的任务获得CPU的控制权,从而处于运行态。指针OSTCBCur指向正在运行的任务。等待或挂起(Pending):正在运行的任务由于调用延时函数

OSTimeDly()或等待事件信号量的来临而将自身挂起,因而处于等待或挂起态。因为等待某事件而被挂起的任务注册在该事件的等待列表中。中断态(Interrupt):正在运行的任务可以被中断,除非是该任务将中断关闭。被中断的任务进入中断服务程序(ISR)。如果中断服务程序使一个更高优先级的任务准备就绪,则中断服务程序结束后,更高优先级的任务开始运行程序。嵌入式操作系统—uC/OS10嵌入式操作系统—uC/OS11任务堆栈在µC/OS-Ⅱ中,每个任务都有自己的堆栈空间。为方便使用,在µC/OS-Ⅱ中专门定义了一个OS_STK类型的数据,这样在应用程序中定义任务的堆栈就非常方便。例如:程序

8‑5#define

TASK_STK_SIZE

200OS_STK

TaskStartStk[TASK_STK_SIZE];嵌入式操作系统—uC/OS任务的数据结构—任务控制块任务控制块

OS_tcb,包括任务堆栈指针,状态,优先级,任务表位置,任务链表指针等。所有的任务控制块分为两条链表,空闲链表和使用链表。新任务TCBTCB0

TCB1

TCBnnext

pre空(2)(3)OSTCBFreeList图4.3

TCB的双向链表结构12嵌入式操作系统—uC/OS13任务控制块结构Struct

os_tcb

{OS_STK

*OSTCBStkPtr;struct

os_tcb*OSTCBNext;struct

os_tcb*OSTCBprev;OS_EVENTvoid*OSTCBEventPtr;*OSTCBMsg;OSTCBDly;OSTCBStat;OSTCBPrio;OSTCBX,

OSTCBY,

OSTCBBitX,

OSTCBBitY;INT16UINT8UINT8UINT8U}

OS_TCB嵌入式操作系统—uC/OS14OSTCBStkPtr是指向当前任务栈顶的指针。μC/OS-Ⅱ允许每个任务有自己的栈,尤为重要的是,每个任务的栈的容量可以是任意的。有些商业内核要求所有任务栈的容量都一样,除非用户写一个复杂的接口函数来改变之。这种限制浪费了RAM,当各任务需要的栈空间不同时,也得按任务中预期栈容量需求最多的来分配栈空间。OSTCBStkPtr是OS_TCB数据结构中唯一的一个能用汇编语言来处置的变量(在任务切换段的代码Context-switchingcode之中),把OSTCBStkPtr放在数据结构的最前面,使得从汇编语言中处理这个变量时较为容易。嵌入式操作系统—uC/OS15.OSTCBNext和.OSTCBPrev用于任务控制块OS_TCBs的双重链接,该链表在时钟节拍函数OSTimeTick()中使用,用于刷新各个任务的任务延迟变量.OSTCBDly,每个任务的任务控制块OS_TCB在任务建立的时候被链接到链表中,在任务删除的时候从链表中被删除。双重连接的链表使得任一成员都能被快

速插入或删除。嵌入式操作系统—uC/OS16OSTCBEventPtr是指向事件控制块的指针,后面的章节中会有所描述(见8.9任务的同步和通信)。.OSTCBMsg是指向传给任务的消息的指针。用法将在后面的章节中提到(见8.9任务的同步和通信)。.OSTCBDly当需要把任务延时若干时钟节拍时要用到这个变量,或者需要把任务挂起一段时间以等待某事

件的发生,这种等待是有超时限制的。在这种情况下,这个变量保存的是任务允许等待事件发生的最多时钟

节拍数。如果这个变量为0,表示任务不延时,或者表示等待事件发生的时间没有限制嵌入式操作系统—uC/OS17OSTCBStat是任务的状态字。当.OSTCBStat为0,任务进入就绪态。可以给.OSTCBStat赋其它的值,在文件uCOS_II.H中有关于这个值的描述。.OSTCBPrio是任务优先级。高优先级任务的.OSTCBPrio值小。也就是说,这个值越小,任务的优先级越高。.OSTCBX,.OSTCBY,.OSTCBBitX和.OSTCBBitY用于加速任务进入就绪态的过程或进入等待事件发生状态的过程(避免在运行中去计算这些值)。这些值是在任务建立时算好的,或者是在改变任务优先级时算出的。.OSTCBDelReq是一个布尔量,用于表示该任务是否需要删除。嵌入式操作系统—uC/OS18任务的调度--OSScheduC/OS是占先式实时多任务内核,优先级最高的任务一旦准备就绪,则拥有CPU的所有权开始投入运行。uC/OS中不支持时间片轮转法,每个任务的优先级要求不一样且是唯一的,所以任务调度的工作就是:查找准备就绪的最高优先级的任务并进行上下文切换。嵌入式操作系统—uC/OS19任务的调度就绪任务表:用于存贮每个任务的就绪状态标志。由两个变量组成:OSRdyGrp:8位,每位表示一组(8个)任务中是否有就绪的任务。OSRdyTbl[]:位图方式表示某个任务是否就绪。嵌入式操作系统—uC/OS20就绪状态标志Bit

0

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[0]is

1.Bit

1

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[1]is

1.Bit

2

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[2]is

1.Bit

3

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[3]is

1.Bit

4

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[4]is

1.Bit

5

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[5]is

1.Bit

6

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[6]is

1.Bit

7

in

OSRdyGrp

is

1

when

any

bit

inOSRdyTbl[7]is

1.嵌入式操作系统—uC/OS根据优先级找到任务在就绪任务表中的位置21嵌入式操作系统—uC/OS22根据优先级确定就绪表假设优先级为

12

的任务进入就绪状态,

12=1

1则OSRdyTbl[1]的第4位置1,且OSRdyGrp的第1位置1,相应的数学表达式为:OSRdyGrpOSRdyTbl[1]而优先级为|=0x02;|=0x10;21

的任务就绪OSRdyTbl[2]的第5位置1,且OSRdyGrp的第2位置

1,相应的数学表达式为:OSRdyGrpOSRdyTbl[2]|=0x04;|=0x20;嵌入式操作系统—uC/OS23根据优先级确定就绪表从上面的计算我们可以得到:若第n位置1,则

应该与2n相或。uC/OS中,把2n的n=0-7的8个值先计算好存在数组OSMapTbl[7]中,也就是:OSMapTbl[0]

=20=0x1;OSMapTbl[1]

=21=0x2;……OSMapTbl[7]

=27=0x80;嵌入式操作系统—uC/OS24根据优先级确定就绪表利用OSMapTbl,通过任务的识别号-优先级prio来设置任务在就绪组和就绪表数组中相应位置的数学式为:OSRdyGrp

|=OSMapTbl[prio>>3];OSRdyTbl[prio>>3] |=OSMapTbl[prio

&

0x07];假设优先级为12,1100bOSRdyGrpOSRdyTbl[1]|=0x02;|=0x10;嵌入式操作系统—uC/OS25根据就绪表确定最高优先级(1)两个关键:优先级数分解为高三位和低三位分别确定;高优先级有着小的优先级号

;嵌入式操作系统—uC/OS26根据就绪表确定最高优先级(2)通过OSRdyGrp值确定高3位,假设为0x24=100

100b,

〉OSRdyTbl[2]和OSRdyTbl[5],高优先级为2通过OSRdyTbl[2]的值来确定低3位,假设为0x12=010

010b,〉第2个和第5个任务,取高优先级第2个〉17嵌入式操作系统—uC/OS27源代码中使用了查表法查表法具有确定的时间,增加了系统的可预测性,uC/OS中所有的系统调用时间都是确定的High3

=OSUnMapTbl[OSRdyGrp];Low3=OSUnMapTbl[OSRdyTbl[High3]];Prio

=(Hign3<<3)+Low3;?为什么频繁的使用查表法?请问OSUnMapTbl的来历;嵌入式操作系统—uC/OSINT8U

const

OSUnMapTbl[]

=

{0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};28嵌入式操作系统—uC/OS29任务调度核心之任务切换宏OS_TASK_SW()任务切换很简单,简单说就是终止正在运行的任务,然后去运行

另外一个任务,这由以下两步完成,将被挂起任务的微处理器寄

存器推入堆栈,然后将较高优先级的任务的寄存器值从栈中恢复

到寄存器中。在μC/OS-Ⅱ中,就绪任务的栈结构总是看起来跟刚

刚发生过中断一样,所有微处理器的寄存器都保存在栈中。换句

话说,μC/OS-Ⅱ运行就绪态的任务所要做的一切,只是恢复所有

的CPU寄存器并运行中断返回指令。为了做任务切换,运行

OS_TASK_SW(),人为模仿了一次中断。多数微处理器有软中断

指令SWI或者陷阱指令TRAP来实现上述操作。中断服务子程序或陷阱处理(Traphardler),也称作事故处理(exceptionhandler),必须提供中断向量给汇编语言函数OSCtxSw()。OSCtxSw()除了需要OS_TCBHighRdy指向即将被挂起的任务,还需要让当前任务控制块OSTCBCur指向即将被挂起的任务嵌入式操作系统—uC/OS30任务间通信手段提供OS_ENTER_CRITICAL和OS_EXIT_CRITICAL来对临界资源进行保护OSSchedLock()禁止调度保护任务级的共享资源。提供了经典操作系统任务间通信方法:信号量、邮箱、消息队列,事件标志。嵌入式操作系统—uC/OS31信号量semaphoreuC/OS中信号量由两部分组成:信号量的计数值和等待该信号任务的等待任务表。信号量的计数值可以为二进制,也可以是其他整数。系统通过OSSemPend()和OSSemPost()来支持信号量的两种原子操作P()和V()。P()操作减少信号量的值,如果新的信号量的值不大于0,则操作阻塞;V()操作增加信号量的值。嵌入式操作系统—uC/OS32中断与时钟节拍我们知道:当发生中断时,首先应保护现场,将CPU寄存器入栈,再处理中断函数,然后恢复现场,将

CPU寄存器出栈,最后执行中断返回iret(x86)指令实现中断返回。uC/OS中提供了OSIntEnter()

和OSIntExit()告诉内核进入了中断状态。OSIntNesting时钟节拍是一种特殊的中断,操作系统的心脏。首先

32位的整数OSTime加一。对任务列表进行扫描,判断是否有延时任务应该处于准备就绪状态,最后进行上下文切换。嵌入式操作系统—uC/OS33多任务的启动首先创建任务最后调用OSStart开始多任务调度void

main(

){ OSInit(

);…..OSTaskcreat()…..OSStart();}嵌入式操作系统—uC/OS34任务的格式每个任务不能占用全部CPU的资源需要有等待,或延时等系统调用典型的一个无限循环。void

mytask(void

*pdata){for

(;;)

{dosomething;waiting;dosomething;}}嵌入式操作系统—uC/OS35揭开神秘的面纱—任务调度全程追踪For

example1

创建2个任务,每个任务仅仅是进行延时,延时不同的时间片,不同优先级void

Task1(void){while(1){blinkled1();Task1Data++;OSTimeDly(25);}}void

Task2(void){while(1){blinkled2();Task2Data++;OSTimeDly(50);}}嵌入式操作系统—uC/OS36void

main(){sysinit();OSInit

();OSTaskCreate

(

Task1,

(void

*)&Task1Data,(void

*)&Task1Stk[TASK_STK_SIZE],Task1prio);OSTaskCreate

(Task2,

(void

*)&Task2Data,(void

*)&Task2Stk[TASK_STK_SIZE],Task2prio);ticker_start(OS_TICKS_PER_SEC);OSStart();}嵌入式操作系统—uC/OS37void

OSStart

(void){INT8U

y,x;if

(OSRunning

==

FALSE)

{判断是否没有启动内核yx=

OSUnMapTbl[OSRdyGrp];=

OSUnMapTbl[OSRdyTbl[y]];OSPrioHighRdy=(INT8U)((y<<3)+x);

找到优先级最高的准备就绪任务OSPrioCur

=OSPrioHighRdy;

当前运行任务优先级OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];

根据任务优先级找到任务OSTCBCurOSStartHighRdy();=

OSTCBHighRdy;让优先级最高的任务运行起来}}嵌入式操作系统—uC/OS38OSStartHighRdy(void)void{OSTaskSwHook();//

Call

Hook

functionasm{ldxOSTCBCur//

Load

the

value0,x//

Loadin

OSTCBCur

or

the

TCB's

address

to

xldsthe

value

pointed

by

OSTCBCur

to

spOSRunning//

OSRunning

=

1OSRunning$30//restore

ppage

from

stackldaaincastaapulastaanoprti}}嵌入式操作系统—uC/OS39void

OSTimeDly

(INT16U

ticks){if

(ticks

>

0)

{

确保tick大于0OS_ENTER_CRITICAL();

进入临界段代码if

((OSRdyTbl[OSTCBCur->OSTCBY]

&=

~OSTCBCur->OSTCBBitX)

==

0){ /*

Delay

current

task

*/OSRdyGrp

&=~OSTCBCur->OSTCBBitY;设置任务为非就绪状态}在TCB中装载延时数退出临界段代码调度下一个任务开始运行OSTCBCur->OSTCBDly=

ticks;OS_EXIT_CRITICAL();OSSched();}}嵌入式操作系统—uC/OS40void

OSSched

(void){INT8U

y;OS_ENTER_CRITICAL();if

((OSLockNesting

|

OSIntNesting)==0){调度锁,或者处于中断状态禁止调度y =

OSUnMapTbl[OSRdyGrp];OSPrioHighRdy

=

(INT8U)((y

<<

3)

+OSUnMapTbl[OSRdyTbl[y]]);获取准备就绪组里最高优先级的任务if

(OSPrioHighRdy

!=

OSPrioCur)

{OSTCBHighRdy

=

OSTCBPrioTbl[OSPrioHighRdy];设置运行任务为最高优先级任务OSCtxSwCtr++;OS_TASK_SW();

执行上下文切换}

}OS_EXIT_CRITICAL();}嵌入式操作系统—uC/OS41OS_TASK_SW

任务的上下文切换保护当前任务的现场恢复新任务的现场执行中断返回指令开始执行新的任务嵌入式操作系统—uC/OS42什么也不做的空闲任务只是为了消耗CPU的时间片void

OSTaskIdle

(

){for

(;;)

{OS_ENTER_CRITICAL();OSIdleCtr++;OS_EXIT_CRITICAL();}}嵌入式操作系统—uC/OS43void

OSTimeTick

(void){OS_TCB

*ptcb;ptcb

=OSTCBList;OSTCB链表指针while

(ptcb->OSTCBPrio!=OS_IDLE_PRIO){

看是不是空闲任务,空闲任务是最后的任务if(ptcb->OSTCBDly!=

0)

{if

(--ptcb->OSTCBDly==

0){是否延时延时减一,看是否延时结束if(!(ptcb->OSTCBStat

&

OS_STAT_SUSPEND))

{OSRdyGrp |=ptcb->OSTCBBitY;

是的话将其列入准备就绪表OSRdyTbl[ptcb->OSTCBY]

|=

ptcb->OSTCBBitX;}

else

{ptcb->OS

温馨提示

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

评论

0/150

提交评论