uC/OSII的任务
从任务存储结构来看,由三部分构成:任务程序代码、任务堆栈和任务控制块。任务控制块用来保存任务属性,任务堆栈用来保存任务工作环境,任务程序代码是任务的执行部分。
系统中把任务链接成任务链表,任务中最主要的是任务控制块,任务控制块中有:
前一个任务控制块的指针
|
后一个任务控制块的指针
|
指向任务的指针
|
指向任务堆栈的指针
|
任务的优先级别
……
|
任务程序代码的结构如下:
void MyTask(void *pdata)
OS_STK *OSTaskStkInit(
void (*task)(void *pd),
void *pdata,
OS_STK *ptos,
INIT16U opt
);
当用户程序调用函数OSTaskCreate()创建一个任务时,这个函数会调用系统函数OSTCBInit()来为任务控制块进行初始化。这个函数首先为被创建任务从空任务控制块链表获取一个任务控制块,然后利用任务的属性对任务控制块各个成员进行赋值,最后再把这个任务控制块链入到任务控制块链表的头部。
设计一个只有一个任务Task1,当程序运行后任务的工作就是每秒在显示器上显示一个字符“M”。代码如下:
#include "includes.h"
#define TASK_STK_SIZE 512
OS_STK MyTaskStk[TASK_STK_SIZE];
INT16S key;
INT8U x=0,y=0;
void MyTask(void *data);
void main (void)
{
char* s_M="M";
OSInit();
PC_DOSSaveReturn(); PC_VectSet(uCOS, OSCtxSw); PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK);
OSTaskCreate(MyTask,s_M, &MyTaskStk[TASK_STK_SIZE - 1], 0);
OSStart();
}
void MyTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr;
#endif
pdata = pdata;
OS_ENTER_CRITICAL();
PC_VectSet(0x08, OSTickISR); PC_SetTickRate(OS_TICKS_PER_SEC);
OS_EXIT_CRITICAL();
OSStatInit();
for (;;)
{
if(x>10)
{
x=0;
y+=2;
}
PC_DispChar(x,y,*(char*)pdata,DISP_BGND_BLACK+DISP_FGND_WHITE);
x+=1;
if(PC_GetKey(&key) == 1)
{
if(key == 0x1B)
{
PC_DOSReturn();
}
}
OSTimeDlyHMSM(0,0,1,0);
}
}
任务的挂起,原型如下:
任务删除
void OSStart (void)
|
{
|
INT8U y;
|
INT8U x;
|
if (OSRunning == FALSE) {
|
y = OSUnMapTbl[OSRdyGrp];
|
x = OSUnMapTbl[OSRdyTbl[y]];
|
OSPrioHighRdy = (INT8U)((y << 3) + x);
|
OSPrioCur = OSPrioHighRdy;
|
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
|
OSTCBCur = OSTCBHighRdy;
|
OSStartHighRdy();
|
}
|
}
|
小结:
2. 系统是按任务就绪表和任务的优先级别来调度任务的。执行任务调度工作的是调度器,它负责查找具有最高优先级别的就绪任务并运行它,同时把这个任务TCB的指针存放在 OSTCBCur中。通常,系统在调用API函数和运行中断服务程序之后都要调用函数OSSched()来进行一次任务调度。
3. 任务切换的核心工作是任务堆栈指针的切换。
4. 任务调度器代码的设计,使得它的运行时间与系统中的任务数无关,从而使它满足了实时系统的要求。
5. 任务的优先级别也是任务的标识。
6. 应用程序首先应该调用函数OSInit()对全局变量和数据结构进行初始化已建立uC/OS-II的运行环境。
7. 应用程序是通过调用函数OSStart()开始进入多任务管理的,但在调用函数OSStart()之前,必须至少创建了一个任务。