FreeRTOS 实时操作系统第八讲 - 时间管理 (系统节拍,延时函数)

本文主要是介绍FreeRTOS 实时操作系统第八讲 - 时间管理 (系统节拍,延时函数),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、系统节拍

  FreeRTOS 实时操作系统需要一个时钟节拍,以供系统处理诸如延时、超时、软件定时器等与时间相关的事件。

  时钟节拍是周期性定时中断,这个中断可以看做是系统心跳。中断时间间隔取决于不同的应用,一般是 1ms – 100ms。时钟的节拍中断使得内核可以将任务延迟若干个时钟节拍,以及当任务等待事件发生时,提供等待超时等依据。时钟节拍率越快,系统响应越快,系统的额外开销也越大。

  对于 Cortex-M3 内核的 STM32F103 ,教程配套的例子都是用滴答定时器来实现系统时钟节拍的。

  • 滴答定时器 Systick

  SysTick 定时器位于 NVIC 中,用于产生 SysTick 异常(异常号:15),滴答定时器是一个 24 位的递减计数器,支持中断。使用比较简单,专门用于给操作系统提供时钟节拍。

  FreeRTOS 的系统时钟节拍可以在配置文件 FreeRTOSConfig.h 里面设置:

#define configTICK_RATE_HZ(( TickType_t) 1000 )

如上所示的宏定义配置表示系统时钟节拍是 1KHz,即 1ms。

二、延时相关函数

2.1、作用

FreeRTOS 中的时间延迟函数主要有以下两个作用:

  1. 为周期性执行的任务提供延迟。
  2. 对于抢占式调度器,让高优先级任务可以通过时间延迟函数释放 CPU 使用权,从而让低优先级任务可以得到执行。

2.2、相关函数

FreeRTOS 时间相关的函数主要有以下 4 个:

  1. vTaskDelay ()
  2. vTaskDelayUntil ()
  3. xTaskGetTickCount()
  4. xTaskGetTickCountFromISR()

下面我们对这 4 个函数依次进行说明:

① 函数原型:void vTaskDelay(const TickType_t xTicksToDelay);

  函数描述:函数 vTaskDelay 用于任务的延迟。 属于相对延时,指每次延时都是从执行函数 vTaskDelay() 开始,直到延时指定的时间(参数:滴答值)结束。

  参数 xTicksToDelay 用于设置延迟的时钟节拍个数,范围 1- 0xFFFFFFFF。

  延迟时间的最大值在 portmacro.h 文件里面有定义:

	typedef uint32_t TickType_t;#define portMAX_DELAY (TickType_t)0xffffffffUL

    即延迟时间的范围是:1- 0xFFFFFFFF

② 函数原型:

void vTaskDelayUntil(TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement);

  函数描述:函数 vTaskDelayUntil 用于周期性延迟。 属于绝对延时,指间隔指定的时间(参数:滴答值),执行一次调用 vTaskDelayUntil() 函数的任务。

  第 1 个参数,存储任务最后一次解除阻塞的时间

  第 2 个参数,周期性延迟时间。

使用这个函数要注意以下问题:

  1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1

#define INCLUDE_vTaskDelayUntil 1

③ 函数原型:

volatile TickType_t xTaskGetTickCount(void);

  函数描述:函数 xTaskGetTickCount 用于获取系统当前运行的时钟节拍数。

  使用这个函数要注意以下问题:

  1. 此函数用于在任务代码里面调用,如果在中断服务程序里面调用的话,需要使用函数 xTaskGetTickCountFromISR,这两个函数切不可混用。

④ 函数原型:

volatile TickType_t xTaskGetTickCountFromISR(void);

  函数描述:函数 xTaskGetTickCountFromISR 用于获取系统当前运行的时钟节拍数。

  使用这个函数要注意以下问题:

  1. 此函数用于在中断服务程序里面调用,如果在任务里面调用的话,需要使用函数 xTaskGetTickCount,这两个函数切不可混用。

三、相对延时与绝对延时的区别与编程测试

1、问题:周期性去处理某一件事情。你会通过什么方式去实现?

  比如:间隔 10ms 去采集传感器的数据,然后通过一种算法计算出一个结果,最后通过串口发送出去。对于裸机编程,首先想到的是:利用定时器,定时 10ms 中断,在中断里面处理。但中断函数适合处理简单数据,要求快进快出,不适合算法、通信等需要长时间占用 CPU 的处理。对计时精度要求比较高的地方适合定时器,像本节说的周期性采集传感器数据,要求不适合很高,那么就引入本文说的绝对延时。

2、 相对延时:指每次延时都是从执行函数 vTaskDelay() 开始,直到延时指定的时间(参数:滴答值)结束。

  绝对延时:指间隔指定的时间(参数:滴答值),执行一次调用 vTaskDelayUntil() 函数的任务。

3、通过编程测试相对延时和绝对延时的区别

  创建 2 个任务,情况如下:

  任务 1:HAL_Delay 延时 50ms,模拟传感器采集数据与被中断或高优先级任务打断的时间,printf 打印任务运行次数,再通过 vTaskDelay 相对延时 200ms;

  任务 2:HAL_Delay 延时 50ms,模拟传感器采集数据与被中断或高优先级任务打断的时间,printf 打印任务运行次数,再通过 vTaskDelayUntil 就绝对延时 200ms;

实验分析:

  任务 1 由于采用相对延时,printf 间隔 250ms(50ms+200ms) 打印信息

  任务 2 由于采用绝对延时,printf 间隔 200ms(50ms+150ms) 打印信息

**疑问:**为什么采用绝对延时,printf 间隔为 50ms+150ms

  **解答:**任务执行时,先花 50ms 执行模拟采集数据与被中断或高优先级任务打断的时间, 接着,调用 vTaskDelayUntil, 此函数会根据第 1 个实参 (存储任务最后一次解除阻塞的时间) 与当前系统时间计算出模拟采集数据与被中断或高优先级任务打断的 50ms 时间,此时只延时 200ms-50ms=150ms,以确保任务周期性执行,所以 vTaskDelayUntil 实际只阻塞了 150ms。

这篇关于FreeRTOS 实时操作系统第八讲 - 时间管理 (系统节拍,延时函数)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/546668

相关文章

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

JWT + 拦截器实现无状态登录系统

《JWT+拦截器实现无状态登录系统》JWT(JSONWebToken)提供了一种无状态的解决方案:用户登录后,服务器返回一个Token,后续请求携带该Token即可完成身份验证,无需服务器存储会话... 目录✅ 引言 一、JWT 是什么? 二、技术选型 三、项目结构 四、核心代码实现4.1 添加依赖(pom

RabbitMQ 延时队列插件安装与使用示例详解(基于 Delayed Message Plugin)

《RabbitMQ延时队列插件安装与使用示例详解(基于DelayedMessagePlugin)》本文详解RabbitMQ通过安装rabbitmq_delayed_message_exchan... 目录 一、什么是 RabbitMQ 延时队列? 二、安装前准备✅ RabbitMQ 环境要求 三、安装延时队

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环