深入理解嵌入式系统编程中的层次化状态机语义

1. 引言

在Miro Samek的第42集视频中,介绍了现代层次化状态机(HSMs)的丰富语义,展示了通过层次化状态嵌套来捕捉行为细微差别的能力。本文将深入讨论这些语义,以及在实际嵌入式系统编程中应用层次化状态机的可行性。

现代层次化状态机(HSMs)

2. 可执行示例

通常,HSMs被视为理论性的练习,用于以图形方式捕捉思想,但不被认为适合实际实现。为了打破这一先入之见,视频中展示了一个可在计算机上作为控制台应用程序运行的可执行示例。该示例被精心设计,包含了高达四级状态嵌套的所有可能的转换配置,包括各种级别状态之间的常规转换、内部转换和守卫条件。该状态机通过软件追踪生成详细的输出,展示了通过键盘注入的事件是如何处理的。

2.1 初始转换

在状态机处理任何事件之前,必须执行最顶层的初始转换。这个转换可以穿越多层状态嵌套,但沿途的每个状态都必须正确进入,因此你的追踪会显示进入状态“s”后紧跟着进入状态“s2”。初始转换结束于状态“s2”,但追踪并不停在那里。这是因为HSM语义规定,任何转换(包括初始转换)都必须“深入”子状态,只要初始转换直接嵌套在主目标状态中。状态“s2”有一个初始转换,因此被执行。接下来,进入“s21”,再进入“s211”。由于“s211”没有更深的子状态,所以运行到完成(RTC)步骤结束于“s211”,状态机达到稳定状态配置,最后进入的状态成为当前状态。

2.2 状态转换

上述描述应该让你了解为什么在HSMs中必须区分转换的主源和源状态配置。例如,在状态“s21”中,转换G首先需要退出当前状态“s211”,然后再退出主源“s21”。

同样,必须区分转换的主目标和目标状态配置。例如,从“s21”到“s1”的转换G的主目标是“s1”,但“s1”有一个初始转换,所以转换继续到“s11”。

2.3 最小公共祖先(LCA)

通常,每个转换都必须退出源配置中的所有状态(从最内层状态开始),并进入目标配置中的所有状态(从最外层状态开始)。关键问题是,如何确定这些配置?

为此,HSM语义应用最小公共祖先(LCA)的概念,它是源状态和目标状态的函数。例如,LCA(s21, s1)是共同的超级状态“s”。然后,HSM语义规定必须在目标配置可以进入之前退出所有状态直到LCA,但不包括LCA本身。

3. 内部转换与自转换

在HSMs中,内部转换和自转换之间有所不同。视频演示了自转换(导致退出当前状态然后干净地重新进入)和内部转换(从不执行退出或进入动作)的区别。

4. 守卫条件与状态层次结构

状态层次结构在处理守卫条件时引入了一些复杂性。根据UML语义,当转换的守卫评估为false时,该转换被视为不存在。因此,事件不被丢弃,而是传递到下一个更高级别的状态。视频演示了在各个状态嵌套级别上的常规或内部转换上的守卫条件。

5. 结语

HSM语义的技术性可能令人生畏,但幸运的是,由此产生的转换行为是直观的。这些规则旨在保证每个状态转换始终执行源状态配置的清理(通过状态退出动作)和目标状态配置的初始化(通过状态进入动作),无论退出或进入路径的复杂性如何。这种保证在安全相关应用中非常有价值,因此功能安全标准(例如IEC 61508)建议使用半正式方法,如层次化状态机。