文档库 最新最全的文档下载
当前位置:文档库 › uCOS-II学习原理

uCOS-II学习原理

ucos-II中的任务有五种状态:等待状态、睡眠状态、就绪状态、运行状态、中断服务状态。
uCOS-II用任务的优先级作为任务的标识。?是不是一个任务有唯一的优先级


uCOS-II的任务代码结构是一个可以带有临界段的无限循环。


空闲任务:
空闲任务:系统经常会在某个时间内无用户任务可以运行而处于所谓的空闲状态
空闲任务只做计数工作。
uCOS-II规定:一个用户程序必须使用这个空闲任务,而且这个空闲任务不能用软件删除。
OSTaskldle()
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
for(;;)
{
OS_ENTER_CRITICAL(); //关闭中断
OSdleCtr++; //计数
OS_EXIT_CRITICAL(); //开放中断
}
}


统计任务OSTaskStat:
统计任务:每秒计算一次CPU在单位时间内被使用的时间,并把计算结果一百分比的形式存放在变量OSCPUSage中,以便应用程序通过访问它来了解CPU的利用率。


任务的优先级别:
uCOS-II把任务分成64个优先级别每个优先级别都用数字表示,数字越大表示优先级别越低,常用OS_LOWEST_PRIO表示最低的优先级别,所以OS-LOWEST_PRIO一旦被确定,就意味着系统可提供的优先级别为0、1、2、……、OS_LOWEST_PRIO,共有OS_LOWEST_PRIO个任务。固定的是系统总是把OS_LOWEST_PRIO自动赋值给空闲任务,如果还使用了统计任务的话,系统则会把OS_LOWEST_PRIO-1自动赋值给统计任务,因此用户可以使用的优先级别分别是:0、1、……、OS_LOWEST_PRIO-2.

任务的堆栈:
保存CPU寄存器中的内容以及存储任务私有数据的需要,每个任务都应该配有自己的堆栈,任务堆栈是任务的重要组成部分。
定义任务的栈区:定义一个OS_STK类型的数组,并在创建一个任务的时候吧这个数组的地址赋值给该任务就OK了。
注意:在创建任务时,要传递任务的堆栈指针和任务的优先级别。使用OSTaskCreate()创建任务时,一定要注意所使用的处理 器堆栈的增长方式是向上的还是向下的。
应用程序在启动任务的时候必须把系统CPU各寄存器所需要的初始数据(任务指针、任务堆栈指针、程序状态字、任务优先级等)事先存放在任务堆栈指针中。uCOS-II在创建任务函数OSTaskCreate()时候,通过调用堆栈初始化函数OSTaskStklint()来完成任务堆栈的初始化。
OS_STK *OSTaskStklint(void (*task)(void *pd),void *pdato,OS_STK *ptos,INT16U opt);
其实,任务堆栈指针的初始化就是对该任务的虚拟处理器的初始化。



任务控制块:
定义:用来记录任务的堆栈指针、任务的当前状态、任务的优先级别等与任务管理有关的属性的表。
任务控制块的作用:保

存该任务的虚拟处理器的堆栈指针寄存器SP。相当于是一个任务的身份证,没有它,任务是不可能被系 统承认和管理的。
任务控制块(TCB):为每个任务创建一个保存与该任务有关的相关信息的数据结构。
任务快控制结构的主要成员:
typedef struct os_tcb
{
OS_STK *OSTCBStkPtr; //指向任务堆栈栈顶的指针
……

struct os_tcb *OSTCBNext;//指向后一个任务控制块的指针
struct os_tcb *OSTCBPrev;//指向前一个任务控制块的指针
……

INT16U OSTCBDly; //任务等待的时限
INT8U OSTCBStat; //任务当前状态标识
INT8U OSTCBPrio; //任务的优先级别
……
}OS_TCB;

当系统进行初始化的时候,初始化函数会按照用户提供的任务书创建具有相应数量的任务控制块,并把它们连接成为一个链表,由于控制块没有对应的任务,所以这个链表是空任务控制块的链表(一些空白的身份证)。当程序调用OSTaskCreate()创建一个任务的时候,这个函数会调用函数OSTCBlint()来为任务控制块进行初始化,该函数首先为被创建任务从空的任务控制块链表获取一个 任务控制块,然后用任务的属性对任务控制块的各个成员进行赋值,最后把这个任务控制块链入到任务控制块链表的头部。


难点:任务就绪表
任务调度:通过一个算法在多个任务中确定该运行的任务的函数,这是多任务操作系统的核心工作。
uCOS-II任务调度的思想:近似地每时每刻总是让优先级最高的就绪任务处于运行状态,它在系统或用户任务调用系统函数执行中断服务程序结束时总是调用调度器,来确定该运行的任务并运行它。
uCOS-II进行调度任务的依据就是任务就绪表。任务就绪表是uCOS-II在ARM中设立的一个记录表,系统中的每个任务都在表中占据一个位置,并用这个位置的状态表示任务是否处于就绪状态。
重点掌握:任务优先级的算法(原理2中P12-P17)


系统通过查找任务就绪表获得待运行任务的优先级
任务的切换过程:
1.获得待运行任务的控制块(根据就绪表获得待运行任务的任务控制块指针)
2.处理器的SP=任务块中保存的SP
3.恢复待运行任务的运行环境
4.处理器的PC=任务堆栈中断点地址 ?是否是为了正确的返回到断点
解释:1和2之间在调用调度器进行调度的时候要进行判断,究竟待运行的任务是否为当前的任务,如果是则不切换,否则切换。而且要保存被中止任务的运行环境。
任务切换宏:OS_TASK_SW();中止正在运行的任务(当前任务),去运行另外一个任务(就绪任务中就绪任务中优先级最高的)。被中止的任务要保护自己的断点

数据以便以后再断点处"无缝"的回复运行

uCOS-II的应用程序通过调用OS_TaskCreate()函数创建一个任务
OS_TaskCreate(void (*task)(void *pd),//指向任务的指针
void *pdata, //传递给任务的参数
OS_STk *ptos, //指向任务堆栈栈顶的指针
INT8U prio) //任务的优先级


任务的创建:
任务可以在调用函数OSStar()启动任务调度之前创建,也可以在任务中创建,uCOS-II规定:在调用启动任务函数OSStar()之前至少有一个已经创建任务。所以,人们习惯在调用函数OSStar()之前先创建一个任务并赋予它最高的优先级,使他成为起始任务,然后再起始任务中创建其他任务,包括系统提供的统计任务也在初始化函数中调用。


uCOS-II的初始化函数
在使用uCOS-II的所有服务之前,必须调用uCOS-II的初始化函数OSInit()对自身运行环境初始化。该函数将对uCOS-II的所有的全局变量和数据结构进行初始化,同时创建空闲任务OSTaskldle,并赋值一最低的优先级别和永远的就绪状态,如果用户程序要使用统计任务(标识:常数OS_TASK_STAT_EN=1),则OSInit()还要以优先级别为OS_LOWEST_PRIO-1来创建统计任务。
初始化函数OSInit():该函数在对数据结构进行初始化时候,主要创建包括任务控制块链表在内的5个空数据缓冲区,同时,为了快速查询控制块链表的各个元素,该函数还要创建一个数组:OSTCBPrioTbl[OS-LOWEST_PRIO+1],在这个数组中,按任务的优先级别把任务控制块的指针存放在对应的元素中。

uCOS-II进行任务管理是从调用启动函数OSStar()开始的,当然开始前至少创建一个用户任务。



uCOS-II的中断响应过程:
当系统接收到中断请求后,如果CPU处于中断允许状态,系统就终止正在运行的任务,按照中断向量的指向转去执行中断服务子程序,当中断服务子程序运行结束后,如果有新的高优先级的任务,则运行高级任务,没有高级任务则返回原任务(P29)
在中断服务程序中调用负责任务切换工作的函数OSIntCtxSw()(中断级任务切换函数)


应用程序中的临界段:在应用程序中有些代码的执行必须不受任何干扰的运行,这样的代码段叫做临界段
为了使临界段在运行时不受中断所打断,在临界段代码钱必须用关中断指令使CPU屏蔽中断请求,而在临界段代码后必须用开中断指令解除屏蔽使得CPU可以相应中断请求


uCOS-II的系统时钟
uCOS-II也是用硬件定时器产生一个周期为ms级的周期性中断实现系统时钟,最小的时钟单位就是两次中断之间的间隔时间,叫做时钟节拍,硬件定时器以时钟节拍为周期定时的产生中断,该中断的中断服务程序叫做OSTickISR()。中断服务

程序通过调用函数OSTimeTick()来完成系统在每个时钟节拍时需要做的工作。
函数OSTimeTick()为时钟节拍服务函数,任务是在每个时钟节拍了解每个任务的延时状态,使其中已经到了延时时限的非挂起任务进入就绪状态

任务的延时
由于嵌入式系统的任务是一个无线循环,还是一个抢占式(???????)内核,所以为了使高优先级别的任务不至独占CPU,可以给其他任务优先级别较低的任务获得CPU使用权的机会,uCOS-II规定:除了空闲任务之外的所有任务必须在任务中合适的位置调用系统提供的函数OSTimeDly(),该函数的作用是时当前的任务运行暂停一段时间并进行一次任务调度,以让出CPU的使用权。

INT8U OSTimeDlyResume( INT8U prio); //取消任务延时函数
INT32U OSTimeGet( void ); //获得系统时间函数
void OSTimeSet( INT32U ticks ); //设置系统时间函数





相关文档
相关文档 最新文档