返回顶部
首页 > 资讯 > 精选 >FreeRTOS系统延时实例分析
  • 823
分享到

FreeRTOS系统延时实例分析

2023-06-29 23:06:36 823人浏览 八月长安
摘要

这篇文章主要讲解了“FreeRTOS系统延时实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“FreeRTOS系统延时实例分析”吧!FreeRTOS提供了两个系统延时函数:相对延时函数v

这篇文章主要讲解了“FreeRTOS系统延时实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“FreeRTOS系统延时实例分析”吧!

FreeRTOS提供了两个系统延时函数:相对延时函数vTaskDelay()和绝对延时函数

vTaskDelayUntil()。相对延时是指每次延时都是从任务执行函数vTaskDelay()开始,延时指定的时间结束;

绝对延时是指每隔指定的时间,执行一次调用vTaskDelayUntil()函数的任务。换句话说:任务以固定的频率执行。

1. 相对延时函数vTaskDelay()

考虑下面的任务,任务A在执行任务主体代码后,调用相对延时函数vTaskDelay()进入阻塞状态。系统中除了任务A外,还有其它任务,但是任务A的优先级最高。

void vTaskA( void * pvParameters )   {              const portTickType xDelay = pdMS_TO_TICKS(500);          for( ;; )       {           //  ...         //  这里为任务主体代码         //  ...                          vTaskDelay( xDelay );       }  }

对于这样一个任务,执行过程如图1-1所示。当任务A获取CPU使用权后,先执行任务A的主体代码,之后调用系统延时函数vTaskDelay()进入阻塞状态。任务A进入阻塞后,其它任务得以执行。

FreeRTOS内核会周期性的检查任务A的阻塞是否达到,如果阻塞时间达到,则将任务A设置为就绪状态。由于任务A的优先级最高,会抢占CPU,再次执行任务主体代码,不断循环。

从图1-1可以看出,任务A每次延时都是从调用延时函数vTaskDelay()开始算起的,延时是相对于这一时刻开始的,所以叫做相对延时函数。

从图1-1还可以看出,如果执行任务A的过程中发生中断,那么任务A执行的周期就会变长,所以使用相对延时函数vTaskDelay(),不能周期性的执行任务A。

FreeRTOS系统延时实例分析

图1-1:相对延时函数执行示意图

我们来看一下源码

void vTaskDelay( const TickType_t xTicksToDelay ){BaseType_t xAlreadyYielded = pdfALSE;        if( xTicksToDelay > ( TickType_t ) 0U )    {        vTaskSuspendAll();        {                        prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );        }        xAlreadyYielded = xTaskResumeAll();    }        if( xAlreadyYielded == pdFALSE )    {        portYIELD_WITHIN_api();    }}

如果延时大于0,则会将当前任务从就绪列表删除,然后加入到延时列表。是调用函数prvAddCurrentTaskToDelayedList()完成这一过程的。我们在前面一系列博文中多次提到,tasks.c中定义了很多局部静态变量,其中有一个变量xTickCount定义如下所示:

static volatile TickType_t xTickCount = ( TickType_t ) 0U;

        这个变量用来计数,记录系统节拍中断的次数,它在启动调度器时被清零,在每次系统节拍时钟发生中断后加1。相对延时函数会使用到这个变量,xTickCount表示了当前的系统节拍中断次数,这个值加上参数规定的延时时间(以系统节拍数表示)xTicksToDelay,就是下次唤醒任务的时间,xTickCount+ xTicksToDelay会被记录到任务TCB中,随着任务一起被挂接到延时列表。      

我们知道变量xTickCount是TickType_t类型的,它也会溢出。在32位架构中,当xTicksToDelay达到4294967295后再增加,就会溢出变成0。为了解决xTickCount溢出问题,FreeRTOS使用了两个延时列表:xDelayedTaskList1和xDelayedTaskList2,并使用两个列表指针类型变量pxDelayedTaskList和pxOverflowDelayedTaskList分别指向上面的延时列表1和延时列表2(在创建任务时将延时列表指针指向延时列表)。顺便说一下,上面的两个延时列表指针变量和两个延时列表变量都是在tasks.c中定义的静态局部变量。        

如果内核判断出xTickCount+ xTicksToDelay溢出,就将当前任务挂接到列表指针pxOverflowDelayedTaskList指向的列表中,否则就挂接到列表指针pxDelayedTaskList指向的列表中。
        每次系统节拍时钟中断,中断服务函数都会检查这两个延时列表,查看延时的任务是否到期,如果时间到期,则将任务从延时列表中删除,重新加入就绪列表。如果新加入就绪列表的任务优先级大于当前任务,则会触发一次上下文切换。

2. 绝对延时函数vTaskDelayUntil()

考虑下面的任务,任务B首先调用绝对延时函数vTaskDelayUntil ()进入阻塞状态,阻塞时间到达后,执行任务主体代码。系统中除了任务B外,还有其它任务,但是任务B的优先级最高。

void vTaskB( void * pvParameters )  {      static portTickType xLastWakeTime;      const portTickType xFrequency = pdMS_TO_TICKS(500);      // 使用当前时间初始化变量xLastWakeTime ,注意这和vTaskDelay()函数不同     xLastWakeTime = xTaskGetTickCount();      for( ;; )      {                          vTaskDelayUntil( &xLastWakeTime,xFrequency );           //  ...         //  这里为任务主体代码,周期性执行.注意这和vTaskDelay()函数也不同         //  ...      }  }

对于这样一个任务,执行过程如图2-1所示。当任务B获取CPU使用权后,先调用系统延时函数vTaskDelayUntil()使任务进入阻塞状态。任务B进入阻塞后,其它任务得以执行。FreeRTOS内核会周期性的检查任务A的阻塞是否达到,如果阻塞时间达到,则将任务A设置为就绪状态。

由于任务B的优先级最高,会抢占CPU,接下来执行任务主体代码。任务主体代码执行完毕后,会继续调用系统延时函数vTaskDelayUntil()使任务进入阻塞状态,周而复始。

从图2-1可以看出,从调用函数vTaskDelayUntil()开始,每隔固定+
-周期,任务B的主体代码就会被执行一次,即使任务B在执行过程中发生中断,也不会影响这个周期性,只是会缩短其它任务的执行时间!所以这个函数被称为绝对延时函数,它可以用于周期性的执行任务A的主体代码。

FreeRTOS系统延时实例分析

  图2-1:绝对延时函数执行示意图

函数vTaskDelayUntil()是如何做到周期性的呢,我们来看一下源码。

void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement ){TickType_t xTimeToWake;BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;    vTaskSuspendAll();    {                const TickType_t xConstTickCount = xTickCount;                xTimeToWake = *pxPreviousWakeTime + xTimeIncrement;                if( xConstTickCount < *pxPreviousWakeTime )        {                        if( ( xTimeToWake < *pxPreviousWakeTime ) && ( xTimeToWake > xConstTickCount ) )            {                xShouldDelay = pdTRUE;            }        }        else        {                        if( ( xTimeToWake < *pxPreviousWakeTime ) || ( xTimeToWake > xConstTickCount ) )            {                xShouldDelay = pdTRUE;            }        }                *pxPreviousWakeTime = xTimeToWake;         if( xShouldDelay != pdFALSE )        {                        prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount, pdFALSE );        }    }    xAlreadyYielded = xTaskResumeAll();         if( xAlreadyYielded == pdFALSE )    {        portYIELD_WITHIN_API();    }}

与相对延时函数vTaskDelay不同,本函数增加了一个参数pxPreviousWakeTime用于指向一个变量,变量保存上次任务解除阻塞的时间。这个变量在任务开始时必须被设置成当前系统节拍中断次数(见上文的任务B举例),此后函数vTaskDelayUntil()在内部自动更新这个变量。

由于变量xTickCount可能会溢出,所以程序必须检测各种溢出情况,并且要保证延时周期不得小于任务主体代码执行时间。这很好理解,不可能出现每5毫秒执行一个需要20毫秒才能执行完的任务。
如果我们以横坐标表示变量xTickCount的范围,则横坐标左端为0,右端为变量xTickCount所能表示的最大值。在如图2-2所示的三种情况下,才可以将任务加入延时列表。

图2-2中

*pxPreviousWakeTime和xTimeToWake之间表示任务周期性延时时间,

*pxPreviousWakeTime和xConstTickCount之间表示任务B主体代码执行时间。

图2-2中

第一种情况处理系统节拍中断计数器(xConstTickCount)和唤醒时间计数器(xTimeToWake)溢出情况;

第二种情况处理唤醒时间计数器(xTimeToWake)溢出情况

第三种情况处理常规无溢出的情况。

从图中可以看出,不管是溢出还是无溢出,都要求在下次唤醒任务之前,当前任务主体代码必须被执行完。表现在图2-2中,就是变量xTimeToWake总是大于变量xConstTickCount(每溢出一次的话相当于加上一次最大值Max)。
 

FreeRTOS系统延时实例分析

图2-2:将任务加入延时列表的三种情况

        计算的唤醒时间合法后,就将当前任务加入延时列表,同样延时列表也有两个。每次系统节拍中断,中断服务函数都会检查这两个延时列表,查看延时的任务是否到期,如果时间到期,则将任务从延时列表中删除,重新加入就绪列表。如果新加入就绪列表的任务优先级大于当前任务,则会触发一次上下文切换。

感谢各位的阅读,以上就是“FreeRTOS系统延时实例分析”的内容了,经过本文的学习后,相信大家对FreeRTOS系统延时实例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: FreeRTOS系统延时实例分析

本文链接: https://lsjlt.com/news/326753.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • FreeRTOS系统延时实例分析
    这篇文章主要讲解了“FreeRTOS系统延时实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“FreeRTOS系统延时实例分析”吧!FreeRTOS提供了两个系统延时函数:相对延时函数v...
    99+
    2023-06-29
  • freertos实时操作系统空闲任务阻塞延时示例解析
    目录前言空闲任务阻塞延时SysTick实验现象前言 阻塞态:如果一个任务当前正在等待某个外部事件,则称它处于阻塞态。 rtos中的延时叫阻塞延时,即任务需要延时的时候,会放弃CPU的...
    99+
    2024-04-02
  • FreeRTOS进阶之系统延时完全解析
    目录1. 相对延时函数vTaskDelay()2. 绝对延时函数vTaskDelayUntil()3.小结FreeRTOS提供了两个系统延时函数:相对延时函数vTaskDelay()...
    99+
    2024-04-02
  • FreeRTOS实时操作系统的内存管理分析
    目录前言1.heap_1.c功能简介:2.heap_2.c功能简介:3.heap_3.c功能简介:4.heap_4.c功能简介:5.heap_5.c(V8.1.0新增)前言 本文介绍...
    99+
    2024-04-02
  • FreeRTOS实时操作系统空闲任务的阻塞延时实现
    目录什么是阻塞延时、为什么需要空闲任务空闲任务的实现阻塞延时的实现xTicksToDelay 递减SysTick初始化仿真什么是阻塞延时、为什么需要空闲任务 RTOS中的延时叫阻塞延...
    99+
    2024-04-02
  • FreeRTOS实时操作系统结构示例
    目录1.查找相关文档页2.获取RTOS源代码3.FreeRTOS源码目录结构移植层目录举例:演示例程目录举例:4.编译工程5.运行演示例程 FreeRTOS可以被移植到很多...
    99+
    2024-04-02
  • FreeRTOS实时操作系统的内核控制示例解析
    目录前言1.强制上下文切换宏2.进入临界区宏3.退出临界区宏4.禁止可屏蔽中断宏5.使能可屏蔽中断宏6.启动调度器6.1函数描述7.停止调度器7.1函数描述8.挂起调度器8.1函数描...
    99+
    2024-04-02
  • FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现
    这篇文章主要介绍“FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“FreeRTOS实时操作系统空闲任务的阻塞延时怎么实现”文章能帮助大家解决问题。...
    99+
    2023-06-29
  • FreeRTOS实时操作系统支持时间片示例详解
    目录什么是时间片时间片实现关键taskSELECT_HIGHEST_PRIORITY_TASK()taskRESET_READY_PRIORITY()什么是时间片 时间片就是同一个优...
    99+
    2024-04-02
  • FreeRTOS进阶系统节拍时钟示例的完全解析
    目录前言1.调度器正常情况2.调度器挂起情况3.自动任务切换前言 操作系统的运行是由系统节拍时钟驱动的。 在FreeRTOS中,我们知道系统延时和阻塞时间都是以系统节拍时钟周期为单位...
    99+
    2024-04-02
  • FreeRTOS实时操作系统移植操作示例指南
    目录1.添加FreeRTOS源码2.向工程分组中添加文件附上delay.c和delay.h的代码1.添加FreeRTOS源码 在基础工程中新建一个名为 FreeRTOS 的文件夹,将...
    99+
    2024-04-02
  • Java中延时Lock vs Synchronized的实例分析
    本篇文章给大家分享的是有关Java中延时Lock vs Synchronized的实例分析,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。几天前,当我诊断一些 JIT 编译期间奇...
    99+
    2023-06-17
  • FreeRTOS操作系统的配置示例解析
    目录1. FreeRTOSConfig.h 文件2.INCLUDE_ 开始的宏3.config开始的宏FreeRTOS 的系统配置文件为 FreeRTOSConfig.h,在此配置文...
    99+
    2024-04-02
  • FreeRTOS实时操作系统特点介绍
    目录1.什么是FreeRTOS?2.为什么择 选择 FreeRTOS ?3.FreeRTOS 特点FreeRTOS资料与源码下载FreeRTOS源码文件介绍1.什么是FreeRTOS...
    99+
    2024-04-02
  • FreeRTOS实时操作系统队列基础
    目录前言1.FreeRTOS队列2.使用模型:最简单、最灵活3.队列阻塞前言 本文介绍队列的基本知识,详细源码分析见FreeRTOS进阶之队列示例分析 1.FreeRTOS队列 队列...
    99+
    2024-04-02
  • FreeRTOS实时操作系统临界段保护场合示例
    目录临界段保护场合非中断场合中断场合临界段保护场合 FreeRTOS中临界段保护有2种场合,中断和非中断,通过关中断(或者关部分中断)来实现临界保护。 非中断场合 task.h 中 ...
    99+
    2024-04-02
  • FreeRTOS实时操作系统信号量基础
    目录前言1.信号量简介2.二进制信号量3.计数信号量4.互斥量5.递归互斥量前言 本文介绍信号量的基础知识,详细源码分析见FreeRTOS进阶信号量分析 1.信号量简介 FreeRT...
    99+
    2024-04-02
  • FreeRTOS实时操作系统结构是什么
    本文小编为大家详细介绍“FreeRTOS实时操作系统结构是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“FreeRTOS实时操作系统结构是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。 Fre...
    99+
    2023-06-29
  • FreeRTOS实时操作系统的多优先级实现
    目录如何实现任务多优先级软件通用方法和硬件指令方法如何实现任务多优先级 FreeRTOS中,数字优先级越小,逻辑优先级也越小,空闲任务优先级为0.List_t pxReadyTask...
    99+
    2024-04-02
  • FreeRTOS实时操作系统的列表与列表项操作示例
    目录前言列表项数据结构列表项初始化列表数据结构将列表项按照升序排列插入到列表将列表项从列表删除    前言 FreeRTOS列表与列表项其实就是链表和节点,在li...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作