T3高精度时钟出现负数问题解决方案

1 问题描述

      问题现象主要表现为连续获取两次高精度时钟,时间差为负数。即后一次获取的时间小于前一次。现象出现随机性较高,属于偶发事件。连续多次获取可复现此问题。后一次出现时间约比前一次少1ms左右,即一个tick值。

2 原因分析

      高精度时钟的基本原理是在tick中断基础上使用定时器当前值校正时间。定时器使用T3的timer0,timer0从一个默认值递减到0表示1ms。并在递减到0时产生中断,定时器恢复到默认值。中断处理中主要执行更新tick值操作。获取高精度时钟分为如下两种情况:

1)获取时刻发生在两个tick中断之间

      获取时刻发生在两个tick中断之间,这时需要通过读取定时器计数值计算从上一次中断发生到当前经过的时间△t,再在当前 tick值的基础上加上△t得出高精度时钟值。如图 2.1所示。

                                               图2.1获取时刻发生在两个tick中断之间

2)获取时刻发生在某个tick中断处理时

      当获取时刻发生在tick中断处理时情况就比较复杂,主要是硬件定时器会复位,△t的值是当前中断发生到现在时间差,即少了一个tick值。这里做了特殊处理,在获取高精度时间时判断中断状态寄存器中的值,若此时发生中断则将最终的结果加上一个tick,如图 2.2所示。

                                    图2.2获取时刻发生在某个tick中断处理时

扫描二维码关注公众号,回复: 4545379 查看本文章

      从上述第二种情况可以看出实际的结果会被清中断的时刻所影响。若清中断操作在更新tick操作之前,且获取时刻在两者之间,则会缺少1个tick,如图 2.3所示。

                                                            图2.3清中断在前

      若清中断操作在更新tick操作之后,且获取时间在两者之间,则会多计算1个tick,如图 2.4所示。

                                                 图2.4清中断在后

3 解决方案

      基本解决思路就是使用锁使得获取时刻无法出现在更新tick操作和清中断操作中间。但由于更新tick操作和获取操作都在base中施加内核锁。因此不可以再重复加锁否则会造成死锁。目前的解决方案是将清中断操作添加在内核回调函数bspTickHook()中,因为bspTickHook()会和更新tick操作一同施加内核锁,这样可以保证获取操作无法插入清中断和更新tick操作之间,即可以解决问题。经多次实验,此方案实测有效。


猜你喜欢

转载自blog.51cto.com/7199226/2331658
今日推荐