嵌入式状态机编程-QP状态机框架与常见状态机方法

💡 原文中文,约14900字,阅读约需36分钟。
📝

内容提要

本文介绍了状态机的关键概念,传统有限状态机的实现方法,以及QP嵌入式实时框架和QP实现有限状态机的方法。最后介绍了QP实时框架的组成和QP nano的特点。

🔎

延伸解读

从嵌套switch到状态表:封装与移植性的权衡

文章对比了嵌套switch、二维状态转换表和一维状态转换表三种传统实现。嵌套switch简单直观,但状态或事件增多时需频繁改动,且缺乏封装性。二维表通过函数指针数组将状态与事件解耦,增加状态或事件时无需修改已有处理函数,但函数粒度小、逻辑分散。一维表进一步引入进入/退出动作和转换表,更贴近状态跃迁图,但每个状态至少需要三个函数。选择时需权衡代码可读性、可维护性与资源开销。

进入/退出动作:状态机健壮性的关键

文章强调进入和退出动作在状态机中尤为重要。进入动作只在刚进入状态时触发一次,用于初始化;退出动作在状态切换时触发一次,用于清除中间参数,为下次进入提供干净环境。嵌套switch和二维表均未实现这一机制,而一维表和QP框架则明确支持。缺少进入/退出动作可能导致状态残留数据,增加隐蔽错误的风险,因此在设计较复杂状态机时应优先考虑支持该机制的实现方式。

QP框架的适用场景与设计难点

QP采用事件驱动和面向对象设计,提供良好的移植性和灵活的粒度,支持层次状态机,适合资源受限的嵌入式系统。但其缺点在于事件定义和粒度控制是设计难点,例如串口接收一帧数据时,是将每个变量更新作为独立事件,还是将整帧数据作为一个事件,需要根据实际需求权衡。此外,QP nano具有低功耗架构和高效事件派发机制,但活动对象数量、信号宽度等均有配置限制,选型时需结合具体资源约束。

❓

Q&A

状态机编程中的关键概念有哪些?

状态机的关键概念包括当前状态、触发条件(事件)、执行动作和后续状态。当前状态是系统此刻呈现的状态;触发条件是当特定条件达成时触发动作或状态转换;执行动作是在触发条件达成时执行的操作,并非强制;后续状态是触发条件满足后系统预期转换到的下一个状态。

传统有限状态机用嵌套switch实现有什么优缺点?

优点是简单、代码阅读连贯、容易理解。缺点是当状态或事件增多时,代码需要经常改动,状态事件处理函数代码量不断增加;状态机没有封装,移植性差;没有实现状态的进入和退出操作。

二维状态转换表和一维状态转换表有什么区别?

二维状态转换表用二维数组表示状态跃迁,适合状态和事件较少的情况,但函数粒度太小,状态和事件多时处理函数增加很快,且没有实现进入退出动作。一维状态转换表通过函数指针和转换表实现,增加了进入和退出动作,容易根据状态跃迁图设计,灵活可实现复杂逻辑,但每个状态至少需要3个函数,仍需列出所有转换关系。

QP框架实现有限状态机有什么优点?

QP框架采用面向对象设计,移植性好;实现了进入退出动作;粒度合适且事件粒度可控;状态切换时通过改变指针效率高;可扩展成为层次状态机。

QP nano有哪些特点?

QP nano完全支持层次式状态嵌套,最多4层状态嵌套下保证进入/退出动作;支持高达8个并发执行的活动对象;支持一个字节宽(255个信号)的信号和可伸缩参数;使用FIFO直接事件派发;每个活动对象有一个一次性时间事件;内建合作式vanilla内核和可抢占型QK-nano内核;带有空闲回调函数的低功耗架构;基于断言的错误处理策略。

QP实时框架由哪些部分组成?

QP实时框架包括内存管理(使用内存池为不同事件分配内存)、事件队列(每个活动对象维护一个事件队列)、事件派发(直接事件发送和发行订阅事件发送)、定时事件(非有序链表管理)以及合作式调度器QV。

🏷️

标签

➡️

继续阅读