浅析Free RTOS任务

news2025/1/18 17:11:24

目录

概述

1 FreeRTOS任务定义

2 任务函数实现

2.1 任务函数原型

2.2 顶层任务状态

2.3 任务优先级

3 任务状态的扩展

3.1 阻塞状态

3.2 挂起状态

3.3 就绪状态

4 空闲任务与空闲任务钩子函数

4.1 空闲任务

4.2 空闲任务钩子函数

4.2.1 钩子函数介绍

4.2.2 空闲任务钩子函数的实现限制

4.2.3 空闲任务钩子函数案例

5 改变任务优先级

5.1 vTaskPrioritySet() API 函数

5.2  uxTaskPriorityGet() API 函数

6 删除任务

7 任务调度算法

7.1  概念介绍

7.2 选择任务优先级

7.3 协作式调度

参考资料: 


概述

本文主要介绍FRESSRTOS任务的相关概念和知识点,对整个任务的概念和使用方法做了详细的梳理,便于在工作中查阅和借鉴。

1 FreeRTOS任务定义

在FreeRTOS中,任务是一段独立执行的代码,可以独自运行并完成特定的功能。任务的定义包括任务的名称、优先级、堆栈大小和任务函数。

2 任务函数实现

2.1 任务函数原型

任务是由 C 语言函数实现的。唯一特别的只是任务的函数原型,其必须返回 void,而且带有一个 void 指针参数。

// 任务函数
void taskFunction(void* parameters)
{
       // 任务的功能代码
}

// 创建任务
xTaskCreate(taskFunction, "TaskName", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

每个任务都是在自己权限范围内的一个小程序。其具有程序入口,通常会运行在一个死循环中,也不会退出。一个任务函数可以用来创建若干个任务——创建出的任务均是独立的执行实例,拥有属于自己的栈空间,以及属于自己的自动变量(栈变量),即任务函数本身定义的变量。

2.2 顶层任务状态

应用程序可以包含多个任务。如果运行应用程序的微控制器只有一个核(core),那么在任意给定时间,实际上只会有一个任务被执行。这就意味着一个任务可以有一个或两个状态,即运行状态和非运行状态。

任务处于运行态:处理器就正在执行它的代码。

非运行态: 该任务进行休眠,它的所有状态都被妥善保存,以便在下一次调试器决定让它进入运行态时可以恢复执行。当任务恢复执行时,其将精确地从离开运行态时正准备执行的那一条指令开始执行。

任务从非运行态转移到运行态:”切换入或切入(switched in)”或”交换入(swapped in)”。

任务从运行态转移到非运行态: ”切换出或切出(switchedout)”或”交换出(swapped out)”。 FreeRTOS 的调度器是能让任务切入切出的唯一实体。

2.3 任务优先级

xTaskCreate() API 函数的参数 uxPriority 为创建的任务赋予了一个初始优先级。这个侁先级可以在调度器启动后调用 vTaskPrioritySet() API 函数进行修改。应 用 程 序 在 文 件 FreeRTOSConfig.h 中 设 定 的 编 译 时 配 置 常 量configMAX_PRIORITIES 的值,即是最多可具有的优先级数目。 FreeRTOS 本身并没有限定这个常量的最大值,但这个值越大,则内核花销的内存空间就越多。所以总是建议将此常量设为能够用到的最小值。

对于如何为任务指定优先级, FreeRTOS 并没有强加任何限制任意数量的任务可以共享同一个优先级——以保证最大设计弹性。当然,如果需要的话,你也可以为每个任务指定唯一的优先级(就如同某些调度算法的要求一样),但这不是强制要求的。

低优先级号表示任务的优先级低,优先级号 0 表示最低优先级。有效的优先级号范围从 0 到(configMAX_PRIORITES – 1)

调度器保证总是在所有可运行的任务中选择具有最高优先级的任务,并使其进入运行态。如果被选中的优先级上具有不止一个任务,调度器会让这些任务轮流执行。这种行为方式在之前的例子中可以明显看出来。两个测试任务被创建在同一个优先级上,并且一直是可运行的。所以每个任务都执行一个”时间片”,任务在时间片起始时刻进入运行态,在时间片结束时刻又退出运行态。 图 3 中 t1 与 t2 之间的时段就等于一个时间片。

3 任务状态的扩展

3.1 阻塞状态


如果一个任务正在等待某个事件,则称这个任务处于”阻塞态(blocked)”。阻塞态是非运行态的一个子状态。

任务可以进入阻塞态以等待以下两种不同类型的事件:

1)定时(时间相关)事件——这类事件可以是延迟到期或是绝对时间到点。比如
说某个任务可以进入阻塞态以延迟 10ms。

2)同步事件——源于其它任务或中断的事件。比如说,某个任务可以进入阻塞态以等待队列中有数据到来。同步事件囊括了所有板级范围内的事件类型。

        FreeRTOS 的队列,二值信号量,计数信号量,互斥信号量(recursive semaphore,递归信号量,本文一律称为互斥信号量, 因为其主要用于实现互斥访问)和互斥量都可以用来实现同步事件。
        任务可以在进入阻塞态以等待同步事件时指定一个等待超时时间,这样可以有效地实现阻塞状态下同时等待两种类型的事件。比如说,某个任务可以等待队列中有数据到来,但最多只等 10ms。如果 10ms 内有数据到来,或是 10ms 过去了还没有数据到来,这两种情况下该任务都将退出阻塞态。

3.2 挂起状态

“挂起(suspended)”也是非运行状态的子状态。处于挂起状态的任务对调度器而言是不可见的。让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend() API 函数;而 把 一 个 挂 起 状 态 的 任 务 唤 醒 的 唯 一 途 径 就 是 调 用 vTaskResume() 或vTaskResumeFromISR() API 函数。大多数应用程序中都不会用到挂起状态。

3.3 就绪状态

如果任务处于非运行状态,但既没有阻塞也没有挂起,则这个任务处于就绪(ready,准备或就绪)状态。处于就绪态的任务能够被运行,但只是”准备(ready)”运行,而当前尚未运行。
 

4 空闲任务与空闲任务钩子函数

4.1 空闲任务

一个例子:如果创建的任务大部份时间都处于阻塞态。这种状态下所有的任务都不可运行,
所以也不能被调度器选中。但处理器总是需要代码来执行,那怎么办呢?

解决方法:

为了保证这一点,当调用 vTaskStartScheduler()时,调度器会自动创建一个空闲任务。空闲任务是
一个非常短小的循环——和最早的示例任务十分相似,总是可以运行。

空闲任务拥有最低优先级(优先级 0)以保证其不会妨碍具有更高优先级的应用任务进入运行态——当然,没有任何限制说是不能把应用任务创建在与空闲任务相同的优先级上;如果需要的话,你一样可以和空闲任务一起共享优先级。

4.2 空闲任务钩子函数

4.2.1 钩子函数介绍

通过空闲任务钩子函数(或称回调, hook, or call-back),可以直接在空闲任务中添加应用程序相关的功能。空闲任务钩子函数会被空闲任务每循环一次就自动调用一次。

通常空闲任务钩子函数被用于:
1)执行低优先级的代码,或者后台以及需要不停处理数据和逻辑运算的功能代码

2)测试处系统处理裕量(空闲任务只会在所有其它任务都不运行时才有机会执行,所以测量出空闲任务占用的处理时间就可以清楚的知道系统有多少富余的处理时间)。

3)将处理器配置到低功耗模式——提供一种自动省电方法,使得在没有任何应用功能需要处理的时候,系统自动进入省电模式。

4.2.2 空闲任务钩子函数的实现限制

空闲任务钩子函数必须遵从以下规则:
1)绝不能阻或挂起。空闲任务只会在其它任务都不运行时才会被执行(除非有应用任务共享空闲任务优先级)。以任何方式阻塞空闲任务都可能导致没有任务能够进入运行态!

2)如果应用程序用到了 vTaskDelete() AP 函数,则空闲钩子函数必须能够尽快返回。因为在任务被删除后,空闲任务负责回收内核资源。如果空闲任务一直运行在钩子函数中,则无法进行回收工作。

4.2.3 空闲任务钩子函数案例

FreeRTOSConfig.h 中的配置常量 configUSE_IDLE_HOOK 必须定义为 1,这样空闲任务钩子函数才会被调用。

/* Declare a variable that will be incremented by the hook function. */
unsigned long ulIdleCycleCount = 0UL;

/* 空闲钩子函数必须命名为vApplicationIdleHook(),无参数也无返回值。 */
void vApplicationIdleHook( void )
{
      /* This hook function does nothing but increment a counter. */
     ulIdleCycleCount++;
}

5 改变任务优先级

5.1 vTaskPrioritySet() API 函数

API 函数 vTaskPriofitySet()可以用于在调度器启动后改变任何任务的优先级。

void vTaskPrioritySet( xTaskHandle pxTask, unsigned portBASE_TYPE uxNewPriority );

参数介绍:

参数名称描述
pxTask被修改优先级的任务句柄(即目标任务)——参考 xTaskCreate() API 函数的参数 pxCreatedTask 以了解如何得到任务句柄方面的信息。任务可以通过传入 NULL 值来修改自己的优先级。
uxNewPriority目标任务将被设置到哪个优先级上。如果设置的值超过了最大可用优 先级(configMAX_PRIORITIES – 1),则会被自动封顶为最大值。常 量 configMAX_PRIORITIES 是在 FreeRTOSConfig.h 头文件中设置 的一个编译时选项

5.2  uxTaskPriorityGet() API 函数

uxTaskPriorityGet() API 函数用于查询一个任务的优先级。

unsigned portBASE_TYPE uxTaskPriorityGet( xTaskHandle pxTask );
参数名称描述
pxTask被查询任务的句柄(目标任务) ——参考 xTaskCreate() API 函数的参数 pxCreatedTask 以了解如何得到任务句柄方面的信息。 任务可以通过传入 NULL 值来查询自己的优先级。

6 删除任务

任务可以使用 API 函数 vTaskDelete()删除自己或其它任务。任务被删除后就不复存在,也不会再进入运行态。空闲任务的责任是要将分配给已删除任务的内存释放掉。因此有一点很重要,那就
是使用 vTaskDelete() API 函数的任务千万不能把空闲任务的执行时间饿死。需要说明一点,只有内核为任务分配的内存空间才会在任务被删除后自动回收。任务自己占用的内存或资源需要由应用程序自己显式地释放。

void vTaskDelete( xTaskHandle pxTaskToDelete );

7 任务调度算法

7.1  概念介绍

FreeRTOS采用固定优先级抢占式调度,其主要特点如下:

1)每个任务都赋予了一个优先级。

2)每个任务都可以存在于一个或多个状态。

3)在任何时候都只有一个任务可以处于运行状态

4)调度器总是在所有处于就绪态的任务中选择具有最高优先级的任务来执行。

任务可以在阻塞状态等待一个事件,当事件发生时其将自动回到就绪态。时间事件发生在某个特定的时刻,比如阻塞超时。时间事件通常用于周期性或超时行为。任务或中断服务例程往队列发送消息或发送任务一种信号量,都将触发同步事件。同步事件通常用于触发同步行为,比如某个外围的数据到达了。
 

7.2 选择任务优先级

作为一种通用规则,完成硬实时功能的任务优先级会高于完成软件时功能任务的优先级。但其它一些因素,比如执行时间和处理器利用率,都必须纳入考虑范围,以保证应用程序不会超过硬实时的需求限制。

单调速率调度(Rate Monotonic Scheduling, RMS)是一种常用的优先级分配技术。其根据任务周期性执行的速率来分配一个唯一的优先级。具有最高周期执行频率的任务赋予高最优先级;具有最低周期执行频率的任务赋予最低优先级。这种优先级分配方式被证明了可以最大化整个应用程序的可调度性(schedulability),但是运行时间不定以及并非所有任务都具有周期性,会使得对这种方式的全面计算变得相当复杂。
 

7.3 协作式调度

协作式调度器的特点:

1)在运行态任务进入阻塞态或是运行态任务显式调用 taskYIELD()时,才会进行上下文切换。

2)任务永远不会被抢占,而具有相同优先级的任务也不会自动共享处理器时间。

3)协作式调度的这作工作方式虽然比较简单,但可能会导致系统响应不够快。
 

参考资料: 

1)《freeRTOS入门手册》

2)《嵌入式系统的实时概念》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1628013.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql索引规范及原理分析

1 Mysql存储引擎 MySQL中的数据用各种不同的技术存储在文件中,每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力,这些不同的技术以及配套的功能在MySQL中称为存储引擎。 存储引擎是MySQL将数据存储在文件系统中的存储方…

Linux多进程(五) 进程池 C++实现

一、进程池的概念 1.1、什么是进程池 进程池是一种并发编程模式,用于管理和重用多个处理任务的进程。它通常用于需要频繁创建和销毁进程的情况,以避免因此产生的开销。 进程池的优点包括: 减少进程创建销毁的开销:避免频繁创建和…

​可视化大屏C位图:城市地图,一览城市全貌信息。

城市地图是一种常见的可视化大屏C位图,用于展示城市的地理分布和相关数据。以下是对城市地图的解读: 地理分布 城市地图可以展示不同地理区域的城市分布情况。通过地图上的点、标记或区域着色等方式,可以清晰地看到城市的位置和分布范围。这…

后端工程师——C++工程师如何准备面试?

相比 Java 语言方向,C++ 入门简单,精通难,找工作竞争压力更小,但 C++ 依然是近年来招聘的热门岗位之一。本文将从以下三个方面进行详细讲解,帮助你对 C++ 相关岗位的就业前景、岗位要求、学习路线等有更充分的了解。 C++工程师面试准备 上两篇文章对 C++ 工程师的招聘需求…

虚拟机VMware下ROS Neotic(Ubuntu 20.04)下安装OpenCV

一、ROS安装 ROS的官方安装步骤: 1、noetic / Ubuntu 20.04 : http://wiki.ros.org/noetic/Installation/Ubuntu 2、melodic / Ubuntu 18.04: http://wiki.ros.org/melodic/Installation/Ubuntu 3、kinetic / Ubuntu 16.04: http:…

如何使用IDEA直接连接MySQL数据库

如何使用IDEA直接连接MySQL数据库 新建一个空项目打开DataBase窗口连接数据库第一次连接 需要先下载驱动上一步驱动下载太慢怎么办?下载好驱动后 测试连接 新建一个空项目 打开DataBase窗口 连接数据库 第一次连接 需要先下载驱动 如果这里下载的很慢 看下一步解决…

算法 || 二分查找

目录 二分查找 在排序数组中查找元素的第一个和最后一个位置 搜索插入位置 一个数组经过划分后具有二段性的都可以用二分查找 二分查找 704. 二分查找 - 力扣(LeetCode) ​ 暴力解法:直接遍历数组,找到 target 便返回下标&am…

星尘智能 AI 机器人 S1——国产机器人的巅峰之作

AI智能机器人真的太炸裂了 国产科技威武-CSDN直播AI智能机器人真的太炸裂了 国产科技威武https://live.csdn.net/v/382519 最近发现了一个国产的机器人,真的让人惊叹不已!它就是星尘智能 AI 机器人 S1! 这个机器人简直太牛逼了!…

13.JAVAEE之HTTP协议

HTTP 最新的版本应该是 HTTP/3.0 目前大规模使用的版本 HTTP/1.1 使用 HTTP 协议的场景 1.浏览器打开网站 (基本上) 2.手机 APP 访问对应的服务器 (大概率) 学习 HTTP 协议, 重点学习 HTTP 的报文格式 前面的 TCP/IP/UDP 和这些不同, HTTP 的报文格式,要分两个部分来看待.请求…

LeetCode - LCR 008.长度最小的子数组

一. 题目链接 LeetCode - 209. 长度最小的子数组 二. 思路分析 由于此问题分析的对象是「⼀段连续的区间」,因此可以考虑「滑动窗口」的思想来解决这道题。 让滑动窗口满足:从 i 位置开始,窗口内所有元素的和小于target (那么当…

Jenkins构建触发器-Git hook自动触发构建

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 Jenkins是一个开源…

c++图论基础(1)

目录 无向图 无向图度 无向图性质 有向图 有向图度 有向图性质 图的分类: 稀疏图: 稠密图: 零图: 有向完全图: 无向完全图: 度序列: 图是由顶点集合(简称点集)和顶点间的边(简称边…

【热议】研究生可以跟导师以外的老师合作吗?

::: block-1 “时问桫椤”是一个致力于为本科生到研究生教育阶段提供帮助的不太正式的公众号。我们旨在在大家感到困惑、痛苦或面临困难时伸出援手。通过总结广大研究生的经验,帮助大家尽早适应研究生生活,尽快了解科研的本质。祝一切顺利!—…

Linux 权限与软件包管理器 yum

一. 研究Linux默认权限 目录 ,起始权限:777 普通文件,起始权限666 Linux系统中存在权限掩码 使用umask指令也可以改变掩码 如果将掩码改为0000 我们可以看到权限发生改变(重新设置掩码) 最终权限起始权限 去掉 权限…

安卓悬浮窗权限检查

目录 悬浮窗权限代码检测悬浮窗功能 悬浮窗权限 请求了这个权限后&#xff0c;app的权限管理中会有「显示悬浮窗」的权限选项。后面会引导用户去开启这个权限。 <uses-permission android:name"android.permission.SYSTEM_ALERT_WINDOW" />代码检测悬浮窗功能…

目标检测算法YOLOv2简介

YOLOv2由Joseph Redmon等人于2016年提出&#xff0c;论文名为&#xff1a;《YOLO9000: Better, Faster, Stronger》&#xff0c;论文见&#xff1a;https://arxiv.org/pdf/1612.08242.pdf &#xff0c;项目网页&#xff1a;https://pjreddie.com/darknet/yolov2/ ,YOLO9000可以…

做外贸SOHO需要考虑什么条件?

一、理清基本的外贸业务 不想给大家泼冷水&#xff0c;但如果你连基本的外贸知识都不懂&#xff0c;不知道业务怎么进行&#xff0c;想成功可能性为0&#xff01; 在开始 soho前&#xff0c;你需要先了解以下几个方面&#xff1a; 1.产品定位(选品) 2.你的供应商资源(选厂) 3.…

【FreeRTOS】RTOS任务的同步与互斥:(四)事件标志组

【FreeRTOS】RTOS任务的同步与互斥&#xff1a;&#xff08;四&#xff09;事件标志组 事件标志组的概念事件标志组相关 API 函数1. 创建事件标志组2. 设置事件标志位3. 清除事件标志位4. 等待事件标志位 事件标志组案例设计cubeMX配置软件程序设计测试结果 同步与互斥是学习Fr…

图像分类导论:从模型设计到端到端

书籍&#xff1a;An Introduction to Image Classification&#xff1a;From Designed Models to End-to-End Learning 作者&#xff1a;Klaus D. Toennies 出版&#xff1a;Springer Singapore 书籍下载-《图像分类导论》图像分类的传统方法包括在特征空间中进行特征提取和…

深度学习运算:CUDA 编程简介

一、说明 如今&#xff0c;当我们谈论深度学习时&#xff0c;通常会将其实现与利用 GPU 来提高性能联系起来。GPU&#xff08;图形处理单元&#xff09;最初设计用于加速图像、2D 和 3D 图形的渲染。然而&#xff0c;由于它们能够执行许多并行操作&#xff0c;因此它们的实用性…