喂狗 AUTOSAR MCAL Wdg 模块:提供安全功能,确保软件按计划执行
2024-09-19 11:07:52发布 浏览304次 信息编号:174330
友情提醒:凡是以各种理由向你收取费用,均有骗子嫌疑,请提高警惕,不要轻易支付。
喂狗 AUTOSAR MCAL Wdg 模块:提供安全功能,确保软件按计划执行
欢迎添加微信,交流学习。
模块介绍
/Wdg 模块是一个独立的定时器,可以供系统使用。它的作用是提供安全功能,确保软件按计划执行,CPU 不会陷入死循环或执行意外代码。如果 Wdg 模块在一定时间内没有被触发/刷新/馈送,它将重置 MCU。这是一个非常常用且非常重要的模块。
MCAL Wdg模块主要提供以下服务/API:
Wdg 通常有两种类型,一种是芯片内部的片上看门狗;一种是通过 SPI 等接口连接到芯片上的片外看门狗。MCAL 只负责第一个片上看门狗。片上看门狗的特点是 Wdg 模块直接访问相关硬件寄存器。片外看门狗属于板级设备抽象层,通常需要借助 MCAL 提供的其他模块(如 SPI 等)才能访问/控制外部看门狗芯片。该类型不能直接访问硬件寄存器。
由于其特殊性,该模块的代码既可以在RAM中运行,也可以在ROM中运行。例如,在刷写Flash时,Wdg模块可能作为二进制文件的一部分在RAM中运行。
本文内容基于该协议最新版本:R19-11
注意:
本模块不提供任何函数,若确实需要关闭本模块,可调用()函数,带参数OFF Mode。
不提供功能主要有两个原因:
计划在未来版本中解决由片上和片外架构之间的差异引起的问题。
现实中有些厂家可能已经扩展了Wdg模块,也就是还可以配置外部看门狗,如果已经扩展了,那么片内和片外的使用通常没什么区别,API都是一样的。
模式介绍
MCAL Wdg模块定义了三种模式,具体定义见下表:
架构定义架构描述
关闭模式
在此模式下,Wdg 硬件处于关闭状态。有时我们可能需要关闭整个 ECU,而看门狗又不提供定期复位功能。这种情况下可以使用此模式。但对于一些安全性要求较高的系统,通常不允许关闭 Wdg。这种情况下,必须配置 Wdg 模块以防止切换到此模式。
慢速模式
此模式用于监控超时较长的场景,例如系统启动/初始化阶段。
快速模式
此模式用于必须在非常短的超时时间内触发看门狗复位的场景,例如在正常的 ECU 操作期间,或者当看门狗配置为窗口模式时(因为窗口模式必须在设置的最小和最大边界内触发,通常这个窗口很窄/很短)。
实现原理
内部看门狗服务程序可以通过独立于其他外设的内部硬件定时器(Timer)中断来实现,也可以通过 GPT 驱动模块的回调函数来实现。如果不是通过 GPT 来实现,而是通过中断(class 1/class 2 中断)来实现,则需要查看厂商提供的文档。通常都会遵循 class 1/class 2 中断的使用条件/注意事项。不过无论采用哪种实现方式,标准中都没有具体的规定,完全由用户自行决定。
在之前的版本中,看门狗服务程序都是由上层软件调用的,这样就造成了难以保证窗口看门狗严格的时间约束的问题。新版本协议对这部分进行了优化。优化的基本思想是将用于维持看门狗硬件时序的服务程序与逻辑控制分离,触发看门狗的时间基准可以由硬件提供,这样保证了最小的时序抖动。控制看门狗硬件的程序可以直接在定时器中断函数中实现,保证最小的延时。这两个条件(最小时序抖动、最小延时)保证了窗口看门狗的时间窗口是可以满足的(也就是上一段提到的实现方法)。
为了保持上层模块(比如WdgM/Wdg )的基本概念不变,Wdg 模块期望看门狗的控制逻辑(是否需要触发/喂狗)由环境(WdgM)来负责。
想想当我们写代码直接操作看门狗硬件寄存器的时候,那么我们能设置的触发时间/喂狗时间就完全由硬件决定了。通常这个时间不会太长,很多芯片都是100ms级别。但是文章开头提到Wdg模块提供了3种模式,其中两种是Slow和Fast模式。如果是这样的话,这种直接操作硬件寄存器的方法是不是很难处理,因为触发/喂狗的周期是固定的,而且比较短,但是很多时候应用层可能不需要这么严格的时间监控,一个秒的周期可能就足够了(总之这个周期大于看门狗硬件寄存器的最大值)。这样的话,应用层是不是需要不停的喂狗呢?这对应用层的代码实现影响很大,需要到处穿插喂狗函数。我觉得可能还有一个很重要的原因。现在大家越来越注重功能安全,所以这种频繁修改看门狗硬件寄存器的做法并不建议(其运行性能不高,而且修改通常需要一个序列)。
为了方便大家进一步理解,我先说一下我所设想的实现方法。其实实现原理也很简单。首先说一下Slow和Fast模式对于时钟的要求。通常这两种模式Wdg使用的参考时钟是不一样的,Slow模式使用的参考时钟频率比较小/慢,而Fast模式使用的参考时钟频率比较大/快。这个应该比较容易理解。根据前面章节的介绍,因为Slow模式通常用在超时时间较长的场景。当然,你说用同一个时钟源也可以吧?当然,技术上是可以的。但是通常都是按照前面的描述来实现的。
除了上面说的 Wdg 模块的参考时钟之外,还需要一个额外的 GPT 时钟(因为这里我们用到了 GPT 回调函数)。GPT 时钟是干什么用的呢?其实真正的看门狗喂食是依赖这个 GPT(看门狗喂食时钟)的,也就是说,应用层调用看门狗喂食函数(ion)并不是直接操作看门狗硬件寄存器,而是配置 GPT,然后 GPT 中断回调操作看门狗硬件寄存器。
具体过程是这样的:调用初始化函数的时候,初始化函数会根据你配置的模式,对应模式的参考时钟源频率,喂狗时钟源频率(连续模式,不是一次性模式)自动计算出喂狗时钟的中断周期。如果是窗口看门狗,GPT的周期就是窗口的中点;如果是非窗口的,周期等于看门狗超时时间(这里细节比较多,就不一一解释了,比如计算带来的小数处理,总之要保证GPT的周期中断小于Wdg硬件超时时间,或者GPT中断优先级高于Wdg中断优先级)。然后启动GPT开始计时,Wdg也开始计时(这里注意它们各自都有自己的定时器)。 GPT中断发生后,会调用GPT对应的回调函数,GPT回调函数会调用Wdg模块相关的喂狗函数(这里才是实际操作看门狗硬件寄存器来喂狗)。
比如说假如Wdg的超时时间为100ms。这里我们讲一下普通()模式。窗口模式的处理思路是一样的,只是细节上有区别。现在用户在时刻0(其实应该初始化时刻0,为了方便理解,我们假设用户调用了喂狗函数)设置超时时间为180ms。程序会记录这个180ms的超时时间。你会发现用户设置的是大于Wdg的超时时间的。当100ms到了,产生GPT中断,发现用户记录的超时时间(180ms)还没到,于是就主动去喂狗(用户不需要调用喂狗函数)。同时之前记录的180ms超时时间会减去100ms,变成80ms。减去的100ms就是已经花费的时间,然后继续运行。
在下一个100ms到来之前,有三种情况,一是用户在80ms之前调用喂狗函数更新;二是用户也喂了狗,但是函数调用在80ms之后,100ms之前;还有一种情况是100ms中断发生,但是喂狗函数还未调用。
对于第一种情况,当再次调用喂狗函数时,程序会计算从上次中断到此刻的时间间隔(也就是花费的时间),这里这个时间小于80ms,说明程序正常运行,用户按照约定喂狗了。然后程序用新传入的超时时间重新计算一个超时时间,更新之前记录的超时时间(当然一般情况下这个新值都会大于100ms,如果小于100ms就和后面的情况一样处理,之所以提到重新计算而不是直接覆盖,是因为会有一定的时间补偿),然后继续正常运行。
第二种情况其实就是第一种情况提到的间隔,大于80ms(如果用户在90ms的时候调用该函数的话)。判断大于80ms之后,虽然用户在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复位的时间其实是有延迟的,具体延迟时间跟不同的时间组合有很大关系。
到这里,你应该已经了解了它的基本工作原理,当然这里面还涉及很多细节,比如模式切换的处理,初始化和运行时独立的超时配置等等。
为了更加直观,下图描述了上述内容:
以上内容是我的一些想法,有些部分可能不够完美,但总体来说应该还可以。
**插曲:**其实上面的内容原本是我分析NXP代码得出的结论,但后来我发现我忽略了它代码中很细节的部分,误解了NXP代码。而且经过仔细对比,我发现有些地方我的理解更有优势,就干脆改成自己的想法了。比如用户设置的超时时间可以不受Wdg最大时间限制的限制。但也有些地方实现起来可能比较麻烦,比如GPT和Wdg的Timer说要同时开启,这个同步可能比较麻烦。即便如此,可以在GPT中断处稍微处理一下,比如适当减去一点时间。当然,和NXP代码相比,它也有缺点(这里指正确理解之后,见下文),我理解的看门狗复位方法误差可能更大。欢迎讨论。看看还有没有其他问题。
现在我们来说说 NXP 的代码是如何实现的。再次强调,不同的厂家可能有不同的实现。NXP 的代码是基于 GPT 回调函数实现的,和我上面描述的区别在于:
Wdg的超时时间为用户配置的超时时间,而GPT周期中断的时间等于用户配置的超时时间的一半。两者在初始化的时候都是固定的,后续不会再改变。这个是什么意思呢?就是说用户配置的超时时间受到Wdg最大时间限制,不能配置太长。这个和我的想法不一样,我的想法是GPT中断可以在Wdg之前,用户没有限制。至于为什么GPT时间是一半,我想是因为我上面说的同步原因,再加上采样定理,所以配置一半。如果更短,理论上是可以的,但是会增加系统负担(中断比较多)。其他地方的思路都是一样的,毕竟我最初的想法来自于NXP的代码。
经过分析,如果不考虑功能安全,从功能上看,NXP 的代码其实并不比我们直接操作看门狗寄存器的方法好,反而占用了更多的 GPT 资源和更复杂的处理逻辑,而我的方法延长了应用层配置的超时时间,并且不受 Wdg 的限制。
提醒:请联系我时一定说明是从星空网上看到的!