UCOSIII操作系统——任务篇(1)创建任务

UCOSIII其他内容导航不迷路
UCOSIII操作系统-简介
UCOSIII操作系统——任务篇(1)创建任务
UCOSIII操作系统——任务篇(2)相关API函数
UCOSIII操作系统——系统初始化篇(1)系统初始化
UCOSIII操作系统——系统初始化篇(2)CPU,SysTick,内存初始化
UCOSIII操作系统——硬件初始化篇(1)硬件初始化以及开始运行系统
正在更新整理…

说在前面:
这个内容不适合0基础的人,因为这里只讲了应用层面的东西,并没有深入内核讲解,所以要从零开始学UCOSIII的朋友,可以先去学完入门内容,再来观看这个笔记加深印象。

UCOSIII操作系统——任务篇(1)创建任务

UCOSIII——任务 简介

在裸机系统中,系统的主体就是main 函数里面顺序执行的无限循环,这个无限循环里面CPU 按照顺序完成各种事情。在多任务系统中,我们根据功能的不同,把整个系统分割成一个个独立的且无法返回的函数,这个函数我们称为任务,也有人称之为线程。
多任务操作系统最主要的就是对任务的管理,包括任务的创建、挂起、删除和调度等,因此对UCOSIII操作系统中任务管理的理解就显得尤为重要。

内容说明

我的笔记里面对概念只是大概说明,并不会进行深入讲解,因为太麻烦,太复杂,有兴趣可以自行深入学习,最重要的就是会用就行

废话不多说,我们进入正题

创建任务流程

定义任务栈

任务堆栈用来在切换任务和调用其他函数的时候保存现场,因此每一个任务都应该有自己的堆栈。

  1. 首先使用宏定义一个堆栈大小
  2. 再定义一个堆栈(实质上是一个数组)

定义堆栈用CPU_STK 数据类型创建一个堆栈(CPU_STK在cpu.h中有定义)
在这里插入图片描述
在这里插入图片描述

//任务堆栈大小	
#define TASK2_STK_SIZE 		128
//任务堆栈	
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];

定义任务控制块TCB

定义好任务函数和任务栈之后,我们还需要为任务定义一个任务控制块,通常我们称这个任务控制块为任务的身份证。在C代码上,任务控制块就是一个结构体,里面有非常多的成员,这些成员共同描述了任务的全部信息。
(关于TCB的具体内容我这里也不写出来了,有兴趣的可以己深入了解)
在这里插入图片描述

//任务控制块
OS_TCB Task1_TaskTCB;

定义任务主体函数

任务实际上就是一个无限循环且不带返回值的C函数。
在这里插入图片描述
严格按照格式,只能修改函数名,关于*p_arg这个参数,不用管,就这样写,反正基本也没用过。

//任务函数
void task1_task(void *p_arg);
void task2_task(void *p_arg);

定义完之后就可以写自己的业务代码了,比如写一个LED翻转的任务1S翻转一次

/**********************************************************************************************
                                          LED TASK
**********************************************************************************************/

static  void  AppTaskLed1 ( void * p_arg )
{
    OS_ERR  err;		// 定义一个“错误” 变量用来存放一些错误的类型
   (void)p_arg;			// 就这样写咯
    while (DEF_TRUE) { 		/*无限循环*/
			macLED3_TOGGLE ();	//	LED翻转
			OSTimeDly ( 10000, OS_OPT_TIME_DLY, & err );		// 阻塞延时
    }
}

任务里面一定要有阻塞延时,如果这个任务的优先级最高且没有阻塞延时,那么操作系统就只会执行这一个任务,其他的任务就得不到执行。

  • 专业解释
    • 任务里面的延时函数必须使用uCOS里面提供的阻塞延时函数,并不能使用我们裸机编程中的那种延时。这两种的延时的区别是uCOS里面的延时是阻塞延时,即调用OSTimeDly0函数的时候,当前任务会被挂起,调度器会切换到其它就绪的任务,从而实现多任务。如果还是使用裸机编程中的那种延时,那么整个任务就成为了一个死循环,如果恰好该任务的优先级是最高的,那么系统永远都是在这个任务中运行,比它优先级更低的任务无法运行,根本无法实现多任务,因此任务中必须有能阻塞任务的函数,才能切换到其他任务中。

创建任务

创建任务调用

OSTaskCreate();
  • OSTaskCreate();详细内容以及参数解释:
	//创建开始任务
	OSTaskCreate((OS_TCB 	* )&StartTaskTCB,		//任务控制块(&传地址)
				 (CPU_CHAR	* )"start task", 		//任务名字(可以随便写,对应上就行)
                 (OS_TASK_PTR )start_task, 			//任务函数(任务主体函数的函数名)
                 (void		* )0,					//传递给任务函数的参数(一般写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);				//存放该函数错误时的返回值,用于保存返回的错误代码。
  • 设置堆栈深度的限制位置->START_STK_SIZE/10: 这个值表示任务的堆栈满溢之前剩余的堆栈容量。例如,指定stk_size 值的10%表示将达到堆栈限制,当堆栈达到90%满就表示任务的堆栈已满。

  • 任务选项->OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR:

//用户可选的任务特定选项
1 #define OS_OPT_TASK_NONE 		(OS_OPT)(0x0000u) (1)
2 #define OS_OPT_TASK_STK_CHK 	(OS_OPT)(0x0001u) (2)
3 #define OS_OPT_TASK_STK_CLR	(OS_OPT)(0x0002u) (3)
4 #define OS_OPT_TASK_SAVE_FP 	(OS_OPT)(0x0004u) (4)
5 #define OS_OPT_TASK_NO_TLS 	(OS_OPT)(0x0008u) (5)
(1):未选择任何选项。
(2):启用任务的堆栈检查。
(3):任务创建时清除堆栈。
(4): 保存任何浮点寄存器的内容,这需要CPU硬件的支持,CPU需要有浮点运算硬件与专门保存浮点类型数据的寄存器。
(5):指定任务不需要TLS支持。

一般就选OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR就行了。

  • 创建任务就到这了

任务的状态

从用户的角度看,UCOSIII的任务一共有5种状态:

  1. 休眠态: 任务已经在CPU的flash中了,但是还不受UCOSIII管理。
  2. 就绪态: 系统为任务分配了任务控制块,并且任务已经在就绪表中登记,这时这个任务就具有了运行的条件,此时任务的状态就是就绪态。
  3. 运行态: 任务获得CPU的使用权,正在运行。
  4. 等待态: 正在运行的任务需要等待一段时间,或者等待某个事件,这个任务就进入了等待态,此时系统就会把CPU使用权转交给别的任务。
  5. 中断服务态: 当发送中断,当前正在运行的任务会被挂起,CPU转而去执行中断服务函数,此时任务的任务状态叫做中断服务态。
    在这里插入图片描述
发布了10 篇原创文章 · 获赞 1 · 访问量 126

猜你喜欢

转载自blog.csdn.net/iiinoname/article/details/105173803