【FreeRTOS】FreeRTOS_任务创建

本文详细介绍了FreeRTOS中任务创建的全过程,包括任务定义、任务栈、任务控制模块、列表和列表项、就绪列表的初始化及调度器的实现。通过任务调度器管理任务,利用任务控制模块存储任务信息,并通过任务栈分配不同的内存空间。文章还探讨了任务的创建函数,如xTaskCreateStatic(),以及任务状态和管理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

零、整体摘要

这篇文章过长了,如果想快速的大体的了解FreeRTOS的创建任务的过程,看这一部分即可。

1、凝练概述

任务调度器通过列表管理任务,列表项作为列表的基本元素与任务控制模块建立联系,任务控制模块则反映了任务中的信息。最终达到任务调度的目的。

2、创建流程概述

  • 任务创建的过程就是:
    • 初始化任务的栈名字、栈大小、堆栈指针传入(任务栈的初始化)
    • 定义任务优先级
    • 定义任务控制块指针(列表项的初始化)
  • 就绪列表的初始化:
    • 初始化列表
    • 把创建的任务tcb插入到列表中
  • 调度器实现
    • 开启调度器
    • svc_hander 重命名(arm和freertos的命名不同,需要调整)
    • 实现任务切换(现有程序,汇编语言)

3、大体思路概述

静态、动态实现任务启动的大体流程思路

  • main
  • 初始化硬件(屏幕、adc、串口【用什么初始化什么】)
  • 创建开始任务(函数)(调用xtaskcreate、准备好参数:任务相关【栈指针、名字、大小等】,这个函数对列表项和任务栈进行了初始化)
    • 创建子任务1(函数)(同上)
    • 创建子任务2(函数)(同上)
    • 删除开始任务(开始任务只是一个中间过程任务)
  • 启动任务调度器【调用函数即可】
    • 1、创建了空闲任务和定时器任务
    • 2、开启了调度器所用的硬件(中断、systick、定时器)
    • 3、任务切换函数开启)

============================================
名词解释

任务调度器:
首先,任务创建的目的是通过freertos的固定格式,对不同的任务进行优先级顺序的管理。为了达到目的我们需要一个核心组件:任务调度器

任务控制模块:
其次,核心组件:任务调度器管理任务需要任务本身自带属性和信息,通过对信息的判断来执行任务的调度。因此我们需要把输入信息结构化表示,这里就出现了能够通过特定格式来方便任务调度器管理的数据结构:任务控制模块,注意任务控制模块的信息只包含了方便管理的基本信息。但信息仍然很丰富,如优先级、任务状态(就绪、阻塞、挂起)、任务栈指针、堆栈大小。。。(任务控制模块是每个任务的"身份证",帮助调度器了解当前各个任务的信息)

任务栈
每个任务因为要分离管理,其数据需要存储的不同的内存块中,任务栈就是分配好的不同的任务内存对栈地址空间。

列表:
然后,任务调度器的目的是更好的管理任务,它通过任务控制模块来了解每个任务的状态,但是当任务多起来时,任务调度器就会变得很复杂,因此这时引入一个任务调度器的小助手:列表。列表本质上是一种双向链表,方便对不同对象的增删查改和遍历与显示,当这个对象是任务控制模块时,这时的链表就可以被是做一种列表。(列表是任务调度器的助手,帮助任务调度器更有调理的了解各个任务的信息)

列表项
每个列表项即列表中的元素,其和具体的对象关联,指针指向关联对象或存储关联对象。

任务就绪态列表
一种列表,TCB里面的属性中状态时就绪态,就会被插入到这个列表末尾中。非就绪态任务时无法调用被任务调配器直接调用。

任务的状态【以买咖啡为例子方便理解】:
就绪:任务创建完成所有资源都准备好了,等待被调用(没获得cpu时间片,没执行)
【买咖啡:前准备好了,但是营业员在忙其他事】

运行态:任务正在cpu上执行(单核处理器只能有一个任务运行)
【买咖啡:营业员正在制作你的咖啡订单】

阻塞:参与调度,但某些资源或条件不具备在等待
【买咖啡:没带钱,在等着你的男/女朋友微信转账】

挂起:不参与cpu实际调度,必须回复才能参与任务调度
【买咖啡:昨天睡的好,挺精神的,不买咖啡了,什么时候困了什么时候再买】

删除/终止:任务完成,删除任务;或者任务被操作系统终止
【买咖啡:买到咖啡了,去做其他工作了 ;今天被通知有ddl截止,被强制停止了买咖啡的事情。】

阻塞和挂起的区别

执行状态:
挂起:任务被挂起后,不会参与调度和执行,不会消耗 CPU 时间。
阻塞:任务被阻塞时,仍然参与调度,但是处于等待状态,不会执行任务代码,直到条件满足。

等待条件:
挂起:通常是手动挂起任务,等待手动恢复。
阻塞:任务被阻塞通常是因为等待某些事件的发生,例如等待资源可用或者等待超时。

恢复方式:
挂起:任务通常需要显式地调用恢复函数来恢复执行。
阻塞:任务在等待的条件满足或者超时时会自动解除阻塞。

一、对任务的定义

通常,裸机编程会将很多功能函数放入到大循环中按顺序执行。

当多任务系统中,将每个功能分割称独立的无法返回的函数

任务函数示例:

参数传入的是指针变量
void task_name (void *parg)
{
   
	任务主体,因无限循环,不会推出,所以无返回值。
	for(;;)
	{
   //代码功能实现
	}
}

二、任务的实现过程函数

整个过程的函数都放在后面了,可能会有点繁琐,如果想看框架和脉络,直接拉到最后部分。

1、任务栈

全局变量----》存放
子函数调用----》局部变量存放
中断发生—》函数的返回地址放
以上三种情况下,裸机程序会都会存放在栈中。(对应物理世界中的ram芯片)
在多任务系统中,每个任务都需要独立的存储空间,保证互不干扰。
其通常是预定义的全局数组动态分配的内存空间,但都是存放在ram芯片中。
由多少个任务,就定义多少个任务栈

例如屏幕系统和检测系统分别是两个任务,则需要定义两个独立的全局数组

这里的128是字,不是字节 128*4=512字节。
FreetRTOS中会把c中的标准数据类型用typedef来重新定义

#define TASK1_STACK_SIZE_128
StackType_t TaskDisplay[TASK1_STACK_SIZE]
#define TASK2_STACK_SIZE_128
StackType_t TaskDetect[TASK2_STACK_SIZE]

2、定义任务函数

void task2_name (void *parg)
{
   
	任务主体,因无限循环,不会推出,所以无返回值。
	for(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值