电子技术单片机ucosII实时操作系统内核 教程.doc

上传人:文库蛋蛋多 文档编号:4149953 上传时间:2023-04-07 格式:DOC 页数:352 大小:4.35MB
返回 下载 相关 举报
电子技术单片机ucosII实时操作系统内核 教程.doc_第1页
第1页 / 共352页
电子技术单片机ucosII实时操作系统内核 教程.doc_第2页
第2页 / 共352页
电子技术单片机ucosII实时操作系统内核 教程.doc_第3页
第3页 / 共352页
电子技术单片机ucosII实时操作系统内核 教程.doc_第4页
第4页 / 共352页
电子技术单片机ucosII实时操作系统内核 教程.doc_第5页
第5页 / 共352页
点击查看更多>>
资源描述

《电子技术单片机ucosII实时操作系统内核 教程.doc》由会员分享,可在线阅读,更多相关《电子技术单片机ucosII实时操作系统内核 教程.doc(352页珍藏版)》请在三一办公上搜索。

1、目录第一章:范例71.00 安装 C/OS-II71.01 INCLUDES.H81.02不依赖于编译的数据类型8OS_EXIT_CRITICAL()111.05基于PC的服务111.05.01字符显示121.06 应用 C/OS-II 的范例131.07例1141.07.01 main()141.07.02 TaskStart()171.07.03 TaskN()181.08.01 main()20TaskClk()函数程序清单L1.18显示当前日期和时间,每秒更新一次。251.09.01 main()26第二章 实时系统概念33前后台系统(Foreground/Background Sys

2、tem)33代码的临界段34资源34共享资源34多任务34任务35任务切换(Context Switch or Task Switch)36内核(Kernel)36调度(Scheduler)36不可剥夺型内核(Non-Preemptive Kernel)37可剥夺型内核38可重入性(Reentrancy)38时间片轮番调度法40任务优先级402.14静态优先级40动态优先级41优先级反转41任务优先级分配43互斥条件44关中断和开中断45测试并置位45禁止,然后允许任务切换46信号量(Semaphores)47死锁(或抱死)(Deadlock (or Deadly Embrace))51同步5

3、2事件标志(Event Flags)53任务间的通讯(Intertask Communication)54消息邮箱(Message Mail boxes)55消息队列(Message Queue)56中断56中断延迟57中断响应57中断恢复时间(Interrupt Recovery)58中断延迟、响应和恢复59中断处理时间59非屏蔽中断(NMI)60时钟节拍(Clock Tick)62对存储器的需求64使用实时内核的优缺点64实时系统小结65第三章 内核结构67临界段(Critical Sections)67任务67任务状态69任务控制块(Task Control Blocks, OS_TCB

4、s)70就绪表(Ready List)73任务调度(Task Scheduling)76给调度器上锁和开锁(Locking and UnLocking the Scheduler)77空闲任务(Idle Task)79统计任务79C/OS中的中断处理83时钟节拍87C/OS-初始化91C/OS-的启动91获取当前C/OS-的版本号94OSEvent?()函数95第四章 任务管理97建立任务,OSTaskCreate()98建立任务,OSTaskCreateExt()102任务堆栈105堆栈检验,OSTaskStkChk()107删除任务,OSTaskDel()110请求删除任务,OSTaskD

5、elReq()113改变任务的优先级,OSTaskChangePrio()116挂起任务,OSTaskSuspend()119恢复任务,OSTaskResume()120获得有关任务的信息,OSTaskQuery()122第五章 时间管理124任务延时函数,OSTimeDly()124按时分秒延时函数 OSTimeDlyHMSM()126让处在延时期的任务结束延时,OSTimeDlyResume()128系统时间,OSTimeGet()和OSTimeSet()129第六章 任务之间的通讯与同步132事件控制块ECB133初始化一个事件控制块,OSEventWaitListInit()137使一

6、个任务进入就绪态,OSEventTaskRdy()138使一个任务进入等待某事件发生状态, OSEventTaskWait()140由于等待超时而将任务置为就绪态, OSEventTO()141信号量141建立一个信号量, OSSemCreate()142等待一个信号量, OSSemPend()143发送一个信号量, OSSemPost()145无等待地请求一个信号量, OSSemAccept()146查询一个信号量的当前状态, OSSemQuery()147邮箱148建立一个邮箱,OSMboxCreate()149等待一个邮箱中的消息,OSMboxPend()149发送一个消息到邮箱中,OS

7、MboxPost()151无等待地从邮箱中得到一个消息, OSMboxAccept()152查询一个邮箱的状态, OSMboxQuery()153用邮箱作二值信号量154用邮箱实现延时,而不使用OSTimeDly()155消息队列156建立一个消息队列,OSQCreate()160等待一个消息队列中的消息,OSQPend()162向消息队列发送一个消息(FIFO),OSQPost()164向消息队列发送一个消息(后进先出LIFO),OSQPostFront()165无等待地从一个消息队列中取得消息, OSQAccept()167清空一个消息队列, OSQFlush()168查询一个消息队列的状

8、态,OSQQuery()168使用消息队列读取模拟量的值170使用一个消息队列作为计数信号量171第七章 内存管理173内存控制块174建立一个内存分区,OSMemCreate()175分配一个内存块,OSMemGet()177释放一个内存块,OSMemPut()179查询一个内存分区的状态,OSMemQuery()180Using Memory Partitions180等待一个内存块182第八章 移植C/OS-1858.00开发工具1878.01目录和文件1878.02INCLUDES.H1888.03OS_CPU.H1888.03.01与编译器相关的数据类型1898.03.02OS_EN

9、TER_CRITICAL()和OS_EXIT_CRITICAL()1908.03.03OS_STK_GROWTH1918.03.04OS_TASK_SW()1918.04OS_CPU_A.ASM1928.04.01OSStartHighRdy()1928.04.02OSCtxSw()1928.04.03OSIntCtxSw()1938.04.04OSTickISR()1958.05OS_CPU_C.C1978.05.01OSTaskStkInt()1978.05.02OSTaskCreateHook()1998.05.03OSTaskDelHook()2008.05.04OSTaskSwHoo

10、k()2008.05.05OSTaskStatHook()2008.05.06OSTimeTickHook()200第九章 C/OS-II在80x86上的移植2069.00开发工具2089.01目录和文件2089.02INCLUDES.H文件2089.03OS_CPU.H文件2099.03.01 数据类型2129.03.02 代码临界区2129.03.03堆栈增长方向2139.03.04OS_TASK_SW()2139.03.05时钟节拍的发生频率2139.04OS_CPU_A.ASM2139.04.01OSStartHighRdy()2139.04.02OSCtxSw()2159.04.03

11、OSIntCtxSw()2179.04.04OSTickISR()2209.05OS_CPU_C.C2249.05.01OSTaskStkInit()2269.05.02OSTaskCreateHook()2289.05.03OSTaskDelHook()2289.05.04OSTaskSwHook()2289.05.05OSTaskStatHook()2289.05.06OSTimeTickHook()2289.06内存占用2289.07运行时间229第十章 从 C/OS 升级到 C/OS-II241目录和文件241INCLUDES.H242OS_CPU.H242与编译有关的数据类型s242

12、OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()244OS_STK_GROWTH244OS_TASK_SW()245OS_FAR245OS_CPU_A.ASM245OSStartHighRdy()246OSCtxSw()247OSIntCtxSw()247OSTickISR()248OS_CPU_C.C248OSTaskStkInit()248OSTaskCreateHook()251OSTaskDelHook()252OSTaskSwHook()252OSTaskStatHook()253OSTimeTickHook()253总结254第11章参考手册256OSI

13、nit( )258OSIntEnter( )259OSIntExit( )261OSMboxAccept( )263OSMboxCreate( )265OSMboxPend( )267OSMboxPost( )269OSMboxQuery( )271OSMemCreate( )273OSMemGet( )275OSMemPut( )277OSMemQuery( )279OSQAccept( )281OSQCreate( )283OSQFlush( )285OSQPend( )286OSQPost( )288OSQPostFront( )290OSQQuery( )292OSSchedLock(

14、 )294OSSchedUnlock( )295OSSemAccept( )297OSSemCreate( )299OSSemPend( )301OSSemPost( )303OSSemQuery( )305OSStart ( )307OSStatInit ( )308OSTaskChangPrio( )309OSTaskCreate( )311OSTaskCreateExt( )315OSTaskDel( )321OSTaskDelReq( )323OSTaskQuery( )325OSTaskResume( )327OSTaskStkChk( )329OSTaskSuspend( )331

15、OSTimeDly( )333OSTimeDlyHMSM( )335OSTimeDlyResume( )337OSTimeGet( )339OSTimeSet( )340OSTimeTick( )341OSVersion( )343OS_ENTER_CRITICAL( )344OS_EXIT_CRITICAL( )344第12章 配置手册345第一章:范例在这一章里将提供三个范例来说明如何使用 C/OS-II。笔者之所以在本书一开始就写这一章是为了让读者尽快开始使用 C/OS-II。在开始讲述这些例子之前,笔者想先说明一些在这本书里的约定。这些例子曾经用Borland C/C+ 编译器(V3.

16、1)编译过,用选择项产生Intel/AMD80186处理器(大模式下编译)的代码。这些代码实际上是在Intel Pentium II PC (300MHz)上运行和测试过,Intel Pentium II PC可以看成是特别快的80186。笔者选择PC做为目标系统是由于以下几个原因:首先也是最为重要的,以PC做为目标系统比起以其他嵌入式环境,如评估板,仿真器等,更容易进行代码的测试,不用不断地烧写EPROM,不断地向EPROM仿真器中下载程序等等。用户只需要简单地编译、链接和执行。其次,使用Borland C/C+产生的80186的目标代码(实模式,在大模式下编译)与所有Intel、AMD、C

17、yrix公司的80x86 CPU兼容。1.00 安装 C/OS-II本书附带一张软盘包括了所有我们讨论的源代码。是假定读者在80x86,Pentium,或者Pentium-II处理器上运行DOS或Windows95。至少需要5Mb硬盘空间来安装uC/OS-II。请按照以下步骤安装:1.进入到DOS(或在Windows 95下打开DOS窗口)并且指定C:为默认驱动器。2.将磁盘插入到A:驱动器。3.键入 A:INSTALL 【drive】注意drive是读者想要将C/OSII安装的目标磁盘的盘符。INSTALL.BAT 是一个DOS的批处理文件,位于磁盘的根目录下。它会自动在读者指定的目标驱动器

18、中建立SOFTWARE目录并且将uCOS-II.EXE文件从A:驱动器复制到SOFTWARE并且运行。C/OSII将在SOFTWARE目录下添加所有的目录和文件。完成之后INSTALL.BAT将删除uCOS-II.EXE并且将目录改为SOFTWAREuCOS-IIEX1_x86L,第一个例子就存放在这里。在安装之前请一定阅读一下READ.ME文件。当INSTALL.BAT已经完成时,用户的目标目录下应该有一下子目录:l SOFTWARE这是根目录,是所有软件相关的文件都放在这个目录下。l SOFTWAREBLOCKS子程序模块目录。笔者将例子中C/OS-II用到的与PC相关的函数模块编译以后放

19、在这个目录下。l SOFTWAREHPLISTC这个目录中存放的是与范例HPLIST相关的文件(请看附录D,HPLISTC和TO)。HPLIST.C存放在SOFTWAREHPLISTCSOURCE目录下。DOS下的可执行文件(HPLIST.EXE)存放在SOFTWARETOEXE中。l SOFTWARETO这个目录中存放的是和范例TO相关的文件(请看附录D,HPLISTC和TO)。源文件TO.C存放在SOFTWARETOSOURCE中,DOS下的可执行文件(TO.EXE)存放在SOFTWARETOEXE中。注意TO需要一个TO.TBL文件,它必须放在根目录下。用户可以在SOFTWARETOEX

20、E目录下找到TO.TBL文件。如果要运行TO.EXE,必须将TO.TBL复制到根目录下。l SOFTWAREuCOS-II与C/OS-II 相关的文件都放在这个目录下。l SOFTWAREuCOS-IIEX1_x86L这个目录里包括例1的源代码(参见 1.07, 例1),可以在DOS(或Windows 95下的DOS窗口)下运行。l SOFTWAREuCOS-IIEX2_x86L这个目录里包括例2的源代码(参见 1.08, 例2),可以在DOS(或Windows 95下的DOS窗口)下运行。l SOFTWAREuCOS-IIEX3_x86L这个目录里包括例3的源代码(参见 1.09, 例3),

21、可以在DOS(或Windows 95下的DOS窗口)下运行。l SOFTWAREuCOS-IIIx86L这个目录下包括依赖于处理器类型的代码。此时是为在80x86处理器上运行uC/OS-II而必须的一些代码,实模式,在大模式下编译。l SOFTWAREuCOS-IISOURCE这个目录里包括与处理器类型无关的源代码。这些代码完全可移植到其它架构的处理器上。1.01 INCLUDES.H用户将注意到本书中所有的 *.C 文件都包括了以下定义:#include includes.hINCLUDE.H可以使用户不必在工程项目中每个*.C文件中都考虑需要什么样的头文件。换句话说,INCLUDE.H是主

22、头文件。这样做唯一的缺点是INCLUDES.H中许多头文件在一些*.C文件的编译中是不需要的。这意味着逐个编译这些文件要花费额外的时间。这虽有些不便,但代码的可移植性却增加了。本书中所有的例子使用一个共同的头文件INCLUDES.H,3个副本分别存放在SOFTWAREuCOS-IIEX1_x86L,SOFTWAREuCOS-IIEX2_x86L,以及SOFTWAREuCOS-IIEX3_x86L 中。当然可以重新编辑INCLUDES.H以添加用户自己的头文件。1.02不依赖于编译的数据类型因为不同的微处理器有不同的字长,C/OS-II的移植文件包括很多类型定义以确保可移植性(参见SOFTWAR

23、EuCOS-IIIx86LOS_CPU.H,它是针对80x86的实模式,在大模式下编译)。COS-II不使用C语言中的short,int,long等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性。笔者代之以移植性强的整数数据类型,这样,既直观又可移植,如表L1.1所示。为了方便起见,还定义了浮点数数据类型,虽然C/OS-II中没有使用浮点数。程序清单 L1.1可移植型数据类型。Typedef unsigned char BOOLEAN;Typedef unsigned char INT8U;Typedef signed char INT8S;Typedef unsigned int

24、 INT16U;Typedef signed int INT16S;Typedef unsigned long INT32U;Typedef signed long INT32S;Typedef float FP32;Typedef double FP64;#define BYTE INT8S#define UBYTE INT8U#define WORD INT16S#define UWORD INT16U#define LONG INT32S#define ULONG INT32U以INT16U数据类型为例,它代表16位无符号整数数据类型。C/OS-II和用户的应用代码可以定义这种类型的数据

25、,范围从0到65,535。如果将CO/S-II移植到32位处理器中,那就意味着INT16U不再不是一个无符号整型数据,而是一个无符号短整型数据。然而将无论C/OS-II用到哪里,都会当作INT16U处理。 表1.1是以Borland C/C+编译器为例,为80x86提供的定义语句。为了和C/OS兼容,还定义了BYTE,WORD,LONG以及相应的无符号变量。这使得用户可以不作任何修改就能将C/OS的代码移植到C/OS-II中。之所以这样做是因为笔者觉得这种新的数据类型定义有更多的灵活性,也更加易读易懂。对一些人来说,WORD意味着32位数,而此处却意味着16位数。这些新的数据类型应该能够消除此

26、类含混不请1.03全局变量以下是如何定义全局变量。众所周知,全局变量应该是得到内存分配且可以被其他模块通过C语言中extern关键字调用的变量。因此,必须在 .C 和 .H 文件中定义。这种重复的定义很容易导致错误。以下讨论的方法只需用在头文件中定义一次。虽然有点不易懂,但用户一旦掌握,使用起来却很灵活。表1.2中的定义出现在定义所有全局变量的.H头文件中。程序清单 L 1.2定义全局宏。#ifdef xxx_GLOBALS#define xxx_EXT#else#define xxx_EXT extern#endif.H 文件中每个全局变量都加上了xxx_EXT的前缀。xxx代表模块的名字。

27、该模块的.C文件中有以下定义:#define xxx_GLOBALS#include includes.h当编译器处理.C文件时,它强制xxx_EXT(在相应.H文件中可以找到)为空,(因为xxx_GLOBALS已经定义)。所以编译器给每个全局变量分配内存空间,而当编译器处理其他.C文件时,xxx_GLOBAL没有定义,xxx_EXT被定义为extern,这样用户就可以调用外部全局变量。为了说明这个概念,可以参见uC/OS_II.H,其中包括以下定义:#ifdef OS_GLOBALS#define OS_EXT#else#define OS_EXT extern#endifOS_EXT IN

28、T32U OSIdleCtr;OS_EXT INT32U OSIdleCtrRun;OS_EXT INT32U OSIdleCtrMax;同时,uCOS_II.H有中以下定义:#define OS_GLOBALS#include “includes.h”当编译器处理uCOS_II.C时,它使得头文件变成如下所示,因为OS_EXT被设置为空。INT32U OSIdleCtr;INT32U OSIdleCtrRun;INT32U OSIdleCtrMax;这样编译器就会将这些全局变量分配在内存中。当编译器处理其他.C文件时,头文件变成了如下的样子,因为OS_GLOBAL没有定义,所以OS_EXT被

29、定义为extern。extern INT32U OSIdleCtr;extern INT32U OSIdleCtrRun;extern INT32U OSIdleCtrMax;在这种情况下,不产生内存分配,而任何 .C文件都可以使用这些变量。这样的就只需在 .H 文件中定义一次就可以了。1.04OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()用户会看到,调用OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()两个宏,贯穿本书的所有源代码。OS_ENTER_CRITICAL() 关中断;而OS_EXIT_CRITICAL()开中断。关中断和

30、开中断是为了保护临界段代码。这些代码很显然与处理器有关。关于宏的定义可以在OS_CPU.H中找到。9.03.02节详细讨论定义这些宏的两种方法。程序清单 L 1.3进入正确部分的宏。#define OS_CRITICAL_METHOD 2#if OS_CRITICAL_METHOD = 1#define OS_ENTER_CRITICAL() asm CLI#define OS_EXIT_CRITICAL() asm STI#endif#if OS_CRITICAL_METHOD = 2#define OS_ENTER_CRITICAL() asm PUSHF; CLI#define OS_E

31、XIT_CRITICAL() asm POPF#endif用户的应用代码可以使用这两个宏来开中断和关中断。很明显,关中断会影响中断延迟,所以要特别小心。用户还可以用信号量来保护林阶段代码。1.05基于PC的服务PC.C 文件和 PC.H 文件(在SOFTWAREBLOCKSPCSOURCE目录下)是笔者在范例中使用到的一些基于PC的服务程序。与 C/OS-II 以前的版本(即 C/OS)不同,笔者希望集中这些函数以避免在各个例子中都重复定义,也更容易适应不同的编译器。PC.C包括字符显示,时间度量和其他各种服务。所有的函数都以PC_为前缀。1.05.01字符显示为了性能更好,显示函数直接向显示

32、内存区中写数据。在VGA显示器中,显示内存从绝对地址0x000B8000开始(或用段、偏移量表示则为B800:0000)。在单色显示器中,用户可以把#define constant DISP_BASE从0xB800改为0xB000。PC.C中的显示函数用x和y坐标来直接向显示内存中写ASCII字符。PC的显示可以达到25行80列一共2,000个字符。每个字符需要两个字节来显示。第一个字节是用户想要显示的字符,第二个字节用来确定前景色和背景色。前景色用低四位来表示,背景色用第4位到6位来表示。最高位表示这个字符是否闪烁,(1)表示闪烁,(0)表示不闪烁。 用PC.H中 #defien const

33、ants定义前景和背景色,PC.C包括以下四个函数:PC_DispClrScr()Clear the screenPC_DispClrLine()Clear a single row (or line)PC_DispChar()Display a single ASCII character anywhere on the screenPC_DispStr()Display an ASCII string anywhere on the screen1.05.02花费时间的测量时间测量函数主要用于测试一个函数的运行花了多少时间。测量时间是用PC的82C54定时器2。 被测的程序代码是放在函数P

34、C_ElapsedStart()和PC_ElapsedStop()之间来测量的。在用这两个函数之前,应该调用PC_ElapsedInit()来初始化,它主要是计算运行这两个函数本身所附加的的时间。这样,PC_ElapsedStop()函数中返回的数值就是准确的测量结果了。注意,这两个函数都不具备可重入性,所以,必须小心,不要有多个任务同时调用这两个函数。表1.4说明了如何测量PC_DisplayChar()的执行时间。注意,时间是以uS为单位的。程序清单 L 1.4测量代码执行时间。INT16U time;PC_ElapsedInit();.PC_ElapsedStart();PC_DispC

35、har(40, 24, A, DISP_FGND_WHITE);time = PC_ElapsedStop();1.05.03其他函数C/OS-II的应用程序和其他DOS应用程序是一样的,换句话说,用户可以像在DOS下编译其他单线程的程序一样编译和链接用户程序。所生成的.EXE程序可以在DOS下装载和运行,当然应用程序应该从main()函数开始。因为C/OS-II 是多任务,而且为每个任务开辟一个堆栈,所以单线程的DOS环境应该保存,在退出C/OS-II 程序时返回到DOS。调用PC_DOSSaveReturn()可以保存当前DOS环境,而调用PC_DOSReturn()可以返回到DOS。 P

36、C.C中使用ANSI C的setjmp(),longjmp()函数来分别保存和恢复DOS环境。Borland C/C+编译库提供这些函数,多数其它的编译程序也应有这类函数。应该注意到无论是应用程序的错误还是只调用exit(0)而没有调用PC_DOSReturn()函数都会使DOS环境被破坏,从而导致DOS或WINDOWS95下的DOS窗口崩溃。调用PC_GetDateTime()函数可得到PC中的日期和时间,并且以SACII字符串形式返回。格式是MM-DD-YY HH:MM:SS,用户需要19个字符来存放这些数据。该函数使用了Borland C/C+的gettime()和getdate()函数

37、,其它DOS环境下的C编译应该也有类似函数。PC_GetKey() 函数检查是否有按键被按下。如果有按键被按下,函数返回其值。这个函数使用了Borland C/C+的kbhit()和getch()函数,其它DOS环境下的C编译应该也有类似函数。函数PC_SetTickRate()允许用户为 C /OS-II定义频率,以改变钟节拍的速率。在DOS下,每秒产生18.20648次时钟节拍,或每隔54.925ms一次。这是因为82C54定时器芯片没有初始化,而使用默认值65,535的结果。如果初始化为58,659,那么时钟节拍的速率就会精确地为20.000Hz。笔者决定将时钟节拍设得更快一些,用的是2

38、00Hz(实际是上是 199.9966Hz)。注意OS_CPU_A.ASM中的OSTickISR()函数将会每11个时钟节拍调用一次DOS中的时钟节拍处理,这是为了保证在DOS下时钟的准确性。如果用户希望将时钟节拍的速度设置为20HZ,就必须这样做。在返回DOS以前,要调用PC_SetTickRate(),并设置18为目标频率,PC_SetTickRate()就会知道用户要设置为18.2Hz,并且会正确设置82C54。PC.C中最后两个函数是得到和设置中断向量,笔者是用Borland C/C+中的库函数来完成的,但是PC_VectGet()和PC_VectSet()很容易改写,以适用于其它编译

39、器。1.06 应用 C/OS-II 的范例本章中的例子都用Borland C/C+编译器编译通过,是在Windows95 的DOS窗口下编译的。可执行代码可以在每个范例的OBJ子目录下找到。实际上这些代码是在Borland IDE (Integrated Development Environment)下编译的,编译时的选项如表1.1所示:表 T1.1IDE中编译选项。Code generationModel: LargeOptions: Treat enums as intsAssume SS Equals DS: Default for memory modelAdvanced code

40、generationFloating point: EmulationInstruction set: 80186Options: Generate underbarsDebug info in OBJsFast floating pointOptimizationsOptimizationsGlobal register allocationInvariant code motionInduction variablesLoop optimizationSuppress redundant loadsCopy propagationDead code eliminationJump opti

41、mizationIn-line intrinsic functionsRegister variablesAutomaticCommon subexpressionsOptimize globallyOptimize forSpeed笔者的Borland C/C+编译器安装在C:CPP目录下,如果用户的编译器是在不同的目录下,可以在Options/Directories的提示下改变IDE的路径。C/OS-II是一个可裁剪的操作系统,这意味着用户可以去掉不需要的服务。代码的削减可以通过设置OS_CFG.H中的#defines OS_?_EN 为0来实现。用户不需要的服务代码就不生成。本章的范例就

42、用这种功能,所以每个例子都定义了不同的OS_?_EN。1.07例1第一个范例可以在SOFTWAREuCOS_IIEX1_x86L目录下找到,它有13个任务(包括 C/OS-II 的空闲任务)。C/OS-II 增加了两个内部任务:空闲任务和一个计算CPU利用率的任务。例1建立了11个其它任务。TaskStart()任务是在函数main()中建立的;它的功能是建立其它任务并且在屏幕上显示如下统计信息:l 每秒钟任务切换次数;l CPU利用百分率;l 寄存器切换次数;l 目前日期和时间;l C/OS-II的版本号; TaskStart()还检查是否按下ESC键,以决定是否返回到DOS。其余10个任务

43、基于相同的代码Task();每个任务在屏幕上随机的位置显示一个0到9的数字。1.07.01 main()例1基本上和最初C/OS中的第一个例子做一样的事,但是笔者整理了其中的代码,并且在屏幕上加了彩色显示。同时笔者使用原来的数据类型(UBYTE, UWORD等)来说明C/OS-II向下兼容。main()程序从清整个屏幕开始,为的是保证屏幕上不留有以前的DOS下的显示L1.5(1)。注意,笔者定义了白色的字符和黑色的背景色。既然要请屏幕,所以可以只定义背景色而不定义前景色,但是这样在退回DOS之后,用户就什么也看不见了。这也是为什么总要定义一个可见的前景色。C/OS-II要用户在使用任何服务之前先调用OSInit() L1.5(2)。它会建立两个任务:空闲任务和统计任务,前者在没有其它任务处于就绪态时运行;后者计算CPU的利用率。程序清单 L 1.5main().void main (void) PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); (1) OSInit(); (2) PC_DOSSaveReturn(); (3) PC_VectSet(uCOS, OSCtxSw); (4) RandomSem = OSSemCreate(1); (5) OSTaskCreate(Ta

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 办公文档 > 其他范文


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号