RT-Thread学习笔记(13):软件定时器

硬件定时器和软件定时器

硬件定时器是芯片本身提供的定时功能。一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式

软件定时器,软件定时器是由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受硬件定时器资源限制的定时器服务,它实现的功能与硬件定时器也是类似的。

使用硬件定时器时,每次在定时时间到达之后就会自动触发一个中断,用户在中断中处理信息;而使用软件定时器时,需要我们在创建软件定时器时指定时间到达后要调用的函数(也称超时函数/回调函数,为了统一,下文均用超时函数描述),在超时函数中处理信息。

软件定时器在被创建之后,当经过设定的时钟计数值后会触发用户定义的超时函数。定时精度与系统时钟的周期有关。一般系统利用SysTick作为软件定时器的基础时钟,超时函数类似硬件的中断服务函数,所以,超时函数也要快进快出,而且超时函数中不能有任何阻塞线程运行的情况,比如rt_thread_delay()以及其它能阻塞线程运行的函数,两次触发超时函数的时间间隔Tick叫定时器的定时周期。

RT-Thread提供的软件定时器支持单次模式周期模式,单次模式和周期模式的定时时间到之后都会调用定时器的超时函数,用户可以在超时函数中加入要执行的工程代码。
单次模式:当用户创建了定时器并启动了定时器后,定时时间到了,只执行一次超时函数之后就将该定时器删除,不再重新执行。
周期模式:这个定时器会按照设置的定时时间循环执行超时函数,直到用户将定时器删除。
在这里插入图片描述
注意:在RT-Thread中创建定时器API接口可以选择软件定时器与硬件定时器,但是硬件定时器超时函数的上下文环境中断,而软件定时器超时函数的上下文是线程。下文所说的定时器均为软件定时器工作模式,RT-Thread中在rtdef.h中定义了相关的宏定义来选择定时器的工作模式:

  • RT_TIMER_FLAG_HARD_TIMER 为硬件定时器。
  • RT_TIMER_FLAG_SOFT_TIMER为软件定时器。

软件定时器的运作机制

软件定时器是系统资源,在创建定时器的时候会分配一块内存空间。当用户创建并启动一个软件定时器时, RT-Thread会根据当前系统rt_tick时间及用户设置的定时确定该定时器唤醒时间timeout,并将该定时器控制块挂入软件定时器列表rt_soft_timer_list。

在RT-Thread定时器模块中维护着两个重要的全局变量:

  • rt_tick,它是一个32位无符号的变量,用于记录当前系统经过的tick时间,当硬件定时器中断来临时,它将自动增加1。
  • 软件定时器列表rt_soft_timer_list。系统新创建并激活的定时器都会以超时时间升序的方式插入到rt_soft_timer_list列表中。系统在定时器线程中扫描rt_soft_timer_list中的第一个定时器,看是否已超时,若已经超时了则调用软件定时器超时函数。 否则出软件定时器线程,因为定时时间是升序插入软件定时器列表的,列表中第一个定时器的定时时间都还没到的话,那后面的定时器定时时间自然没到。

在这里插入图片描述
在这里插入图片描述
那么系统如何处理软件定时器列表?系统在不断运行,而rt_tick随着SysTick的触发一直在增长(每一次硬件定时器中断来临,rt_tick变量会加1),在软件定时器线程中扫描rt_soft_timer_list,比较当前系统时间rt_tick是否大于或等于timeout,若是则表示超时,定时器线程调用对应定时器的超时函数,否则退出软件定时器线程 。

使用软件定时器时候要注意以下几点:

  • 软件定时器的超时函数中应快进快出,绝对不允许使用任何可能引软件定时器起线程挂起或者阻塞的API接口,在超时函数中也绝对不允许出现死循环。
  • 软件定时器使用了系统的一个队列和一个线程资源,软件定时器线程的优先级默认为RT_TIMER_THREAD_PRIO。
  • 创建单次软件定时器,该定时器超时执行完超时函数后,系统会自动删除该软件定时器,并回收资源。
  • 定时器线程的堆栈大小默认为RT_TIMER_THREAD_STACK_SIZE,512个字节。

定时器超时函数

在RT-Thread实时操作系统中,定时器超时函数存在着两种情况:

  • 超时函数在(系统时钟)中断上下文环境中执行(硬件定时器);
  • 超时函数在线程的上下文环境中执行(软件定时器)。

如果超时函数是在中断上下文环境中执行,显然对于超时函数的要求与中断服务例程的要求相同:执行时间应该尽量短执行时不应导致当前上下文挂起、等待。例如在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等,也不允许调用rt_thread_delay()等导致上下文挂起的API接口。
在这里插入图片描述
软件定时器的超时函数在线程上下文中执行,则不会有这个限制,但是通常也要求超时函数执行时间应该足够短,不允许在超时函数中有阻塞的情况出现更不允许有死循环,也不应该影响到其他定时器执行超时函数本定时器的下一次超时回调。软件定时器的超时函数在线程中执行,下面一起来看看软件定时器超时函数是怎么样实现的。

在RT-Thread启动的时候会创建几个必要的线程:main_thread_entry线程、rt_thread_idle_entry线程、rt_thread_timer_entry线程。rt_thread_timer_entry是定时器线程,用于扫描软件定时器列表中是否有超时的定时器,然后执行其对应的超时函数
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
本节笔记参考于:野火-《RT-Thread内核实现与应用开发实战》

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值