《第3章 uCOS_II中的任务ytu》由会员分享,可在线阅读,更多相关《第3章 uCOS_II中的任务ytu(76页珍藏版)》请在金锄头文库上搜索。
1、第3章 COS_II中的任务通信工程教研室通信工程教研室嵌入式嵌入式RTOSC/OS-II简介简介 C/OS由 Jean J. Labrosse 先生(加拿大) 1992编写的RTOS,1999年改写后命名为 C/OS-II 。 2000年被美航空管理局认证。C/OS-II中的代码 90%用C语言编写,有少量的相关于硬件的代码用汇编编写,易移植到各类体系结构的8位、16位、32位处理器。官方网站:www.uCOS-II.comCOS-体系结构体系结构typedef unsigned char BOOLEAN;typedef unsigned char INT8U; /* 8位无符号整数*/ty
2、pedef signed char INT8S; /* 8位有符号整数*/typedef unsigned short INT16U; /*16位无符号整数*/typedef signed short INT16S; /*16位有符号整数*/typedef unsigned long INT32U; /* 32位无符号整数*/typedef signed long INT32S; /* 32位有符号整数*/typedef float FP32; /* 单精度浮点数*/typedef double FP64; /* 双精度浮点数*/typedef unsigned short OS_STK; /
3、* Each stack entry is 16-bit wide */ os_cpu.h(C/OS-II中的数据类型中的数据类型)#define BYTE INT8S /字节 #define UBYTE INT8U #define WORD INT16S /半字#define UWORD INT16U#define LONG INT32S /字#define ULONG INT32U /*Define data types for backward compatibility . */* . to uC/OS V1.xx. Not actually needed for . */* . uC
4、/OS-II.*/#define OS_STK_GROWTH 1 /堆栈增长方式 . .os_cpu.h(C/OS-II中的数据类型中的数据类型)堆栈增长方式堆栈增长方式堆栈是一个按特定顺序进行存取的存储区,操作顺序为“后进先出” 。堆栈寻址是隐含的,它使用一个专门的寄存器(堆栈指针)指向一块存储区域(堆栈),指针所指向的存储单元即是堆栈的栈顶。存储器堆栈可分为两种: n向上生长:向高地址方向生长,称为递增堆栈n向下生长:向低地址方向生长,称为递减堆栈栈底栈顶栈区SP堆栈存储区栈顶栈底栈区SP向下增长向上增长0x123456780x12345678堆栈压栈堆栈压栈堆栈增长方式堆栈增长方式堆栈指
5、针堆栈指针栈顶SP栈顶SP栈底空堆栈栈底满堆栈0x123456780x12345678栈顶SP0x12345678栈顶SP压栈压栈堆栈指针指向最后压入的堆栈的有效数据项,称为满堆栈;堆栈指针指向下一个待压入数据的空位置,称为空堆栈。堆栈方式堆栈方式四种类型的堆栈方式:满递增:堆栈向上增长,堆栈指针指向内含有效数据项的最高地址。指令如LDMFA、STMFA等; 空递增:堆栈向上增长,堆栈指针指向堆栈上的第一个空位置。指令如LDMEA、STMEA等; 满递减:堆栈向下增长,堆栈指针指向内含有效数据项的最低地址。指令如LDMFD、STMFD等;空递减:堆栈向下增长,堆栈指针向堆栈下的第一个空位置。指
6、令如LDMED、STMED等。 本章主要内容本章主要内容1、任务的基本概念2、任务堆栈3、任务控制块及任务控制块链表4、任务就绪表及任务调度5、任务的创建6、任务的挂起和恢复7、其他任务管理函数8、uC/OS-II的初始化和任务的启动本章主要内容(补充)本章主要内容(补充)1、任务的特性2、任务的划分目标3、任务的划分方法4、任务的可调度性分析5、任务的执行分类和优先级安排6、任务设计中的问题7、系统设计编码实现过程8、中断服务程序的设计3.1任务的基本概念任务的基本概念3.1.1任务及其内存结构任务及其内存结构问题解题思路:复杂问题 “分而治之” 。针对目标系统拆分后的 “小”且“易”的问题
7、处理方法,其编码和数据结构的程序实体-任务。C/OS-II的两种任务:n系统任务:为应用程序或系统本身提供某种服务;n用户任务:为实现某些具体应用编写的。C/OS-II的任务代码上为一函数,其组成:n任务控制块任务控制块 - uC/OS-II进行任务管理用的一个数据结构,记录任务的各个属性。n任务代码任务代码 - 描述任务算法的程序编码n任务堆栈任务堆栈 - 保存任务的工作现场环境。3.1.1任务的基本概念任务的基本概念C/OS-II的任务代码上为一函数,其组成:n任务控制块任务控制块- uC/OS-II进行任务管理用的一个数据结构,记录任务的各个属性。n任务代码任务代码 - 描述任务算法的程
8、序编码。n任务堆栈任务堆栈 - 保存任务的工作现场环境。3.1.1任务的基本概念任务的基本概念(进程:具有自己的私有运行空间;)(线程:没有自己的私有运行空间;)C/OS-没有给任务定义私有运行空间,因此C/OS-的所有任务都属于线程;系统可以根据任务控制块了解代码的相关信息,也能够找到该任务相关代码;C/OS-利用任务控制块链表对任务进行管理。C/OS-目前支持64个任务。3.1.1任务的基本概念任务的基本概念3.1.2任务的状态任务的状态Sleep(休眠)- 仅有编码未激活;未被分配任务控制块。Ready(就绪)- 已激活并“万事俱备,只欠调度”,就绪表中已经登记,Running(运行)-
9、 已经获得 CPU 的使用权。Wait(等待)- 等待某事件发生。ISR_Sta(被中断)- Running状态的任务被中断后进入的状态。3.1.2任务的状态任务的状态正在运行的任务,需要等待一段时间或需要等待一个事件发生再运行时,该任务就会把CPU的使用权让给别的任务而使任务进入等待状态。 任务在没有被配备任务控制块或被剥夺了任务控制块时的状态叫做任务的休眠状态 系统为任务配备了任务控制块且在任务就绪表中进行了就绪登记,这时任务的状态叫做就绪状态。 处于就绪状态的任务如果经调度器判断获得了CPU的使用权,则任务就进入运行状态 一个正在运行的任务一旦响应中断申请就会中止运行而去执行中断服务程序
10、,这时任务的状态叫做中断服务状态 3.1.3任务的状态任务的状态用户任务代码的一般结构用户任务代码的一般结构void MyTask(void *pdata) / “void”可传递任何类型数可传递任何类型数据据 / 任务的初始化任务的初始化 for ( ; ; ) /超循环结构超循环结构构成任务体构成任务体 可被中断的用户代码片断;可被中断的用户代码片断; OS_ENTER_CRITICAL(); /宏,进入临界区(关中断)宏,进入临界区(关中断) 不可被中断的用户代码片断;不可被中断的用户代码片断; OS_EXIT_CRITICAL(); /宏,宏,退出临界区(开中断)退出临界区(开中断)
11、可被中断的用户代码片断;可被中断的用户代码片断; 3.1.3任务的状态任务的状态用户应用程序的一般结构用户应用程序的一般结构n “用户任务” 代码形式上很像 C函数,但不是函数!n “任务”不能被主函数main( )或其他函数调用,只能被主函数或已激活任务创建;n “任务” 和main( )地位平等;n “任务”的运行由操作系统调度管理;n main( )是整个程序的入口,不调用任务,但负责任务的创建并将创建的任务交给系统,何时运行任务则与main( )无关。3.1.3任务的状态任务的状态用户应用程序的一般结构用户应用程序的一般结构voidMyTask1(void*pdata)/定义用户任务定
12、义用户任务1for(;)voidMyTask2(void*pdata)for(;)voidMyTask2(void*pdata)for(;)3.1.3任务的状态任务的状态用户应用程序的一般结构用户应用程序的一般结构voidmain()OSInit();/系统初始化系统初始化OSTaskCreate(MyTask1,);/创建任务创建任务1OSTaskCreate(MyTask2,);OSTaskCreate(MyTask3,);OSStart();/启动任务启动任务3.1.3任务的状态任务的状态用户应用程序的一般结构用户应用程序的一般结构OSInit()函数原型:函数原型:voidOSInit
13、(void)OSStar()函数原型:函数原型:voidOSStart(void)OSTaskCreate()函数原型:函数原型:INT8UOSTaskCreate(void(*task)(void*pd),/指向任务的指针指向任务的指针void*pdata,/传递给任务的参数传递给任务的参数OS_STK*ptos,/任务堆栈栈顶的指针任务堆栈栈顶的指针INT8Uprio/任务的优先级别任务的优先级别)3.1.3任务的状态任务的状态 OSTaskCreateOSTaskCreate( )( )函数使用举例:函数使用举例:/ 定义任务定义任务 task_Avoid task_A(void* pd
14、ata) ; /任务初始化部分 while (1) ; /任务功能代码 / 在系统在系统 “创建创建” 任务任务 task_Avoid main(void) OSInit(); /系统初始化部分 OSTaskCreate( task_A, void * 0, &MystackTop, 8 ); OSStart();3.1.4系统任务系统任务空闲任务空闲任务 OSTaskIdel()nC C/OS-II/OS-II规定用户程序中必须使用规定用户程序中必须使用OSTaskIdelOSTaskIdel。n该任务不能用软件删除。该任务不能用软件删除。n该任务是该任务是C C/OS-II/OS-II初始
15、化时自动创建,其任务优初始化时自动创建,其任务优先级固定为最低级,用户也可修改该任务的业务。先级固定为最低级,用户也可修改该任务的业务。n目的目的 - - 使使CPUCPU在没有用户任务可执行时也有事在没有用户任务可执行时也有事可做。可做。n原型:原型:void void OSTaskIdel(voidOSTaskIdel(void* * pdatapdata) )3.1.4系统任务系统任务空闲任务空闲任务 OSTaskIdelOSTaskIdel( )( )VoidOSTaskIdel()#ifOS_CRITICAL_MATHOD=3OS_CPU_SRcpu_sr;#endifpdata=p
16、data;/为防止编译错误为防止编译错误for(;)OS_ENTER_CRITICAL();/进入中断进入中断OSdleCtr+;/任务运行次数计数器加任务运行次数计数器加1OS_EXIT_CRITICAL();/退出中断退出中断3.1.4系统任务系统任务统计任务统计任务OSTaskStat()n功能:每秒钟计算一次功能:每秒钟计算一次CPU单位时间内被使用的时间,即单位时间内被使用的时间,即完成用户任务完成用户任务CPU使用率的统计,结果以百分比的形式使用率的统计,结果以百分比的形式存放在变量存放在变量OSCPUsage中。中。n该任务用户可选择使用。该任务用户可选择使用。OS_CFG.H文
17、件中的常数文件中的常数OS_TASK_STAT_EN设置为设置为1,使能该函数。,使能该函数。n用户在用户在OS_CFG.H中使能该任务后,系统自动创建该任务,中使能该任务后,系统自动创建该任务,但在用户使用统计数据前必须调用系统函数但在用户使用统计数据前必须调用系统函数OSStatInit()先进行初始化。先进行初始化。n该任务固定拥有次末任务优先级。该任务固定拥有次末任务优先级。n原型:原型:voidOSTaskStat(void*pdata)3.1.5任务的优先权和优先级任务的优先权和优先级C/OS-II采用采用优先级抢占式优先级抢占式规则,选择任务运行。规则,选择任务运行。C/OS-I
18、I的每个任务都必须有的每个任务都必须有唯一唯一的优先级。的优先级。C/OS-II最多可以管理最多可以管理64个优先级别分配给个优先级别分配给64个任务,个任务,从从063。C/OS-II中用一个中用一个8b的整型数来表示优先级别,的整型数来表示优先级别,数字数字越小,优先级越高越小,优先级越高,prio=0的任务优先级最高。的任务优先级最高。C/OS-II中使用任务的优先级(中使用任务的优先级(prio)作为)作为任务句柄任务句柄。用户通过修改用户通过修改OS_CFG.H中的宏定义常数中的宏定义常数OS_LOWEST_PRIO的值,约定本用户系统的最大优的值,约定本用户系统的最大优先级数。先级
19、数。系统自动将系统自动将OS_LOWEST_PRIO的值付给空闲任务,将的值付给空闲任务,将OS_LOWEST_PRIO-1的值付给统计任务。的值付给统计任务。每个任务具有唯一的优先级,因此优先级别也是任务在每个任务具有唯一的优先级,因此优先级别也是任务在系统中的标识。系统中的标识。3.2任务堆栈任务堆栈堆栈堆栈 - 后进先出后进先出LIFO访问原则组织的连续访问原则组织的连续 存储器。存储器。任务堆栈在任务堆栈在 uC/OS-II 中的应用:中的应用:任务堆栈是任务的三大组成部分之一。任务堆栈是任务的三大组成部分之一。保存保存 CPU 寄存器现场(寄存器现场(R0R12、LR、SPSR 等)
20、。等)。本本 Task 的私有数据。的私有数据。3.2.1任务堆栈的创建任务堆栈的创建在创建任务的同时,任务堆栈即被创建。在创建任务的同时,任务堆栈即被创建。在在OS_CPU.H中定义堆栈数据类型中定义堆栈数据类型OS_STKntypedefunsignedintOS_STK#define MyTaskStkSize 64OS_STK MyTaskStk MyTaskStkSize /在在 OS_CPU.H中定义中定义 OS_STK / typedef INT32U OS_STKINT8U OSTaskCreate(void (*task) (void *pd), /指向任务的指针指向任务的指
21、针void * pdata, /传递给任务的参数传递给任务的参数MyTaskStk MyTaskStkSize 1 /任务堆栈任务堆栈栈顶栈顶的指针的指针INT8U prio /任务的优先级别任务的优先级别 )3.2.1任务堆栈的创建任务堆栈的创建任务堆栈的使用注意事项:存在两种堆栈形式任务堆栈的使用注意事项:存在两种堆栈形式n递增堆栈递增堆栈 - 进栈操进栈操作向大地址方向发展。作向大地址方向发展。n递减堆栈递减堆栈 - 进栈操进栈操作向小地址方向发展。作向小地址方向发展。OSTaskCreate( &MyTaskStkStkSize - 1, )OSTaskCreate( &MyTaskS
22、tk 0 , )备注:利用备注:利用条件编译条件编译技术和技术和 OS_CPU.H 中的宏定义常数中的宏定义常数OS_STK_GROWTH 编写易移植用户系统;编写易移植用户系统; “1” - 递减堆栈递减堆栈 for ARM CPU。3.2.2任务堆栈的初始化任务堆栈的初始化初始化:指向任务的指针、任务堆栈指针、程初始化:指向任务的指针、任务堆栈指针、程序状态字等事先存放在任务堆栈中;序状态字等事先存放在任务堆栈中;堆栈初始化函数:堆栈初始化函数:OS_STKOSTaskStkInit()()该函数由该函数由C/OS-II提供的任务创建函数提供的任务创建函数OSTaskCreate()调用,
23、用户一般不接触。调用,用户一般不接触。OS_STK OSTaskStkInit(void (*task) (void *pd), void * pdata, OS_STK *ptos, INT16U opt )3.3任务控制块及其链表任务控制块及其链表任务控制块(任务控制块(TCB)-任务在系统中的身份任务在系统中的身份证证TCB-uC/OS-II中用于记录任务信息(任中用于记录任务信息(任务务堆栈指针堆栈指针、任务当前状态任务当前状态、任务优先级别任务优先级别等)等)的数据结构。的数据结构。没有任务控制块的任务不能被系统承认和管理;没有任务控制块的任务不能被系统承认和管理;uC/OS-II将
24、系统中的所有将系统中的所有TCB构成两个链表构成两个链表(OSTCBList、OSTCBFreeList)进行任务管)进行任务管理理n空任务控制块链表空任务控制块链表-未被分配的未被分配的TCB链链OSTCBFreeList。n任务控制块链表任务控制块链表-已分配的已分配的TCB链链OSTCBList3.3.1任务控制块的结构任务控制块的结构任务控制块结构的主要成员:任务控制块结构的主要成员:typedefstructos_tcbstructos_tcb*OSTCBNext;/指向下一个指向下一个TCB的指针的指针structos_tcb*OSTCBPrev;/指向前一个指向前一个TCB的指针
25、的指针OS_STK*OSTCBStkPtr;/指向任务堆栈栈顶的指针指向任务堆栈栈顶的指针INT16UOSTCBDly;/任务等待时限任务等待时限(节拍数节拍数)INT8UOSTCBStat;/任务的当前状态标志任务的当前状态标志INT8UOSTCBPrio;/任务的优先级别任务的优先级别OS_TCB;3.3.1任务控制块的结构任务控制块的结构 OSTCBStat存放任务的当前状态标志存放任务的当前状态标志值说 明OS_STAT_RDY表示任务处于就绪状态OS_STAT_SEM表示任务处于等待信号状态OS_STAT_MBOX表示任务处于等待消息邮箱状态OS_STAT_Q表示任务处于消等待息队列
26、状态OS_STAT_SUSPEND表示任务处于被挂起状态OS_STAT_MUTEX表示任务处于等待互斥型信号量状态3.3.2任务控制链表任务控制链表uC/OS-II将系统中的所有将系统中的所有TCB构成两个链表构成两个链表(OSTCBList、OSTCBFreeList)进行任务管)进行任务管理理n空任务控制块链表空任务控制块链表-未被分配的未被分配的TCB链链OSTCBFreeList。n任务控制块链表任务控制块链表-已分配的已分配的TCB链链OSTCBList3.3.2任务控制链表任务控制链表空任务控制块链表空任务控制块链表 - - 未被分配(空白)的未被分配(空白)的TCBTCB 链表链
27、表 OSTCBFreeListOSTCBFreeList。nOSTCBFreeList由由OSInit()在在RAM中由系统自建;中由系统自建;nOSTCB1OS_MAX_TASKS:用户最大任务数;用户最大任务数;(OS_CFG.H中定义中定义)nOS_N_SYS_TASKS:系统任务数;:系统任务数;(uCOS_II.H中定义中定义)3.3.2任务控制链表任务控制链表空任务控制块链表空任务控制块链表 - - 未被分配(空白)的未被分配(空白)的TCB TCB 链表链表 OSTCBFreeListOSTCBFreeListn当进行系统初始化时,初始化函数会按用户提供的任务数为系统创建具有相应
28、数量的任务控制块并把它们链接为一个链表。n由于这些任务控制块还没有对应的任务,故这个链表叫做空任务块链表。即相当于是一些空白的身份证。n应用程序调用OSTaskCreate( )创建一个任务时,该函数会调用系统函数OSTCBInit( )来为任务控制块进行初始化。首先为被创建任务从空任务控制块链表获取一个任务控制块,然后用任务的属性对任务控制块各个成员进行赋值,最后再把该任务控制块链入到任务控制块链表的头部。任务控制块链表任务控制块链表OSTCBList3.3.2任务控制链表任务控制链表任务控制块链表空任务控制块链表3.3.2任务控制链表任务控制链表uCuC/OS-II/OS-II中提供了系统
29、函数中提供了系统函数 OSTaskDelOSTaskDel( )( ),用于删除一个任务用于删除一个任务 - - 实质就是将该任务的实质就是将该任务的TCBTCB从从“任务控制块列表任务控制块列表” ” 移到了移到了“空任务控空任务控制块列表制块列表”;“任务控制块任务控制块” ” 就相当于是一个任务的身份就相当于是一个任务的身份证,没有任务控制块的任务是不能被系统承认证,没有任务控制块的任务是不能被系统承认和管理。和管理。 3.3.2任务控制链表任务控制链表任务控制块链表其他相关系统管理变量任务控制块链表其他相关系统管理变量nOSTCBPrioTbl:OS_TCB*数据类型的数组,以数据类型
30、的数组,以Prio为下标存放已使能的为下标存放已使能的TCB指针。用于加速指针。用于加速TCB的的访问。访问。nOSTCBCur:全局系统变量,指向当前正在运行的任务的:全局系统变量,指向当前正在运行的任务的TCB。nOSTCBFreeList、OSTCBListnOSTCBTbl-OSInit()建立的任务控制块数组建立的任务控制块数组nOSTCBPrioTbl-任务控制块优先级数组任务控制块优先级数组3.3.3任务控制块的初始化任务控制块的初始化任务控制块链表其他相关系统管理变量任务控制块链表其他相关系统管理变量INT8UOS_TCBInit(INT8Uprio,/优先级优先级,存于存于O
31、STCBPrio中中OS_STK*ptos,/栈顶指针栈顶指针,存于存于OSTCBStkPrt中中OS_STK*pbos,/栈底指针栈底指针,存于存于OSTCBStkBottom中中INT16Uid,/任务标识符任务标识符,存于存于OSTCBId中中INT32Ustk_size,/堆栈长度堆栈长度,存于存于OSTCBStkSize中中void*pext,/控制块扩展指针控制块扩展指针,存于存于OSTCBExtPtr中中INT16Uopt/控制块选择项控制块选择项,存于存于OSTCBOPt中中)n为被创建任务从空任务控制块中获取一个任务控制块;为被创建任务从空任务控制块中获取一个任务控制块;n用
32、任务的属性对任务控制块各成员进行赋值;用任务的属性对任务控制块各成员进行赋值;n把该任务控制块链接到任务控制链表中把该任务控制块链接到任务控制链表中3.4任务就绪表及任务调度任务就绪表及任务调度多任务多任务OS-的基本工作方式的基本工作方式简单地说,就是能用一个处理器并发(注意不是同时!)地运行多个程序的计算机管理系统。并发:由同一个处理器轮换地运行多个程序。或者说是由多个程序轮班地占用处理器这个资源。且在占用这个资源期间,并不一定能够把程序运行完毕。处理器如何进行程序的切换?程序的切换程序的切换处理器是个傻瓜,PCPC让它干啥,它就干啥。PC是个指路器,它指向哪儿,处理器就去哪儿 哪个程序占
33、有了PC,哪个程序就占有了处理器。如何操作如何操作PCPC切换切换:PC PC 目标地址目标地址系统是通过把待运行程序的地址赋予程系统是通过把待运行程序的地址赋予程序计数器序计数器 PC PC 来实现程序的切换的。来实现程序的切换的。指令指令:不同计算机类型的指令不同:不同计算机类型的指令不同n数据传送指令数据传送指令n子程序返回指令(子程序返回指令(由堆栈弹出由堆栈弹出)n中断、中断返回指令(中断、中断返回指令(由堆栈弹出由堆栈弹出)任务运行时与处理器之间的关系任务运行时与处理器之间的关系任务代码任务堆栈内存内存内存内存处理器PCSP处理器通过两个指针寄存器(PC和SP)来与任务代码和任务堆
34、栈建立联系并运行它寄存器组程序运行环境运行环境包括了两部分:处理器中的运行环境和内存中的运行环境多多任务时的任务时的问题问题任务代码任务堆栈内存处理器PCSP任务代码任务堆栈内存任务代码任务堆栈内存?当有多个任务时,处理器中的运行环境应该怎么办?寄存器组程序运行环境多任务时任务与处理器之间关系的多任务时任务与处理器之间关系的处理处理程序 虚拟处理器PCSP 虚拟处理器PCSP 虚拟处理器PCSP 虚拟处理器PCSP调度器程序处理器PCSP在内存中为每个任务创建一个虚拟的处理器(处理器部分的运行环境由操作系统的调度器按某种规则来进行这两个复制工作复制当需要运行某个任务时就把该任务的虚拟处理器复制
35、到实际处理器中复制当需要中止当前任务时,则把任务对应的虚拟处理器复制到内存复制再把另一个需要运行的任务的虚拟处理器复制到实际处理器中寄存器组寄存器组也就是说,任务的切换是任务运行环境的切换虚拟处理器虚拟处理器虚拟处理器应该存储的主要信息:n程序的断点地址(PC)n任务堆栈指针(SP)n程序状态字寄存器(PSW)n通用寄存器内容n函数调用信息(已存在于堆栈)这些内容通常保存在任务堆栈中,这些内容也常叫做任务的上下文。程序切换的关键是把程序的私有堆栈指针赋予处理器的堆栈指针SP;实质上系统是通过SP的切换来实现程序的切换的。虚拟处理器虚拟处理器要建立一个概念:具有控制块的程序才是一个可以被系统所运
36、行的任务。程序代码、私有堆栈、任务控制块 是任务的三要件。任务控制块提供了运行环境的存储位置。调度调度多任务操作系统的核心工作就是任务调度。多任务操作系统的核心工作就是任务调度。所谓所谓调度调度,就是通过一个算法在多个任务中确,就是通过一个算法在多个任务中确定该运行的任务,做这项工作的函数就叫做定该运行的任务,做这项工作的函数就叫做调调度器度器。C/OS_II进行任务调度的思想是进行任务调度的思想是“近似地近似地每时每刻总是让优先级最高的就绪任务处于运每时每刻总是让优先级最高的就绪任务处于运行状态行状态”。为了保证这一点,它在系统或用。为了保证这一点,它在系统或用户任务调用系统函数及执行中断服
37、务程序结束户任务调用系统函数及执行中断服务程序结束时总是调用调度器,来确定应该运行的任务并时总是调用调度器,来确定应该运行的任务并运行它。运行它。C/OS_II进行任务调度的依据就是进行任务调度的依据就是任务就绪任务就绪表表3.4.1 3.4.1 任务就绪表的结构任务就绪表的结构为能够使系统清楚地知道,系统中哪些为能够使系统清楚地知道,系统中哪些任务已经就绪,哪些还没有就绪,任务已经就绪,哪些还没有就绪,CC/OS_II /OS_II 在在 RAMRAM中设立了一个记录表,中设立了一个记录表,系统中的每个任务都在这个表中占据一系统中的每个任务都在这个表中占据一 Bit Bit 的位置,并用这个
38、位置的状态(的位置,并用这个位置的状态(1 1或或者者0 0)来表示任务是否处于就绪状态)来表示任务是否处于就绪状态,这,这个表就叫做任务就绪状态表,简称叫个表就叫做任务就绪状态表,简称叫任任务就绪表务就绪表 - 一个一个 INT8U INT8U 的数组的数组 OSRdyTblOSRdyTbl 充当,最多充当,最多8 8个元素,可以标示个元素,可以标示6464个个任务。任务。3.4.1 3.4.1 任务就绪表的结构任务就绪表的结构就绪表:就绪表:INT8类型的二维数组类型的二维数组OSRdyTb1;以任务优先级别以任务优先级别进行标识;进行标识;为为1表示对应任务表示对应任务处于就绪状态;处于
39、就绪状态;8个任务可看成一个任务可看成一个任务组;个任务组;3.4.1 3.4.1 任务就绪表的结构任务就绪表的结构为加快访问任务就绪表的速度,系统定义了一个变量OSRdyGrp来表明就绪表每行中是否存在就绪任务3.4.1 3.4.1 任务就绪表的结构任务就绪表的结构任务就绪表的示意图3.4.1 3.4.1 任务就绪表的结构任务就绪表的结构任务优先级数据结构分析任务优先级数据结构分析nuC/OS-II最多管理最多管理64个任务,个任务,Prio值域:值域:063,对应的二进制数,对应的二进制数000,000111,111(6bit),),OSRdyGrp(任务组就绪变量)(任务组就绪变量)8b
40、it,任务就绪数组元素任务就绪数组元素OSRdyTbl也是也是8bit。nprio.D5:3-对应对应OSRdyTbl的下标(任务的下标(任务组号组号y),也对应),也对应OSRdyGrp的位号。的位号。nprio.D2:0-对应对应OSRdyTbl元素的位号(任元素的位号(任务组号务组号x)n备注:这就是备注:这就是prio的值和任务就绪表的映射关系。的值和任务就绪表的映射关系。3.4.1 3.4.1 任务就绪表的结构任务就绪表的结构举例举例:prio=29的任务在任务就续表中的表的任务在任务就续表中的表示。示。29的二进制表示为:的二进制表示为:000111013(y)5(x)3.4.1
41、3.4.1 任务就绪表的结构任务就绪表的结构举例举例:prio=29的任务在任务就续表中的的任务在任务就续表中的表示。表示。29的二进制表示为:的二进制表示为:000111013(y)5(x)3.4.2 3.4.2 任务就绪表的操作任务就绪表的操作任务就绪表的操作有:登记、注销和最高任务就绪表的操作有:登记、注销和最高优先级查找。优先级查找。依照依照prio“置置/清清”任务就绪表的操作,在任务就绪表的操作,在uC/OS-II中预定义了一个中预定义了一个OSMapTbl数组,数组,以加快运算速度:以加快运算速度:OSMapTbl0 = 0000,0001BOSMapTbl1 = 0000,00
42、10BOSMapTbl2 = 0000,0100BOSMapTbl3 = 0000,1000BOSMapTbl4 = 0001,0000BOSMapTbl5 = 0010,0000BOSMapTbl6 = 0100,0000BOSMapTbl7 = 1000,0000B3.4.2 3.4.2 任务就绪表的操作任务就绪表的操作举例举例:prio=29的任务在任务就续表中的的任务在任务就续表中的表示。表示。29的二进制表示为:的二进制表示为:000111013(y)5(x)3.4.2 3.4.2 任务就绪表的操作任务就绪表的操作在程序中,可以用下面的代码把优先级别为在程序中,可以用下面的代码把优先
43、级别为 prioprio 的任务置为就绪状态:的任务置为就绪状态: OSRdyGrp|=OSMapTblprio3;OSRdyTblprio3|=OSMapTblprio&0x07;使用如下代码可使一个优先级别为使用如下代码可使一个优先级别为prioprio的任务脱离的任务脱离就绪状态:就绪状态:if(OSRdyTblprio3&=OSMapTblprio&0x07)=0)OSRdyGrp&=OSMapTblprio3;3.4.2 3.4.2 任务就绪表的操作任务就绪表的操作最高优先级就绪任务的查找最高优先级就绪任务的查找n从就绪表从就绪表(OSRdyGrp、OSRdyTbl)的当前的当前状态
44、(位图)到状态(位图)到最高优先级别最高优先级别prio的(任务)的(任务)映射操作。映射操作。n在在uC/OS-II中预定义了一个中预定义了一个OSUnMapTbl数组数组3.4.2 3.4.2 任务就绪表的操作任务就绪表的操作INT8UconstOSUnMapTbl256=0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x00to0x0F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x10to0x1F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x20to0x2F*/4,0,1,0,2,0,1,0,3,0,1,0
45、,2,0,1,0,/*0x30to0x3F*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x40to0x4F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x50to0x5F*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x60to0x6F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x70to0x7F*/7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x80to0x8F*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0x90to0x9F*/5
46、,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xA0to0xAF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xB0to0xBF*/6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xC0to0xCF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xD0to0xDF*/5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,/*0xE0to0xEF*/4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0/*0xF0to0xFF*/;3.4.2 3.4.2 任务就绪表的操作任务就绪表
47、的操作在就绪表中查找最高优先级别任务的过程在就绪表中查找最高优先级别任务的过程说明:在说明:在 “ “按图索骥按图索骥” ” 算法中,对于所有的任务其算法中,对于所有的任务其 “ “索骥索骥” ” 时间都是一致的。时间都是一致的。S1S1、以系统变量、以系统变量 OSRdyGrpOSRdyGrp 为下标,查为下标,查 OSUnMapTblOSUnMapTbl 表,可得表,可得 y y 。S2S2、以、以 OSRdyTblOSRdyTbl 的第的第 y y 元素为下标,查元素为下标,查 OSUnMapTblOSUnMapTbl 表,可得表,可得 x x 。4096Prio=8*y+x3.4.2
48、3.4.2 任务就绪表的操作任务就绪表的操作用下代码可从任务就绪表中获取优先级别最高的就绪用下代码可从任务就绪表中获取优先级别最高的就绪任务(任务(prio):):y=OSUnMapTalOSRdyGrp; / prio 的D5、D4、D3位x=OSUnMapTalOSRdyTbly; / prio 的D2、D1、D0位prio=(y3)+x; / 优先级别或y=OSUnMapTblOSRdyGrp;prio=(INT8U)(y3)+OSUnMapTblOSRdyTbly);3.4.3 3.4.3 任务的调度任务的调度任务控制块链表其他相关系统管理变量任务控制块链表其他相关系统管理变量nOST
49、CBPrioTbl:OS_TCB*数据类型的数组,以数据类型的数组,以Prio为下标存放的为下标存放的TCB指针。用于加速指针。用于加速TCB的访问。的访问。3.4.3 3.4.3 任务的调度任务的调度任务控制块链表其他相关系统管理变量任务控制块链表其他相关系统管理变量nOSTCBCur:全局系统变量,指向当前正在运行的任务的:全局系统变量,指向当前正在运行的任务的TCB。3.4.3 3.4.3 任务的调度任务的调度任务切换任务切换-CPU从运行某一任务转换到运行从运行某一任务转换到运行另一任务的过程。另一任务的过程。任务调度任务调度-按照某规则进行任务切换的工作过按照某规则进行任务切换的工作
50、过程。程。uC/OS-II中的任务切换由中的任务切换由“任务调度器任务调度器”完完成。成。任务调度器的两项主要工作任务调度器的两项主要工作:n从任务就绪表中查找优先级最高的就绪任务从任务就绪表中查找优先级最高的就绪任务n实现任务切换实现任务切换uC/OS-II中有两个中有两个“任务调度器任务调度器”:n任务级的调度器任务级的调度器OS_Sched()n中断级的调度器中断级的调度器OSIntCtxSw()3.4.3 3.4.3 任务的调度任务的调度1.获得待运行任务获得待运行任务TCB的指针的指针获得了最高优先权就绪任务的获得了最高优先权就绪任务的“优先级优先级”后(存后(存放在全局系统变量放在
51、全局系统变量OSPrioHighRdy),用下指,用下指令即可获取该任务的令即可获取该任务的TCB:OSTCBHighRdy=OSTCBPrioTblOSPrioHighRdy备注:备注:OSTCBPrioTbl是以优先权为下标的是以优先权为下标的“任任务指针数组务指针数组”3.4.3 3.4.3 任务的调度任务的调度1.获得待运行任务获得待运行任务TCB的指针的指针任务控制块(任务控制块(TCB)的结构)的结构任务控制块结构的主要成员任务控制块结构的主要成员typedefstructos_tcbstructos_tcb*OSTCBNext;/指向下一个指向下一个TCB的指针的指针struct
52、os_tcb*OSTCBPrev;/指向前一个指向前一个TCB的指针的指针OS_STK*OSTCBStkPtr;/指向任务堆栈栈顶的指针指向任务堆栈栈顶的指针INT16UOSTCBDly;/任务等待时间任务等待时间INT8UOSTCBStat;/任务的当前状态标志任务的当前状态标志INT8UOSTCBPrio; /任务的优先级别任务的优先级别OS_TCB;3.4.3 3.4.3 任务的调度任务的调度-任务调度OS_Sched()voidOS_Sched(void)#ifOS_CRITICAL_METHOD=3/*AllocatestorageforCPUstatusregister*/OS_C
53、PU_SRcpu_sr;#endifINT8Uy;OS_ENTER_CRITICAL();/*所有代码都属于临界代码,在寻找进入就绪态的优所有代码都属于临界代码,在寻找进入就绪态的优先级最高的任务过程中,为防止中断服务程序把一个或几个任务的就绪位置位,中断先级最高的任务过程中,为防止中断服务程序把一个或几个任务的就绪位置位,中断要关掉要关掉*/if(OSIntNesting=0)&(OSLockNesting=0)/*Sched.onlyifallISRsdone¬locked*/y=OSUnMapTblOSRdyGrp;/*GetpointertoHPTreadytorun*/OSPr
54、ioHighRdy=(INT8U)(y3)+OSUnMapTblOSRdyTbly);if(OSPrioHighRdy!=OSPrioCur)/*NoCtxSwifcurrenttaskishighestrdy*/OSTCBHighRdy=OSTCBPrioTblOSPrioHighRdy;/获取获取TCB控制块控制块OSCtxSwCtr+;/*Incrementcontextswitchcounter*/OS_TASK_SW();/*宏调用,完成实际上的任务切换宏调用,完成实际上的任务切换*/OS_EXIT_CRITICAL();3.4.3 3.4.3 任务的调度任务的调度-任务调度OS_S
55、ched()说明:说明:OSIntNesting=0&OSLockNesting=0只有不是在中断服务子程序中且调度是允许时,才只有不是在中断服务子程序中且调度是允许时,才可以进行可以进行OS_Sched调度。调度。y=OSUnMapTblOSRdyGrp;OSPrioHighRdy=(INT8U)(y已就绪最高优先级号已就绪最高优先级号(整数型整数型)OSPrioCur-当前任务优先级号当前任务优先级号(整数型整数型)3.4.3 3.4.3 任务的调度任务的调度-任务调度OS_Sched()说明:说明:OSTCBPrioTbl-数组元素为指向数组元素为指向OS_TCB类类型指针,数组的下标号
56、为型指针,数组的下标号为TCB相应任务的优先级相应任务的优先级号号OSTCBHighRdy-指向已就绪的最高优先级任务指向已就绪的最高优先级任务的的TCB指针指针OSCtxSwCtr任务切换次数计数器。目的是让用户任务切换次数计数器。目的是让用户知道每秒做了多少次任务切换。用户需每秒将知道每秒做了多少次任务切换。用户需每秒将OSCtxSwCtr的值存入另一个变量,然后将的值存入另一个变量,然后将OSCtxSwCtr清清0。OS_TASK_SW()宏调用,完成实际上的任务切换。宏调用,完成实际上的任务切换。 3.4.3 3.4.3 任务的调度任务的调度2.任务切换宏任务切换宏OS_TASK_SW()完成当前任务到待运行任务的切换完成当前任务到待运行任务的切换几个概念:几个概念:n断点断点-当前任务被终止运行的位置。当前任务被终止运行的位置。n断点数据断点数据-断点处断点处CPU的的PC、SP、PSW以及通用以及通用寄存器寄存器(R0R12)的当前数据。的当前数据。程序程序“无缝无缝”接续运行要求断点和断点数据(现接续运行要求断点和断点数据(现场)的完全保护和恢复。场)的完全保护和恢复。