事件广播的早返回逻辑

正确图表行为指南

这些指南确保事件驱动系统中的图表行为正确:
当一个状态处于活动状态时,其父级也应处于活动状态。
具有异或分解的状态(或图表)不得有多个活动子状态。
如果并行状态处于活动状态,则优先级较高的同级状态也必须处于活动状态。

早返回逻辑是如何工作的

Stateflow图表在单个线程上运行。因此,图表必须中断当前活动以处理事件。基于状态或转换动作的事件广播的活动可能与当前活动冲突。图表通过使用事件广播的早返回逻辑来解决这些冲突,如下所示:

动作类型早返回逻辑
Entry如果在事件广播结束时状态不再处于活动状态,则图表不会执行进入状态的剩余步骤。
Exit如果状态在事件广播结束时不再处于活动状态,则图表不会执行剩余的退出操作或从一个状态转换到另一个状态。
During如果在事件广播结束时状态不再处于活动状态,则图表不会执行执行活动状态的剩余步骤。
Condition如果内部或外部流程图的源状态(或默认流程图的父状态)在事件广播结束时不再处于活动状态,则该图表不会执行执行流程图的其余步骤。
Transition如果转换路径的父级未处于活动状态,或者该父级有一个活动的子状态,则图表不会执行其余的转换操作和状态输入操作。

早返回逻辑示例

在这里插入图片描述
在这个例子中,假设状态A最初是活动的。事件E发生,导致以下行为:
图表根检查事件E是否导致有效的活动状态a转换。
1 存在向状态B的有效转换。
2 有效转换的条件动作执行并广播事件F。
3 事件F中断了从A到B的转换。
4 图表根检查事件F是否导致有效的活动状态a转换。
5 存在向状态C的有效转换。
6 状态A执行其退出操作。
7 状态A变为非活动状态。
8 状态C变为活动状态。
9 状态C执行并完成其输入操作。

C状态现在是其图表中唯一活跃的子状态。状态流程图无法返回到从状态A到状态B的转换,并在广播事件F的条件操作后继续(步骤3)。首先,其源状态A不再处于活动状态。其次,如果图表允许转换,状态B将成为图表的第二个活动子状态。此行为违反了具有排他性(or)分解的状态(或图表)不能有多个活动子状态的准则。因此,该图表使用早期返回逻辑并停止从状态A到状态B的转换。

避免使用无向的本地事件广播,这可能会导致图表中出现不必要的递归行为。使用send操作符进行定向本地事件广播。

下面我搭建一个类似的模型,其中E是输入事件,F是本地事件,生成一下代码
在这里插入图片描述

在这里插入图片描述

/* Function for Chart: '<Root>/Chart' */
static void untitled_c3_untitled(void)
{
  int32_T b_previousEvent;
  if (untitled_DW.is_c3_untitled == untitled_IN_A) {
    switch (untitled_DW.sfEvent) {
     case untitled_event_E:
      b_previousEvent = untitled_DW.sfEvent;
      untitled_DW.sfEvent = untitled_event_F;

      /* Chart: '<Root>/Chart' */
      /* Chart: '<Root>/Chart' */
      untitled_c3_untitled();
      untitled_DW.sfEvent = b_previousEvent;
      if (untitled_DW.is_c3_untitled == untitled_IN_A) {
        untitled_DW.is_c3_untitled = untitled_IN_B;

        /* Outport: '<Root>/Out1' incorporates:
         *  Inport: '<Root>/In1'
         */
        untitled_Y.Out1 = untitled_U.In1 + 1.0;
      }
      break;

     case untitled_event_F:
      untitled_DW.is_c3_untitled = untitled_IN_C;

      /* Outport: '<Root>/Out1' incorporates:
       *  Inport: '<Root>/In1'
       */
      untitled_Y.Out1 = untitled_U.In1 + 100.0;
      break;
    }
  }
}

/* Model step function */
void untitled_step(void)
{
  /* Chart: '<Root>/Chart1' */
  if (untitled_DW.is_active_c1_untitled == 0U) {
    untitled_DW.is_active_c1_untitled = 1U;

    /* Chart: '<Root>/Chart' */
    /* Chart: '<Root>/Chart' */
    untitled_DW.sfEvent = untitled_event_E;
    untitled_c3_untitled();
  }

  /* End of Chart: '<Root>/Chart1' */
}

可以看到untitled_c3_untitled函数中使用了递归,但是在递归中有switch判断,函数直接会跳到untitled_event_F这个条件中,从而执行untitled_IN_C图表中的内容,完成后break跳出函数,从而不会陷入无限的函数递归中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值