FreeRtos源码分析之任务状态管理(三)

2023-05-16

一、概述

FreeRtos的每一个任务都有一个对应的优先级,较高优先级的任务具有优先运行的权利,当高优先级的任务调用系统的延时函数或者需要阻塞等待某些信号时,会让出CPU的使用权,从而使低优先级的任务得以运行。

FreeRtos支持抢占式调度,当低优先级的任务正在运行时,如果有高优先级的任务处于就绪状态,系统优先运行高优先级的任务。

如果两个或者多个任务具有相同的优先级,这些任务会轮换运行,并且它们会占用相同的时间片。

FreeRtos有两种切换任务的方式,一种是让内核自己按照约定好的规则进行切换,一种是调用portYIELD函数主动进行任务切换。

二、FreeRtos任务管理

在了解任务切换之前,我们需要先了解FreeRtos是如何进行任务管理的。
FreeRtos的任务共有5种状态:

  • 运行态,表示任务正在运行;
  • 阻塞态,任务调用了vTaskDelay或者其它阻塞API;
  • 就绪态,任务处于等待运行的状态;
  • 挂起态,任务被挂起,调用vTaskSuspend函数;
  • 删除态,任务被删除;
#define tskRUNNING_CHAR      ( 'X' ) //运行态
#define tskBLOCKED_CHAR      ( 'B' ) //阻塞态
#define tskREADY_CHAR        ( 'R' ) //就绪态
#define tskDELETED_CHAR      ( 'D' ) //删除态
#define tskSUSPENDED_CHAR    ( 'S' ) //挂起态

FreeRtos使用四个列表对阻塞态、就绪态、挂起态任务进行管理,使用pxCurrentTCB对运行态任务进行管理(系统运行时,同一时刻只能有一个任务处于运行状态):

PRIVILEGED_DATA TCB_t * volatile pxCurrentTCB = NULL;

PRIVILEGED_DATA static List_t pxReadyTasksLists[ configMAX_PRIORITIES ]; /*< 就绪态任务列表,按照优先级顺序排列. */
PRIVILEGED_DATA static List_t xDelayedTaskList1;                         /*< Delayed tasks. */
PRIVILEGED_DATA static List_t xDelayedTaskList2;                         /*< Delayed tasks (two lists are used - one for delays that have overflowed the current tick count. */
PRIVILEGED_DATA static List_t * volatile pxDelayedTaskList;              /*< 延时任务列表,初始化时指向xDelayedTaskList1. */
PRIVILEGED_DATA static List_t * volatile pxOverflowDelayedTaskList;      /*< 当前系统计数器溢出的延时任务列表,初始化时指向xDelayedTaskList2 */
PRIVILEGED_DATA static List_t xPendingReadyList;                         /*< 挂起态任务列表.  */

任务在创建的时候,系统会将所有任务按照优先级的顺序放入pxReadyTasksLists列表中,换句话说,在任务调度器启动前,所有的任务都处于就绪状态,并且pxCurrentTCB始终指向优先级最高的任务;
当任务调度器启动后,如果某个任务调用了诸如vTaskDelay的系统延时函数或者其它会造成阻塞的API函数,系统会将对应的任务添加到pxDelayedTaskList列表中,此时任务就处于阻塞状态;
当任务调度器启动之后,如果调用了vTaskSuspend函数挂起了某个任务,系统会将其添加到挂起态任务列表xPendingReadyList,此时任务进入挂起状态,直到调用vTaskResume函数接触阻塞。
pxDelayedTaskList和pxOverflowDelayedTaskList
相信很多人都会有这样的疑问:为什么要使用两个列表对阻塞态任务进行管理?
要想了解这一点,我们首先需要了解一个全局变量:xTickCount

PRIVILEGED_DATA static volatile TickType_t xTickCount = ( TickType_t ) configINITIAL_TICK_COUNT;//系统的时钟节拍

在32位系统中TickType_t是一个32位无符号的整型数据,它所能表示的最大值是0xFFFFFFFF,当系统运行满0xFFFFFFFF个时钟节拍后就会产生溢出。
FreeRtos通过调用prvAddCurrentTaskToDelayedList函数将任务添加到延时(阻塞)任务列表,在该函数中系统同样使用一个32位的无符号整数记录任务唤醒的时刻,所以随着系统的不断运行,也会产生溢出,所以需要两个链表来进行记录,当系统计时器溢出时,只需要切换延时任务列表就可以了,实际代码如下:

 xTimeToWake = xConstTickCount + xTicksToWait;//xConstTickCount表示系统时钟节拍xTickCount,xTicksToWait表示延时时间

                listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake );

                if( xTimeToWake < xConstTickCount )//如果产生了溢出
                {
                    /* Wake time has overflowed.  Place this item in the overflow
                     * list. */
                    vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );
                }
                else
                {
                    /* The wake time has not overflowed, so the current block list
                     * is used. */
                    vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );

                    if( xTimeToWake < xNextTaskUnblockTime )
                    {
                        xNextTaskUnblockTime = xTimeToWake;
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }

三、FreeRtos的任务状态转换

FreeRtos的任务在创建之初都会被放到就绪列表中,即处于就绪态。当任务调度器启动之后,处于最高优先级的任务就会被运行,处于运行态。运行态的任务可以通过调用vTaskDelay或者具有阻塞功能的其它API(如xQueueReceive等函数)将任务从运行态变为阻塞态,当阻塞时间到该任务会从阻塞态重新回到就绪态。运行态的任务还可以通过vTaskSuspend函数从运行态变为挂起状态,挂起态的任务只能手动调用vTaskResume函数主动恢复成就绪状态。
处于就绪态的任务还可以通过portYIELD函数主动进行任务切换,使其进入运行状态。
FreeRtos单个任务转换状态图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l3ZmZrqn-1611371821183)(en-resource://database/600:1)]

FreeRtos带中文注释源码Gitee地址:https://gitee.com/zBlackShadow/FreeRtos10.4.3.git

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRtos源码分析之任务状态管理(三) 的相关文章

  • 心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)

    文章目录 前言 介绍 系统框架 原项目地址 本项目开发开源地址 硬件PCB 软件功能 详细内容 硬件外壳制作 WS2812级联及控制 MAX30102血氧传感器 0 96OLED FreeRTOS 效果视频 总结 前言 在好几年前 我好像就
  • FreeRTOS学习笔记(3、信号量、互斥量的使用)

    FreeRTOS学习笔记 3 信号量 互斥量的使用 前言 往期学习笔记链接 学习工程 信号量 semaphore 两种信号量的对比 信号量的使用 1 创建信号量 2 give 3 take 4 删除信号量 使用计数型信号量实现同步功能 使用
  • 【FreeRTOS】多任务创建

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • Freertos中vTaskDelay()是怎么用的

    1 常见的使用场景 void vLED Task void pvParameters while 1 Heartbeat LED vTaskDelay 1000 portTICK RATE MS 说明 上面这段代码的意思是 led翻转后经过
  • STM32移植FreeRTOS的Tips

    转自 http bbs armfly com read php tid 7140 1 在FreeRTOS的demo文件夹中拷贝对应的FreeRTOSConfig h文件后 需要加入一行 define configUSE MUTEXES 1
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • FreeRTOS_中断

    传送门 博客汇总帖 传送门 Cortex M3 中断 异常 传送门 Cortex M3笔记 基础 笔记内容参考 正点原子的FreeRTOS开发手册 cortex m3权威指南 Cortex M3和Cortex M4权威指南等 文中stm32
  • 【FreeRTOS】任务通知的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • 基于HAL库的FREERTOS-----------三.队列

    一 队列简介 在实际的应用中 常常会遇到一个任务或者中断服务需要和另外一个任务进行 沟通交流 这个 沟通交流 的过程其实就是消息传递的过程 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式 但是如果在使用操作系统的应用中用
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS学习(三)开关中断

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 背景知识 Cotex M3的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽 NMI 1个Systick 滴答定时器 Cortex M处理
  • 啊哈C的简单使用

    打开啊哈C 新建一个程序输出hello world include
  • 基于STM32的FreeRTOS学习之中断测试实验(五)

    记录一下 方便以后翻阅 本章内容是接着上一章节进行的实际演练 1 实验目的 FreeRTOS可以屏蔽优先级低于configMAX SYSCALL INTERRUPT PRIORITY的中断 不会屏蔽高于其的中断 本次实验就是验证这个说法 本
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • [FreeRTOS入门学习笔记]定时器

    定时器的使用步骤 1 定义一个handle xTimerCreate创建 2 启动定时器 在Task1中调用 通过队列通知守护任务来执行定时器任务 要再config头文件中定义守护任务相关配置 虽然定时器是在task1中启动 但是定时器的任
  • STM32 Freertos 添加 外部sram heap_5.c

    1 添加外部SRAM 初始化 2 添加heap 5 c 3 初始化heap 5 c 外部堆栈 Define the start address and size of the two RAM regions not used by the
  • FreeRTOS实时操作系统(三)任务挂起与恢复

    系列文章 FreeRTOS实时操作系统 一 RTOS的基本概念 FreeRTOS实时操作系统 二 任务创建与任务删除 HAL库 FreeRTOS实时操作系统 三 任务挂起与恢复 FreeRTOS实时操作系统 四 中断任务管理 FreeRTO
  • FreeRTOS之系统配置

    1 FreeRTOS的系统配置文件为FreeRTOSConfig h 在此配置文件中可以完成FreeRTOS的裁剪和配置 在官方的demo中 每个工程都有一个该文件 2 先说一下 INCLUDE 开始的宏 使用 INCLUDE 开头的宏用来
  • 如何更改 FreeRTOS 中任务的最大可用堆大小?

    我通过以下方式在任务中创建元素列表 l dllist pvPortMalloc sizeof dllist dlllist 有 32 字节大 我的嵌入式系统有 60kB SRAM 所以我希望系统可以轻松处理我的 200 个元素列表 我发现在

随机推荐

  • 一起DIY四轴飞行器(三)添加实时操作系统--freeRTOS

    开发环境 xff1a Windows 软件 xff1a 1 STM32CubeMX 6 3 0 2 MDK 5 14 一 初识freeRTOS系统 1 什么是FreeRTOS xff1f Free 即免费的 xff0c RTOS 全称是 R
  • ESP8266 初次使用

    一 工具 1 ESP8266 01S 淘宝上搜索ESP8266 01S 引脚说明 xff1a 2 USB转串口 给设备供电3 3V xff08 官方说不要用USB转串口的3 3V xff0c 需要单独供电 xff09 xff0c USB转串
  • ubuntu安装boost

    ubuntu安装boost 系统 Ubuntu 18 04 boost中 xff0c 用到了别的函数库 xff0c 所以为了使用boost中相应的功能 xff0c 需要先安装系统中可能缺失的库 1 卸载已经安装的boost 删除 usr l
  • 简单的状态机图

    一 什么是状态机 xff1f 做产品的时候 xff0c 我们总能遇到一些比较复杂的逻辑问题 比如状态的转换 xff0c 字段状态的确认 xff0c 权限的控制 xff0c 状态的对应 而普通的流程图 xff0c 或时序图 xff0c 更侧重
  • js-对象转基本类型

    起因是收到朋友发的一道题 xff0c 如下 xff1a span class token comment 请在问号处填写你的答案 使下方等式成立 span span class token keyword let span a span c
  • 局域网内wakeonlan远程唤醒其它计算机

    背景 xff1a 需要管理多台计算机 xff0c 所有计算机在一个局域网内 xff0c 并且有的安装了Windows系统 xff0c 有的安装了Linux系统 我们想远程关闭和启动所有计算机 关闭计算机直接通过网络发生操作系统关机命令即可实
  • D3D中的三种Buffer

    在D3D中 针对视窗有三种Buffer 它们分别是 Color Buffer Depth Buffer和Stencil Buffer Color Buffer在D3D中又称为Render Target 意思是最后着色的目标Buffer 就是
  • 创建镜像(更新与构建镜像)

    创建镜像 有时从Docker镜像仓库中下载的镜像不能满足我们的要求 xff0c 此时可以基于这个镜像 xff08 基础镜像 xff09 封装一个自 己的镜像 两种方式 xff1a 更新镜像 xff1a 使用docker commit命令构建
  • (十)CMake链接已有的动态库

    使用一个已经存在的动态库 xff0c 需要用到CMake中两个命令 xff0c 分别是 xff1a link directoriestarget link libraries 下面先介绍以下两个命令的格式及其含义 xff0c 最后是一个使用
  • ROS入门21讲笔记(四)自定义话题消息类型和使用

    除了ROS内置消息外 xff0c 我们还能自定义消息 这一次我们不再与海龟较劲 xff0c 而是自定义一个订阅消息类型 xff0c 让订阅者和发布者通过这个结构进行数据通信 一 如何自定义话题消息 xff1f 话题消息是以 msg结尾的文件
  • ROS入门21讲笔记(七)自定义消息消息类型和使用

    这一节主要是学习如何自定义一个服务类型并使用它 一 如何自定义服务消息 xff1f 服务数据是以 srv结尾的文件 xff0c 是一个用于描述ROS服务信息简单文本文件 xff0c 用于生成不同语言消息的源代码 srv文件存放在packag
  • ROS入门21讲笔记(十二)常用可视化工具

    一 QT类可视化工具 1 1 rqt console rqt console 为显示和过滤ROS信息提供了一个GUI插件 1 2 rqt plot rqt plot使用不同的绘图后端提供数值可视化功能 1 3 rqt Image view
  • (二)CMake 使用头文件

    一 include directories 该命令用于增加一个编译头文件 其基本语法是 xff1a include directories span class token punctuation span span class token
  • cargo 宏展开遇到的问题

    最近学习rust xff0c 看到宏展开命令 span class token comment 单独文件 span rustc Z unstable options pretty span class token operator 61 s
  • 工程师笔记|常见的嵌入式软件工程师面试题

    Q xff1a 什么是ISR xff1f A xff1a ISR 是指中断服务程序 这些是存储在特定内存地址的函数 xff0c 当发生某种类型的中断时会调用这些函数 Cortex M 处理器系列具有管理中断执行的 NVIC Q xff1a
  • 计算机中的速率、带宽、时延、利用率解读

    计算机网络的性能一般是指它的几个重要的性能指标 但除了这些重要的性能指标外 xff0c 还有一些非性能特征 xff08 nonperformance characteristics xff09 也对计算机网络的性能有很大的影响 那么 xff
  • 手把手教你写链表,小学生看了都说好~

    摘要 xff1a 明明我们在之前已经接触了数组 xff0c 感到数组已经是万能的数据存储位置了 但是 xff0c 如果我们一直在使用比较复杂的数据 xff08 也就是比较多的数据时 xff09 xff0c 肯定会感到很反感 因为对于数组这种
  • 15-JavaScript高级程序设计-创建对象

    一 创建对象 创建单个对象 xff1a Object构造函数 new Object 对象字面量 xff08 参见8 Object amp Array xff09 创建多个对象 xff1a 以下7种方式 1 工厂模式 span class t
  • FreeRtos源码分析之启动任务调度vTaskStartScheduler(二)

    一 概述 FreeRtos在创建任务之后 xff0c 需要启动任务调度器才能使任务正常有序的运行 任务调度器的开启依赖于底层硬件 xff0c 对于CortexM3内核而言 xff0c 任务调度器需要用到中断和滴答定时器 FreeRtos在对
  • FreeRtos源码分析之任务状态管理(三)

    一 概述 FreeRtos的每一个任务都有一个对应的优先级 xff0c 较高优先级的任务具有优先运行的权利 xff0c 当高优先级的任务调用系统的延时函数或者需要阻塞等待某些信号时 xff0c 会让出CPU的使用权 xff0c 从而使低优先