入门FreeRTOS笔记整理

该笔记基于公开免费视频整理,介绍了FreeRTOS实时操作系统。包含RTOS简介、移植方法、启动流程等内容,重点讲解任务管理、调度、通讯机制,如消息队列、信号量等,还涉及系统配置、调试方法、动态内存管理及低功耗模式等,有编程测试与综合应用示例。

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

视频名:视频专辑 - FreeRTOS实时操作系统(十年功力,力求全面,通俗易懂)

https://www.bilibili.com/video/BV18R4y147DB/?spm_id_from=333.999.0.0&vd_source=6815e3297898473155e44cdd9339ebe0
在这里插入图片描述
非常推荐这套FreeRTOS教程。对新手友好,收获很多。但有部分视频不公开(少数),要收费
这个笔记根据公开的免费视频整理,部分内容还需补充,但不影响知识的获取

视频中未公开章节,章节名后面用***号标注

UP主对源码进行了解析,有助于培养初学者的良好习惯

内含一些小作业
好了,那就开始吧
(¬‿¬)

入门FreeRTOS笔记整理

绪论

在这里插入图片描述
第一部分:介绍操作系统、移植操作系统等
第二部分:比较重要,特别是任务管理
第三部分:任务跟任务之间、任务跟中断之间通讯,数据传输问题。操作系统中链表用的非常多,一定要了解。通讯方面的
第四部分:
第五部分:把一些外设结合起来,进行一些系统的应用

RTOS简介

在这里插入图片描述
嵌入式操作系统
分时操作系统:按时间片完成,任务之间没有优先级
例如电脑是分时操作系统,FreeRTOS是实时操作系统(弱实时操作系统)
在这里插入图片描述
FreeRTOS实时操作系统简介
在这里插入图片描述
在这里插入图片描述
好处
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
裸机系统与多任务系统
裸机系统事件在主函数中完成。多任务系统事件在任务中完成,同时,任务有优先级
操作系统编程核心在任务,裸机系统编程核心在主函数

FreeRTOS移植

在这里插入图片描述

手动移植FreeRTOS***

STM32cubeMX生成FreeRTOS***

FreeRTOS启动流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

FreeRTOS编码风格

在这里插入图片描述
在这里插入图片描述
32位和64位设置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

FreeRTOS调试方法

理论

在这里插入图片描述
查看栈的使用情况,避免栈溢出,栈多了就减一点
运行状态,空闲状态
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
定时器2,HAL_Delay()时间基准。现在滴答定时器作为系统定时器调用了,所以需要单独的定时器作为延时
在这里插入图片描述
定时器3配置为20kHz,作为系统的计数
在这里插入图片描述
任务的配置:
划线部分(从上到下):任务名称长度(最大32)
配置操作系统内存(默认3k)这里是10k
启用任务状态的功能宏定义
在这里插入图片描述
在回调函数里面定义一个变量,让它加1
在这里插入图片描述
在这里插入图片描述
第一个是初始化函数,系统启用任务调度时,会调用这个函数,把这个数据清0
第二个函数,每隔一段时间获取这个值,这个值在定时器里面计数的。每个任务单独获取,任务启动获取一次,任务结束获取一次,知道任务占用时间,除以总数得到利用率
在这里插入图片描述
创建一个任务,定义一个数组保存信息,调用函数就会把信息放到数组里面,只需要打印就行了

现场编程***

系统配置

说明

在这里插入图片描述
FreeRTOS.h:如果没有定义,就定义
在FreeRTOSConfig.h中定义

Config宏-内核配置***

Config宏-其他配置***

INCLUDE宏配置***

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过预编译移除未使用的内核组件

任务管理

任务概念与任务状态

在这里插入图片描述
理论上对任务数量没有限制。耦合性小。任何时刻,只有一个任务得到运行,因为单片机是单CPU。栈空间:一段连续的内存。任务不会退出,只不过是由调度器调度而已。释放系统资源(栈空间)
在这里插入图片描述
因为任务是由调度器调用的,所以有任务状态。就绪态任务在等待CPU(等待调度),因为FreeRTOS是抢占式的,任务是有优先级的。挂起需要手动挂起、手动恢复,阻塞是等待一些标志位
在这里插入图片描述

系统启动与空闲任务

在这里插入图片描述
函数没有形参,很容易看。下面是标准的启动函数(task.c里面),上面是HAL库的封装
在这里插入图片描述
在这里插入图片描述
FreeRTOSConfig.h中定义内存空间
在这里插入图片描述

任务创建

在这里插入图片描述
静态任务、动态任务创建。栈空间,任务控制块(结构体、任务的参数都在里面)
在这里插入图片描述
在这里插入图片描述
任务函数(任务体)名和任务名(只是个字符串)可以一样,也可以不一样
栈空间太大就浪费,太小就出错,在32里面是4字节。128就是512字节
0是优先级最小的,一般给空闲任务
可以通过任务句柄,操作任务。非常重要。指针的指针,所以需要进行取址
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
方便创建不同的任务

详解任务句柄***

指向任务控制块的一个结构体指针,可以操作任务

任务删除、挂起、恢复

在这里插入图片描述
可裁剪
动态内存:比如一个任务,任务里面又重新申请了内存 (通过内存申请函数),需要手动删除,任务释放只是释放了任务的栈空间
在这里插入图片描述
删除任务前,要判断任务存不存在,不存在就不能删除,否则会出错
删除后,设置任务句柄为空,下一次不会再删除
在这里插入图片描述
可以多次调用,任务肯定存在。跟删除不一样(还需要判断任务是否存在)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
中断与任务的同步:比如在任务里面挂起,在中断里面恢复。按道理会立马执行这个任务(同步了),但在恢复中,如果别的任务优先级更高,就会去执行别的任务(不会执行这个任务),中断与任务之间就不会同步了
在这里插入图片描述
比如:外部中断中使用

任务管理编程***

任务调度

调度器

在这里插入图片描述
调度算法应用不需要了解。合作式调度很少使用

调度方式

在这里插入图片描述
单任务,不是多任务,不能进行任务的抢占
不需要给每个任务分配单独的栈空间,RAM占用空间小。算法简单,ROM占用空间小
在这里插入图片描述
这里的多任务是每次只有一个程序在运行,但在反复切换(速度非常快,感觉在同时进行)
CPU永远都在执行高优先级任务
在这里插入图片描述
系统默认开启,不要关闭
同优先级任务:如果没有启用时间片调度,那么所有任务的优先级就不能使用同样的优先级了
任务运行时,按时间片来的
时间片可以在配置文件里设置Tick…()(Tick:1000-1ms,100-10ms,20-50ms),一个任务一个时间片
FreeRTOS只能设置的一个Tick,不能设置例如4个Tic。其他操作系统可能可以

抢占式调度编程测试***

时间片调度编程测试

在这里插入图片描述
时间片设为20,50ms,任务是10ms,可以执行5次
写错了。不能阻塞10ms,应该正常延时10ms
可以在配置文件中,用宏定义禁止时间片调度

任务栈大小确认***

任务栈溢出检测

在这里插入图片描述
栈溢出检测机制在出产品时,可以关掉

任务栈溢出编程测试***

任务与中断优先级、临界保护

中断优先级

NVIC知识回顾
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
抢占优先级:
响应优先级:
在这里插入图片描述
在这里插入图片描述
调度器通过SVC中断启动第一个任务
系统服务中断配置为0,优先级最高
PendSV任务挂起中断、Systick滴答定时器中断优先级最低。不会打断任务中断。PendSV用于做任务切换,Systick中断是一个时基中断。中断优先级太高,影响系统实时性
在这里插入图片描述
在这里插入图片描述
源码里面有临界段代码(非常重要的代码):并不希望任何中断把它停下来。在执行这段代码前,会关全局中断。结束后,再开启全局中断。这会带来副作用,任务非常重要,任务中断被关闭,系统实时性遭到破坏,比如飞机、有害气体检测
basepri一般配置为5
在这里插入图片描述
不受系统临界处理,管理的中断

任务优先级

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
中断优先级值越小,优先级越高。任务优先级值越小,优先级越低
时间片调度要启用
永远执行优先级最高的任务,因为是抢占系统
在这里插入图片描述
必须是阻塞式的原因:如果不阻塞,低优先级得不到执行
在这里插入图片描述
在这里插入图片描述
IRQ任务,比如:按键中断、串口中断(比如通过MODBUS解析协议)
低优先级的时间片调度任务,这类任务一般设置成一样的(1、 2),让它们时间片运行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

开关中断与临界段函数

在这里插入图片描述
不允许中断打断的方法:关操作系统可以管理的中断
在这里插入图片描述
全局变量被很多任务使用,需要做临界段处理的原因:一个变量一次性只能被一个任务调用,如果被两个任务同时调用就会出问题,这个时候就要保护了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
临界区关闭了中断,同时会计数
在这里插入图片描述
退出临界区,变量会减1,变量为0,才会开启中断
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
临界段处理函数必须要成对使用,每进入一次,计数值都会加一。进来几次,退几次

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
有形参(会保存原来的值,然后恢复原来的值),跟开关中断函数不一样(默认是0)
在这里插入图片描述
在这里插入图片描述

编程测试临界段处理函数***

调度锁、中断锁、任务锁

在这里插入图片描述

调度锁编程测试

在这里插入图片描述
不是开挂函数
在这里插入图片描述
应用代码:比如对时间要求很高的代码,通过一定的时序采集数据,避免被其他任务打断
在这里插入图片描述
使用定时器延时,而不是系统延时

时间管理(系统节拍、延时函数)

在这里插入图片描述
延时,比如说,高优先级任务需要延时,延时之后释放CPU
超时,等待一个时间,不能一直等待
任务切换也需要时钟节拍。通常有一定的时间,去检查任务需不需要切换
系统的额外开销:占用CPU的时间
在这里插入图片描述
SysTick裸机编程中,当成定时器使用。操作系统中,用作系统节拍
100KHz-10ms,10KHz-100ms,一般是1-100ms之间。如果配置太小,CPU一直在响应中断,开销特别大。配置太大,没办法精确延时。一般用1KHz
在这里插入图片描述
释放CPU使用权,也可以采用等待一个事件。时间延迟用的比较多一点
第一个是相对延时,第二个是绝对延时,第三个是获取当前计数值(任务里面),第四个是获取当前计数值(中断里面)
在这里插入图片描述
延时多少个Ticks(时钟节拍),相对调用这一刻的延时
在这里插入图片描述
在这里插入图片描述
第一个时参。采集任务开始运行的时间赋给它
在这里插入图片描述
50s后150s调用这个函数,时间精确,能够实现周期性延时
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相对延时和绝对延时的区别与编程测试***

链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
操作系统,任务的数据就是非连续的,可以给所有任务新建一个链表,然后进行排序,就可以进行系统调度了。添加任务是添加任务节点,删除任务是删除任务节点
双向链表更加灵活

单向、双向链表

在这里插入图片描述
首尾相连,首就是尾,尾就是首。根节点:不存储数据,链表的生产者,比如记录整个节点的数量。通过一个节点,只能找到下一个节点,不能找到上一个节点。所占内存小一点
在这里插入图片描述
离散的数据:比如操作系统中任务、软件定时器、消息队列、信号量

FreeRTOS中链表实现***

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

链表与节点初始化函数

在这里插入图片描述
后面两行用于验证
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
里面的指针,因为没有节点,指向自己

链表操作函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
排列,比如任务优先级查找最高优先级,非常方便
在这里插入图片描述
第一个参数是链表,第二个参数是节点。将节点按升序插入链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
只需要一个形参,需要删除的节点。节点里面已经包含链表,所以不需要链表

链表编程仿真与测试***

消息队列

在这里插入图片描述
在这里插入图片描述
不固定长度的消息:比如说串口接收、spi接口传输
在这里插入图片描述
具有超时机制,比如说用FreeRTOS读数据,如果没有数据,会进行等待(把任务挂起来),一旦有数据,任务就立马去获得这个数据。如果超时,就退出来
有效管理任务,比如任务1发数据,如果消息队列满了,发不了。就会进行任务1挂起操作,等空了,再发送数据。任务2读数据,如果消息队列里面没有数据,任务2挂起,一旦有数据,就会立马获得这个数据
防止多任务访问冲突,比如说任务在读队列(锁定队列),其他任务也要读这个队列(这个任务就读不了,只能等待)。如果使用数组,有可能两个任务同时读写数组,有可能出错
FIFO:默认是FIFO,先进先出
LIFO:后进先出
在这里插入图片描述
通过标志位可以判断,读到Pass,没有读到Fail
在这里插入图片描述
在这里插入图片描述
队列控制块:一个结构体,里面有一些变量,比如:队列的长度、个数、队头、队尾
在这里插入图片描述
在这里插入图片描述
数据是复制过去的,有些操作系统是传地址。所以中断里面一般不建议搬运太长的数据(中断要快进快出),可以通过一个信号量发送一个标志位,让任务去搬运数据

消息队列常用API函数

在这里插入图片描述
第一个是消息队列的动态创建,第二个是消息队列的删除,第三、四个队列的发送(任务、中断),第五个是接收数据(任务里面)
传数据一般是从中断里面发送,用任务来接收

消息队列句柄、创建与删除***

任务中消息队列的发送

在这里插入图片描述
复制指定固定长度的数据,比如一个变量只占了四个字节(32位),传10个字节,后面六个地址是连续地址(无效数据)。创建队列长度要合适
在这里插入图片描述
太长数据可以分段发送
pdPASS改为pdTRUE

中断中消息队列的发送

中断中发送与任务中发送不一样。中断中发送,没有超时机制,不会等待
在这里插入图片描述
如果有高优先级任务准备就绪,立马进行一次任务切换,不等系统调度,提高系统实时性
第三个参数不一样
在这里插入图片描述
在这里插入图片描述
因为是数组,所以没有取址

任务中消息队列的接收

在这里插入图片描述
在这里插入图片描述
如果空间小了,比如说5个比特的数据,只有4个比特的空间,第5个比特也会写过来(未定义的地址),随便写数据可能会导致系统故障
在这里插入图片描述
在这里插入图片描述

消息队列应用编程-任务与任务***

消息队列应用编程-中断与任务***

信号量

信号量是消息队列的一种简化应用
在这里插入图片描述
资源管理:比如说机房的电脑管理、文件的管理
信号量本身不是数据,本身只是一个机制
在这里插入图片描述
技术信号量改为计数信号量

二值信号量的定义与应用

在这里插入图片描述
二值信号量是操作系统的一个资源,可以直接用
在这里插入图片描述
在这里插入图片描述
消息大小为0,说明本身不能存数据
信号量的实现(创建、发送、获取、释放)都是通过队列的函数实现的
在这里插入图片描述
在这里插入图片描述
采集一次,刷新一次。更好的发挥CPU性能

二值信号量的运作机制

在这里插入图片描述
任务1获取信号量,因为信号量没有,所以进入阻塞。需要任务2发送一个同步信号,任务1才能继续执行
在这里插入图片描述
在这里插入图片描述
任务1获取信号量,因为信号量没有,所以进入阻塞。串口接收中断,接收数据之后,发送一个信号,任务1(处理串口数据)开始执行
在这里插入图片描述

二值信号量的常用API函数

在这里插入图片描述
在这里插入图片描述
释放和获取需要同步操作
第一个是创建二值信号量。第二、三个是释放二值信号量(任务中、中断中)。第四个是获取二值信号量。第五个是删除二值信号量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
没有超时机制的原因:0释放变为1,1不需要释放
不支持递归互斥(用不到)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
有两个形参,第二个形参为了提高系统实时性(中断中任务不能切换,所以中断完之后立马切换一下)
在这里插入图片描述
在这里插入图片描述
第二个形参是超时机制。获取时,可能是无效的,也可能是有效的。如果有效,就会立马同步,如果无效就需要等待(等待多少个Ticks)。如果超时了,就会自动退出来
任务中获取
在这里插入图片描述
很少在中断里面获取信号
串口接收一般都是永久等待。可用可不用就不需要永久等待
在这里插入图片描述
等待原因:串口数据还没过来
这里只是打印串口信息,也可以通过MODBUS协议控制一些外设

二值信号量同步应用编程(任务与任务)***

二值信号量同步应用编程(中断与任务)***

计数信号量的定义与应用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
计数信号量,因为可以计数,所以可以用作资源管理
在这里插入图片描述
在这里插入图片描述
计数信号量为0时,需要等待

计数信号量的运作机制

在这里插入图片描述
在这里插入图片描述
中断和应用一般都是同步使用,很少会用计数
共享资源:比如停车位、机房电脑、产品外设
任务1获取资源,如果资源变为0,可以等待,如果超时,自动退出来。如果资源被别的任务释放了,就可以获取资源,继续运行,运行之后,释放资源

计数信号量的常用API函数

在这里插入图片描述
一般不删除信号量,除非真的不用了
第一个是创建计数信号量,其他的函数和二值信号量一样
在这里插入图片描述
在这里插入图片描述
如果初始值定义为0,没信号量可用,必须等待释放。如果定义为N,就可以使用计数信号量
heap大小不足,内存不够
在这里插入图片描述
在这里插入图片描述
configUSE_COUNTING_SEMAPHORES,默认是0(节约内存),必须配置为1。后面的那个是动态分配,基本都是1,因为一些任务,还有其他的一些组件都是动态分配的
形参校验 configASSERT
在这里插入图片描述
删除的形参应该是句柄,不是void
在这里插入图片描述
释放的形参只有句柄,没有超时(要么成功,要么失败)。比如停车场把车开出去,不需要等待。开进来,要等待
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第三个形参设为0,不会等待

计数信号量的应用编程详解***

互斥信号量的定义与应用

在这里插入图片描述
二值信号量可以用于同步(类似于裸机编程的Flag),可以但不建议临界资源管理(存在优先级反转问题)。互斥信号量可以用于临界资源管理
在这里插入图片描述
在这里插入图片描述
默认长度是1,资源可用。二值信号量默认可能是0或1
在这里插入图片描述
互斥信号量只能用于任务与任务之间
在这里插入图片描述
在这里插入图片描述
死锁,比如说只是普通的互斥信号量,任务1获取,互斥信号量无效(1->0),任务1再次获取(用完互斥信号量没有释放),就会等待(任务挂起),信号量发生死锁(信号量本身是无效的,别的任务用不了,任务永久等待),出现问题
获取一次,释放一次

优先级翻转详解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果使用互斥信号量,优先级继承机制:当任务1等待任务3的时候,会临时把任务3的优先级抬高到任务1的优先级。低优先级任务继承高优先级任务。这样一来,任务3执行的时候,任务2就不能打断任务3了,任务3执行完之后,优先级会恢复。任务1开始执行(任务1只要等待任务3执行完成,不用等待任务2),然后再执行任务2

优先级翻转编程测试***

优先级翻转的串口打印详解***

互斥信号量的运作机制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为会抬高任务优先级,所以中断中是无效的,只能用于任务中

互斥信号量的常用API函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
释放是不会等待的
在这里插入图片描述
在这里插入图片描述
获取需要等待,第二个形参为0就是不等待,这里是永远等待

互斥信号量的应用编程***

事件

事件的概念与应用

在这里插入图片描述
如果要用到数据传输,可以用队列
信号量只能实现一对一的同步,任务可以一对多(比如裸机编程中的if语句)
比如按键标志、串口接收都可以看作事件
在这里插入图片描述
在这里插入图片描述

事件的运作机制

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

事件的常用API函数

在这里插入图片描述
删除事件组一般很少用,除非不用了
第一个是动态创建事件组,一般很少静态。第三个等待事件组一般在任务中等待,很少在中断中等待
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在中断里面调用了这个函数,但不会在中断里面置位这个事件标志组,中断把这个任务交给定时器,在定时器里面进行置位
优先级设置高,退出中断后,立马执行这个任务(置位)。优先级太低,可能被别的任务抢占,影响同步功能
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

事件的编程应用-任务与任务***

事件的编程应用-中断与任务***

软件定时器

软件定时器的概念

在这里插入图片描述
软件定时器在任务中执行回调函数,上下文是任务。硬件定时器通过中断实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
很重要,所有软件定时器都是通过定时器守护任务管理
在这里插入图片描述
在这里插入图片描述

软件定时器的应用

在这里插入图片描述
对时间精度要求不高的任务:比如说间隔1s或者一定时间采集传感器,WiFi数据模块定时传数据
在这里插入图片描述
在这里插入图片描述
1000-1s中执行1000次,1ms
在这里插入图片描述
定时器的应用是在回调函数中完成一些功能
回调函数:作为参数传递(函数指针),函数的形参是函数指针,通过函数指针调用的这个函数,叫做回调函数
回调函数方便是因为操作系统写好之后,函数指针已经定义好了,函数可以自己命名之后,把函数地址赋给指针,就可以调用它,非常方便移植。如果没有回调函数,就不能自己创建函数了,不灵活
在这里插入图片描述
回调函数的调用
通过定时器的句柄可以识别到ID号,以辨别是哪个定时器的回调函数
通过句柄间接调用自己创建的函数
在这里插入图片描述
软件定时器通过任务来执行,如果优先级很低,定时器精度会受到影响
在这里插入图片描述
守护任务需要间隔一定的时间,检查有没有任务被定时到。还要去接收队列的指令
如果上面一个函数挂起,那就意味着下面那个函数就不执行了,会影响实时性
回调函数要跟中断一样,快进快出,不要长时间的停留

软件定时器的常用API函数

删除软件定时器不一定,如果用完了,可以释放资源。获取ID可要可不要
在这里插入图片描述
这里的定时器的创建是动态创建(一般都是)
启动可以在任务中启动,也可以在系统启动之前启动(中断中启动,用的很少)
中断中停止,用的很少
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
操作定时器通过句柄来实现,所以要先了解一下它的句柄
方便调试,打印的时候,可以把定时器的名称打印出来
所有定时器在链表里面进行排序,守护任务在链表里面读取信息
单次模式,运行一次就会自动删除
通过ID号识别是哪个定时器。通过名字(字符串)来识别,比较麻烦
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ID号是指针,所以要取址,再把指针转换一下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不会立即执行的原因,执行是在守护任务里执行的,如果调度器还没开始调度,尽管发送队列成功了,但守护任务还没有执行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
返回时指针
在这里插入图片描述

软件定时器的应用编程***

任务通知

在这里插入图片描述
不用的话,可以配置为0,每次创建任务时,可以减少5个字节的RAM
在这里插入图片描述
在这里插入图片描述
前面两个可以当作队列来使用,
只能一对一
通知不会等待,没有超时机制

任务通知的运行机制

在这里插入图片描述
在这里插入图片描述
比如说有个任务等待通知,如果没有通知就阻塞了,如果别的任务或中断向这个任务发通知,它就会被唤醒。如果别的任务没有发通知,它也会超时退出来
跟其他通信机制一致,可以在一定程度上替代

任务通知的常用API函数

在这里插入图片描述
在这里插入图片描述
任务通知值,别的任务或者中断可以发通知改变这个值
在这里插入图片描述
任务中的通知状态一般又三种。第一种是默认状态。没有等待通知。第二种是任务正在等待通知。第三种,如果一个任务向另一个任务发送通知,另一个任务表示已经接收到通知
状态的切换:比如说第一次发送通知给任务,发送完之后,任务的状态就会变成已经接收。再次发送,还是处于接收的状态。如果任务开始获取通知,现在没有通知值,就会进入阻塞(等待中),如果接收到通知了,处理完之后,又会变成没有在等待了。三个状态里面不断切换。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
pdTRUE当作二值信号量使用,pdFALSE当作计数信号量使用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第一个参数,仅仅改变任务通知的状态,不会改变任务通知值
不懂的,可以适当看一看源码
返回值应该是返回pdFAIL
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第三个参数保存通知值(获得),可以通过这个参数来回传通知值
可以节约5个字节,不是8个字节

任务通知代替二值信号量的应用编程

在这里插入图片描述

任务通知代替计数信号量的应用编程***

任务通知代替消息队列的应用编程***

任务通知代替事件组的应用编程***

综合应用1与代码讲解

在这里插入图片描述
在这里插入图片描述
LED:只是指示作用,所以优先级最低,代表系统正在运行状态
KEY:事件组的触发
Display:数码管的显示,软件定时器在函数里面发送任务通知,来刷新这个数据
Event_Sync:事件同步的任务
Modbus:单片机通过空闲中断+DMA功能产生一个中断,通过二值信号量同步过去,进行一个协议解析。二值信号量的同步应用
Queue_Receive:队列接收,Modbus收到的数据通过队列发送给任务,这个任务再把16进制数据转换成ASCII码,打印出来
操作系统就是管理任务的,任务就是用来管理裸机代码的,从而实现想要的功能
计数信号量和互斥信号量没用,在单片机中用的很少

动态内存管理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
动态内存,内存可以申请,可以释放
在这里插入图片描述
在这里插入图片描述
内存碎片:比如说一开始是一百块内存,后面有很多申请释放(大小不一样),会出现很多内存小块(不方便使用,因为太小),造成资源的浪费
内存碎片的回收,通过链表实现,小的内存块通过链表的合并组成大的内存
在这里插入图片描述
不连续的内存区,比如单片机内部有SRAM(不够用),外部SRAM,方式五能够把这两个SRAM链接在一起,能够一起使用

动态内存管理的总结与应用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

动态内存的编程测试(heap_4和heap_1)

在这里插入图片描述

动态内存的编程测试(heap_5)***

独立看门狗检测任务执行

在这里插入图片描述

看门狗检测多任务执行思路

在这里插入图片描述
在这里插入图片描述
监测系统死机(跑飞),由于某种原因:比如恶劣的工业环境
监测任务有没有长时间得到执行,比如低优先级任务长时间得不到执行
一对多。比如可以在一定时间内监测这个事件
如果任务出现挂起和删除,就不检测这个任务

看门狗检测多任务编程***

低功耗Tickless模式

STM32低功耗模式介绍

在这里插入图片描述
在这里插入图片描述

STM32低功耗的编程***

Tickless模式介绍

在这里插入图片描述
在这里插入图片描述
不能直接把睡眠模式放在空闲任务的原因,因为Tick是中断,如果直接在空闲任务睡眠,会反复被唤醒,低功耗不是最优的
Tick时钟不能关断,不然就没法执行一些堵塞任务。比如定时任务需要中断唤醒
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Tickless模式源码分析

在这里插入图片描述

Tickless模式编程测试***

综合应用2

在这里插入图片描述
间隔1s一般是用软件定时器,再通过二值信号量同步
第二点可以用二值信号量,也可以用任务通知做同步,中断里面给同步信号,任务里面处理串口数据
第三点是第二点通过队列传输数据
数码管显示,可以通过二值信号量同步显示
在这里插入图片描述
在这里插入图片描述

综合应用3

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值