RTT时钟管理篇——软硬定时器理解(二)

野火RTT第22章软件定时器
2018年12月29日
10:48

打开软件定时器的宏才能用软件定时器线程、才能使用软件定时器。否则还是硬件定时器(在systic中断中管理超时函数)。
有两个定时器列表:一个硬件定时器链表、一个是软件定时器链表。

问题1:软件定时器的上下文是线程——啥意思?硬件定时器的上下文是中断。为何称为软件定时器?

问题1解答:明白了,软件定时器原来是另外开辟了个线程来专门管理软件定时器的,优先级默认4,所以说软件定时器的上下文是线程——可不么?它就在线程里面的,它就是个线程。在这个线程里各查询软件定时器是否到期,和那个系统定时器(线程的阻塞延时就是挂在系统定时器的链表下,升序排列)一样的方法,升序排列。软件定时器是挂在软件定时器的链表上的,在软件定时器线程中进行查询。

问题2:为啥有软件定时器?

问题2解答:因为硬件定时器资源限制,数量不满足客户需求。

问题3:32位的无符号变量作为系统节拍计数器,有没有考虑翻转?

问题3解答:这个没问题的,到最后了FFFF FFFF再+1就变成0了,不耽误的,比如当前tick值为FFFF FFF0 有个软件定时器要延迟20个tick,20的十六进制是14,那么值就变成,FFFF FFF0+14=4,不耽误呀,不影响呀,当前计数值tick会继续加加加,直到翻0继续加达到4,就能达到20的延时值了呀,所以不用担心!至于为何要用32为变量,是因为可以扩大一次性输入的延时值。假如是8位的,你最大255,你说我要延时300怎么办?直接超了,如果此时tick值为0,你延时300,一加等于45,那tick值到45时就达到延时的执行延时了,这就不对了嘛!而32位的一次性延时尺度可以达到49天的时间,已经很长了。

问题4:软件定时器没有硬件定时器准,怎么理解?

问题4解答:因为软件定时器是个线程,所有软件定时器超时管理在这个线程中实现,而所有线程是有优先级,如果有更高优先级占用CPU使用权,那么就会影响软件定时器的精度。换句话说,当软件定时器管理这个线程唤醒了,但是不一定立马运行,所以这个不精准。而硬件定时器是在中断里实现管理的,那肯定比软件定时器在线程里管理更准确。

问题5:我在想不能用systick的中断或其他中断来执行硬定时器么?

问题5解答:定时器分为软件定时器和硬件定时器,可以选择在systick中断中实现定时器超时函数的管理(也是回调函数),这就是硬件定时器超时函数管理。也可以选择线程中实现软件定时器超时函数管理。

问题6:定时为何要限制到32位变量的一半呢?另外用当前值-超时时间<32位无符号变量值的一半来判断是否超值,什么意思?

问题6解答:这个需要自己大脑动态想一下,或者自己计算下就出来了。大脑动态想一下,比如当当前tick值为0时,延时值设置要小于最大值的一半(此时这就是超时值),那么当tick值减去这个超时值时,其值大于最大值的一半。因为是无符号值,0-1变成最大值了呀0xFFFF FFFF,那么因为延时值不能<最大值一半,所以没有超时时其值是大于最大值一半的。当超时了,tick值减去超时值肯定小于最大值一半。而且基本上很快执行超时函数把这个值更新掉了。由下图可知,就算当前32位tick变量值要溢出了,加上延时值后的超时值已经溢出了,但是因为是无符号的32位变量,溢出就是翻0向上计数呀,这样的话依然不影响超时判断,超时判断公式依然成立,每次systick定时器中断判断:当前值-超时值<32位值的一半,若满足,则说明超时了,否则没超时。所以在systick中断中无符号计数变量不需要对它溢出处理,溢出也是对的,丝毫不影响定时器超时判断。

问题7:硬件定时器不是管理线程的么?还能管理超时函数?

问题7解答:你搞胡涂了,所有线程都内置它自己的定时器,所有线程创建的时把它们内置的定时器的超时函数都指向了同一个超时函数:恢复线程、执行调度。而你另外创建的创建的定时器不是线程内置的定时器,两码事用户创建的定时器的超时函数是指向用户自己定义的超时函数,所以这是两码事:一个是线程的内置定时器的超时函数,一个是用户开辟的新的定时器的超时函数。当用硬件定时器(systick)就是和线程用的是同一个定时器列表时,用户开的定时器和线程的定时器花在同一个定时器链表上——系统定时器链表(硬件定时器链表)。当开启软件定时器时,用户自己定义的定时器是挂在软件定时器链表上的,而线程内置的定时器链表挂在硬件定时器上的。

软件定时器资源占用:1,一条队列资源2,一个线程资源

硬件定时器因为是在中断中执行,所以对超时函数有很强的限制:1.时间不能太久2,不能有挂起、等待操作3.不能申请动态内存、释放动态内存

软件定时器因为是在线程中执行,所以要求就比较宽泛一点:1.时间也要短2,不允许有阻塞挂起、死循环3,不能影响其他超时函数的下一次回调。也就是时间短的标准。其他的定时器的定时到了你这还没运行完,那别的超时函数就没用了完蛋了!

使用硬件定时器,在时基更新的时候,查询的定时器包含线程的内置定时器和用户定义的定时器,它们都挂在硬件定时器列表上(系统定时器列表),而且特点是:所有线程的内置定时器的回调函数都是一个函数,而用户自定义的定时器的回调函数由用户自定义。

在每次系统滴答中断进行线程恢复和调度是通过调用线程内置的定时器的超时函数实现的。抛开一切不说,滴答中断里是查询定时器,有超时的定时器就调用其超时函数,当这个定时器是线程内置的定时器,它这个超时函数就是恢复线程和执行调度。如果这个定时器是用户自己开的硬件定时器时,其调用的超时函数就是用户自己写的。

这就是定时器的巨大作用了,这是定时器和线程、用户自定义相结合的结果。

你可能感兴趣的:(rt-thread)