嵌入式系统学习课件C5_第1页
嵌入式系统学习课件C5_第2页
嵌入式系统学习课件C5_第3页
嵌入式系统学习课件C5_第4页
嵌入式系统学习课件C5_第5页
已阅读5页,还剩90页未读 继续免费阅读

下载本文档

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

文档简介

嵌入式技术及应用——ARM与C/OS-Ⅱ五、C/OS-Ⅱ操作系统12中断和时间管理任务之间的通信与同步中断处理中断:由于某种事件的发生而导致程序流程的改变。产生中断的事件称为中断源。CPU响应中断的条件:至少有一个中断源向CPU发出中断信号;系统允许中断,且对此中断信号未予屏蔽。中断的分类

分类方式硬件中断是否可以被屏蔽:可屏蔽中断和不可屏蔽中断

中断源:硬件中断和软件中断

中断信号的产生:边缘触发中断和电平触发中断

中断服务程序的调用方式:向量中断、直接中断和间接中断

可屏蔽中断和不可屏蔽中断由于中断的发生是异步的,程序的正常执行流程随时有可能被中断服务程序打断。如果程序正在进行某些重要运算,中断服务程序的插入将有可能改变某些寄存器的数据,造成程序的运行发生错误。可屏蔽中断:能够被屏蔽掉的中断。外部设备的中断请求信号一般需要先通过CPU外部的中断控制器,再与CPU相应的引脚相连。可编程中断控制器可以通过软件进行控制,以禁止或是允许中断。不可屏蔽中断:在任何时候都不可屏蔽的。一个比较典型的例子是掉电中断,当发生掉电时,无论程序正在进行什么样的运算,它都肯定无法正常运行下去。这种情况下,急需进行的是一些掉电保护的操作。对这类中断,应随时进行响应。硬件中断和软件中断硬件中断:由于CPU外部的设备所产生的中断。异步事件:可能在程序执行的任何位置发生,发生中断的时间通常是不确定的。软件中断:同步中断或是自陷,通过处理器的软件指令来实现。产生中断的时机是预知的,可根据需要在程序中进行设定。软件中断的处理程序以同步的方式进行执行。其处理方式同硬件中断处理程序类似。硬件中断和软件中断软件中断是一种非常重要的机制:系统可通过该机制在用户模式执行特权模式下的操作。是软件调试的一个重要手段,如Intel80x86中的INT3,使指令进行单步执行,调试器可以用它来形成观察点,并查看随程序执行而动态变化的事件情况。边缘触发中断和电平触发中断边缘触发中断:中断线从低变到高或是从高变到低时,中断信号就被发送出去,并只有在下一次的从低变到高或是从高变到低时才会再度触发中断。事件发生的时间非常短,有可能出现中断控制器丢失中断的情况。如果多个设备连接到同一个中断线,即使只有一个设备产生了中断信号,也必须调用中断线对应的所有中断服务程序来进行匹配,否则会出现中断的软件丢失情况。边缘触发中断和电平触发中断电平触发中断:在硬件中断线的电平发生变化时产生中断信号,并且中断信号的有效性将持续保持下去,直到中断信号被清除。能够降低中断信号传送丢失的情况能通过更有效的方式来服务中断,每个为该中断服务后的ISR都要向外围设备进行确认,然后取消该设备对中断线的操作。当中断线的最后一个设备得到中断服务后,中断线的电平就会发生变化,不用对连接到同一个硬件中断线的所有中断服务程序进行尝试。向量中断、直接中断和间接中断向量中断:通过中断向量来调用中断服务程序。直接中断:中断对应的中断服务程序的入口地址是一个固定值,当中断发生的时候,程序执行流程将直接跳转到中断服务程序的入口地址,执行中断服务程序。间接中断:中断服务程序的入口地址由寄存器提供。向量中断中断硬件设备的硬件中断线(也称为中断请求IRQ)被中断控制器汇集成中断向量(interruptvector);每个中断向量对应一个中断服务程序(interruptserviceroutine,ISR),用来存放中断服务程序的入口地址或是中断服务程序的第一条指令。系统中通常包含多个中断向量,存放这些中断向量对应中断服务程序入口地址的内存区域被称为中断向量表。向量中断在Intel80x86处理器中,中断向量表包含256个入口,每个中断向量需要四个字节(存放中断服务程序的首址)。ARM的中断向量表开始于内存地址0x00000000或是0xFFFF0000处。5.1.2中断服务程序ISR中断一旦被识别,CPU会保存部分(或全部)运行上下文(context,即寄存器的值),然后跳转到专门的子程序去处理此次事件,称为中断服务子程序(ISR)。μC/OS-Ⅱ中,中断服务子程序要用汇编语言来编写,然而,如果用户使用的C语言编译器支持在线汇编语言的话(混编),用户可以直接将中断服务子程序代码放在C语言的程序文件中。(1)保存全部CPU寄存器的值;(2)调用OSIntEnter(),或直接把全局变量OSIntNesting(中断嵌套层次)加1;(3)执行用户代码做中断服务;(4)调用OSIntExit();(5)恢复所有CPU寄存器;(6)执行中断返回指令。用户ISR的框架(服务过程)5.1.3相关函数介绍OSIntEnter()/*在调用本函数之前必须先将中断关闭*/voidOSIntEnter(void){if(OSRunning==TRUE){if(OSIntNesting<255){OSIntNesting++;}}}OSIntExit的意义OSIntExit()voidOSIntExit(void){OS_ENTER_CRITICAL();//关中断if((--OSIntNesting|OSLockNesting)==0)//判断嵌套是否为零{//把高优先级任务装入OSIntExitY=OSUnMapTbl[OSRdyGrp];OSPrioHighRdy=(INT8U)((OSIntExitY<<3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);if(OSPrioHighRdy!=OSPrioCur){OSTCBHighRdy=

OSTCBPrioTbl[OSPrioHighRdy];OSCtxSwCtr++;

OSIntCtxSw();}}OS_EXIT_CRITICAL();//开中断返回}OSIntCtxSw()在任务切换时,为什么使用OSIntCtxSw()而不是调度函数中的OS_TASK_SW()?原因有二点一半的任务切换工作,即CPU寄存器入栈,已经在前面做完了;需要保证所有被挂起任务的栈结构是一样的。OSIntExit的关键——OSIntCtxSw实现中断级的任务切换ARM在栈指针调整过程中的优势为了实现资源共享,一个操作系统必须提供临界区操作的功能;μC/OS采用关闭/打开中断的方式来处理临界区代码,从而避免竞争条件,实现任务间的互斥;

μC/OS定义两个宏(macros)来开关中断,即:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL();这两个宏的定义取决于所用的微处理器,每种微处理器都有自己的OS_CPU.H文件。

...

OS_ENTER_CRITICAL();任务1的临界区代码;OS_EXIT_CRITICAL();...任务1任务2...

OS_ENTER_CRITICAL();任务2的临界区代码;OS_EXIT_CRITICAL();...临界资源当处理临界段代码时,需要关中断,处理完毕后,再开中断;关中断时间是实时内核最重要的指标之一;在实际应用中,关中断的时间很大程度中取决于微处理器的结构和编译器生成的代码质量;C/OS-II定义两个宏开关中断:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL();C/OS-II中开关中断的方法OS_CRITICAL_METHOD==1用处理器指令关中断,执行OS_ENTER_CRITICAL(),开中断执行OS_EXIT_CRITICAL();OS_CRITICAL_METHOD==2实现OS_ENTER_CRITICAL()时,先在堆栈中保存中断的开/关状态,然后再关中断;实现OS_EXIT_CRITICAL()时,从堆栈中弹出原来中断的开/关状态;OS_CRITICAL_METHOD==3把当前处理器的状态字保存在局部变量中(如OS_CPU_SR,关中断时保存,开中断时恢复C/OS-II中采用了3种开关中断的方法Intel80x86实模式下中断的打开与关闭;方法1#defineOS_ENTER_CRITICAL()asmCLI#defineOS_EXIT_CRITICAL()asmSTI方法2#defineOS_ENTER_CRITICAL()asm{PUSHF;CLI}#defineOS_EXIT_CRITICAL()asmPOPF时间管理时间管理一般具有以下功能:维持日历时间;任务有限等待的计时;软定时器的定时管理;维持系统时间片轮转调度。

硬件时钟设备

大多数嵌入式系统有两种时钟源:实时时钟(realtimeclock,RTC)定时器/计数器实时时钟:一般靠电池供电,即使系统断电,也可以维持日期和时间。实时时钟独立于操作系统,所以也被称为硬件时钟,为整个系统提供一个计时标准。定时器/计数器:实时内核需要一个定时器作为系统时钟(或称OS时钟),并由实时内核控制系统时钟工作。一般情况下,系统时钟的最小刻度是由应用和操作系统的特点决定的。硬件时钟设备在不同的操作系统中,实时时钟和系统时钟之间的关系是不同的。实时时钟和系统时钟之间的关系通常也被称作操作系统的时钟运作机制。一般来说,实时时钟是系统时钟的时间基准,实时内核通过读取实时时钟来初始化系统时钟,此后二者保持同步运行,共同维系系统时间。系统时钟并不是本质意义上的时钟,只有当系统运行起来以后才有效,并且由实时内核完全控制。时钟节拍时钟节拍是一种特殊的中断,相当于操作系统的心脏起搏器;μC/OS需要用户提供周期性信号源,用于实现时间延时和确认超时。节拍率应在10到100Hz之间,时钟节拍率越高,系统的额外负荷就越重;时钟节拍的实际频率取决于用户应用程序的精度。时钟节拍源可以是专门的硬件定时器,或是来自50/60Hz交流电源的信号。时间管理与时间管理相关的系统服务:OSTimeDLY()OSTimeDLYHMSM()OSTimeDlyResmue()OStimeGet()OSTimeSet()OSTimeDLY()OSTimeDLY():任务延时函数,申请该服务的任务可以延时一段时间;调用OSTimeDLY后,任务进入等待状态;使用方法voidOSTimeDly(INT16Uticks);ticks表示需要延时的时间长度,用时钟节拍的个数来表示。OSTimeDLY()voidOSTimeDly(INT16Uticks){if(ticks>0){OS_ENTER_CRITICAL();if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0){OSRdyGrp&=~OSTCBCur->OSTCBBitY;}OSTCBCur->OSTCBDly=ticks;OS_EXIT_CRITICAL();OSSched();}}OSTimeDLY(1)的问题OSTimeDlyHMSM()OSTimeDlyHMSM():OSTimeDly()的另一个版本,即按时分秒延时函数;使用方法INT8UOSTimeDlyHMSM(

INT8Uhours,//小时

INT8Uminutes,//分钟

INT8Useconds,//秒

INT16Umilli//毫秒

);OSTimeDlyResume()OSTimeDlyResume():让处在延时期的任务提前结束延时,进入就绪状态;使用方法INT8UOSTimeDlyResume(INT8U

prio);prio表示需要提前结束延时的任务的优先级/任务ID。系统时间每隔一个时钟节拍,发生一个时钟中断,将一个32位的计数器OSTime加1;该计数器在用户调用OSStart()初始化多任务和4,294,967,295个节拍执行完一遍的时候从0开始计数。若时钟节拍的频率等于100Hz,该计数器每隔497天就重新开始计数;OSTimeGet():获得该计数器的当前值;INT32UOSTimeGet(void);OSTimeSet():设置该计数器的值。voidOSTimeSet(INT32Uticks);watchdog软件定时器可用于实现“看门狗”在应用的某个地方进行软件定时器的停止计时操作,确保定时器在系统正常运行的情况下不会到期,即不会触发定时器服务例程;如果某个时候系统进入了定时器服务例程,就表示使用停止计时操作的地方没有执行到,系统出现了错误。何时启动系统定时器如果在OSStart之前启动定时器,则系统可能无法正确执行完OSStartHighRdyOSStart函数直接调用OSStartHighRdy去执行最高优先级的任务,OSStart不返回。系统定时器应该在系统的最高优先级任务中启动使用OSRunning变量来控制操作系统的运行在我们的移植版本中,使用了uCOS-II中的保留任务1作为系统任务。负责启动定时器时钟节拍的启动用户必须在多任务系统启动以后再开启时钟节拍器,也就是在调用OSStart()之后;在调用OSStart()之后做的第一件事是初始化定时器中断。voidmain(void){...OSInit();/*初始化uC/OS-II*//*应用程序初始化代码...*//*调用OSTaskCreate()创建至少一个任务*/

允许时钟节拍中断;/*错误!可能crash!*/OSStart();/*开始多任务调度*/}12中断和时间管理任务之间的通信与同步概述多任务系统中任务之间的关系相互独立仅竞争CPU资源竞争除CPU外的其他资源(互斥)同步协调彼此运行的步调通信彼此间传递数据或信息,以协同完成某项工作任务能以以下方式与中断处理程序或其他任务进行同步或通信:单向同步或通信:一个任务与另一个任务或一个ISR同步或通信。双向同步或通信:两个任务相互同步或通信。双向同步不能在任务与ISR之间进行,因为ISR不能等待。TaskxTaskyPOSTPENDISRxTaskyPOSTPENDTaskxTaskyPOSTPENDPOSTPEND任务与任务之间的同步(单向)任务与ISR之间的同步(单向)任务与任务之间的同步(双向)任务间通信与同步任务间通信的管理:事件控制块ECB;同步与互斥临界区(CriticalSections);信号量(Semaphores);任务间通信邮箱(MessageMailboxes);消息队列(MessageQueues)。事件控制块ECBECB数据结构typedefstruct{void*OSEventPtr;/*指向消息或消息队列的指针*/INT8UOSEventTbl[OS_EVENT_TBL_SIZE];//等待任务列表INT16UOSEventCnt;/*计数器(当事件是信号量时)*/INT8UOSEventType;/*事件类型:信号量、邮箱等*/INT8UOSEventGrp;/*等待任务组*/}OS_EVENT;

与TCB类似的结构,使用两个链表,空闲链表与使用链表所有的通信信号都被看成是事件(event),C/OS-II通过事件控制块(ECB)来管理每一个具体事件。事件控制块ECB数据结构2017654310891514131211181617232221201926242531302928273432333938373635424041474645444350484955545352515856576362616059·OSRdyTbl[8]·OSEventGrp·OSEventPtr·OSEventCnt·OSEventTypepreventOS_Event等待任务列表每个正在等待某个事件的任务被加入到该事件的ECB的等待任务列表中,该列表包含两个变量OSEventGrp和OSEventTbl[]。在OSEventGrp中,任务按优先级分组,8个任务为一组,共8组,分别对应OSEventGrp当中的8位。当某组中有任务处于等待该事件的状态时,对应的位就被置位。同时,OSEventTbl[]中的相应位也被置位。最低优先级任务(即空闲任务,不可能处于等待状态)565758596061626348495051525354554041424344454647323334353637383924252627282930311617181920212223891011121314150123456701234567[0][1][2][3][4][5][6][7].OSEventGrpOSEventTbl[OS_LOWEST_PRIO/8+1]XY最高优先级任务正在等待该事件的任务的优先级XXXYYY00任务的优先级.OSEventTbl[]中相应位的位置.OSEventGrp中相应位的位置及.OSEventTbl[]中的数组下标空闲ECB的管理ECB的总数由用户所需要的信号量、邮箱和消息队列的总数决定,由OS_CFG.H中的#defineOS_MAX_EVENTS定义。在调用OSInit()初始化系统时,所有的ECB被链接成一个单向链表——空闲事件控制块链表;每当建立一个信号量、邮箱或消息队列时,就从该链表中取出一个空闲事件控制块,并对它进行初始化。0OS_MAX_EVENTSOSEventFreeListOS_EVENTECB的基本操作OSEventWaitListInit()初始化一个事件控制块。当创建一个信号量、邮箱或消息队列时,相应的创建函数会调用本函数对ECB的内容进行初始化,将OSEventGrp和OSEventTbl[]数组清零;OSEventWaitListInit(OS_EVENT*pevent);prevent:指向需要初始化的事件控制块的指针。OSEventTaskRdy()。使一个任务进入就绪态。当一个事件发生时,需要将其等待任务列表中的最高优先级任务置为就绪态;OSEventTaskRdy(OS_EVENT*pevent,

void*msg,INT8Umsk);msg:指向消息的指针;msk:用于设置TCB的状态。ECB的基本操作(续)OSEventTaskWait()使一个任务进入等待状态。当某个任务要等待一个事件的发生时,需要调用本函数将该任务从就绪任务表中删除,并放到相应事件的等待任务表中;OSEventTaskWait(OS_EVENT*pevent);OSEventTO()由于等待超时而将任务置为就绪态。如果一个任务等待的事件在预先指定的时间内没有发生,需要调用本函数将该任务从等待列表中删除,并把它置为就绪状态;OSEventTO(OS_EVENT*pevent);信号量信号量在多任务系统中的功能实现对共享资源的互斥访问(包括单个共享资源或多个相同的资源);实现任务之间的行为同步;必须在OS_CFG.H中将OS_SEM_EN开关常量置为1,这样μC/OS才能支持信号量。信号量的种类信号量一般分为三种:用于解决互斥问题的互斥信号量。它比较特殊,可能会引起优先级反转问题。用于解决同步问题的二值信号量。用于解决资源计数问题的计数信号量。将信号量进行种类细分,可以根据其用途,在具体实现时做专门处理,提高执行效率和可靠性。用互斥信号量保护的代码区称作“临界区”,临界区代码通常用于对共享资源的访问。互斥信号量的值被初始化成1,表明目前没有任务进入“临界区”,但最多只有一个任务可以进入“临界区”。第一个试图进入“临界区”的任务将成功获得互斥信号量,而随后试图进入用同一信号量保护的临界区的所有其他任务就必须等待。当任务离开“临界区”时,它将释放信号量并允许正在等待该信号量的任务进入“临界区”。互斥信号量Task1Task2共享资源二值信号量二值信号量主要用于任务与任务之间、任务与中断服务程序之间的同步用于同步的二值信号量初始值为0,表示同步事件尚未产生;任务申请信号量以等待该同步事件的发生;另一个任务或ISR到达同步点时,释放信号量(将其值设置为1)表示同步事件已发生,以唤醒等待的任务。二值信号量availableunavailableacquire(value=0)release(value=1)Initialvalue=0二值信号量状态图计数信号量计数信号量用于控制系统中共享资源的多个实例的使用,允许多个任务同时访问同一种资源的多个实例计数信号量被初始化为n(非负整数),n为该种共享资源的数目。Task1Task2共享资源实例nTaskm共享资源实例1…………计数信号量availableunavailableInitialcount>0acquire(count=0)release(count=1)Initialcount=0计数信号量状态图acquire(count=count-1)release(count=count+1)uC/OS中信号量由两部分组成:信号量的计数值(16位无符号整数)和等待该信号量的任务所组成的等待任务表;信号量系统服务OSSemCreate()OSSemPend(),OSSemPost()OSSemAccept(),OSSemQuery()任务、ISR和信号量的关系或任务任务ISROSSemAccept()OSSemPend()OSSemQuery()OSSemPost()OSSemPost()OSSemAccept()OSSemCreate()NN创建一个信号量OSSemCreate()创建一个信号量,并对信号量的初始计数值赋值,该初始值为0到65,535之间的一个数;OS_EVENT*OSSemCreate(INT16Ucnt);cnt:信号量的初始值。执行步骤从空闲事件控制块链表中得到一个ECB;初始化ECB,包括设置信号量的初始值、把等待任务列表清零、设置ECB的事件类型等;返回一个指向该事件控制块的指针。等待一个信号量OSSemPend()等待一个信号量,即操作系统中的P操作,将信号量的值减1;OSSemPend(OS_EVENT*pevent,

INT16Utimeout,INT8U*err);执行步骤如果信号量的计数值大于0,将它减1并返回;如果信号量的值等于0,则调用本函数的任务将被阻塞起来,等待另一个任务把它唤醒;调用OSSched()函数,调度下一个最高优先级的任务运行。发送一个信号量OSSemPost()发送一个信号量,即操作系统中的V操作,将信号量的值加1;OSSemPost(OS_EVENT*pevent);执行步骤检查是否有任务在等待该信号量,如果没有,将信号量的计数值加1并返回;如果有,将优先级最高的任务从等待任务列表中删除,并使它进入就绪状态;调用OSSched(),判断是否需要进行任务切换。无等待地请求一个信号量OSSemAccept()当一个任务请求一个信号量时,如果该信号量暂时无效,则让该任务简单地返回,而不是进入等待状态;INT16UOSSemAccept(OS_EVENT*pevent);执行步骤如果该信号量的计数值大于0,则将它减1,然后将信号量的原有值返回;如果该信号量的值等于0,直接返回该值(0)。查询一个信号量的当前状态OSSemQuery()查询一个信号量的当前状态;INT8UOSSemQuery(OS_EVENT*pevent,

OS_SEM_DATA*pdata);将指向信号量对应事件控制块的指针pevent所指向的ECB的内容拷贝到指向用于记录信号量信息的数据结构OS_SEM_DATA数据结构的指针pdata所指向的缓冲区当中。任务间通信低级通信只能传递状态和整数值等控制信息,传送的信息量小;例如:信号量高级通信能够传送任意数量的数据;例如:共享内存、邮箱、消息队列共享内存在C/OS-II中如何实现共享内存?内存地址空间只有一个,为所有的任务所共享!为了避免竞争状态,需要使用信号量来实现互斥访问。消息邮箱邮箱(MailBox):一个任务或ISR可以通过邮箱向另一个任务发送一个指针型的变量,该指针指向一个包含了特定“消息”(message)的数据结构;必须在OS_CFG.H中将OS_MBOX_EN开关常量置为1,这样μC/OS才能支持邮箱。一个邮箱可能处于两种状态:满的状态:邮箱包含一个非空指针型变量;空的状态:邮箱的内容为空指针NULL;邮箱的系统服务OSMboxCreate()OSMboxPost()OSMboxPend()OSMboxAccept()OSMboxQuery()任务、ISR和消息邮箱的关系邮箱的系统服务(1)OSMboxCreate():创建一个邮箱在创建邮箱时,须分配一个ECB,并使用其中的字段OSEventPtr指针来存放消息的地址;OS_EVENT*OSMboxCreate(void*msg);msg:指针的初始值,一般情形下为NULL。OSMboxPend():等待一个邮箱中的消息若邮箱为满,将其内容(某消息的地址)返回;若邮箱为空,当前任务将被阻塞,直到邮箱中有了消息或等待超时;OSMboxPend(OS_EVENT*pevent,

INT16Utimeout,INT8U*err);邮箱的系统服务(2)OSMboxPost():发送一个消息到邮箱中如果有任务在等待该消息,将其中的最高优先级任务从等待列表中删除,变为就绪状态;OSMboxPost(OS_EVENT*pevent,void*msg);OSMboxAccept():无等待地请求邮箱消息若邮箱为满,返回它的当前内容;若邮箱为空,返回空指针;OSMboxAccept(OS_EVENT*pevent);OSMboxQuery():查询一个邮箱的状态OSMboxQuery(OS_EVENT*pevent,

OS_MBOX_DATA*pdata);样例程序(1)OSMboxCreate()函数OS_EVENT*CommMbox;voidmain(void)

{...

OSInit();

...

CommMbox=

OSMboxCreate((void*)0);

...

OSStart();}OSMboxPend()函数voidCommTask(void*pdata){INT8Uerr;

void*msg;pdata=pdata;

for(;;){

...msg=OSMboxPend(CommMbox,

10,&err);

if(err==OS_NO_ERR){/*收到消息时的代码*/}else{/*未收到消息时的代码*/}}样例程序(2)OSMboxPost()函数OS_EVENT*CommMbox;INT8UCommRxBuf[100];voidCommTaskRx(void*pdata){INT8Uerr;

...for(;;){...

err=OSMboxPost(CommMbox,(void*)&CommRxbuf[0]);...}}消息队列消息队列(MessageQueue):消息队列可以使一个任务或ISR向另一个任务发送多个以指针方式定义的变量;为了使μC/OS能够支持消息队列,必须在OS_CFG.H中将OS_Q_EN开关常量置为1,并且通过常量OS_MAX_QS来决定系统支持的最多消息队列数。一个消息队列可以容纳多个不同的消息,因此可把它看作是由多个邮箱组成的数组,只是它们共用一个等待任务列表:消息队列的系统服务OSQCreate()OSQPend()、OSQAccept()OSQPost()、OSQPostFront()OSQFlush()OSQQuery()消息队列的体系结构回忆一下ECB数据结构ECB数据结构typedefstruct{void*OSEventPtr;/*指向消息或消息队列的指针*/INT8UOSEventTbl[OS_EVENT_TBL_SIZE];//等待任务列表INT16UOSEventCnt;/*计数器(当事件是信号量时)*/INT8UOSEventType;/*事件类型:信号量、邮箱等*/INT8UOSEventGrp;/*等待任务组*/}OS_EVENT;在实现消息队列时,哪些字段可以用?队列控制块队列控制块数据结构typedefstructos_q{structos_q*OSQPtr;//空闲队列控制块指针

void**OSQStart;//指向消息队列的起始地址void**OSQEnd;//指向消息队列的结束地址void**OSQIn;//指向消息队列中下一个插入消息的位置void**OSQOut;//指向消息队列中下一个取出消息的位置INT16UOSQSize;//消息队列中总的单元数INT16UOSQEntries;//消息队列中当前的消息数量}OS_EVENT;空闲队列控制块的管理每一个消息队列都要用到一个队列控制块。在C/OS中,队列控制块的总数由OS_CFG.H中的常量OS_MAX_QS定义。在系统初始化时,所有的队列控制块被链接成一个单向链表——空闲队列控制块链表OSQFreeList;OSQPtrOSQStartOSQEndOSQEntriesOSQInOSQSizeOSQOutOSQPtrOSQStartOSQEndOSQEntriesOSQInOSQSizeOSQOutOSQPtrOSQStartOSQEndOSQEntriesOSQInOSQSizeOSQOutOSQFreeListOS_MAX_QSOS_Q01324C/OS-II概述任务管理中断和时间管理任务之间的通信与同步5存储管理概述C/OS中是实模式存储管理不划分内核空间和用户空间,整个系统只有一个地址空间,即物理内存空间,应用程序和内核程序都能直接对所有的内存单元进行访问;系统中的“任务”,实际上都是线程–––只有运行上下文和栈是独享的,其他资源都是共享的。内存布局代码段(text)、数据段(data)、bss段、堆空间、栈空间;内存管理,管的是谁?堆!malloc/free?在ANSIC中可以用malloc()和free()两个函数动态地分配内存和释放内存。在嵌入式实时操作系统中,容易产生碎片。由于内存管理算法的原因,malloc()和free()函数执行时间是不确定的。µC/OS-II对malloc()和free()函数进行了改进,使得它们可以分配和释放固定大小的内存块。这样一来,malloc()和free()函数的执行时间也是固定的了

3Kb堆初始状态A(1Kb)B(1Kb)C(1Kb)3个申请1KbB(1Kb)1Kb释放A,CC/OS中的存储管理C/OS采用的是固定分区的存储管理方法µC/OS把连续的大块内存按分区来管理,每个分区包含有整数个大小相同的块;在一个系统中可以有多个内存分区,这样,用户的应用程序就可以从不同的内存分区中得到不同大小的内存块。但是,特定的内存块在释放时必须重新放回它以前所属于的内存分区;采用这样的内存管理算法,上面的内存碎片问题就得到了解决。内存分区示意图分区1分区2分区3分区4内存块内存控制块为了便于管理,在µC/OS中使用内存控制块MCB(MemoryControlBlock)来跟踪每一个内存分区,系统中的每个内存分区都有它自己的MCB。typedefstruct{void*OSMemAddr; /*分区起始地址*/void*OSMemFreeList;//下一个空闲内存块INT32UOSMemBlkSize;/*内存块的大小*/INT32UOSMemNBlks; /*内存块数量*/INT32UOSMemNFree; /*空闲内存块数量*/}OS_MEM;内存管理初始化如果要在µC/OS-II中使用内存管理,需要在OS_CFG.H文件中将开关量OS_MEM_EN设置为1。这样µC/OS-II在系统初始化OSInit()时就会调用OSMemInit(),对内存管理器进行初始化,建立空闲的内存控制块链表。OSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSMemNFreeOSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSMemNFreeOSMemAddrOSMemFreeListOSMemBlkSizeOSMemNBlksOSMemNFreeOSMemFreeList0OS_MAX_MEM_PA

温馨提示

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

评论

0/150

提交评论