UCOS学习笔记——任务相关的API函数的使用
任务的创建与删除
OSTaskCreateO创建任务函数
UCOSIII是多任务系统,那么肯定要能创建任务,创建任务就是将任务控制块、任务堆栈、任务代码等联系在一起,并且初始化任务控制块的相应字段。在UCOSIII中我们通过函数OSTaskCreate(来创建任务,OSTaskCreate()函 数原型如下(在os_task.c 中有义)。调用OSTaskCreat()创建一一个任务 以后,刚创建的任务就会进入就绪态,注意!不能在中断服务程序中调用OSTaskCreat( )函数来创建任务。
void OSTaskCreate (OS TCB *p_ tcb,
CPU CHAR *p_ name,
OS TASK PTR p_ task,
void *p_ arg,
OS PRIO prio,
CPU STK *p_ stk_ base,
CPU STK SIZE stk_ limit,
CPU STK_ SIZE stk_ size,
OS MSG QTY q size,
OS TICK time_ quanta,
void *p_ ext,
OS OPT opt,
OS ERR *p_ err)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
*p_ tcb: 指向任务的任务控制块OS_ TCB
*P_ name: 指向任务的名字,我们可以给每个任务取一一个名字
p_ task: 执行任务代码,也就是任务函数名字.
*P_ arg: 传递给任务的参数
prio: 任务优先级,数值越低优先级越高,用户不能使用系统任务使用的那些优先级!
*p_stk_base: 指向任务堆栈的基地址。
stk_ limit: 任务堆栈的堆栈深度,用来检测和确保堆栈不溢出。
stk_ size: 任务堆栈大小
q_ size: UCOSIII中每个任务都有一一个可选的内部消息队列,我们要定义宏OS_ CFG_ TASK_ Q EN>0,这是才会使用这个内部消息队列。
time_quanta: 在使能时间片轮转调度时用来设置任务的时间片长度,默认值为时钟节拍除以10。
*P_ ext: 指向用户补充的存储区。
opt: 包含任务的特定选项,有如下选项可以设置。
OS OPT TASK NONE | 表示没有任何选项 |
---|---|
OS_ OPT_ TASK STK_ CHK | 指定是否允许检测该任务的堆栈 |
OS OPT TASK STK CLR | 指定是否清除该任务的堆栈 |
OS OPT TASK SAVE FP | 指定是否存储浮点寄存器,CPU 需要有浮点运算硬件并且有专用代码保存浮点寄存器。 |
*p_ err: 用来保存调用该函数后返回的错误码。
OSTaskDel()删除任务函数
OSTaskDel()函数用来删除任务,当一个任务不需要运行的话,我们就可以将其删除掉,删除任务不是说删除任务代码,而是UCOSIII不再管理这个任务,在有些应用中我们只需要某个任务只运行一一次,运行完成后就将其删除掉,比如外设初始化任务, OSTaskDel()函数原型如下:
void OSTaskDel (OS_TCB *P_ tcb,
OS_ERR *p_err)
- 1
*P_ tcb | 指向要删除的任务TCB,也可以传递一一个NULL指针来删除调用OSTaskDel()函数的任务自身。 |
---|---|
*p_ err | 指向一个变量用来保存调用OSTaskDel0函数后返回的错误码。 |
虽然UCOSIII允许用户在系统运行的时候来删除任务,但是应该尽量的避免这样的操作,如果多个任务使用同一个共享资源,这个时候任务A正在使用这个共享资源,如果删除了任务A,这个资源并没有得到释放,那么其他任务就得不到这个共享资源的使用权,会出现各种奇怪的结果。
我们调用OSTaskDel()删除一个任务后, 这个任务的任务堆栈、OS_ TCB所占用的内存并没有释放掉,因此我们可以利用他们用于其他的任务,当然我们也可以使用内存管理的方法给任务堆栈和OS_ TCB分配内存,这样当我们删除掉某个任务后我们就可以使用内存释放函数将这个任务的任务堆栈和OS_ TCB所占用的内存空间释放掉。
任务的挂起与恢复
OSTaskSuspend()函数
有时候有些任务因为某些原因需要暂停运行,但是以后还要运行,因此我们就不能删除掉任务,这里我们可以使用OSTaskSuspend()函 数挂起这个任务,以后再恢复运行,函数OSTaskSuspend()的原型如下:
void OSTaskSuspend (OS TCB *p tcb,OS ERR*p_ err)
OSTaskResume()函数
OSTaskResume()函数用来恢复被OSTaskSuspend()函数挂起的任务,OSTaskResume()函数是唯一能恢复被挂起任务的函数。如果被挂起的任务还在等待别的内核对象,比如事件标志组、信号量、互斥信号量、消息队列等,即使使用OSTaskResume()函数恢复了被挂起的任务,该任务也不一定能立即运行,该任务还是要等相应的内核对象,只有等到内核对象后才可以继续运行,OSTaskResume()函数原型如下:
void OSTaskResume (OS_ TCB *p_ tcb,OS_ ERR *p_ err)
*p_ tcb:
向需要解挂的任务的OS_ TCB, 指向一个NULL指针是无效的,因为该任务正
在运行,不需要解挂。
*p err:
指向一个变量,用来保存该函数的错误码。
程序设计
(1)创建开始任务start_ task, start_ task任务用来创建另外两个任务: task1_ task和task2_ task。
(2)开始任务start_ task 中用来创建任务1: taskl_ task.
(3)开始任务start task 中用来创建任务2: task2_ task.
(4)开始任务start task只是用来创建任务task1_ task 和task2_ task, 那么这个任务肯定只需要执行–次,两个任务创建完成以后就可以删除掉start_task任务了,这里我们使用OSTaskDel()函数删除掉任务自身,这里传递给OSTaskDel(函数参数p_ tcb 的值为0,表示删除掉任务自身。
(5)根据要求我们在任务1执行5次后由任务1删除掉任务2,这里通过调用OSTaskDel()函数删除掉任务2,注意这时我们传递给OSTaskDel)中参数p_ tcb 的值为任务2的任务控制块Task2_ TaskTCB的地址,因此这里我们用了取址号“&”。
(6)调用函数OSTimeDlyHMSM(延时ls, 调用OSTimeDlyHMSM()函数以后就会发起一个任务切换。
主函数:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "includes.h"
//任务优先级
#define START_TASK_PRIO 3
//任务堆栈大小
#define START_STK_SIZE 128
//任务控制块
OS_TCB StartTaskTCB;
//任务堆栈
CPU_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *p_arg);
//任务优先级
#define TASK1_TASK_PRIO 4
//任务堆栈大小
#define TASK1_STK_SIZE 128
//任务控制块
OS_TCB Task1_TaskTCB;
//任务堆栈
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
void task1_task(void *p_arg);
//任务优先级
#define TASK2_TASK_PRIO 5
//任务堆栈大小
#define TASK2_STK_SIZE 128
//任务控制块
OS_TCB Task2_TaskTCB;
//任务堆栈
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
//任务函数
void task2_task(void *p_arg);
//LCD刷屏时使用的颜色
int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED,
GRED, GBLUE, RED, MAGENTA,
GREEN, CYAN, YELLOW,BROWN,
BRRED, GRAY };
int main(void)
{
OS_ERR err;
CPU_SR_ALLOC();
delay_init(); //时钟初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
uart_init(115200); //串口初始化
LED_Init(); //LED初始化
LCD_Init(); //LCD初始化
POINT_COLOR = RED;
LCD_ShowString(30,10,200,16,16,"ALIENTEK STM32F1");
LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 6-1");
LCD_ShowString(30,50,200,16,16,"Task Creat and Del");
LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,90,200,16,16,"2015/3/19");
OSInit(&err); //初始化UCOSIII
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_ERR * )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT(); //退出临界区
OSStart(&err); //开启UCOSIII
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
开始任务函数
void start_task(void *p_arg)
{
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); //统计任务
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间
CPU_IntDisMeasMaxCurReset();
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候
//使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms
OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
OS_CRITICAL_ENTER(); //进入临界区
//创建TASK1任务
//创建TASK1任务
OSTaskCreate((OS_TCB * )&Task1_TaskTCB,
(CPU_CHAR * )"Task1 task",
(OS_TASK_PTR )task1_task,
(void * )0,
(OS_PRIO )TASK1_TASK_PRIO,
(CPU_STK * )&TASK1_TASK_STK[0],
(CPU_STK_SIZE)TASK1_STK_SIZE/10,
(CPU_STK_SIZE)TASK1_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
//创建TASK2任务
OSTaskCreate((OS_TCB * )&Task2_TaskTCB,
(CPU_CHAR * )"task2 task",
(OS_TASK_PTR )task2_task,
(void * )0,
(OS_PRIO )TASK2_TASK_PRIO,
(CPU_STK * )&TASK2_TASK_STK[0],
(CPU_STK_SIZE)TASK2_STK_SIZE/10,
(CPU_STK_SIZE)TASK2_STK_SIZE,
(OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
OS_CRITICAL_EXIT(); //退出临界区
OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
tsck1()任务函数
void task1_task(void *p_arg)
{
u8 task1_num=0;
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
POINT_COLOR = BLACK;
OS_CRITICAL_ENTER();
LCD_DrawRectangle(5,110,115,314); //画一个矩形
LCD_DrawLine(5,130,115,130); //画线
POINT_COLOR = BLUE;
LCD_ShowString(6,111,110,16,16,"Task1 Run:000");
OS_CRITICAL_EXIT();
while(1)
{
task1_num++; //任务执1行次数加1 注意task1_num1加到255的时候会清零!!
LED0= ~LED0;
printf("任务1已经执行:%d次\r\n",task1_num);
if(task1_num==5)
{
OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err); //任务1执行5此后删除掉任务2
printf("任务1删除了任务2!\r\n");
}
LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //填充区域
LCD_ShowxNum(86,111,task1_num,3,16,0x80); //显示任务执行次数
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
task2()任务函数
void task2_task(void *p_arg)
{
u8 task2_num=0;
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
POINT_COLOR = BLACK;
OS_CRITICAL_ENTER();
LCD_DrawRectangle(125,110,234,314); //画一个矩形
LCD_DrawLine(125,130,234,130); //画线
POINT_COLOR = BLUE;
LCD_ShowString(126,111,110,16,16,"Task2 Run:000");
OS_CRITICAL_EXIT();
while(1)
{
task2_num++; //任务2执行次数加1 注意task1_num2加到255的时候会清零!!
LED1=~LED1;
printf("任务2已经执行:%d次\r\n",task2_num);
LCD_ShowxNum(206,111,task2_num,3,16,0x80); //显示任务执行次数
LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //填充区域
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
任务的挂起与恢复
(1) 根据要求任务1运行5次后调用OSTaskSuspend()函数挂起任务2。
(2)当任务1运行到第10次就调用函数OSTaskResume()函数解挂任务2。
文章来源: wlybsy.blog.csdn.net,作者:万里羊,版权归原作者所有,如需转载,请联系作者。
原文链接:wlybsy.blog.csdn.net/article/details/103490290
- 点赞
- 收藏
- 关注作者
评论(0)