事件驱动架构把中断、定时器和输入转换为事件,再由状态机根据当前状态执行短小动作。它解决的不是“如何写一个循环”,而是如何把隐藏在大量 if、延时和标志位里的状态关系显式写出来。这样超时、取消和异常输入才有清楚的去处。
中断里只投递事件
中断处理程序应该尽快读取必要状态、清除硬件标志并投递事件。它不应等待通信、调用复杂回调或执行状态转换,因为这些操作会放大中断延迟,也容易与主循环并发修改同一份状态。事件队列的生产者、消费者和满队列策略要明确:关键故障事件不能被普通日志挤掉。
让所有退出路径都可见
好的状态机不仅有“成功下一步”,还要有超时、取消、资源缺失和恢复路径。给每个等待状态配置一个超时事件,给每个外部输入定义可接受状态,避免收到旧事件后误触发新的任务。状态转换表比层层嵌套的 switch 更容易审查,尤其适合通信协议、升级流程和设备初始化。
用转换函数守住状态边界
事件结构应包含类型和必要快照,不能只放一个全局标志。状态机消费事件时先判断当前状态,再执行动作并更新状态。无法处理的事件要有统一策略:忽略、记录,或转入 fault,而不是落入未定义路径。
1 | typedef enum { ST_IDLE, ST_WAIT_ACK, ST_RUNNING, ST_FAULT } state_t; |
当一次操作可以被取消并重新开始时,事件最好携带 generation 或 request ID。状态机只接受与当前操作一致的 ACK 和超时,避免上一轮迟到事件破坏新状态。
证据边界
这种结构不能自动保证实时性。最坏响应时间还取决于队列深度、事件生产速率、单次转换耗时和中断屏蔽时间。EFSM 链接用于观察一种实现方式,具体队列并发、内存占用和许可证仍需按目标项目核对。
参考:EFSM