当前位置: 首页 >  软件学堂 >  《Mastering the FreeRTOS Real Time Kernel》读书笔记(4)软定时器

《Mastering the FreeRTOS Real Time Kernel》读书笔记(4)软定时器

导读:5.软件定时器管理.软件定时器由FreeRTOS内核实现,并受其控制。它们不需要硬件支持,也与硬件计时器或硬件计数器无关。.软件定时器功能是可选的。包括软件定时器功能:1。作为项目的一部分,构建FreeRTOS源文件FreeRTOS/source/timers.c。2.在Free

5.软件定时器管理

软件定时器由FreeRTOS内核实现,并受其控制。它们不需要硬件支持,也与硬件计时器或硬件计数器无关。
软件定时器功能是可选的。包括软件定时器功能:1。作为项目的一部分,构建FreeRTOS源文件FreeRTOS/source/timers.c。2.在FreeRTOSConfig.h中将configUSE_TIMERS设置为1。

5.2 软件定时器回调函数

void ATimerCallback( TimerHandle_t xTimer );

返回值为void,并将软件计时器的句柄作为其唯一参数。
软件定时器回调函数是在启动FreeRTOS调度器时自动创建的任务的上下文中执行的。因此,重要的是,软件计时器回调函数永远不要调用FreeRTOS API函数,这将导致调用任务进入阻止状态。可以调用xQueueReceive()等函数,但前提是函数的xTicksToWait参数(指定函数的块时间)设置为0。

5.3 软件计时器的属性和状态

周期

软件定时器的“周期”是软件定时器启动和软件定时器回调功能执行之间的时间。

一次性与自动装载

1.一次性计时器一旦启动,一次性计时器将只执行一次回调功能。一次性计时器可以手动重新启动,但不会自行重新启动。
2.自动重新加载定时器一旦启动,自动重新加载计时器将在每次到期时重新启动,从而定期执行其回调功能。

两种状态

1.休眠状态:只有句柄,但是回调函数是没有反应的。
2.运行状态:正常状态,回调函数可以被触发。一次性计时器执行完一次回调函数后,回到休眠状态。

5.4 软件定时器的环境

OS的守护进程(Daemon Task)

守护进程,又有叫精灵进程。很多博文都介绍说守护进程是伴随创建其的那个进程(A进程)而存在的。如果A进程没了,其守护进程就没了。OS的守护进程是随着OS启动便一直运行,它是一个标准的FreeRTOS任务,也有优先级和堆栈,分别由configTIMER_TASK_priority和configTIMER_TASK_stack_DEPTH编译时配置常量设置。
软定时器的检测和运行都在RTOS的守护进程中。

定时器命令队列

通过向定时器命令队列发送命令以控制软件定时器,命令有启动定时器、停止定时器、重置定时器。
这个队列是一个标准的FreeRTOS队列,它是在调度程序启动时自动创建的。队列的长度由FreeRTOSConfig.h中的configTIMER_queue_length编译时配置常量设置。
守护进程中的软定时器功能,会接受定时器命令队列中的命令,来进行操作。

守护进程的优先级

守护进程的优先级可以小于包含软件定时器开始和停止命令的任务的优先级,也可以大于其优先级。这两种方式的程序有不同的用途。
通过改变configTIMER_TASK_PRIORITY设置会实现两种执行模式。

5.5 创建和启动一个软件定时器

主要包括创建函数和启动函数。

xTimerCreate()

TimerHandle_t xTimerCreate( const char * const pcTimerName,
                            TickType_t xTimerPeriodInTicks,
                            UBaseType_t uxAutoReload,
                            void * pvTimerID,
                            TimerCallbackFunction_t pxCallbackFunction );

1.pcTimerName:描述性命名。人类可读的命名比单纯的句柄名称好理解得多。
2.xTimerPeriodInTicks:以刻度为单位指定的计时器周期。可使用pdMS_TO_TICKS()宏。
3.uxAutoReload:设置为pdTRUE以创建自动重新加载计时器。设置为pdFALSE以创建一次性计时器。
4.pvTimerID:ID是一个空指针,应用程序编写器可以将其用于任何目的。当多个软件计时器使用相同的回调函数时,ID特别有用,因为它可以用于提供特定于计时器的存储。万用指针。
5.pxCallbackFunction:是指向回调函数名称的指针,用作正在创建的软件计时器的回调函数。
6.返回值:如果返回NULL,则无法创建软件计时器,因为没有足够的堆内存可用于FreeRTOS分配必要的数据结构。

xTimerStart() & xTimerStop()

xTimerStart() 用于启动处于休眠状态的软件定时器,或重置(重新启动)处于运行状态的软件计时器。相同的xTimerStop()用于停止处于运行状态的软件计时器。

BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );

1.xTimer:正在启动或重置的软件计时器的句柄。句柄将从用于创建软件计时器的xTimerCreate()调用中返回。
2.xTicksToWait:启动命令是需要发送到定时器命令队列的,这里的参数解释与队列发送的xTicksToWait解释相同。
3.返回值:与发送消息给队列的返回值解释相同。

例子13是分别创建一次性和自动装填软件定时器的例程。

5.6 定时器的ID

每个软件定时器都有一个ID,这是一个标签值,应用程序编写器可以将其用于任何目的 。ID存储在一个void指针(void*)中,因此可以直接存储一个整数值,指向任何其他对象,或用作函数指针。

创建软件计时器时,会为ID分配一个初始值,之后可以使用vTimerSetTimerID()API函数更新ID,并使用pvTimerGetTimerID()API函数查询ID。与其他软件计时器API函数不同的是,vTimerSetTimerID()和pvTimerGetTimerID()直接访问软件计时器—它们不向计时器命令队列发送命令。

vTimerSetTimerID()

void vTimerSetTimerID( const TimerHandle_t xTimer, void *pvNewID );

pvTimerGetTimerID()

void *pvTimerGetTimerID( TimerHandle_t xTimer );

例子14:定时器ID的使用场景

示例14创建了与示例13创建的功能类似的功能,但为两个软件定时器分配了相同的回调功能。

/* Create the one shot timer software timer, storing the handle in xOneShotTimer. */
xOneShotTimer = xTimerCreate( "OneShot",
                                mainONE_SHOT_TIMER_PERIOD,
                                pdFALSE,
                                /* The timer’s ID is initialized to 0. */
                                0,
                                /* prvTimerCallback() is used by both timers. */
                                prvTimerCallback );

/* Create the auto-reload software timer, storing the handle in xAutoReloadTimer */
xAutoReloadTimer = xTimerCreate( "AutoReload",
                                  mainAUTO_RELOAD_TIMER_PERIOD,
                                  pdTRUE,
                                  /* The timer’s ID is initialized to 0. */
                                  0,
                                  /* prvTimerCallback() is used by both timers. 
                                  这里使用了相同的回调函数 */
                                  prvTimerCallback );

static void prvTimerCallback( TimerHandle_t xTimer )
{
TickType_t xTimeNow;
uint32_t ulExecutionCount;
  /* A count of the number of times this software timer has expired is stored in the         timer's
  ID. Obtain the ID, increment it, then save it as the new ID value. The ID is a void
  pointer, so is cast to a uint32_t. */
  ulExecutionCount = ( uint32_t ) pvTimerGetTimerID( xTimer );
  ulExecutionCount++;
  vTimerSetTimerID( xTimer, ( void * ) ulExecutionCount );
  /* Obtain the current tick count. */
  xTimeNow = xTaskGetTickCount();
  /* The handle of the one-shot timer was stored in xOneShotTimer when the timer was   created.
  Compare the handle passed into this function with xOneShotTimer to determine if it was the
  one-shot or auto-reload timer that expired, then output a string to show the time at which
  the callback was executed. */
  if( xTimer == xOneShotTimer )
  {
    vPrintStringAndNumber( "One-shot timer callback executing", xTimeNow );
  }
  else
  {
    /* xTimer did not equal xOneShotTimer, so it must have been the auto-reload timer that
    expired. */
    vPrintStringAndNumber( "Auto-reload timer callback executing", xTimeNow );
    if( ulExecutionCount == 5 )
    {
      /* Stop the auto-reload timer after it has executed 5 times. This callback function
      executes in the context of the RTOS daemon task so must not call any functions that
      might place the daemon task into the Blocked state. Therefore a block time of 0 is
      used. */
      xTimerStop( xTimer, 0 );
    }
  }
}

在同一个回调函数中,判断是哪个定时器触发的,并且执行该定时器相应的打印任务。

5.7 更改定时器的值

可以实现类似呼吸灯等需要改变“重装填值”的效果。

BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
                                TickType_t xNewTimerPeriodInTicks,
                                TickType_t xTicksToWait );

1.xTimer:定时器的句柄,由create返回。
2.xNewTimerPeriodInTicks:新的重装填值。
3.xTicksToWait:由于这个函数也算是一个命令,所以也需要发送到命令队列,也必须有一个最长等待时间。

5.8 重置一个软件定时器

官方解释:重置软件计时器意味着重新启动计时器;计时器的到期时间将重新计算为相对于计时器重置的时间,而不是计时器最初启动的时间。

也就是将定时器内部已经积累的计数值清零。

BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );

这个函数也是一个命令,需要发送到定时器命令队列。

例子15讲述了如何使用重置软件定时器功能,来阻止一些定时事件的发生。

总结

其实软件定时器,在裸机程序中,就应该是已经很好用的了。
使用一个1ms的硬件定时器,通过每次进硬件中断后进行++的计数。并在每次都判断计数值是否达到阈值,以达到比如10ms软定时器中断、100ms软定时器中断、1s的软定时器中断。但是这些中断不能处理很多信息,一定不能超过1ms,不然会影响下一次进硬中断,导致程序卡死。

本章节就是讲了一下如何使用FreeRTOS的框架实现软件定时器的,利用前面讲的任务和队列,将软件定时器的实现规范化,使得在FreeRTOS的心跳时钟下,还能分出很多软件定时器和它们的回调函数,来处理不同的信息。

具体的使用和自己的案例就不在读书笔记中分享了。

内容
  • 什么是软件供应链?
    什么是软件供应链?
    2023-12-05
    1 软件供应链定义.需方和供方基于供应关系,开展并完成软件采购、开发、交付、获取、运维和废止等供应活动而形成的网链结构。
  • FlashDuty Changelog 2023-09-21 | 自定义字段和开发者中心
    FlashDuty Change
    2023-12-04
    FlashDuty:一站式告警响应平台,前往此地址免费体验!.自定义字段.FlashDuty 已支持接入大部分常见的告警
  • 汽车ECU软件开发之应用层软件与底层软件
    汽车ECU软件开发之应用层软件与
    2023-12-03
    随着汽车产品日渐趋向电子化,人们对各类先进的安全系统、高级驾驶辅助系统的接受程度日益提升。而原本昂贵的盲点检测、自动紧急
  • 华为云CodeArts Artifact,5大特性守护制品质量与安全
    华为云CodeArts Arti
    2023-12-03
    摘要: 2023年2月23日,华为云CodeArts.Artifact制品仓库服务正式上线,目标进一步赋能企业伙伴与开发
  • 软件研发CI/CD流水线图解
    软件研发CI/CD流水线图解
    2023-12-02
    当谈到现代软件开发流程时,持续集成(Continuous Integration,简称CI)和持续交付(Continuo
  • 线段简化的几种算法
    线段简化的几种算法
    2023-12-01
    翻译自:https://www.codeproject.com/Articles/114797/Polyline-.Si
  • 实时光线追踪(3)Ray Casting
    实时光线追踪(3)Ray Cas
    2023-12-01
    目录.硬件光追(Hardware Ray Tracing).加速结构(Acceleration Structure,AS
  • 智能车载设备
    智能车载设备
    2023-10-02
    智能车载设备.我们的智能车载设备是一款结合了最新科技和创新设计的汽车配件,旨在提升驾驶体验、提高安全性和为用户带来智能化
  • 智能医疗设备
    智能医疗设备
    2023-10-02
    智能医疗设备产品介绍.智能医疗设备是一款集成了先进技术的高科技产品,旨在提高医疗保健的效率和质量。该设备主要应用于医院、
  • 互联网金融服务平台
    互联网金融服务平台
    2023-10-01
    互联网金融服务平台.产品功能.个人理财:用户可以通过平台进行投资理财,选择适合自己的理财产品,实现资金增值。.贷款服务:
  • 电子元件电感
    电子元件电感
    2023-10-02
    电子元件电感.产品功能.电感是一种重要的电子元件,用于储存和释放电能,调节电路中的电流和电压。它在电子设备和通讯设备中起
  • 智能智能家居设备
    智能智能家居设备
    2023-10-05
    智能家居设备介绍.产品概述.我们当前运营的产品是智能家居设备,它是一款智能化的家居控制系*,旨在为用户提供更便捷、舒适的
  • 智能可穿戴设备
    智能可穿戴设备
    2023-10-03
    产品功能介绍.我们的智能可穿戴设备是一款集健康监测、运动追踪、通讯互动等多种功能于一体的产品。它采用先进的传感技术,可实
  • 智能手机
    智能手机
    2023-10-01
    产品功能介绍:智能手机.智能手机是一款集通讯、娱乐、办公等功能于一体的移动智能设备。首先,智能手机具有强大的通讯功能,支
  • 智能智能物流设备
    智能智能物流设备
    2023-10-04
    智能物流设备.1. 产品描述.智能物流设备是一款基于物联网技术的智能设备,主要用于运输、储存和**物流货物。其核心功能是
  • 智能智能娱乐设备
    智能智能娱乐设备
    2023-10-04
    产品功能介绍.1. 智能娱乐设备.我们的智能娱乐设备是一款结合了智能技术和娱乐功能的产品。它拥有丰富的娱乐资源,包括音乐
  • 智能电视
    智能电视
    2023-10-01
    产品功能介绍.智能电视是一款结合了传统电视和智能硬件的产品。它内置了智能操作系*,能够连接互联网并运行各种应用程序。智能