单片机基础核心知识点汇总(三十八)

目录

前言

一、调度器到底做什么

[二、FreeRTOS 四大任务状态](#二、FreeRTOS 四大任务状态)

[1、运行态 Running:](#1、运行态 Running:)

[2、就绪态 Ready:](#2、就绪态 Ready:)

[3、阻塞态 Blocked:](#3、阻塞态 Blocked:)

[4、挂起态 Suspended:](#4、挂起态 Suspended:)

三、优先级抢占机制

四、时间片轮转机制

五、空闲任务是什么

六、工程实战现象总结

[1、高优先级任务 while 循环无延时。](#1、高优先级任务 while 循环无延时。)

2、同优先级任务之间互不交替执行。

[3、任务调用 vTaskDelay 之后 CPU 占用率没有降下来。](#3、任务调用 vTaskDelay 之后 CPU 占用率没有降下来。)

4、任务挂起之后,系统好像整体卡住。


前言

本篇重点剖析 FreeRTOS 内核调度逻辑:四大任务状态切换、优先级抢占机制、时间片轮转以及空闲任务。把这一块理解透彻之后再去学习队列、信号量,才能够真正处理多任务同步互斥带来的各类工程问题。

一、调度器到底做什么

FreeRTOS 调度器就是操作系统内核里负责挑选任务的模块。

单片机是单核 CPU,同一时刻只能够执行一份任务代码。调度器不断从就绪任务列表选出最合适的任务交给 CPU 执行。整体遵循两条核心规则:高优先级任务优先执行;同优先级就绪任务开启时间片轮转。

这里有一个很重要误区:多任务并不是真正物理并行运行。单核 MCU 只是高速来回切换任务,切换速度极快,给人的感官效果好像多个任务同时跑。

二、FreeRTOS 四大任务状态

1、运行态 Running:

任务此刻占有 CPU 资源,正在执行自身任务函数。单核单片机任意时间点最多只能有一个任务处于运行态。一旦发生任务切换,当前任务立刻退出运行态。

2、就绪态 Ready:

任务运行条件全部满足,可以随时投入运行,但是此刻 CPU 正在运行另一个优先级更高的任务。任务万事俱备,只等待调度器选中自己。新创建出来的任务默认进入就绪态。

3、阻塞态 Blocked:

任务主动放弃 CPU 进入等待状态,最典型场景就是调用 vTaskDelay 延时。处于阻塞态的任务不再消耗 CPU 时间,调度器直接跳过该任务,转而执行其它就绪任务。新手高频踩坑:任务内部使用 for 循环空延时等待,而不是 vTaskDelay,任务会一直停留在就绪态,死死占用 CPU 不放。

4、挂起态 Suspended:

调用 vTaskSuspend 把任务挂起。挂起之后任务直接停止,不会参与调度,哪怕没有任何延时,也得不到 CPU 执行机会,需要调用 vTaskResume 恢复才可以重新参与调度。
简单梳理状态流转:新建任务→就绪态;调度器选中→切换为运行态;调用延时 / 等待信号量→进入阻塞;延时结束回到就绪;调用挂起函数进入挂起;解除挂起回到就绪。

三、优先级抢占机制

FreeRTOS 默认开启优先级抢占。只要出现一个更高优先级任务变为就绪态,调度器立刻发生任务切换,暂停当前正在跑的低优先级任务,立刻执行高优先级任务。

举个工程例子:任务 A 优先级 2 正在运行,此刻任务 B 优先级 3 解除延时进入就绪,系统马上抢占 CPU,任务 B 开始运行。

这里一个非常常见工程坑:高优先级任务如果一直处于就绪态,永远不会让出 CPU,低优先级任务会彻底饿死,永远得不到执行机会。比如高优先级任务 while 循环里面没有 vTaskDelay,不停空跑,低优先级任务完全无法运行。很多人遇到优先级失效,实际就是发生任务饿死现象。

四、时间片轮转机制

抢占模式下,如果多个任务拥有完全相同优先级,就会启用时间片轮转。

每个任务分配固定长度时间片,任务用完自己时间片之后,即便还没有做完事情,也要让出 CPU,交给同优先级下其它就绪任务执行。

注意配置项 configUSE_TIME_SLICING,如果关闭这个宏,同优先级任务就不会做时间片轮转,一旦某个同优先级任务拿到 CPU 就会一直跑下去。实际项目一般保持打开。

时间片不等于延时,时间片只是分配 CPU 使用时长,任务如果中途进入阻塞态,会直接放弃剩余时间片。

五、空闲任务是什么

系统启动调度器之后会自动创建空闲任务,优先级是 0,也就是整个系统最低优先级。

当所有用户任务全部进入阻塞或者挂起状态,没有其它就绪任务的时候,CPU 就跑空闲任务。

空闲任务有几点工程注意事项:

  1. 千万不要在空闲任务里面做耗时业务逻辑;
  2. 如果开启 configUSE_IDLE_HOOK 空闲钩子函数,钩子函数内部不能调用会造成阻塞的 API,例如 vTaskDelay;空闲钩子里面一旦阻塞,系统行为就异常;
  3. 低功耗场景经常利用空闲钩子,在空闲任务里面进入单片机休眠。

六、工程实战现象总结

1、高优先级任务 while 循环无延时。

  • 后果:一直占用 CPU,低优先级任务彻底饿死。,
  • 解决:合适时机释放 CPU,调用阻塞类 API;

2、同优先级任务之间互不交替执行。

  • 排查方向:检查 configUSE_TIME_SLICING 宏是否打开;

3、任务调用 vTaskDelay 之后 CPU 占用率没有降下来。

  • 排查:确认是 vTaskDelay,不要自己写 for 循环空等待;

4、任务挂起之后,系统好像整体卡住。

  • 排查:确认是否把全部任务都挂起,如果全部任务挂起,系统只会跑空闲任务。
相关推荐
黑妹天下第一乖4 小时前
第09讲 · 多媒体与音频 SDK:硬件编解码与端侧语音
人工智能·嵌入式硬件·深度学习·机器人·音视频·iot
comyccccc4 小时前
LM2596电源PCB布局布线全解析学习笔记
单片机·嵌入式硬件
恒锐丰科技林技术员6 小时前
EG2122 半桥栅极驱动芯片原理与工程应用解析
经验分享·嵌入式硬件·硬件工程
qq_401700416 小时前
FreeRTOS 堆内存管理源码剖析:释放一块内存,空闲块数量反而变少了?
单片机·freertos
新晨单片机设计7 小时前
S017C-基于STM32汽车防酒驾系统(心率、血氧、短信)【Proteus仿真+Keil程序+原理图】
stm32·单片机·proteus·防酒驾报警系统
fly_sunnn8 小时前
STM32-GPIO输出以及按键控制LED&光敏传感器控制蜂鸣器
stm32·单片机·嵌入式硬件
数字新视界8 小时前
U位资产管理系统发布全面数字化监控解决方案
嵌入式硬件·物联网·系统架构·机房管理·动力与环境监控系统
qq_4017004110 小时前
FreeRtos:SysTick的功能分析
单片机·嵌入式硬件
zbyyd11 小时前
i.MX6ULL 裸机开发|GT9147 触控 + SPI 与 ADXL345 加速度传感器驱动
单片机·嵌入式硬件
fly_sunnn11 小时前
STM32-LED闪烁·LED流水灯·蜂鸣器
stm32·单片机·嵌入式硬件