对UCOSIII系统的任务管理包括了任务的创建、任务挂起、任务的删除以及任务的调度等。
UCOSIII的启动和初始化
- 最先肯定是调用OSInit()初始化UCOSIII。
- 创建任务,一般我们在main()函数中只创建一个start_task任务,其他任务都在start_task任务中创建,在调用OSTaskCreate()函数创建任务的时候一定要调用OS_CRITICAL_ENTER()函数进入临界区,任务创建完以后调用OS_CRITICAL_EXIT()函数退出临界区。
- 最后调用OSStart()函数开启UCOSIII。
int main(void)
{
OS_ERR err;
CPU_SR_ALLOC();
Write_Through(); //透写
Cache_Enable(); //打开L1-Cache
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhz
delay_init(216); //延时初始化
uart_init(115200); //串口初始化
LED_Init(); //初始化LED
OSInit(&err); //UCOS初始化
OS_CRITICAL_ENTER(); //进入临界区
OSTaskCreate(
(OS_TCB*)&StartTaskTCB, //任务控制块
(CPU_CHAR*)"start task", //任务名字
(OS_TASK_PTR)start_task, //任务函数
(void*)0, //传递给任务函数的参数
(OS_PRIO)START_TASK_PRIO, //任务优先级
(CPU_STK*)&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY)0, //任务内部消息队列能够接收的最大消息数目,为0时静止接收消息
(OS_TICK)0, //当使能时间片轮转时的时间片长度,为0时为默认长度
(void*)0, //用户补充的存储区
(OS_OPT)OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任务选项,为了保险起见,所有任务都保存浮点寄存器的值
(OS_ERR*)&err //存放该函数错误时的返回值
);
OS_CRITICAL_EXIT();//退出临界区
OSStart(&err);//开启UCOSIII
while(1);
}
任务状态
UCOSIII支持的是单核CPU,不支持多核CPU,这样在某一时刻只有一个任务会获得CPU使用权进入运行态,其他的任务就会进入其他状态,UCOSIII中的任务有多个状态:
休眠态:休眠态就是任务只是以任务函数的方式存在,只是存储区中的一段代码,并未用OSTaskCreate()函数创建这个任务,不受UCOSIII管理的。
就绪态:任务在就绪表中已经登记,等待获取CPU使用权。
运行态:正在运行的任务就处于运行态。
等待态:正在运行的任务需要等待某一个事件,比如信号量、消息、事件标志组等,就会暂时让出CPU使用权,进入等待事件状态。
中断服务态:一个正在执行的任务被中断打断,CPU转而执行中断服务程序,这时这个任务就会被挂起,进入中断服务态。
任务控制块
UCOSIII系统中有一个重要的数据结构:任务控制块OS_TCB,其用来保存任务的信息,我们使用OSTaskCreate()函数来创建任务的时候就会给任务分配一个任务控制块。
任务堆栈
任务堆栈用来在切换任务和调用其他函数的时候保存现场,因此每个任务都应该有自己的堆栈。堆栈创建的步骤:
//两种写法:
//第一种
CPU_STK START_TASK_STK[512];
//第二种
//设置任务堆栈大小
#define START_STK_SIZE 512
//任务堆栈
CPU_STK START_TASK_STK[START_STK_SIZE];
创建了任务堆栈之后,就是通过使用OSTaskCreat()函数创建任务的时候把创建的堆栈传递给任务。
OSTaskCreate(
(OS_TCB*)&StartTaskTCB, //任务控制块
(CPU_CHAR*)"start task", //任务名字
(OS_TASK_PTR)start_task, //任务函数
(void*)0, //传递给任务函数的参数
(OS_PRIO)START_TASK_PRIO, //任务优先级
//堆栈的传递
(CPU_STK*)&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY)0, //任务内部消息队列能够接收的最大消息数目,为0时静止接收消息
(OS_TICK)0, //当使能时间片轮转时的时间片长度,为0时为默认长度
(void*)0, //用户补充的存储区
(OS_OPT)OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任务选项,为了保险起见,所有任务都保存浮点寄存器的值
(OS_ERR*)&err //存放该函数错误时的返回值
);
任务就绪表
UCOSIII中将已经就绪的任务放到任务就绪表中,任务就绪表有两个部分:优先级位映射表OSPrioTBI[]和就绪任务列表OSRdyList[]。
任务调度和切换
可剥夺型调度:
任务调度和切换就是让就绪表中优先级最高的任务获得CPU的使用权,UCOSIII是可剥夺型,抢占式的,可以抢了低优先级任务的CPU使用权,任务的调度是由一个叫任务调度器的东西来完成的,任务调度器有两种:一种是任务机调度器,一种是中断级调度器。
时间片轮转调度:
在UCOSIII 中允许一个任务运行一段时间(时间片)后让出CPU 的使用权,让拥有同优先级的下一个任务运行,这种任务调度方法就是时间片轮转调度。
|