2.1任务的基本概念
2.1.1任务及其内存结构 在设计一个较为复杂的程序时,通常把一个大型任务分解为多个小任务,然后在计算机中通过运行小任务,最终达到完成大人物的目的。这种方法可以使系统并发运行多个任务,从而提高处理器的利用率,加快程序的执行速度,因此现代操作系统几乎都是多任务操作系统。 在uC/OS-II中,与上述小任务对应的程序实体叫“任务”,而uC/OS-II就是一个能对这些小任务的运行进行管理和调度的多任务操作系统。 从代码上看,uC/OS-II的任务是一个函数; 从任务的存储结构上看,uC/OS-II任务由:任务程序代码(函数)、任务堆栈和任务控制块组成。
uC/OS-II任务的组成
进程:具有私有空间的任务
线程:没有私有空间的任务
uC/OS-II中的任务属于线程。
uC/OS-II用任务控制块链表对任务进行管理
用户任务:由应用程序设计者编写的任务(为了解决应用问题)
uC/OS-II任务
系统任务:由系统提供的任务(为应用程序提供某种服务或系统本身服务的)
目前,在uC/OS-II中,最多可以含有64个任务(包括用户任务和系统任务)
2.1.2 任务的状态
uC/OS-II任务的5种状态:睡眠、就绪、运行、等待、中断服务
2.1.3 用户任务代码的一般结构
1.用户任务代码的一般结构
任务的执行代码是一个无线循环结构,在循环当中可以响应中断,这种结构也叫做超循环结构。
void MyTask(void *pdata)
{
for(;;)
{
可以被中断的用户代码;
OS_ENTER_CRITICAL(); //进入临界段(关中断)
不可以被中断的用户代码;
OS_EXIT_CRITICAL(); //退出临界段(开中断)
可以被中断的用户代码;
}
}
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()是uC/OS-II定义的两个宏。
2.用户应用程序的一般结构
用户任务是C语言函数,不由主函数main()调用,何时运行及何时中止由操作系统来调度。
main()函数是程序运行的入口,虽不用调度任务,但要负责任务的创建并将它们交给系统。
用户应用程序的结构:
void MyTask1(void *pdata) //定义用户任务1
{
for(;;)
{
……
}
}
void MyTask2(void *pdata) //定义用户任务2
{
for(;;)
{
……
}
}
void MyTask23void *pdata) //定义用户任务3
{
for(;;)
{
……
}
}
void main()
{
……
OSInit(); //初始化uC/OS-II
……
OSTaskCreate(MyTask1,……); //创建用户任务1
OSTaskCreate(MyTask2,……); //创建用户任务2
OSTaskCreate(MyTask3,……); //创建用户任务3
……
OSSTART(); //启动uC/OS-II
……
}
2.1.4系统任务
空闲任务:每个应用程序必须使用的
统计任务:应用程序根据实际需要来选择使用
1.空闲任务
void OSTASKIdle(void * pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata; //防止某些编译器报错
for(;;)
{
OS_ENTER_CRITICAL(); //关闭中断
OSdleCtr++; //计数
OS_EXIT_CRITICAL(); //开放中断
}
}
代码中的“pdata = pdata ”,是为了防止编译器报错而使用的程序设计技巧。
2.统计任务
该任务每秒计算一次CPU在单位时间内被使用的时间,并把计算结果以百分比的形式存放在变量OSCPUsage中,以便其他应用程序来了解CPU的利用率。
如果用户应用程序决定要使用统计任务,则必须把定义在系统头文件OS_CFG.H中的系统配置常数OS_TASK_STAT_EN设置为1,并且在程序中要调用函数OSStatInit()来统计任务进行初始化。
2.1.5 任务的优先权及优先级别
uC/OS-II在系统配置文件OS_CFG.H中定义了一个用来表示最低优先级别常数OS_LOWEST_PRIO,如果用户为其赋了值,则系统中可供使用的优先级别为0、1、2、……、OS_LOWEST_PRIO,对应的,任务的总数不能超过OS_LOWEST_PRIO + 1个。
用户任务的优先级别要由用户创建一个任务时显式地定义。
2.2任务堆栈
所谓堆栈,就是在存储器中按数据“后进先出(LIFO)”的原则组织的连续存储空间。
2.2.1 任务堆栈的创建
为了定义任务堆栈方便,在文件OS_CPU.H中专门定义了一个数据类型OS_STK:
typedef unsigned int OS_STK; //该类型长度为16位
这样,在定义任务堆栈的栈区时,只需定义一个OS_STK类型的数组即可。例如:
#define TASK_STK_SIZE 512 //定义堆栈的长度(1024字节)
OS_STK TaskStk[TASK_STK_SIZE]; //定义一个数组来作为任务堆栈
创建任务函数OSTaskCreate()
INT8U OSTaskCreate(
void(* task)(void * pd), //指向任务的指针
void * pdata, //传递给任务的参数
OS_STK * ptos, //任务堆栈栈顶的指针
INT8U prio //指定任务优先级别的参数
);
创建任务:任务堆栈长度为128字节,优先级别为20,任务参数为pdata的实参为MyTaskAgu.
#define MyTaskStk N 64
OS_STK MyTaskStk[MyTaskStkN];
void main()
{
……
OSTaskCreate(
MyTask, //任务的指针
&MyTaskAgu, //传递给任务的参数
& MyTaskStk[MyTaskStkN - 1], //任务堆栈栈顶地址
20 //任务的优先级别
);
……
}
堆栈的增长方式是随系统所使用的处理器不同而不同的。
为了增强应用程序的可移植性,可将上述代码改为:
#define MyTaskStk N 64
OS_STK MyTaskStk[MyTaskStkN];
void main()
{
……
#if OS_STK_GROWTH == 1
OSTaskCreate(
MyTask, //任务的指针
&MyTaskAgu, //传递给任务的参数
& MyTaskStk[MyTaskStkN - 1], //任务堆栈栈顶地址
20 //任务的优先级别
);
#else
OSTaskCreate(
MyTask, //任务的指针
&MyTaskAgu, //传递给任务的参数
& MyTaskStk[0], //任务堆栈栈顶地址
20 //任务的优先级别
);
#endif
……
}
2.2.2 任务堆栈的初始化
函数原型如下:
OS_STK * OSTaskStkInit(
void (* task)(void * pd),
void * pdato,
OS_STK * ptos,
INT16U opt
);
2.1.1任务及其内存结构 在设计一个较为复杂的程序时,通常把一个大型任务分解为多个小任务,然后在计算机中通过运行小任务,最终达到完成大人物的目的。这种方法可以使系统并发运行多个任务,从而提高处理器的利用率,加快程序的执行速度,因此现代操作系统几乎都是多任务操作系统。 在uC/OS-II中,与上述小任务对应的程序实体叫“任务”,而uC/OS-II就是一个能对这些小任务的运行进行管理和调度的多任务操作系统。 从代码上看,uC/OS-II的任务是一个函数; 从任务的存储结构上看,uC/OS-II任务由:任务程序代码(函数)、任务堆栈和任务控制块组成。
uC/OS-II任务的组成
进程:具有私有空间的任务
线程:没有私有空间的任务
uC/OS-II中的任务属于线程。
uC/OS-II用任务控制块链表对任务进行管理
用户任务:由应用程序设计者编写的任务(为了解决应用问题)
uC/OS-II任务
系统任务:由系统提供的任务(为应用程序提供某种服务或系统本身服务的)
目前,在uC/OS-II中,最多可以含有64个任务(包括用户任务和系统任务)
2.1.2 任务的状态
uC/OS-II任务的5种状态:睡眠、就绪、运行、等待、中断服务
2.1.3 用户任务代码的一般结构
1.用户任务代码的一般结构
任务的执行代码是一个无线循环结构,在循环当中可以响应中断,这种结构也叫做超循环结构。
void MyTask(void *pdata)
{
for(;;)
{
可以被中断的用户代码;
OS_ENTER_CRITICAL(); //进入临界段(关中断)
不可以被中断的用户代码;
OS_EXIT_CRITICAL(); //退出临界段(开中断)
可以被中断的用户代码;
}
}
OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()是uC/OS-II定义的两个宏。
2.用户应用程序的一般结构
用户任务是C语言函数,不由主函数main()调用,何时运行及何时中止由操作系统来调度。
main()函数是程序运行的入口,虽不用调度任务,但要负责任务的创建并将它们交给系统。
用户应用程序的结构:
void MyTask1(void *pdata) //定义用户任务1
{
for(;;)
{
……
}
}
void MyTask2(void *pdata) //定义用户任务2
{
for(;;)
{
……
}
}
void MyTask23void *pdata) //定义用户任务3
{
for(;;)
{
……
}
}
void main()
{
……
OSInit(); //初始化uC/OS-II
……
OSTaskCreate(MyTask1,……); //创建用户任务1
OSTaskCreate(MyTask2,……); //创建用户任务2
OSTaskCreate(MyTask3,……); //创建用户任务3
……
OSSTART(); //启动uC/OS-II
……
}
2.1.4系统任务
空闲任务:每个应用程序必须使用的
统计任务:应用程序根据实际需要来选择使用
1.空闲任务
void OSTASKIdle(void * pdata)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
pdata = pdata; //防止某些编译器报错
for(;;)
{
OS_ENTER_CRITICAL(); //关闭中断
OSdleCtr++; //计数
OS_EXIT_CRITICAL(); //开放中断
}
}
代码中的“pdata = pdata ”,是为了防止编译器报错而使用的程序设计技巧。
2.统计任务
该任务每秒计算一次CPU在单位时间内被使用的时间,并把计算结果以百分比的形式存放在变量OSCPUsage中,以便其他应用程序来了解CPU的利用率。
如果用户应用程序决定要使用统计任务,则必须把定义在系统头文件OS_CFG.H中的系统配置常数OS_TASK_STAT_EN设置为1,并且在程序中要调用函数OSStatInit()来统计任务进行初始化。
2.1.5 任务的优先权及优先级别
uC/OS-II在系统配置文件OS_CFG.H中定义了一个用来表示最低优先级别常数OS_LOWEST_PRIO,如果用户为其赋了值,则系统中可供使用的优先级别为0、1、2、……、OS_LOWEST_PRIO,对应的,任务的总数不能超过OS_LOWEST_PRIO + 1个。
用户任务的优先级别要由用户创建一个任务时显式地定义。
2.2任务堆栈
所谓堆栈,就是在存储器中按数据“后进先出(LIFO)”的原则组织的连续存储空间。
2.2.1 任务堆栈的创建
为了定义任务堆栈方便,在文件OS_CPU.H中专门定义了一个数据类型OS_STK:
typedef unsigned int OS_STK; //该类型长度为16位
这样,在定义任务堆栈的栈区时,只需定义一个OS_STK类型的数组即可。例如:
#define TASK_STK_SIZE 512 //定义堆栈的长度(1024字节)
OS_STK TaskStk[TASK_STK_SIZE]; //定义一个数组来作为任务堆栈
创建任务函数OSTaskCreate()
INT8U OSTaskCreate(
void(* task)(void * pd), //指向任务的指针
void * pdata, //传递给任务的参数
OS_STK * ptos, //任务堆栈栈顶的指针
INT8U prio //指定任务优先级别的参数
);
创建任务:任务堆栈长度为128字节,优先级别为20,任务参数为pdata的实参为MyTaskAgu.
#define MyTaskStk N 64
OS_STK MyTaskStk[MyTaskStkN];
void main()
{
……
OSTaskCreate(
MyTask, //任务的指针
&MyTaskAgu, //传递给任务的参数
& MyTaskStk[MyTaskStkN - 1], //任务堆栈栈顶地址
20 //任务的优先级别
);
……
}
堆栈的增长方式是随系统所使用的处理器不同而不同的。
为了增强应用程序的可移植性,可将上述代码改为:
#define MyTaskStk N 64
OS_STK MyTaskStk[MyTaskStkN];
void main()
{
……
#if OS_STK_GROWTH == 1
OSTaskCreate(
MyTask, //任务的指针
&MyTaskAgu, //传递给任务的参数
& MyTaskStk[MyTaskStkN - 1], //任务堆栈栈顶地址
20 //任务的优先级别
);
#else
OSTaskCreate(
MyTask, //任务的指针
&MyTaskAgu, //传递给任务的参数
& MyTaskStk[0], //任务堆栈栈顶地址
20 //任务的优先级别
);
#endif
……
}
2.2.2 任务堆栈的初始化
函数原型如下:
OS_STK * OSTaskStkInit(
void (* task)(void * pd),
void * pdato,
OS_STK * ptos,
INT16U opt
);