状态机进阶(smp 状态机介绍)

状态机进阶(smp 状态机介绍)

Bluedroid中的线程介绍 那篇文章中,我们介绍了最简单的一种状态机实现方式。这个状态机的缺点也很明显,如果事件和状态都很多的话,那么状态转换表会很大(事件个数),状态转换表也要很多个(状态个数)。
在smp模块中,我们可以看到如何设计实现状态和事件都比较多的状态机。

smp状态机需求分析

  • smp状态机的状态很多(17个状态)
  • smp状态机的事件很多(41个事件)
  • BLE分为master和slave role,smp状态机需要同时支持这两个role的功能。
  • smp的每个状态处理的事件很少,状态之间跳转简单(流程简单一步一步往下走,但是步骤很多)

smp状态机设计思路

状态很多,每个状态处理的事件很少。可以把每个状态拆分成小的状态转换表,只需要当前状态要处理的事件的项。不需要每个状态实现一个大表(包含所有的事件的状态转换表),因为大表的话,很多项都是无用的项,还占内存。
状态机的三要素就是:状态,事件,处理函数。
原先大表的话,事件这一列可以省略只有action和next state两列。拆成小表后就需要事件这一列了。
处理函数还是跟前面一样,通过枚举值查对应的函数;
拆分后的状态表的查询比较简单,通过当前状态和role(区分master和slave),就可以获取状态转换表;
最关键的地方是如何把事件映射到小表的对应列上。映射做好后,就可以使用小表做事件处理和状态跳转了。下面结合代码详细介绍。

代码分析

stack/smp/smp_main.cc

action list

enum {
  SMP_PROC_SEC_REQ,
  SMP_SEND_PAIR_REQ,
  SMP_SEND_PAIR_RSP,
  SMP_SEND_CONFIRM,
  SMP_SEND_PAIR_FAIL,
  SMP_SEND_RAND,
  SMP_SEND_ENC_INFO,
  SMP_SEND_ID_INFO,
  SMP_SEND_LTK_REPLY,
  SMP_PROC_PAIR_CMD,
  SMP_PROC_PAIR_FAIL,
  SMP_PROC_CONFIRM,
  SMP_PROC_RAND,
  ...
}

static const tSMP_ACT smp_sm_action[] = {
    smp_proc_sec_req,
    smp_send_pair_req,
    smp_send_pair_rsp,
    smp_send_confirm,
    smp_send_pair_fail,
    smp_send_rand,
    smp_send_enc_info,
    smp_send_id_info,
    smp_send_ltk_reply,
    smp_proc_pair_cmd,
    smp_proc_pair_fail,
    smp_proc_confirm,
    smp_proc_rand,
    ...
}

上面的代码我们看到action和前面介绍的一样,enum和处理函数一一对应,在状态转换表中填enum的值,可以通过这个值来找到对应的处理函数。

状态表

static const uint8_t smp_master_idle_table[][SMP_SM_NUM_COLS] = {
    /* Event                  Action               Next State */
    /* L2C_CONN */
    {SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
    /* SEC_REQ */
    {SMP_PROC_SEC_REQ, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
    /* L2C_DISC */
    {SMP_IDLE_TERMINATE, SMP_SM_NO_ACTION, SMP_STATE_IDLE},
    /* AUTH_CMPL */
    {SMP_PAIRING_CMPL, SMP_SM_NO_ACTION, SMP_STATE_IDLE},
    /* CR_LOC_SC_OOB_DATA */
    {SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION,SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA}
};

static const tSMP_SM_TBL smp_state_table[][2] = {
    /* SMP_STATE_IDLE */
    {smp_master_idle_table, smp_slave_idle_table},

    /* SMP_STATE_WAIT_APP_RSP */
    {smp_master_wait_for_app_response_table,
    ¦smp_slave_wait_for_app_response_table},

    /* SMP_STATE_SEC_REQ_PENDING */
    {
  NULL, smp_slave_s
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值