学习RTOS(4)任务

什么是任务
在裸机系统中,系统的主体就是 main 函数里面顺序执行的无限循环,这个无限循环里面 CPU 按照顺序完成各种事情。在多任务系统中,我们根据功能的不同,把整个系统分割成一个个独立的且无法返回的函数,这个函数我们称为任务。 任务的大概形式具体见代码清单 7-2。
在这里插入图片描述

创建任务

创建任务

我们先回想下,在一个裸机系统中,如果有全局变量,有子函数调用,有中断发生。那么系统在运行的时候,全局变量放在哪里,子函数调用时,局部变量放在哪里,中断发生时,函数返回地址放哪里。如果只是单纯的裸机编程,它们放哪里我们不用管,但是如果要写一个 RTOS,这些种种环境参数,我们必须弄清楚他们是如何存储的。在裸机系统中,他们统统放在一个叫栈的地方,栈是单片机 RAM 里面一段连续的内存空间,栈的大小一般在启动文件或者链接脚本里面指定,最后由 C 库函数_main 进行初始化。

但是,在多任务系统中,每个任务都是独立的,互不干扰的,所以要为每个任务都分配独立的栈空间,这个栈空间通常是一个预先定义好的全局数组,也可以是动态分配的一段内存空间,但它们都存在于RAM中。
本章我们要实现两个变量按照一定的频率轮流的翻转,每个变量对应一个任务,那么就需要定义两个任务栈,具体见代码清单 7-3。在多任务系统中,有多少个任务就需要定义多少个任务栈。
在这里插入图片描述

代码清单 7-3 (1):任务栈其实就是一个预先定义好的全局数据,数据类型为StackType_t,大小由TASK1_STACK_SIZE 这个宏来定义, 默认为 128,单位为字,即 512字节,这也是 FreeRTOS 推荐的最小的任务栈。

定义任务函数

任务是一个独立的函数,函数主体无限循环且不能返回。本章我们在 main.c 中定义的两个任务具体见代码清单 7-5。
在这里插入图片描述

定义任务控制块

在裸机系统中,程序的主体是 CPU 按照顺序执行的。而在多任务系统中,任务的执行是由系统调度的。系统为了顺利的调度任务,为每个任务都额外定义了一个任务控制块,这个任务控制块就相当于任务的身份证,里面存有任务的所有信息,比如任务的栈指针,任务名称,任务的形参等。有了这个任务控制块之后,以后系统对任务的全部操作都可以通过这个任务控制块来实现。 定义一个任务控制块需要一个新的数据类型, 该数据类型在task.c 这 C 头文件中声明。
在这里插入图片描述

代码清单 7-6 (1):栈顶指针,作为 TCB 的第一个成员。
代码清单 7-6 (2):任务节点,这是一个内置在 TCB 控制块中的链表节点,通过这个节点,可以将任务控制块挂接到各种链表中。这个节点就类似晾衣架的钩子, TCB 就是衣服。
代码清单 7-6 (3):任务栈起始地址。
代码清单 7-6 (4):任务名称,字符串形式, 长度由宏 configMAX_TASK_NAME_LEN来控制,该宏在 FreeRTOSConfig.h 中定义,默认为 16。
代码清单 7-6 (5):数据类型重定义。

实现任务创建函数

任务的栈,任务的函数实体,任务的控制块最终需要联系起来才能由系统进行统一调度。那么这个联系的工作就由任务创建函数 xTaskCreateStatic()来实现,该函数在 task.c( task.c 第一次使用需要自行在文件夹 freertos 中新建并添加到工程的 freertos/source 组)中定义, 在 task.h 中声明, 所有跟任务相关的函数都在这个文件定义。 xTaskCreateStatic()函数的实现见代码清单 7-8。
在这里插入图片描述

代码清单 7-8 (1): FreeRTOS 中,任务的创建有两种方法,一种是使用动态创建,一种是使用静态创建。动态创建时,任务控制块和栈的内存是创建任务时动态分配的,任务删除时,内存可以释放。静态创建时,任务控制块和栈的内存需要事先定义好,是静态的内存,任务删除时,内存不能释放。目前我们以静态创建为例来讲解,configSUPPORT_STATIC_ALLOCATION 在 FreeRTOSConfig.h 中定义,我们配置为1
代码清单 7-8 (2):任务入口,即任务的函数名称。 TaskFunction_t 是在 projdefs.h中重定义的一个数据类型,实际就是空指针。
代码清单 7-8 (3): 任务名称,字符串形式,方便调试。
代码清单 7-8 (4): 任务栈大小,单位为字。
代码清单 7-8 (5): 任务形参。
代码清单 7-8 (6): 任务栈起始地址。
代码清单 7-8 (7): 任务控制块指针。
代码清单 7-8 (8): 定义一个任务句柄 xReturn, 任务句柄用于指向任务的 TCB。 任务句柄的数据类型为 TaskHandle_t, 在 task.h 中定义,实际上就是一个空指针。
代码清单 7-8 (9): 调用 prvInitialiseNewTask()函数,创建新任务,该函数在 task.c 实现,具体实现见代码清单 7-11。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值