层次状态机-HSM代码解析

article/2025/9/23 5:22:59

有限状态机在学习和工作中经常能够遇到,前面的文章也有使用到。但是对于层次状态机网上的学习资源却很少,导致一直不理解这个工作机制,后面偶然在GitHub看到一篇文章,深入学习后发现层次状态机太实用了,如果将其在项目上结合,肯定能够创造出一个比较好的代码框架。

一、HSM状态调度机制

HSM状态间是存在等级关系,状态间至少存在2个等级,并且除根状态外至少存在ENTER和EXTI事件,我认为HSM的状态机结构类似树状结构,HSM状态如图所示:

很明显这里存在四个等级,CAMERA为d0,其余为d1,d2,d3。 CAMERA为根状态(根状态不做任何处理),其余的六种状态,有些的父状态为根状态,有些则作为其他的父状;

1.切换状态-等级不同

例如从CAMERA_StateOnDispPlay状态(d3)切换到CAMERA_StateOnShoot(d2)状态;

首先函数调度会先找到他们共同的父状态,这里即为CAMERA_StateOn,然后依次调用CAMERA_StateOnDispPlay和CAMERA_StateOnDisp状态的EXTI事件,再调用CAMERA_StateOnShoot的ENTER事件,即可切换到目标状态,方向如图:

 2.切换状态-等级相同

例如从CAMERA_StateOnDisp状态(d2)切换到CAMERA_StateOnShoot(d2)状态;

 他们父状态是相同的,所以只需要调用当前状态的EXTI事件后,再进入目标状态的ENTER事件即可。

状态调度函数源码如下

// Func: void HSM_Tran(HSM *This, HSM_STATE *nextState, void *param, void (*method)(HSM *This, void *param))
// Desc: Transition to another HSM STATE
// This: Pointer to HSM instance
// nextState: Pointer to next HSM STATE
// param: Optional Parameter associated with HSME_ENTRY and HSME_EXIT event
// method: Optional function hook between the HSME_ENTRY and HSME_EXIT event handling
void HSM_Tran(HSM *This, HSM_STATE *nextState, void *param, void (*method)(HSM *This, void *param))
{
#if HSM_FEATURE_SAFETY_CHECK// [optional] Check for illegal call to HSM_Tran in HSME_ENTRY or HSME_EXITif (This->hsmTran){HSM_DEBUG("!!!!Illegal call of HSM_Tran[%s -> %s] in HSME_ENTRY or HSME_EXIT Handler!!!!",This->curState->name, nextState->name);return;}// Guard HSM_Tran() from certain recursive callsThis->hsmTran = 1;
#endif // HSM_FEATURE_SAFETY_CHECKHSM_STATE *list_exit[HSM_MAX_DEPTH];HSM_STATE *list_entry[HSM_MAX_DEPTH];uint8_t cnt_exit = 0;uint8_t cnt_entry = 0;uint8_t idx;// This performs the state transition with calls of exit, entry and init// Bulk of the work handles the exit and entry event during transitionsHSM_DEBUGC2("Tran %s[%s -> %s]", This->name, This->curState->name, nextState->name);// 1) Find the lowest common parent stateHSM_STATE *src = This->curState;HSM_STATE *dst = nextState;// 1a) Equalize the levelswhile (src->level != dst->level){if (src->level > dst->level){// source is deeperlist_exit[cnt_exit++] = src;src = src->parent;}else{// destination is deeperlist_entry[cnt_entry++] = dst;dst = dst->parent;}}// 1b) find the common parentwhile (src != dst){list_exit[cnt_exit++] = src;src = src->parent;list_entry[cnt_entry++] = dst;dst = dst->parent;}// 2) Process all the exit eventsfor (idx = 0; idx < cnt_exit; idx++){src = list_exit[idx];HSM_DEBUGC3("  %s[%s](EXIT)", This->name, src->name);src->handler(This, HSME_EXIT, param);}// 3) Call the transitional method hookif (method){method(This, param);}// 4) Process all the entry eventsfor (idx = 0; idx < cnt_entry; idx++){dst = list_entry[cnt_entry - idx - 1];HSM_DEBUGC3("  %s[%s](ENTRY)", This->name, dst->name);dst->handler(This, HSME_ENTRY, param);}// 5) Now we can set the destination stateThis->curState = nextState;
#if HSM_FEATURE_SAFETY_CHECKThis->hsmTran = 0;
#endif // HSM_FEATURE_SAFETY_CHECK
#if HSM_FEATURE_INIT// 6) Invoke INIT signal, NOTE: Only HSME_INIT can recursively call HSM_Tran()HSM_DEBUGC3("  %s[%s](INIT)", This->name, nextState->name);This->curState->handler(This, HSME_INIT, param);
#endif // HSM_FEATURE_INIT
}

二、HSM事件调度机制

HSM事件的调度比较简单,HSM状态事件如图所示:

 这里的状态关系和上述的一致,可以看到不同状态均会存在ENTER和EXTI事件,并且每个状态也有自己可能触发的事件类型;

1.切换事件-目标状态不存在事件

例如在CAMERA_StateOnDispPlay状态中触发LOWBATT事件;

调度函数HSM_Run首先会进入回调函数,如果没有该事件则会返回LOWBATT事件类型,HSM_Run接着进入父状态CAMERA_StateOnDisp回调函数查看是否存在LOWBATT事件,很明显没有,最后回到CAMERA_StateOn状态回调函数,触发LOWBATT事件进行关机处理。

2.切换事件-目标状态存在事件

例如在CAMERA_StateOn状态中触发LOWBATT事件,立即执行关机处理后退出HSM_Run函数

事件调度函数源码如下

void HSM_Run(HSM *This, HSM_EVENT event, void *param)
{
#if HSM_FEATURE_DEBUG_ENABLE && HSM_FEATURE_DEBUG_NESTED_CALL// Increment the nesting countgucHsmNestLevel++;
#endif // HSM_FEATURE_DEBUG_ENABLE && HSM_FEATURE_DEBUG_NESTED_CALL// This runs the state's event handler and forwards unhandled events to// the parent stateHSM_STATE *state = This->curState;
#ifdef HSM_DEBUG_EVT2STRHSM_DEBUGC1("Run %s[%s](evt:%s, param:%08lx)", This->name, state->name, HSM_DEBUG_EVT2STR(event), (unsigned long)param);
#elseHSM_DEBUGC1("Run %s[%s](evt:%lx, param:%08lx)", This->name, state->name, (unsigned long)event, (unsigned long)param);
#endif // HSM_DEBUG_EVT2STRwhile (event){event = state->handler(This, event, param);state = state->parent;if (event){
#ifdef HSM_DEBUG_EVT2STRHSM_DEBUGC1("  evt:%s unhandled, passing to %s[%s]", HSM_DEBUG_EVT2STR(event), This->name, state->name);
#elseHSM_DEBUGC1("  evt:%lx unhandled, passing to %s[%s]", (unsigned long)event, This->name, state->name);
#endif // HSM_DEBUG_EVT2STR}}
#if HSM_FEATURE_DEBUG_ENABLE// Restore debug back to the configured debugThis->hsmDebug = This->hsmDebugCfg;
#if HSM_FEATURE_DEBUG_NESTED_CALLif (gucHsmNestLevel){// Decrement the nesting countgucHsmNestLevel--;}
#endif // HSM_FEATURE_DEBUG_NESTED_CALL
#endif // HSM_FEATURE_DEBUG_ENABLE
}

三、HSM实例和状态创建

1.HSM状态结构体

在创建HSM状态函数前,需要了解状态结构体里面的成员;

struct  HSM_STATE_T为HSM状态结构体,包含指向父状态的指针,状态的回调函数,状态的字符串名称,状态的等级;

结构体源码如下:

//----Structure declaration----
typedef uint32_t HSM_EVENT;
typedef struct HSM_STATE_T HSM_STATE;
typedef struct HSM_T HSM;
typedef HSM_EVENT (* HSM_FN)(HSM *This, HSM_EVENT event, void *param);struct HSM_STATE_T
{HSM_STATE *parent;          // parent stateHSM_FN handler;             // associated event handler for stateconst char *name;           // name of stateuint8_t level;              // depth level of the state
};

2.HSM状态创建

使用HSM_STATE_Create函数创建HSM状态,首先会判断该结构体是否添加父状态,如果没有默认会将根状态作为该结构体节点的父状态,依次将字符串名称、回调函数、状态等级、父状态等注册到输入的结构体内;

HSM_EVENT HSM_RootHandler(HSM *This, HSM_EVENT event, void *param)
{
#ifdef HSM_DEBUG_EVT2STRHSM_DEBUG("\tEvent:%s dropped, No Parent handling of %s[%s] param %lx",HSM_DEBUG_EVT2STR(event), This->name, This->curState->name, (unsigned long)param);
#elseHSM_DEBUG("\tEvent:%lx dropped, No Parent handling of %s[%s] param %lx",(unsigned long)event, This->name, This->curState->name, (unsigned long)param);
#endif // HSM_DEBUG_EVT2STRreturn HSME_NULL;
}HSM_STATE const HSM_ROOT =
{.parent = ((void *)0),.handler = HSM_RootHandler,.name = ":ROOT:",.level = 0
};void HSM_STATE_Create(HSM_STATE *This, const char *name, HSM_FN handler, HSM_STATE *parent)
{if (((void *)0) == parent){parent = (HSM_STATE *)&HSM_ROOT;}This->name = name;This->handler = handler;This->parent = parent;This->level = parent->level + 1;if (This->level >= HSM_MAX_DEPTH){HSM_DEBUG("Please increase HSM_MAX_DEPTH > %d", This->level);// assert(0, "Please increase HSM_MAX_DEPTH");while(1);}
}

 3.HSM状态获取

通过HSM_GetState函数可以获取到当前最新的状态

HSM_STATE *HSM_GetState(HSM *This)
{// This returns the current HSM statereturn This->curState;
}uint8_t HSM_IsInState(HSM *This, HSM_STATE *state)
{HSM_STATE *curState;// Traverse the parents to find the matching state.for (curState = This->curState; curState; curState = curState->parent){if (state == curState){// Match found, HSM is in state or parent statereturn 1;}}// This HSM is not in state or parent statereturn 0;
}

4.HSM实例结构体

struct HSM_T为HSM实例结构体,该类型里面包含一个struct  HSM_STATE_T状态结构体成员指针,相当于在HSM状态结构体的基础上进行封装,在创建HSM实例后,该指针会一直记录当前的最新的HSM状态。

结构体源码如下:

struct HSM_T
{HSM_STATE *curState;        // Current HSM State
#if HSM_FEATURE_DEBUG_ENABLEconst char *name;           // Name of HSM Machineconst char *prefix;         // Prefix for debugging (e.g. grep)uint8_t hsmDebugCfg;        // HSM debug configuration flaguint8_t hsmDebug;           // HSM run-time debug flag
#endif // HSM_FEATURE_DEBUG_ENABLE
#if HSM_FEATURE_SAFETY_CHECKuint8_t hsmTran;            // HSM Transition Flag
#endif // HSM_FEATURE_SAFETY_CHECK
};

5.HSM实例创建

通过HSM_Create函数可以创建一个HSM实例,并且初始化当前的状态

void HSM_Create(HSM *This, const char *name, HSM_STATE *initState)
{// Setup debug
#if HSM_FEATURE_DEBUG_ENABLEThis->name = name;This->prefix = "";This->hsmDebugCfg = 0;This->hsmDebug = 0;
#endif // HSM_FEATURE_DEBUG_ENABLE// Supress warning for unused variable if HSM_FEATURE_DEBUG_ENABLE is not defined(void)name;// Initialize stateThis->curState = initState;// Invoke ENTRY and INIT eventHSM_DEBUGC1("  %s[%s](ENTRY)", This->name, initState->name);This->curState->handler(This, HSME_ENTRY, 0);HSM_DEBUGC1("  %s[%s](INIT)", This->name, initState->name);This->curState->handler(This, HSME_INIT, 0);
}

四、总结

HSM层次状态两个关键因素为状态的切换和事件的切换,前面状态和事件的调度是重中之重,必须得理解HSM类似树结构的运行方式。至此HSM层次状态机的核心代码解析完成;

早在2022年12月就应该写这篇文章,因为工作刚好上了项目比较紧急一直没有时间,也是当时没有完全理解调度机制,导致这个文章在四个月后在编写完成。本文章只是介绍HSM层次状态机的核心代码,下一篇文章会继续把GitHub文章HSM应用例子写完。


http://chatgpt.dhexx.cn/article/T5jkqEO2.shtml

相关文章

车规级安全芯片HSM、SE等:

目录 1、相关标准 2、汽车安全芯片应用 3、安全芯片供应商 4、安全芯片测试 5、针对控制器的安全测试 给学习做个总结&#xff0c;写的不对处希望大家指出。 说明&#xff1a;关于汽车安全中可以使用SE安全单元针对外部通信的安全形式&#xff0c;可以是内嵌HSM硬件安全模…

Infineon TC3XX的 通过HSM 实现Secure Debug

AURIX™ 调试接口保护- 内部开关概览 Gate1: 通过OCDS模块控制TriCoreTM 调试访问接口&#xff1b; Gate2: 通过DMU模块控制TriCoreTM 调试访问接口&#xff1b; Gate3和Gate4: HSM直接控制。控制Host CPU的访问并且也可以支持禁用HSM自身的调试功能。 AURIX™ 挑战应答机制-…

汽车信息安全系列-3.TI HSM笔记(更新中)

HSE 相对于 SHE 主要多了独立的CPU 并且支持非对称算法 HSM 架构的安全目标: 安全启动,安全运行,安全debug,算法加速 HSM 架构有以下feature: 防火墙保护 独立CPU,保护efuse和密匙并且给其他内核提供认证和解密服务 安全Boot ROM 建立可信任硬件和外部软件镜像加解密…

hsm加密机

1.三级密钥体制示意图&#xff1a; 1. 主密钥用于加密密钥交换密钥和数据密钥作本地存储&#xff1b; 2. 密钥交换密钥用于加密数据密钥作网络传输&#xff1b; 3. 数据密钥用于对数据进行加解密。 2.三级密钥体制 3.三级密钥体制说明 第一层&#xff0c;LMK为本地主密钥,&…

HSM和AsyncChannel介绍

HSM(hierarchical state machine, 层次状态机)和AsyncChannel是Android Java Framework中两个重要的类。 这两个类的作用如下。 HSM在传统状态机对所有状态都一视同仁的基础上做了一些改变,使得状态和状态之间有了层级关系。HSM中的状态层级关系与Java中父子类的派生和继承关…

英飞凌 AURIX 系列单片机的HSM详解(2)——与HSM相关的UCB和寄存器

本系列的其它几篇文章&#xff1a; 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;1&#xff09;——何为HSM》 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;3&#xff09;——开发方法》 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;4&#xff09;——Tricore核与H…

英飞凌 AURIX 系列单片机的HSM详解(3)——开发方法

本系列的其它几篇文章&#xff1a; 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;1&#xff09;——何为HSM》 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;2&#xff09;——与HSM相关的UCB和寄存器》 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;4&#xff09;—…

HSM硬件加密机国密标准解读

HSM全称硬件安全模块&#xff0c;是数据安全领域的关键硬件设备&#xff0c;是公钥基础设施的一部分。本文从国密0054出发&#xff0c;概要分析了HSM也就是通常说的服务器密码机需要遵循的国密相关标准&#xff0c;以及与等保的关系。 一、信息系统密钥应用的基本要求 1、总体…

HSM和TEE

本文摘自牛咖网文章 HSM和TEE HSM为其他应用程序提供密钥管理和加密功能。 TEE还提供让应用程序&#xff08;或应用程序的安全相关部分&#xff09;在其隔离环境中执行的功能。 常规执行环境 (REE)是TEE社区中的术语&#xff0c;用于表示设备中特定TEE之外的所有内容。 HSM如何…

满足AUTOSAR基础软件要求的硬件安全模块(HSM)加密运算

随着软件日益复杂&#xff0c;并且车载系统和传感器数量稳步增加&#xff0c;车内系统的通讯成几何增长&#xff0c;必须加强密码保护。这种保护可以通过经典的实时汽车开放系统架构&#xff08;AUTOSAR&#xff09;来实现。即便在资源稀缺的情况下&#xff0c;安装合适固件的硬…

硬件安全模块- HSM

目录 一、什么是硬件安全模块 二、HSM是如何工作的 三、HSM的应用 公钥基础设施&#xff08;Public Key Infrastructure - PKI&#xff09; 卡支付系统&#xff08;Card Payment HSM&#xff09; 安全套接字协议&#xff08;Secure Sockets Layer - SSL&#xff09; 车载…

鉴源实验室丨HSM技术浅述

作者 | 徐奕华 上海控安可信软件创新研究院汽车网络安全组 来源 | 鉴源实验室 引言&#xff1a;2023年5月初&#xff0c;工业和信息化部装备工业一司组织全国汽车标准化技术委员会开展《汽车整车信息安全技术要求》等四项强制性国家标准的制修订[1]。这意味着车辆信息安全管理…

英飞凌 AURIX 系列单片机的HSM详解(1)——何为HSM

本系列的其它几篇文章&#xff1a; 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;2&#xff09;——与HSM相关的UCB和寄存器》 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;3&#xff09;——开发方法》 《英飞凌 AURIX 系列单片机的HSM详解&#xff08;4&#xff09;—…

硬件安全模块(HSM)

一、什么是HSM 说起信息安全和加解密&#xff0c;我们很容易会在脑海中浮现出锁和钥匙。那我们来想象一个场景&#xff1a; 假设一位父亲有三个儿子&#xff0c;他给每个儿子各买了一台掌上游戏机。为避免他们沉迷游戏&#xff0c;父亲把每台游戏机都锁到一个小盒子里。盒子归…

什么是WSDL?

WSDL&#xff08;Web Service Description Language&#xff09;Web服务器描述语言是用XML文档来描述Web服务的标准&#xff0c;是Web服务的接口定义语言&#xff0c;由Ariba、Intel、IBM、MS等共同提出&#xff0c;通过WSDL&#xff0c;可描述Web服务的三个基本属性&#xff1…

已有wsdl,怎么去调用他的方法

1&#xff0c;在浏览器验证该wsdl地址是否可以打开&#xff0c;显示为该模式 2&#xff0c;新建一个项目&#xff0c;右击该项目&#xff0c;other&#xff0c;webservice,webservice clent , 讲该wsdl地址输入&#xff0c;finish 3,新建一个类&#xff0c;实例化impl,调用一个…

WSDL的文件结构(WSDL 1.1规范

为能将一个WebService描述清楚&#xff0c;WSDL从三个层面对一个服务进行了描述&#xff1a; 一&#xff1a;描述服务的接口(<wsdl:portType/>部分)&#xff0c;也就是服务有哪些操作(<wsdl:operation/>部分)以及每个操作的输入输出参数(<wsdl:message/>部分…

WSDL阅读方法

我们以天气预报WebService服务为例&#xff0c;来看看怎么阅读一个wsdl文档。 打开一个wsdl文档后&#xff0c;先看底部。 binding在这里&#xff1a; portType在这里&#xff1a; 好了&#xff0c;看了上面的&#xff0c;我们来说说wsdl说明书的整体结构吧&#xff1a; 1.&l…

IDEA wsdl教程

这篇文章教你如何利用IDEA发布WSDL 博主大学复习周精心制作,共推出几个模块供大家利用, ####今天我们先来学习一下如何利用IDEA发布WSDL 首先打开IDEA 新建一个Java项目 OK了基本的项目已经创建完成! 创建一个新的类命名为Java6WB代码如下所示: package com.company; im…

【WebService】wsdl配置详解以及使用注解修改wsdl配置

欢迎关注我新搭建的博客&#xff1a;http://www.itcodai.com/ WebService系列文章&#xff1a; 【WebService】带你走进webservice的世界 【WebService】自定义WebService服务及其调用 【WebService】CXF处理javaBean等复合类型以及Map等复杂类型的数据 【WebService】CXF拦…