闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析

众所周知,现行公历中,平年有365天,闰年有366天。如何用“整除法”判断闰年,这事连小学生都清楚;农历中有闰月,“十九年七闰”的传言也颇为流行。但“闰秒”,究竟又是怎么一回事?

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图1)

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图2)

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图3)1

2012年我们已经见识过一次“闰秒”了,今年它将再次到来——协调世界时(UTC)2015年6月30日23:59:59之后要加上一个“07:59:60”,它就是闰秒。对于东八区的人来说,这一秒会发生在7月1日07:59:60。

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图4)

模块简介

看门狗/Wdg模块是一个独立的定时器,可用于系统使用。它的作用是提供安全功能以确保软件按计划执行,并且CPU不会陷入无限循环或执行意外的代码。如果Wdg模块在一定时间内未被触发/刷新/喂狗,它将复位MCU。这是一个非常常用、非常重要的一个模块。

7月1日早上7点59分60秒,你打算和谁度过这“偷来的一秒”?


天文时,最自然的计时系统

要搞清楚闰秒,先得从历法的历史说起。历法是在天文观测中产生的。寒来暑往,日升日落,经过对自然节律漫长的观察,古人逐渐认识到年、月、日等时间概念。

AUTOSAR MCAL Wdg模块主要提供以下服务/API:

初始化/Wdg_Init设置模式/Wdg_SetMode设置触发条件(设置超时时间/喂狗)/Wdg_SetTriggerCondition

Wdg通常有两种,一种是芯片内部自带的片内看门狗;还有一种是在芯片外部通过SPI这种接口连接的片外看门狗。MCAL只负责第一种片内看门狗,片内看门狗的特点是Wdg模块是直接访问相关硬件寄存器。片外看门狗属于板级设备抽象层负责,通常需要使用MCAL提供的其他模块(比如SPI等)来访问/控制外扩看门狗芯片。这种不能直接访问硬件寄存器。

由于其特殊性,该模块的代码除了可以在ROM里面运行外,也可能会在RAM里面运行。比如在Bootloader刷写Flash时,Wdg模块可能作为二进制文件里面的一部分在RAM上运行。

1年,即1个寒暑周期,也就是约等于地球绕太阳一周的时间。更准确地说,真正的寒暑周期是太阳在黄道上运行1周的时间,即为1个“回归年”。月的概念则来自月亮的运行,月亮的圆缺周期就是“月”,或者叫“朔望月”。现行公历中也借用了这个概念,虽然它不再反映月相变化。“日”的概念最为自然,因为日夜的周期性最明显。我们取太阳两次到达某个点的时间差为一日,定义为“太阳日”。至于比年月日更小的时间单位,则是在“日”的基础上平分得到的。

本文内容基于目前最新版协议:R19-11

有了年、月、日的概念,就可以构建历法系统。根据细节的区别,历史上曾经有过很多种历法系统,但它们都是在天体运行基础上建立起来的,所以这样的历法系统统称为“天文历”。

注意:

该模块不提供DeInit函数。如果的确需要关闭该模块,可通过调用Wdg_SetMode()函数,参数为OFF Mode来实现。

不提供DeInit函数的原因主要有两点:

天文历的优越性不言而喻,但它所确定的天文时标有一个巨大缺陷,那就是时间长度的不均匀性。比如,如果地球自转速度发生了变化,那么由此得出的时间长度也会发生变化。

而随着科学技术的发展,对时间的精度要求越来越高,在很多精密科学中,失之“毫秒”,谬以千里。天文时的精度已经远远不能满足现代社会的需要,于是,原子时便诞生了。

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图5)

传统的沙漏计时器,以及依靠太阳位置来测定时间的日晷,都是古老的计时装置。图/Wiki commons

1、因为很多硬件不支持关闭功能。

2、一些安全性要求高的系统不允许关闭看门狗。

片内和片外这两种体系结构差异导致的问题,在未来的版本中有计划得到解决。

实际情况,可能有些厂商在Wdg模块里面已经扩展了,也就是在里面也可以配置外挂看门狗。如果已经扩展了,通常片内和片外在使用上没有区别,API这些都是一样的。

原子时,精确而刻板的时标

科学家发现,原子内部的某些运动是非常稳定的,而且不受外界条件的影响,这给时间标准的再现和统一提供了方便。20世纪60年代,国际计量大会决定用“原子秒”取代原来的“天文秒”。

2模式简介

MCAL Wdg模块定义了三种模式,具体定义见下表:

模式定义模式描述Off Mode该模式下,Wdg硬件关闭。有时候我们可能需要将整个ECU关闭,而不需要看门狗提供周期复位功能,这种情况下可使用该模式。但对于一些安全性要求很高的系统,通常关闭Wdg是不允许的,这种情况下,必须配置Wdg模块以防止切换到该模式。Slow Mode该模式用于监控那些具有较长超时时间的场景,比如系统启动阶段/初始化阶段。Fast Mode对于那些必须在很短超时时间内完成触发看门狗复位的场景则需使用此模式。比如ECU正常运行期间。又或者看门狗配置为窗口模式时(因为窗口模式必须在设置的最小和最大边界内去触发,通常这个窗口比较窄/时间短)。
3实现原理

内部看门狗服务程序可以通过独立于其他外设的内部硬件计时器(Timer)中断来实现,也可以通过GPT驱动模块的回调函数来实现。如果不通过GPT实现,而通过中断(一类/二类中断)实现,则需要查看厂商提供的文档描述,通常它遵循一类/二类中断的使用条件/注意事项。但是不管哪种实现方式,标准里面并没有具体规定,由用户自行决定。

一般情况下,制订历法时先根据自然周期确定回归年、朔望月、太阳日等计时单位的长度,然后再划分秒长。比如,先测定1日的长度,再规定1日的86400分之1为1秒。但原子时与宏观自然周期没有本质的对应关系,它们的设置带有随意性和人为性。在制订时是先定秒长,再按照“60秒1分钟,60分钟……”的原则推得年月日的长度。

如何确定“原子秒”的长度呢?大自然中的固有周期当然是最重要的参照。比如,在较长一段时间内,利用原子时所得到的1天要尽量接近用太阳时得到的1天。否则就会给生活带来很多不便。

考虑到这一点,在1967年召开的第13届国际度量大会上,人们确定了原子秒的长度:以铯-133原子基态的两个超精细能级之间跃迁所对应辐射的9192631770个周期的持续时间为1秒。这个时间单位已经成为国际单位制中的基本单位之一。

既然秒长确定下来了,1天的时间也就确定了。无论地球自转如何变化,每天都是86400秒。在这个意义上我们可以认为,原子时是以秒长为出发点的。

在之前的版本中,看门狗服务例程是由上层软件来调用的,这会有一个问题,就是很难保证针对窗口式看门狗这种严格的时间约束。新版协议对这部分做了优化。优化的基本思想是将用于维护看门狗硬件时序的服务例程与逻辑控制分开。触发看门狗的时基可以通过硬件来提供,这样可确保最小的时序抖动。而控制看门狗硬件的程序可直接在定时器中断函数里面实现以确保最小延迟。这两个条件(最小时序抖动、最小延迟)确保可以满足窗口式看门狗的时间窗口(也就是上一段提到的实现方法)。

为了保持上层模块(比如WdgM/Wdg管理器)的基本概念不变,Wdg驱动模块期望看门狗的控制逻辑(是否需要被触发/喂狗)由环境环境(WdgM)负责。

想想我们自己平时写代码直接去操作看门狗硬件寄存器,那么我们所能设置的触发时间/喂狗就完全由硬件决定了,通常这个时间不会太长,很多芯片在100ms这种级别。但是文章一开始说了Wdg模块提供3种模式,其中两种是Slow,Fast模式,如果这样的话,我们直接去操作硬件寄存器这种方法是不是就很难处理了,因为触发/喂狗周期都是固定的且比较短,但很多时候应用层可能并不需要那么严格的时间监控,可能秒级的周期即可(总之就是这个周期大于看门狗硬件寄存器的最大值了),这种情况是不是就需要应用层不断去喂狗,这对应用层的代码实现影响就很大了,他需要到处穿插喂狗函数。我想可能还有一个很重要的原因,现在大家对功能安全越来越重视,那么对这种频繁修改看门狗硬件寄存器的操作是不推荐的(本身他的操作性能就不高,通常需要一个序列才能进行修改)。

但无论如何,原子时已经失去了时间的原始意义,尽管它可以调整到比天文时更接近日月运行的真实周期,但这其实只是外在形式上的接近而已。不过,还是有很多人认为,虽然原子时不是原始意义上的时间,但既然它异常精确,在日常生活中使用又何妨呢?

“子夜太阳”奇观?

主张在生活中使用原子时的人忽略了一个重要的事实,那就是,地球的自转速度并不均匀,从长远来看,这种不均匀并非时快时慢,而是越来越慢,所以误差只会逐渐积累。

而原子时丝毫不顾及天地得变化,它精确而刻板,按照自己的固有速度一往无前。如果简单地采用原子时,就会出现这样的情况:太阳升到了上中天,时钟却敲响了子夜12点。当然,这需要很长时间的积累。科学家估计,要经过数千年,两者相差才能达到12小时,才会出现“子夜太阳”的奇观。这看起来似乎微不足道,但它对于现代社会来说,是一个无法忽略的误差。

因此,天文时形象,原子时精确;天文时分日为秒,原子时积秒成日;天文时是诗人笔下的春云秋月、北雁南飞,而原子时则是加速器中转瞬即逝的幽灵;天文时宏大,以日月为载体,统摄世间万物;原子时精深,隐身于玄奥幽邃的原子之中,使万物谐调一致;柏拉图会对天文时的误差疑惑不解,柏格森则慨叹,原子时使人类离真实的时间又远了一步!

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图6)

为了方便大家进一步理解,接下来我先说说我对实现方法的一种想法。其实实现原理也很简单。首先说一下Slow,Fast两种模式对时钟的要求,通常这两种模式Wdg所使用的参考时钟不一样,Slow模式使用的参考时钟频率比较小/慢,而Fast模式所使用的参考时钟频率比较大/快。这应该比较好理解吧。根据上一章节得知,因为通常Slow模式用于那种对超时时间比较长的场景。当然你说我就用同一个时钟源是否可以呢?技术上当然是可以的。但通常都是按照前面描述来实现。

除了上面提到的Wdg模块的参考时钟,还需要额外的GPT时钟(我们这里因为使用的GPT回调函数的实现方式),GPT这个时钟用来干嘛呢?实际上,真正喂狗就靠这个GPT了(喂狗时钟),也就是说应用层调用喂狗函数(Wdg_SetTriggerCondition)并不是直接去操作看门狗硬件寄存器的,而是去配置GPT,然后由GPT中断回调去操作看门狗硬件寄存器。

要现在人们使用的计时系统,其实就是天文时和原子时相调和的产物。图/deviantart.com

具体流程是这样的:在调用初始化函数的时候,初始化函数会自动根据你配置的模式、对应模式的参考时钟源频率以及喂狗时钟源频率来计算喂狗时钟的中断周期(为连续模式,而非一次性模式),如果为窗口式看门狗,则GPT的周期为窗口的中间点;如果为非窗口式,则周期等于看门狗超时时间(这里细节上的东西比较多,就不一一讲解了,比如由于运算导致的小数处理等。总之,GPT的周期中断需保证小于Wdg硬件超时时间,或者GPT中断优先级高于Wdg的中断优先级)。然后启动该GPT开始计时,Wdg也开始计时(注意,这里他们各自有各自的计时器)。GPT中断发生后调用GPT对应的回调函数,GPT回调函数调用Wdg模块相关的喂狗函数(这里才是真正去操作看门狗硬件寄存器进行喂狗的)。

举个例子,假如Wdg的超时时间是100ms。我们这里就讲普通(Toggle)模式哈,窗口模式处理思路一样,只是细节上有差别。现在用户在0时刻设置了超时时间是180ms(0时刻其实应该是初始化完成的,为了好理解,我们假设用户调用了喂狗函数),程序会记录这个180ms超时时间,你会发现用户设置的已经大于Wdg的超时时间了,当100ms到达时,GPT中断产生了,发现用户记录的超时时间(180ms)还没到,于是主动去喂狗了(不需要用户调用喂狗函数),同时会将之前记录的180ms超时时间减去100ms,变成80ms,减去的100ms正式已经花掉的时间,然后继续运行。

在下一次100ms到达前就有三种情况了,一种是用户在80ms之前调用了喂狗函数来更新。第二种情况是用户也喂狗了,但是调用函数的时间是在80ms之后,100ms之前。还有一种就是100ms中断发生了都还没有调用喂狗函数。

针对第一种情况,当再次调用喂狗函数时,程序会计算上一次中断发生到此刻的时间间隔(也就是花掉的时间),我们这里这个时间是小于80ms的,说明程序运行是正常的,用户按照约定来喂狗,于是程序以新传入的超时时间重新计算一个超时时间更新之前记录的超时时间(当然,正常情况下,这个新的值会大于100ms,如果小于100ms,那就和后面几种情况处理一样了,这里提重新计算而没有说直接覆盖,是由于里面会有一些时间补偿),然后继续正常运行。

第二种情况其实就是前面第一种情况里面提的那个间隔时间会大于80ms(假如用户是在90ms这个时间调用的函数),判断大于后,虽然用户在100ms中断前调用了,但是还是没有按照用户自己说的180ms来喂狗(加上第一次的的100ms中断时间,用户是在190ms才喂狗),用户还是违约了,所以程序立马停掉GPT Timer。当第二个100ms到后,这时Wdg的超时时间到了,但是由于GPT已经停掉,不会产生中断去喂狗,于是Wdg就复位ECU(严格来说,这里的行为与用户配置有关,可能是直接复位ECU,也可能是产生中断等等)。

第三种情况和第二种类似,区别在于100ms到达后,GPT的中断还是会产生,然后在中断回调里面去判断记录的超时时间80ms小于了中断的周期时间100ms,于是立马停掉GPT Timer,不喂狗。接下来Wdg也立马发现时间到了,于是复位ECU。

看出来没有,这就是为何前面说GPT的周期小于Wdg的超时时间/中断优先级高的原因。如果他大于Wdg的超时时间,那么他根本没有办法自主喂狗了,也没办法在第三种情况立即停掉Timer。同时ECU复位的时间其实也是有延时的,具体延时时间与不同时间组合有很大关系。


闰秒,协调世界!

天文时和原子时各有特色,却又都难以单独承担起为现代社会计时的重任。也许把两者的优点结合起来,会有一种更好的计时方式。我们现在采用的,正是这样一种计时系统——“协调世界时”。严格来讲,协调世界时不是一种单独的时标,而是原子时和天文时(世界时)相调和的产物。这个充当中介的“调解人”就是闰秒。

1972年,国际计量大会对世界时做了调整,方法是:当世界时与原子时之差将要超过0.9秒时,就在世界时的时序上加上1秒,这1秒称为“(正)闰秒”。因此,闰秒就是让原子停下脚步,等候太阳1秒钟。也可以说是原子向太阳“看齐”——精确的时间向不精确的时间“看齐”!

具体什么时候出现闰秒,由国际地球自转和参考座标系统决定。一般规则是,如果本年度有闰秒出现,那么它会出现于6月或12月最后一天的最后一分钟(这里说的是中时区的时刻)。正常的时序是“……23:59:59,00:00:00……”,有正闰秒时,要在两者之间加一个“23:59:60”,而有负闰秒时,只需在正常时序中去掉23:59:59即可。

讲到这里应该已经明白了它的基本工作原理了。当然里面涉及到很多细节就无法一一展开了,比如模式切换的处理,初始化和运行期间独立的超时配置等等。

协调世界时,在宏观上是天文时,在微观上是原子时。我们钟表里的秒针以原子时的频率跳动,却必须时刻不离天文时左右。这样协调的意义在于,两种时标的差距始终不会超过1秒,避免了时刻与自然节律的明显不一致。

更直观一点,下图描述了上面的内容:

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图7)

历法改进,闰秒存废?

虽然闰秒有十分重要的意义,但并非所有人都支持它的存在。

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图8)

闰秒调整:今年多出一秒钟,你想用它做什么?AUTOSAR软件架构 --- MCAL Wdg模块解析(图9)以上内容是我的一些想法,可能有些地方还不太完善,但大体上应该没问题。

**小插曲:**实际上以上的内容最开始是我分析NXP的代码得到的结论,但后面发现我忽略了其代码的一个很细节的地方,把NXP的代码理解错了,更扯的是,经过仔细对比后发现我的理解有些地方反而更有优势,索性就变成自己的想法了

标签: 时序计时器

随便看看