当前位置: 首页 > news >正文

FreeRTOS学习14——时间管理

时间管理

  • 时间管理
    • FreeRTOS 系统时钟节拍
      • FreeRTOS 系统时钟节拍简介
      • FreeRTOS 系统时钟节拍处理
      • FreeRTOS 系统时钟节拍来源
    • FreeRTOS 任务延时函数
      • vTaskDelay()
      • vTaskDelayUntil()

时间管理

在前面的章节实验例程中,频繁地使用了 FreeRTOS 提供的延时函数,使用延时函数会使得任务进入阻塞态,直至延时完成,任务才会重新进入就绪态FreeRTOS 是如何对延时任务进行阻塞的,又是如何判断任务延时超时的,这些都是属于 FreeRTOS 时间管理的相关内容。

FreeRTOS 系统时钟节拍

FreeRTOS 系统时钟节拍简介

任务的操作系统都需要时钟节拍,FreeRTOS 也不例外。FreeRTOS 有一个系统时钟节拍计数器——xTickCount,xTickCount 是一个全局变量,在 tasks.c文件中有定义,具体的代码如下所示:

PRIVILEGED_DATA static volatile TickType_t xTickCount =( TickType_t ) configINITIAL_TICK_COUNT;

从 上 面 的 代 码 可 以 看 到 , xTickCount 在 定 义 时 , 被 赋 了 初 值 , 初 值 由 宏 定 义configINITIAL_TICK_COUNT 定义,在通常情况下系统使用节拍计数器的初值都是设置为 0。

FreeRTOS 系统时钟节拍处理

既然 FreeRTOS 的系统时钟节拍来自 SysTick,那么 FreeRTOS 系统时钟节拍的处理,自然就是在 SysTick 的中断服务函数中完成的

SysTick 的中断服务函数定义在 delay.c 文件中,具体的代码如下所示:

void SysTick_Handler(void)
{HAL_IncTick();/* OS 开始跑了,才执行正常的调度处理 */if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED){xPortSysTickHandler();}
}

从上面的代码可以看出,在 SysTick 的中断服务函数中,除了调用函数 HAL_IncTick()外,还通过函数 xTaskGetSchedulerState()判断任务调度器是否运行,如果任务调度器运行,那么就调用函数 xPortSysTickHandler()处理 FreeRTOS 的时钟节拍,及相关事务。

函数 xPortSysTickHandler()在 port.c 文件中有定义,具体的代码如下所示:

/* SyaTick 中断服务函数 */
void xPortSysTickHandler( void )
{/* 屏蔽所有受 FreeRTOS 管理的中断* 因为 SysTick 的中断优先级设置为最低的中断优先等级,* 因此需要屏蔽所有受 FreeRTOS 管理的中断*/vPortRaiseBASEPRI();{/* 处理系统时钟节拍,* 并决定是否进行任务切换*/if( xTaskIncrementTick() != pdFALSE ){/* 需要进行任务切换,* 这是中断控制状态寄存器,以挂起 PendSV 异常*/portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;}}/* 取消中断屏蔽 */vPortClearBASEPRIFromISR();
}

从上面的代码可以看出,函数 xPortSysTickHandler()调用了函数 xTaskIncrementTick()来处理系统时钟节拍。在调用函数 xTaskIncrementTick()前后分别屏蔽了受 FreeRTOS 管理的中断和取消中断屏蔽,这是因为 SysTick 的中断优先级设置为最低的中断优先等级,在 SysTick 的中断中处理FreeRTOS 的系统时钟节拍时,并不希望收到其他中断的影响。在通过函数xTaskIncrementTick()处理完系统时钟节拍和相关事务后,再根据函数 xTaskIncrementTick 的返回值,决定是否进行任务切换,如果进行任务切换,就触发 PendSV 异常,在本次 SysTick 中断及其他中断处理完成后,就会进入 PendSV 的中断服务函数进行任务切换

接下来分析函数 xTaskIncrementTick()是如何处理系统时钟节拍及相关事务的,函数xTaskIncrementTick()在 task.c 文件中有定义,具体函数内部可自行查看,本次只讲述该函数做了哪些处理。

  • 处理系统时钟节拍,就是在每次 SysTick 中断发生的时候,将全局变量 xTickCount 的值加1,也就是将系统时钟节拍计数器的值加 1。
  • 处理阻塞任务列表,就是判断阻塞态任务列表中是否有阻塞任务超时,如果有,就将阻塞时间超时的阻塞态任务移到就绪态任务列表中,准备执行。同时在系统时钟节拍计数器xTickCount 的加 1 溢出后,将两个阻塞态任务列表调换,这是 FreeRTOS 处理系统时钟节拍计数器溢出的一种机制

当一个任务因为等待某个事件而进入阻塞状态时,系统会记录当前xTickCount的值,这个值作为任务开始阻塞的时间点,
任务的超时时间是基于这个记录的xTickCount值加上任务指定的阻塞时间来计算的
当xTickCount从最大值(0xFFFFFFFF)溢出到0x00000000时,FreeRTOS会交换两个阻塞列表的角色。
原来的当前阻塞列表变成了备用阻塞列表,而原来的备用阻塞列表变成了新的当前阻塞列表
阻塞延时重新计时
补充: 等待就绪列表 用来存放在任务调度器已经挂起时阻塞延时解除的任务,在任务调度器恢复后,把该列表的任务恢复到就绪列表中

  • 处理时间片调度,就是在每次系统时钟节拍加 1 后,切换到另外一个同等优先级的任务中运行,要注意的是,此函数只是做了需要进行任务切换的标记,在函数退出后,会统一进行任务切换,因此时间片调度导致的任务切换,也可能因为有更高优先级的阻塞任务就绪导致任务切换,而出现任务切换后运行的任务比任务切换前运行任务的优先级高,而非相等优先级。

FreeRTOS 系统时钟节拍来源

FreeRTOS 的系统时钟节拍计数器为全局变量 xTickCount,一般使用 SysTick 作为 RTOS 的时钟节拍。

FreeRTOS 任务延时函数

FreeRTOS 提供了与任务延时相关的 API 函数,如下表所示:
函数描述
vTaskDelay()任务延时函数,延时单位:系统时钟节拍
vTaskDelayUntil()任务绝对延时函数,延时单位:系统时钟节拍
xTaskAbortDelay()终止任务延时函数

相对延时:指每次延时都是从执行函数vTaskDelay()开始,直到延时指定的时间结束
绝对延时:指将整个任务的运行周期看成一个整体,适用于需要按照一定频率运行的任务

vTaskDelay()

void vTaskDelay( const TickType_t xTicksToDelay );

  • INCLUDE_vTaskDelay必须定义为 1,才可使用此函数
  • 按给定的滴答数延迟任务。任务保持阻塞的实际时间取决于滴答频率

参数:xTicksToDelay 调用任务应阻塞的 tick 周期数

用法示例

void vTaskFunction( void * pvParameters )
{/* Block for 500ms. */const TickType_t xDelay = 500 / portTICK_PERIOD_MS;for( ;; ){/* Simply toggle the LED every 500ms, blocking between each toggle. */vToggleLED();vTaskDelay( xDelay );}
}

vTaskDelayUntil()

函数原型:

void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
INCLUDE_vTaskDelayUntil必须定义为 1,才可使用此函数

将任务延迟到指定时间。此函数可以由周期性任务使用, 来确保恒定的执行频率。

也就是说该函数的延时是绝对延时,整个任务的运行周期由vTaskDelayUntil()函数的传入参数xTimeIncrement 决定,任务的运行周期包括任务主体进入阻塞时切换其他任务运行后其他任务的运行时间

下图 (1)为任务主体,也就是任务真正要做的工作
(2)是任务函数中调用vTaskDelayUntil()对任务进行延时
3)为其他任务在运行
在这里插入图片描述

参数

  • pxPreviousWakeTime
    指向一个变量的指针,该变量用于保存任务最后一次解除阻塞的时间。该变量在首次使用前 必须用前时间初始化(见下面的示例)。在这之后,该变量 会在 vTaskDelayUntil()内自动更新。

  • xTimeIncrement
    周期时间段。该任务将在 (*pxPreviousWakeTime + xTimeIncrement)时间解除阻塞。 使用相同的 xTimeIncrement 参数值调用 vTaskDelayUntil将导致任务 以固定的间隔期执行。

用法示例

// Perform an action every 10 ticks.
void vTaskFunction( void * pvParameters )
{TickType_t xLastWakeTime;const TickType_t xFrequency = 10;// Initialise the xLastWakeTime variable with the current time.xLastWakeTime = xTaskGetTickCount();for( ;; ){// Wait for the next cycle.vTaskDelayUntil( &xLastWakeTime, xFrequency );// Perform action here.}
}

相关文章:

FreeRTOS学习14——时间管理

时间管理 时间管理FreeRTOS 系统时钟节拍FreeRTOS 系统时钟节拍简介FreeRTOS 系统时钟节拍处理FreeRTOS 系统时钟节拍来源 FreeRTOS 任务延时函数vTaskDelay()vTaskDelayUntil() 时间管理 在前面的章节实验例程中,频繁地使用了 FreeRTOS 提供的延时函数&#xff0c…...

统⼀数据返回格式快速⼊⻔

为什么会有统⼀数据返回? 其实统一数据返回是运用了AOP(对某一类事情的集中处理)的思维。 优点: 1.⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据。 2.降低前端程序员和后端程序员的沟通成本,因为所有接⼝都…...

Python学习------第十天

数据容器-----元组 定义格式,特点,相关操作 元组一旦定义,就无法修改 元组内只有一个数据,后面必须加逗号 """ #元组 (1,"hello",True) #定义元组 t1 (1,"hello") t2 () t3 tuple() prin…...

Win11 24H2新BUG或影响30%CPU性能,修复方法在这里

原文转载修改自(更多互联网新闻/搞机小知识): 一招提升Win11 24H2 CPU 30%性能,小BUG大影响 就在刚刚,小江在网上冲浪的时候突然发现了这么一则帖子,标题如下:基准测试(特别是 Time…...

element ui 走马灯一页展示多个数据实现

element ui 走马灯一页展示多个数据实现 element ui 走马灯一页展示多个数据实现 element ui 走马灯一页展示多个数据实现 主要是对走马灯的数据的操作,先看js处理 let list [{ i: 1, name: 1 },{ i: 2, name: 2 },{ i: 3, name: 3 },{ i: 4, name: 4 },]let newL…...

40分钟学 Go 语言高并发:Goroutine基础与原理

Day 03 - goroutine基础与原理 1. goroutine创建和调度 1.1 goroutine基本特性 特性说明轻量级初始栈大小仅2KB,可动态增长调度方式协作式调度,由Go运行时管理创建成本创建成本很低,可同时运行数十万个通信方式通过channel进行通信&#x…...

Figma插件指南:12款提升设计生产力的插件

在当今的设计领域,Figma已经成为许多UI设计师和团队的首选原型和数字设计软件。随着Figma的不断更新和插件库的扩展,这些工具极大地提升了设计工作的效率。本文将介绍12款实用的Figma插件,帮助你在UI设计中更加高效。 即时AI 即时AI利用先进…...

【K8S系列】Kubernetes集群资源管理与调度 深度分析

在现代微服务架构中,Kubernetes(K8s)作为容器编排平台,提供了强大的资源管理和调度能力。然而,随着应用规模的扩大和复杂性增加,如何高效地管理和调度集群资源成为一个关键挑战。本文将深入探讨 Kubernetes…...

delphi fmx android 离线人脸识别

搜遍全网都没有找到delphi android 能用的 离线人脸识别,无需注册什么开发者 有这方面需求的可以用fsdk 这边用的luxand.FSDK8.0 android下的注册号要自己找下 1,用老猫的工具将android 下的sdk,FSDK.java 编译成FSDK.jar 老猫的工具 2,用上面的工具将FSDK.jar 生成de…...

Linux mountpoint 命令详解

前言 在 Linux 系统中,文件系统管理是一个非常重要的任务。mountpoint 是一个常用的小工具,用于检查目录是否是挂载点。本篇博客将详细介绍 mountpoint 命令的用法及其在日常系统管理中的应用。 什么是挂载点? 挂载点是一个目录&#xff0…...

Linux驱动开发(9):pinctrl子系统和gpio子系统--led实验

在前面章节,我们有过使用寄存器去编写字符设备的经历了。这种直接在驱动代码中, 通过寄存器映射来对外设进行使用的编程方式,从驱动开发者的角度可以说是灾难。 因为每当芯片的寄存器发生了改动,那么底层的驱动几乎得重写。 那么…...

用sqlmap工具打sqli-labs前20关靶场

这个星期我们用手动注入打了前20关靶场,今天我们用sqlmap直接梭哈前20关 1.介绍sqlmap sqlmap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL和SQL注入漏洞。 2.下载和使用sqlmap 官方下载地址:GitHub - sq…...

代码随想录算法训练营第二十一天 | 93.复原IP地址 | 78.子集

Day 20 总结 自己实现中遇到哪些困难 一句话讲明白问题分类 组合问题和分割问题都是收集树的叶子节点,子集问题是找树的所有节点!切割字符串问题回顾 昨天的切割回文子串,和今天的切割ip地址,都是需要将字符串拆分成 n 份。只不过…...

#Uniapp篇:支持纯血鸿蒙发布适配UIUI

uni-ui梳理 组件生命周期 https://uniapp.dcloud.net.cn/tutorial/page.html#componentlifecycle 页面生命周期 https://uniapp.dcloud.net.cn/collocation/App.html#applifecycle onLaunch 当uni-app 初始化完成时触发(全局只触发一次)&#xff0c…...

边缘提取函数 [OPENCV--2]

OPENCV中最常用的边界检测是CANNY函数 下面展示它的用法 通常输入一个灰度图像(边界一般和颜色无关)这样也可以简化运算cv::Canny(inmat , outmat , therhold1, therhold2 ) 第一个参数是输入的灰度图像,第二个是输出的图像这两个参数都是引用…...

插值原理(数值计算方法)

插值原理(数值计算方法) 一. 原理介绍二. 图例三. 唯一性表述 一. 原理介绍 在数学中,插值(Interpolation)是指通过已知的离散数据点,构造一个连续的函数,该函数能够精确地通过这些数据点&#…...

【Pikachu】SSRF(Server-Side Request Forgery)服务器端请求伪造实战

尽人事以听天命 1.Server-Side Request Forgery服务器端请求伪造学习 SSRF(服务器端请求伪造)攻击的详细解析与防范 SSRF(Server-Side Request Forgery,服务器端请求伪造) 是一种安全漏洞,它允许攻击者通…...

IDEA怎么定位java类所用maven依赖版本及引用位置

在实际开发中,我们可能会遇到需要搞清楚代码所用依赖版本号及引用位置的场景,便于排查问题,怎么通过IDEA实现呢? 可以在IDEA中打开项目,右键点击maven的pom.xml文件,或者在maven窗口下选中项目,…...

Discuz论坛网站管理员的默认用户名admin怎么修改啊?

当我们在某个论坛注册账号后,处于某种原因想要修改用户名,该如何修改? Discuz论坛网站管理员处于安全性或某种原因想要修改默认用户名admin该如何修改?驰网飞飞和你分享 其实非常简单,但是普通用户没有修改权限&…...

BIO、NIO、AIO的区别?

文章目录 BIO、NIO、AIO的区别?为什么不使用java 原生nio哪些项目使用了netty BIO阻塞I/O存在问题 NIO(nonblocking IO)Java NIO channel(通道)、buffer、selector(选择器) AIO(Asynchronous I/O) BIO、NIO…...

基于2026校招数据分析:拥有这几张AI证书的学生,起薪普遍高30%

2026年校招季已近尾声,随着DeepSeek等大模型技术的持续突破与“人工智能”向千行百业的深度渗透,AI人才市场的竞争呈现白热化态势。前程无忧51job发布的《2026届校招市场AI人才需求报告》显示,AI相关岗位校招薪酬中位数已突破2万元/月&#x…...

Git提交时Personal Access Token权限不足:如何正确配置workflow scope

1. 为什么Git提交会提示Personal Access Token权限不足? 最近在团队协作中遇到一个典型问题:当开发者尝试推送包含.github/workflows目录的代码到GitHub仓库时,系统突然报错refusing to allow a Personal Access Token to create or update w…...

ComfyUI与Stable Diffusion WebUI模型共享终极指南:如何通过extra_model_paths.yaml一键配置

ComfyUI与Stable Diffusion WebUI模型共享终极指南:如何通过extra_model_paths.yaml一键配置 在AI绘图领域,ComfyUI和Stable Diffusion WebUI(简称WebUI)各有优势。ComfyUI以其高度可定制的工作流著称,而WebUI则提供了…...

Rainmeter皮肤主题用户行为分析:使用数据统计

Rainmeter皮肤主题用户行为分析:使用数据统计 【免费下载链接】rainmeter Desktop customization tool for Windows 项目地址: https://gitcode.com/gh_mirrors/ra/rainmeter Rainmeter作为一款强大的Windows桌面自定义工具,允许用户通过皮肤主题…...

Babel polyfill配置全解析:为什么你的Next.js项目在IE11还是报错?

Babel polyfill配置全解析:为什么你的Next.js项目在IE11还是报错? 在2023年的前端生态中,浏览器兼容性依然是个令人头疼的问题。最近接手一个企业级Next.js项目时,我遇到了一个典型场景:开发环境一切正常,但…...

用MobaXterm替代传统终端的完整指南

Windows远程运维革命:用MobaXterm替代传统终端的完整指南 每次打开 PuTTY 时,你是否会对着那个灰暗的界面叹气?当需要在Xshell中频繁切换标签时,是否感到效率低下?作为Windows系统管理员或开发者,我们长期忍…...

解决Beyond Compare 5授权问题的完整方案:BCompare_Keygen工具使用指南

解决Beyond Compare 5授权问题的完整方案:BCompare_Keygen工具使用指南 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 当你在使用Beyond Compare 5进行文件比较或同步操作时&#x…...

Elasticsearch IK 分词器远程词典

一、背景 在使用 Elasticsearch IK 分词器进行中文检索时,默认词库往往无法覆盖业务中的专业词汇(如:知识库、RAG架构、向量检索等)。 如果不进行扩展,这些词可能被错误拆分,导致: 检索结果不准…...

怎么看待OpenClaw?

特别附:"词元"为何是理解这一切的关键引言:一只龙虾爬到Linux头顶2026年3月,GitHub星标榜上出现了一个奇观——一只"龙虾"爬到了Linux头顶。OpenClaw,这个从个人项目演变成的AI智能体框架,在不到四…...

3个场景解密LeagueAkari:如何让英雄联盟游戏效率提升300%

3个场景解密LeagueAkari:如何让英雄联盟游戏效率提升300% 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit LeagueAkari…...