量子平台(Quantum Platform, 简称QP)是一个用于实时嵌入式系统的软件框架,QP是轻量级的、开源的、基于层次式状态机的、事件驱动的平台。
QP包括事件处理器(QEP)、轻量级的事件驱动框架(QF)、任务调度微内核(QK)和实时跟踪调试器(QS)四个部分。
利用QP可以开发出结构清晰的嵌入式应用程序(使用C或C++语言)。
QEP的核心思想就是,用一个函数指针指向当前状态函数,使用这个函数指针有条件地执行某状态函数,并根据执行结果执行其它的相应动作。
(1)状态图到C语言的转换 状态图可以很容易地转换到C语言表示,下面举例说明(略去了构造函数和初始化函数)。
例如下面的平面状态机FSM,图中有两个状态:设置状态setting和定时状态timing。
可以转换成C代码如下 两个状态函数声明:
static QState Bomb4_setting(Bomb4 *me, QEvent const *e);/*声明设置状态函数*/ static QState Bomb4_timing (Bomb4 *me, QEvent const *e);/*声明计时状态函数*/ 两个状态函数的实现(对事件的处理): QState Bomb4_setting(Bomb4 *me, QEvent const *e) { switch (e->sig) { case UP_SIG: {/*UP_SIG事件处理---增加定时处理*/ return Q_HANDLED(); case DOWN_SIG: {/*DOWN_SIG事件处理---减少定时事件处理*/ return Q_HANDLED(); case ARM_SIG: {/*ARM_SIG事件处理---定时事件处理*/ return Q_TRAN(&Bomb4_timing); /* 转到定时状态*/ return Q_IGNORED(); /*忽略事件*/ /*----6.4-状态函数(定时状态处理)-----.*/ QState Bomb4_timing(Bomb4 *me, QEvent const *e) { switch (e->sig) { case Q_ENTRY_SIG: {/*状态进入处理*/ return Q_HANDLED(); case UP_SIG: {/*UP_SIG事件处理---保存密码设置*/ return Q_HANDLED(); case DOWN_SIG: {/*DOWN_SIG事件处理---保存密码设置*/ return Q_HANDLED(); case ARM_SIG: {/*ARM_SIG事件处理---密码正确则解除定时引爆,转到设置状态*/ if (me->code == me->defuse) { return Q_TRAN(&Bomb4_setting); return Q_HANDLED(); case TICK_SIG: {/*定时事件处理*/ return Q_HANDLED(); return Q_IGNORED(); (2)状态函数指针 在QP中用函数表示状态,叫状态函数,一个状态用一个状态函数表示,系统有多个状态,也就可以用多个函数来表示。在QEP中定义了一个状态函数指针QStateHandler,用这个函数指针可以指向任何一个状态函数。在状态函数内使用了结构清晰的switch---case语句,对不同的事件(信号)进行分类处理。 状态函数指针定义如下: typedef QState (*QStateHandler)(void *me, QEvent const *e); /*状态函数指针,指向状态机中任何一个状态函数*/ 其中 QState是调用状态函数的返回值,其定义如下: typedef uint8_t QState;/*状态返回值,状态机状态处理函数返回值*/ 有四种返回值:0---QRETHANDLED,表示事件被处理了,但没有转换,叫内部转换; 1---QRETIGNORED, 表示事件被忽略,没有处理; 2---QRETTRAN,表示事件被处理了,并有转换,转换到其它状态; 3---QRETSUPER,表示进入父状态了,只用于层次状态机HSM中。 (3)状态机的当前状态 平面状态机FSM或层次状态机HSM内部定义了一个QStateHandler类型的state变量,它是一个指向状态函数的指针,state指向哪个状态函数,哪个状态函数就是当前状态,有事件时,总是把事件发给当前状态的状态函数来处理。状态机有多个状态,但同一时刻,只有一个“焦点”(当前状态),“焦点”可以用QTRAN(target)来改变。 当前状态变量定义如下: typedef struct QFsmTag {QStateHandler state; /*状态变量,当前活动状态,也就是经常用到的me->state */ } QFsm; /*平面状态机FSM数据结构*/ typedef struct QFsmTag QHsm; /*层次状态机HSM数据结构,与FSM一样*/ 状态转换定义如下: #define Q_TRAN(target_)(((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN) 发给状态机的事件,总是发到当前状态变量所指向的状态函数来处理。 (4)事件处理器 事件处理器,也可以理解为一个状态机引擎,当处理有事件时,调用当前状态的状态函数处理这个事件,并处理调用状态函数的返回值,根据返回值进行相应的状态变换(如转移到父状态)。 同时状态引擎也处理状态的进入(ENTER)、退出(EXIT),并处理初始伪状态。 事件处理器利用状态函数指针来调用状态函数,总是把事件发送到当前状态,但事件不是在当前状态处理了,由调用的结果来判断。 用状态函数指针从原理上可以调用任何状态函数,并检查调用结果。状态机引擎也就成了一个事件分派执行器。QHsm_dispatch()函数是QP中最复杂的函数,是理解状态机处理的关键。 【1】QP量子平台、量子编程:http://www.state-machine.com
两个状态函数的实现(对事件的处理):
QState Bomb4_setting(Bomb4 *me, QEvent const *e) { switch (e->sig) { case UP_SIG: {/*UP_SIG事件处理---增加定时处理*/ return Q_HANDLED(); case DOWN_SIG: {/*DOWN_SIG事件处理---减少定时事件处理*/ return Q_HANDLED(); case ARM_SIG: {/*ARM_SIG事件处理---定时事件处理*/ return Q_TRAN(&Bomb4_timing); /* 转到定时状态*/ return Q_IGNORED(); /*忽略事件*/ /*----6.4-状态函数(定时状态处理)-----.*/ QState Bomb4_timing(Bomb4 *me, QEvent const *e) { switch (e->sig) { case Q_ENTRY_SIG: {/*状态进入处理*/ return Q_HANDLED(); case UP_SIG: {/*UP_SIG事件处理---保存密码设置*/ return Q_HANDLED(); case DOWN_SIG: {/*DOWN_SIG事件处理---保存密码设置*/ return Q_HANDLED(); case ARM_SIG: {/*ARM_SIG事件处理---密码正确则解除定时引爆,转到设置状态*/ if (me->code == me->defuse) { return Q_TRAN(&Bomb4_setting); return Q_HANDLED(); case TICK_SIG: {/*定时事件处理*/ return Q_HANDLED(); return Q_IGNORED(); (2)状态函数指针 在QP中用函数表示状态,叫状态函数,一个状态用一个状态函数表示,系统有多个状态,也就可以用多个函数来表示。在QEP中定义了一个状态函数指针QStateHandler,用这个函数指针可以指向任何一个状态函数。在状态函数内使用了结构清晰的switch---case语句,对不同的事件(信号)进行分类处理。 状态函数指针定义如下: typedef QState (*QStateHandler)(void *me, QEvent const *e); /*状态函数指针,指向状态机中任何一个状态函数*/ 其中 QState是调用状态函数的返回值,其定义如下: typedef uint8_t QState;/*状态返回值,状态机状态处理函数返回值*/ 有四种返回值:0---QRETHANDLED,表示事件被处理了,但没有转换,叫内部转换; 1---QRETIGNORED, 表示事件被忽略,没有处理; 2---QRETTRAN,表示事件被处理了,并有转换,转换到其它状态; 3---QRETSUPER,表示进入父状态了,只用于层次状态机HSM中。 (3)状态机的当前状态 平面状态机FSM或层次状态机HSM内部定义了一个QStateHandler类型的state变量,它是一个指向状态函数的指针,state指向哪个状态函数,哪个状态函数就是当前状态,有事件时,总是把事件发给当前状态的状态函数来处理。状态机有多个状态,但同一时刻,只有一个“焦点”(当前状态),“焦点”可以用QTRAN(target)来改变。 当前状态变量定义如下: typedef struct QFsmTag {QStateHandler state; /*状态变量,当前活动状态,也就是经常用到的me->state */ } QFsm; /*平面状态机FSM数据结构*/ typedef struct QFsmTag QHsm; /*层次状态机HSM数据结构,与FSM一样*/ 状态转换定义如下: #define Q_TRAN(target_)(((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN) 发给状态机的事件,总是发到当前状态变量所指向的状态函数来处理。 (4)事件处理器 事件处理器,也可以理解为一个状态机引擎,当处理有事件时,调用当前状态的状态函数处理这个事件,并处理调用状态函数的返回值,根据返回值进行相应的状态变换(如转移到父状态)。 同时状态引擎也处理状态的进入(ENTER)、退出(EXIT),并处理初始伪状态。 事件处理器利用状态函数指针来调用状态函数,总是把事件发送到当前状态,但事件不是在当前状态处理了,由调用的结果来判断。 用状态函数指针从原理上可以调用任何状态函数,并检查调用结果。状态机引擎也就成了一个事件分派执行器。QHsm_dispatch()函数是QP中最复杂的函数,是理解状态机处理的关键。 【1】QP量子平台、量子编程:http://www.state-machine.com
(2)状态函数指针 在QP中用函数表示状态,叫状态函数,一个状态用一个状态函数表示,系统有多个状态,也就可以用多个函数来表示。在QEP中定义了一个状态函数指针QStateHandler,用这个函数指针可以指向任何一个状态函数。在状态函数内使用了结构清晰的switch---case语句,对不同的事件(信号)进行分类处理。
状态函数指针定义如下:
typedef QState (*QStateHandler)(void *me, QEvent const *e); /*状态函数指针,指向状态机中任何一个状态函数*/ 其中 QState是调用状态函数的返回值,其定义如下: typedef uint8_t QState;/*状态返回值,状态机状态处理函数返回值*/ 有四种返回值:0---QRETHANDLED,表示事件被处理了,但没有转换,叫内部转换; 1---QRETIGNORED, 表示事件被忽略,没有处理; 2---QRETTRAN,表示事件被处理了,并有转换,转换到其它状态; 3---QRETSUPER,表示进入父状态了,只用于层次状态机HSM中。 (3)状态机的当前状态 平面状态机FSM或层次状态机HSM内部定义了一个QStateHandler类型的state变量,它是一个指向状态函数的指针,state指向哪个状态函数,哪个状态函数就是当前状态,有事件时,总是把事件发给当前状态的状态函数来处理。状态机有多个状态,但同一时刻,只有一个“焦点”(当前状态),“焦点”可以用QTRAN(target)来改变。 当前状态变量定义如下: typedef struct QFsmTag {QStateHandler state; /*状态变量,当前活动状态,也就是经常用到的me->state */ } QFsm; /*平面状态机FSM数据结构*/ typedef struct QFsmTag QHsm; /*层次状态机HSM数据结构,与FSM一样*/ 状态转换定义如下: #define Q_TRAN(target_)(((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN) 发给状态机的事件,总是发到当前状态变量所指向的状态函数来处理。 (4)事件处理器 事件处理器,也可以理解为一个状态机引擎,当处理有事件时,调用当前状态的状态函数处理这个事件,并处理调用状态函数的返回值,根据返回值进行相应的状态变换(如转移到父状态)。 同时状态引擎也处理状态的进入(ENTER)、退出(EXIT),并处理初始伪状态。 事件处理器利用状态函数指针来调用状态函数,总是把事件发送到当前状态,但事件不是在当前状态处理了,由调用的结果来判断。 用状态函数指针从原理上可以调用任何状态函数,并检查调用结果。状态机引擎也就成了一个事件分派执行器。QHsm_dispatch()函数是QP中最复杂的函数,是理解状态机处理的关键。 【1】QP量子平台、量子编程:http://www.state-machine.com
其中 QState是调用状态函数的返回值,其定义如下:
typedef uint8_t QState;/*状态返回值,状态机状态处理函数返回值*/ 有四种返回值:0---QRETHANDLED,表示事件被处理了,但没有转换,叫内部转换; 1---QRETIGNORED, 表示事件被忽略,没有处理; 2---QRETTRAN,表示事件被处理了,并有转换,转换到其它状态; 3---QRETSUPER,表示进入父状态了,只用于层次状态机HSM中。 (3)状态机的当前状态 平面状态机FSM或层次状态机HSM内部定义了一个QStateHandler类型的state变量,它是一个指向状态函数的指针,state指向哪个状态函数,哪个状态函数就是当前状态,有事件时,总是把事件发给当前状态的状态函数来处理。状态机有多个状态,但同一时刻,只有一个“焦点”(当前状态),“焦点”可以用QTRAN(target)来改变。 当前状态变量定义如下: typedef struct QFsmTag {QStateHandler state; /*状态变量,当前活动状态,也就是经常用到的me->state */ } QFsm; /*平面状态机FSM数据结构*/ typedef struct QFsmTag QHsm; /*层次状态机HSM数据结构,与FSM一样*/ 状态转换定义如下: #define Q_TRAN(target_)(((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN) 发给状态机的事件,总是发到当前状态变量所指向的状态函数来处理。 (4)事件处理器 事件处理器,也可以理解为一个状态机引擎,当处理有事件时,调用当前状态的状态函数处理这个事件,并处理调用状态函数的返回值,根据返回值进行相应的状态变换(如转移到父状态)。 同时状态引擎也处理状态的进入(ENTER)、退出(EXIT),并处理初始伪状态。 事件处理器利用状态函数指针来调用状态函数,总是把事件发送到当前状态,但事件不是在当前状态处理了,由调用的结果来判断。 用状态函数指针从原理上可以调用任何状态函数,并检查调用结果。状态机引擎也就成了一个事件分派执行器。QHsm_dispatch()函数是QP中最复杂的函数,是理解状态机处理的关键。 【1】QP量子平台、量子编程:http://www.state-machine.com
有四种返回值:0---QRETHANDLED,表示事件被处理了,但没有转换,叫内部转换; 1---QRETIGNORED, 表示事件被忽略,没有处理; 2---QRETTRAN,表示事件被处理了,并有转换,转换到其它状态; 3---QRETSUPER,表示进入父状态了,只用于层次状态机HSM中。
(3)状态机的当前状态
平面状态机FSM或层次状态机HSM内部定义了一个QStateHandler类型的state变量,它是一个指向状态函数的指针,state指向哪个状态函数,哪个状态函数就是当前状态,有事件时,总是把事件发给当前状态的状态函数来处理。状态机有多个状态,但同一时刻,只有一个“焦点”(当前状态),“焦点”可以用QTRAN(target)来改变。
当前状态变量定义如下:
typedef struct QFsmTag {QStateHandler state; /*状态变量,当前活动状态,也就是经常用到的me->state */ } QFsm; /*平面状态机FSM数据结构*/ typedef struct QFsmTag QHsm; /*层次状态机HSM数据结构,与FSM一样*/ 状态转换定义如下: #define Q_TRAN(target_)(((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN) 发给状态机的事件,总是发到当前状态变量所指向的状态函数来处理。 (4)事件处理器 事件处理器,也可以理解为一个状态机引擎,当处理有事件时,调用当前状态的状态函数处理这个事件,并处理调用状态函数的返回值,根据返回值进行相应的状态变换(如转移到父状态)。 同时状态引擎也处理状态的进入(ENTER)、退出(EXIT),并处理初始伪状态。 事件处理器利用状态函数指针来调用状态函数,总是把事件发送到当前状态,但事件不是在当前状态处理了,由调用的结果来判断。 用状态函数指针从原理上可以调用任何状态函数,并检查调用结果。状态机引擎也就成了一个事件分派执行器。QHsm_dispatch()函数是QP中最复杂的函数,是理解状态机处理的关键。 【1】QP量子平台、量子编程:http://www.state-machine.com
状态转换定义如下:
#define Q_TRAN(target_)(((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN) 发给状态机的事件,总是发到当前状态变量所指向的状态函数来处理。 (4)事件处理器 事件处理器,也可以理解为一个状态机引擎,当处理有事件时,调用当前状态的状态函数处理这个事件,并处理调用状态函数的返回值,根据返回值进行相应的状态变换(如转移到父状态)。 同时状态引擎也处理状态的进入(ENTER)、退出(EXIT),并处理初始伪状态。 事件处理器利用状态函数指针来调用状态函数,总是把事件发送到当前状态,但事件不是在当前状态处理了,由调用的结果来判断。 用状态函数指针从原理上可以调用任何状态函数,并检查调用结果。状态机引擎也就成了一个事件分派执行器。QHsm_dispatch()函数是QP中最复杂的函数,是理解状态机处理的关键。 【1】QP量子平台、量子编程:http://www.state-machine.com
发给状态机的事件,总是发到当前状态变量所指向的状态函数来处理。
(4)事件处理器 事件处理器,也可以理解为一个状态机引擎,当处理有事件时,调用当前状态的状态函数处理这个事件,并处理调用状态函数的返回值,根据返回值进行相应的状态变换(如转移到父状态)。
同时状态引擎也处理状态的进入(ENTER)、退出(EXIT),并处理初始伪状态。
事件处理器利用状态函数指针来调用状态函数,总是把事件发送到当前状态,但事件不是在当前状态处理了,由调用的结果来判断。
用状态函数指针从原理上可以调用任何状态函数,并检查调用结果。状态机引擎也就成了一个事件分派执行器。QHsm_dispatch()函数是QP中最复杂的函数,是理解状态机处理的关键。