全部学习汇总: GitHub - GreyZhang/g_FreeRTOS: learning notes about FreeRTOS.
其实,从这个简单的描述就能够知道软件定时器的作用。如果做一个比喻的话,软件定时器的作用就像一个定时炸弹的引爆器一样。它可以控制起爆的时间,而起爆对应的就是软件执行启动的时间。
FreeRTOS的软件定时器其实是依赖于已经存在的FreeRTOS的功能来实现的而不是依赖于定时器的中断。因此,这样的实现不会在中断的上下文中执行任何代码。如果不是超时发生,也不会引入额外的执行时间开销。同时,也不会给tick中断增加额外的负担。在中断关闭之后,不会遍历任何链表结构。这样,软件定时器对于整个应用甚至整个系统的影响就会很小。但是这个标题考虑到了效率问题,文中并没有直白说FreeRTOS的软件定时器效率低,但是相比硬件中断来说它的效率会低一些肯定是意料之中的了。
回调函数是在定时器服务任务的上下文中执行的,因此有一个关键点需要注意:不要让这一段的上下文信息出现阻塞,否则影响的会是整个系统级别的定时器服务。因此,不要在软件定时器的回调函数中调用任何系统提供的delay函数,也不要使用阻塞型的队列或者信号。
上面这部分解释了软件定时器的大概的机理。如果之前用过FreeRTOS的队列功能的话,这个实现就很容易理解了。其实,FreeRTOS的软件定时器本质上来说就是通过一个队列激活一个任务处理不同的内容。之前,了解了FreeRTOS的队列机制后我觉得很多功能都可以利用队列来进行处理,的确是非常灵活。
从另一个角度讲,既然这个可以通过队列来实现,也就意味着这个在FreeRTOS中属于偏应用的一个实现。本身,软件定时器并不是FreeRTOS内核的一部分,只是一个功能相对底层一些的一个特殊任务。而这里用到的这个队列是一个私有队列,由于其功能上的特殊性,给它取了一个特殊的名字:定时器命令队列。
如果OS中不用这个定时器的功能,如果实现一个“延时起爆”的效果其实也是很容易的。也是利用队列发送一个信号激活一个任务,信号中带着延时时间信息,而激活的任务执行相关的功能之前先利用FreeRTOS提供的延时函数做一个延时再执行相关的处理逻辑即可。
如果要在软件中使用软件定时器的功能,第一需要把相应的代码加进去;第二需要配置一系列的参数。具体需要配置的参数参考上面的表格,内容其实是很简单明了的。除了一个使能开关的配置之外,其他的配置参数都是可以映射到使用队列的任务的基础配置上的。
定时器分为一次性的和可以重新加载两类。基本的特性其实简单,一个回调函数只执行一次,另一个创建了一个周期性执行的回调函数。如果不去利用现有的功能,考虑如何实现类似功能的话,我觉得简单的机制可以做成:可以重新加载的服务在执行结束后给自己发送一个队列信号再次激活任务并阻塞掉就可以了。
软件定时器是可以重置的,这个相对于前面的实现来说应该就难一些了。我自己能够想到的是在软件服务任务中加上一个状态量,当状态量发生变化的时候取消前一次的定时操作。但是如果这个实现真使用了FreeRTOS提供的delay函数的话,delay已经开始了类似的处理就会难处理一些。比较好处理的是delay也全都打散,每次执行的粒度是一个tick,这样至少可以保证在tick的粒度时间单位上尽可能靠近控制效果。
关于这个功能在FreeRTOS中的具体实现,我多少也有点兴趣去研究一下了。很想看看,他们是如何在这样的前提条件下实现了相应的功能。
这是FreeRTOS的软件定时器可以提供的API,看起来功能还是很细腻的。后面得逐个使用一下,同时研究一下他们的实现。如果有可能,摘取出来作为可以应用于其他OS或者前后台程序中的一个灵活可用的模块。
下面有介绍的两个接口,一个是可以用于获取软件定时器服务任务的句柄的接口;另一个则可以利用这个结果获取定时器相关联的名称。从描述看,这两个接口在进行软件调试的时候应该有很大的帮助。
|