This commit is contained in:
MMS 2023-12-11 20:31:00 -05:00
parent d4a08a1608
commit c2347e81c9
15 changed files with 271 additions and 57 deletions

View File

@ -31,6 +31,8 @@
#include "qpc.h" // QP/C framework
#include "qhsmtst.h" // this application
Q_DEFINE_THIS_FILE
//$declare${SMs::QHsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${SMs::QHsmTst} ............................................................
@ -43,6 +45,7 @@ typedef struct QHsmTst {
// public:
} QHsmTst;
extern QHsmTst QHsmTst_inst;
// protected:
@ -74,6 +77,37 @@ void QHsmTst_ctor(void) {
QHsm_ctor(&me->super, Q_STATE_CAST(&QHsmTst_initial));
}
//$enddef${Shared::QHsmTst_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${Shared::QHsmTst_isIn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${Shared::QHsmTst_isIn} ....................................................
bool QHsmTst_isIn(uint32_t const state_num) {
QHsm * const me = &QHsmTst_inst.super;
bool stat = false;
switch (state_num) {
case 0:
stat = QHsm_isIn(me, Q_STATE_CAST(&QHsmTst_s));
break;
case 1:
stat = QHsm_isIn(me, Q_STATE_CAST(&QHsmTst_s1));
break;
case 11:
stat = QHsm_isIn(me, Q_STATE_CAST(&QHsmTst_s11));
break;
case 2:
stat = QHsm_isIn(me, Q_STATE_CAST(&QHsmTst_s2));
break;
case 21:
stat = QHsm_isIn(me, Q_STATE_CAST(&QHsmTst_s21));
break;
case 211:
stat = QHsm_isIn(me, Q_STATE_CAST(&QHsmTst_s211));
break;
default:
Q_ERROR();
}
return stat;
}
//$enddef${Shared::QHsmTst_isIn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${SMs::QHsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${SMs::QHsmTst} ............................................................

View File

@ -52,14 +52,17 @@ enum QHsmTstSignals {
//${Shared::the_sm} ..........................................................
extern QAsm * const the_sm;
//${Shared::QHsmTst_ctor} ....................................................
void QHsmTst_ctor(void);
//${Shared::BSP_display} .....................................................
void BSP_display(char const * msg);
//${Shared::BSP_terminate} ...................................................
void BSP_terminate(int16_t const result);
//${Shared::QHsmTst_ctor} ....................................................
void QHsmTst_ctor(void);
//${Shared::QHsmTst_isIn} ....................................................
bool QHsmTst_isIn(uint32_t const state_num);
//$enddecl${Shared} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // QHSMTST_H_

View File

@ -27,11 +27,6 @@
<documentation>opaque pointer to the test SM</documentation>
<code>= &amp;QHsmTst_inst.super.super;</code>
</attribute>
<!--${Shared::QHsmTst_ctor}-->
<operation name="QHsmTst_ctor" type="void" visibility="0x00" properties="0x00">
<code>QHsmTst *me = &amp;QHsmTst_inst;
QHsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;QHsmTst_initial));</code>
</operation>
<!--${Shared::BSP_display}-->
<operation name="BSP_display" type="void" visibility="0x00" properties="0x00">
<!--${Shared::BSP_display::msg}-->
@ -42,6 +37,41 @@ QHsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;QHsmTst_initial));</code>
<!--${Shared::BSP_terminate::result}-->
<parameter name="result" type="int16_t const"/>
</operation>
<!--${Shared::QHsmTst_ctor}-->
<operation name="QHsmTst_ctor" type="void" visibility="0x00" properties="0x00">
<code>QHsmTst *me = &amp;QHsmTst_inst;
QHsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;QHsmTst_initial));</code>
</operation>
<!--${Shared::QHsmTst_isIn}-->
<operation name="QHsmTst_isIn" type="bool" visibility="0x00" properties="0x00">
<!--${Shared::QHsmTst_isIn::state_num}-->
<parameter name="state_num" type="uint32_t const"/>
<code>QHsm * const me = &amp;QHsmTst_inst.super;
bool stat = false;
switch (state_num) {
case 0:
stat = QHsm_isIn(me, Q_STATE_CAST(&amp;QHsmTst_s));
break;
case 1:
stat = QHsm_isIn(me, Q_STATE_CAST(&amp;QHsmTst_s1));
break;
case 11:
stat = QHsm_isIn(me, Q_STATE_CAST(&amp;QHsmTst_s11));
break;
case 2:
stat = QHsm_isIn(me, Q_STATE_CAST(&amp;QHsmTst_s2));
break;
case 21:
stat = QHsm_isIn(me, Q_STATE_CAST(&amp;QHsmTst_s21));
break;
case 211:
stat = QHsm_isIn(me, Q_STATE_CAST(&amp;QHsmTst_s211));
break;
default:
Q_ERROR();
}
return stat;</code>
</operation>
</package>
<!--${SMs}-->
<package name="SMs" stereotype="0x02">
@ -349,9 +379,12 @@ $declare ${Shared}
<text>#include &quot;qpc.h&quot; // QP/C framework
#include &quot;qhsmtst.h&quot; // this application
Q_DEFINE_THIS_FILE
$declare ${SMs::QHsmTst}
$define ${Shared::the_sm}
$define ${Shared::QHsmTst_ctor}
$define ${Shared::QHsmTst_isIn}
$define ${SMs::QHsmTst}</text>
</file>
</directory>

View File

@ -18,6 +18,17 @@ expect("@timestamp BSP_DISPLAY s21-ENTRY;")
expect("@timestamp BSP_DISPLAY s211-ENTRY;")
expect("@timestamp Trg-Done QS_RX_EVENT")
test("QHsmTst isIn", NORESET)
command(1, 1)
expect("@timestamp CMD 0 1");
expect("@timestamp Trg-Done QS_RX_COMMAND")
command(1, 21)
expect("@timestamp CMD 1 21");
expect("@timestamp Trg-Done QS_RX_COMMAND")
command(1, 211)
expect("@timestamp CMD 1 211");
expect("@timestamp Trg-Done QS_RX_COMMAND")
test("QHsmTst dispatch", NORESET)
dispatch("A_SIG")
expect("@timestamp BSP_DISPLAY s21-A;")

View File

@ -1,7 +1,7 @@
//============================================================================
// Purpose: Fixture for QUTEST
// Last Updated for Version: 7.3.0
// Date of the Last Update: 2023-08-25
// Last Updated for Version: 7.3.1
// Date of the Last Update: 2023-12-11
//
// Q u a n t u m L e a P s
// ------------------------
@ -38,6 +38,7 @@ Q_DEFINE_THIS_FILE
enum {
BSP_DISPLAY = QS_USER,
CMD,
};
//----------------------------------------------------------------------------
@ -56,6 +57,7 @@ int main(int argc, char *argv[]) {
// dictionaries...
QS_OBJ_DICTIONARY(the_sm);
QS_USR_DICTIONARY(BSP_DISPLAY);
QS_USR_DICTIONARY(CMD);
QHsmTst_ctor(); // instantiate the QHsmTst object
@ -89,8 +91,18 @@ void QS_onCommand(uint8_t cmdId,
//PRINTF_S("<TARGET> Command id=%d param=%d\n", (int)cmdId, (int)param);
switch (cmdId) {
case 0U: {
break;
case 0U: {
QS_BEGIN_ID(CMD, 0U) // app-specific record
QS_END()
break;
}
case 1U: {
bool ret = QHsmTst_isIn(param1);
QS_BEGIN_ID(CMD, 0U) // app-specific record
QS_U8(0U, ret ? 1 : 0);
QS_U8(0U, (uint8_t)param1);
QS_END()
break;
}
default:
break;

View File

@ -31,6 +31,8 @@
#include "qpc.h" // QP/C framework
#include "qmsmtst.h" // this application
Q_DEFINE_THIS_FILE
//$declare${SMs::QMsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${SMs::QMsmTst} ............................................................
@ -43,6 +45,7 @@ typedef struct QMsmTst {
// public:
} QMsmTst;
extern QMsmTst QMsmTst_inst;
// protected:
@ -132,6 +135,37 @@ void QMsmTst_ctor(void) {
QMsm_ctor(&me->super, Q_STATE_CAST(&QMsmTst_initial));
}
//$enddef${Shared::QMsmTst_ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${Shared::QMsmTst_isInState} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${Shared::QMsmTst_isInState} ...............................................
bool QMsmTst_isInState(uint32_t const state_num) {
QMsm * const me = &QMsmTst_inst.super;
bool stat = false;
switch (state_num) {
case 0:
stat = QMsm_isInState(me, &QMsmTst_s_s);
break;
case 1:
stat = QMsm_isInState(me, &QMsmTst_s1_s);
break;
case 11:
stat = QMsm_isInState(me, &QMsmTst_s11_s);
break;
case 2:
stat = QMsm_isInState(me, &QMsmTst_s2_s);
break;
case 21:
stat = QMsm_isInState(me, &QMsmTst_s21_s);
break;
case 211:
stat = QMsm_isInState(me, &QMsmTst_s211_s);
break;
default:
Q_ERROR();
}
return stat;
}
//$enddef${Shared::QMsmTst_isInState} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//$define${SMs::QMsmTst} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//${SMs::QMsmTst} ............................................................

View File

@ -52,14 +52,17 @@ enum QMsmTstSignals {
//${Shared::the_sm} ..........................................................
extern QAsm * const the_sm;
//${Shared::QMsmTst_ctor} ....................................................
void QMsmTst_ctor(void);
//${Shared::BSP_display} .....................................................
void BSP_display(char const * msg);
//${Shared::BSP_terminate} ...................................................
void BSP_terminate(int16_t const result);
//${Shared::QMsmTst_ctor} ....................................................
void QMsmTst_ctor(void);
//${Shared::QMsmTst_isInState} ...............................................
bool QMsmTst_isInState(uint32_t const state_num);
//$enddecl${Shared} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#endif // QMSMTST_H_

View File

@ -27,11 +27,6 @@
<documentation>opaque pointer to the test SM</documentation>
<code>= &amp;QMsmTst_inst.super.super;</code>
</attribute>
<!--${Shared::QMsmTst_ctor}-->
<operation name="QMsmTst_ctor" type="void" visibility="0x00" properties="0x00">
<code>QMsmTst *me = &amp;QMsmTst_inst;
QMsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;QMsmTst_initial));</code>
</operation>
<!--${Shared::BSP_display}-->
<operation name="BSP_display" type="void" visibility="0x00" properties="0x00">
<!--${Shared::BSP_display::msg}-->
@ -42,6 +37,41 @@ QMsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;QMsmTst_initial));</code>
<!--${Shared::BSP_terminate::result}-->
<parameter name="result" type="int16_t const"/>
</operation>
<!--${Shared::QMsmTst_ctor}-->
<operation name="QMsmTst_ctor" type="void" visibility="0x00" properties="0x00">
<code>QMsmTst *me = &amp;QMsmTst_inst;
QMsm_ctor(&amp;me-&gt;super, Q_STATE_CAST(&amp;QMsmTst_initial));</code>
</operation>
<!--${Shared::QMsmTst_isInState}-->
<operation name="QMsmTst_isInState" type="bool" visibility="0x00" properties="0x00">
<!--${Shared::QMsmTst_isInStat~::state_num}-->
<parameter name="state_num" type="uint32_t const"/>
<code>QMsm * const me = &amp;QMsmTst_inst.super;
bool stat = false;
switch (state_num) {
case 0:
stat = QMsm_isInState(me, &amp;QMsmTst_s_s);
break;
case 1:
stat = QMsm_isInState(me, &amp;QMsmTst_s1_s);
break;
case 11:
stat = QMsm_isInState(me, &amp;QMsmTst_s11_s);
break;
case 2:
stat = QMsm_isInState(me, &amp;QMsmTst_s2_s);
break;
case 21:
stat = QMsm_isInState(me, &amp;QMsmTst_s21_s);
break;
case 211:
stat = QMsm_isInState(me, &amp;QMsmTst_s211_s);
break;
default:
Q_ERROR();
}
return stat;</code>
</operation>
</package>
<!--${SMs}-->
<package name="SMs" stereotype="0x02">
@ -349,9 +379,12 @@ $declare ${Shared}
<text>#include &quot;qpc.h&quot; // QP/C framework
#include &quot;qmsmtst.h&quot; // this application
Q_DEFINE_THIS_FILE
$declare ${SMs::QMsmTst}
$define ${Shared::the_sm}
$define ${Shared::QMsmTst_ctor}
$define ${Shared::QMsmTst_isInState}
$define ${SMs::QMsmTst}</text>
</file>
</directory>

View File

@ -18,6 +18,17 @@ expect("@timestamp BSP_DISPLAY s21-ENTRY;")
expect("@timestamp BSP_DISPLAY s211-ENTRY;")
expect("@timestamp Trg-Done QS_RX_EVENT")
test("QMsmTst isInState", NORESET)
command(1, 1)
expect("@timestamp CMD 0 1");
expect("@timestamp Trg-Done QS_RX_COMMAND")
command(1, 21)
expect("@timestamp CMD 1 21");
expect("@timestamp Trg-Done QS_RX_COMMAND")
command(1, 211)
expect("@timestamp CMD 1 211");
expect("@timestamp Trg-Done QS_RX_COMMAND")
test("QMsmTst dispatch", NORESET)
dispatch("A_SIG")
expect("@timestamp BSP_DISPLAY s21-A;")

View File

@ -1,7 +1,7 @@
//============================================================================
// Purpose: Fixture for QUTEST
// Last Updated for Version: 7.3.0
// Date of the Last Update: 2023-08-25
// Last Updated for Version: 7.3.1
// Date of the Last Update: 2023-12-11
//
// Q u a n t u m L e a P s
// ------------------------
@ -38,6 +38,7 @@ Q_DEFINE_THIS_FILE
enum {
BSP_DISPLAY = QS_USER,
CMD,
};
//----------------------------------------------------------------------------
@ -56,6 +57,7 @@ int main(int argc, char *argv[]) {
// dictionaries...
QS_OBJ_DICTIONARY(the_sm);
QS_USR_DICTIONARY(BSP_DISPLAY);
QS_USR_DICTIONARY(CMD);
QMsmTst_ctor(); // instantiate the QMsmTst object
@ -89,8 +91,18 @@ void QS_onCommand(uint8_t cmdId,
//PRINTF_S("<TARGET> Command id=%d param=%d\n", (int)cmdId, (int)param);
switch (cmdId) {
case 0U: {
break;
case 0U: {
QS_BEGIN_ID(CMD, 0U) // app-specific record
QS_END()
break;
}
case 1U: {
bool ret = QMsmTst_isInState(param1);
QS_BEGIN_ID(CMD, 0U) // app-specific record
QS_U8(0U, ret ? 1 : 0);
QS_U8(0U, (uint8_t)param1);
QS_END()
break;
}
default:
break;

View File

@ -15,7 +15,7 @@ def on_teardown():
# tests...
test("Command")
note('''
this test invokes command(1,1,1)
this test invokes command(<cmd>,<param1>,<param2>)
''')
command("CMD_X", 1, 2, 3)
expect("@timestamp COMMAND CMD_X 0")

46
qpc.qm
View File

@ -790,17 +790,23 @@ QF_CRIT_EXIT();
bool inState = false; // assume that this HSM is not in 'state'
// scan the state hierarchy bottom-up
QState r;
do {
// do the states match?
if (me-&gt;super.temp.fun == state) {
inState = true; // 'true' means that match found
r = Q_RET_IGNORED; // cause breaking out of the loop
QStateHandler s = me-&gt;super.state.fun;
int_fast8_t limit = QHSM_MAX_NEST_DEPTH_ + 1; // loop hard limit
QState r = Q_RET_SUPER;
for (; (r != Q_RET_IGNORED) &amp;&amp; (limit &gt; 0); --limit) {
if (s == state) { // do the states match?
inState = true; // 'true' means that match found
break; // break out of the for-loop
}
else {
r = QHSM_RESERVED_EVT_(me-&gt;super.temp.fun, Q_EMPTY_SIG);
r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG);
s = me-&gt;super.temp.fun;
}
} while (r != Q_RET_IGNORED); // QHsm_top() state not reached
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, limit &gt; 0);
QF_CRIT_EXIT();
#ifndef Q_UNSAFE
me-&gt;super.temp.uint = ~me-&gt;super.state.uint;
@ -1325,15 +1331,23 @@ me-&gt;temp.uint = ~me-&gt;state.uint;
<parameter name="stateObj" type="QMState const * const"/>
<code>bool inState = false; // assume that this SM is not in 'state'
for (QMState const *s = me-&gt;super.state.obj;
s != (QMState *)0;
s = s-&gt;superstate)
{
if (s == stateObj) {
inState = true; // match found, return 'true'
QMState const *s = me-&gt;super.state.obj;
int_fast8_t limit = 6; // loop hard limit
for (; (s != (QMState *)0) &amp;&amp; (limit &gt; 0); --limit) {
if (s == stateObj) { // match found?
inState = true;
break;
}
else {
s = s-&gt;superstate; // advance to the superstate
}
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, limit &gt; 0);
QF_CRIT_EXIT();
return inState;</code>
</operation>
<!--${QEP::QMsm::stateObj}-->
@ -1378,7 +1392,7 @@ if (!isFound) { // still not found?
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(890, isFound);
Q_ENSURE_INCRIT(890, isFound);
QF_CRIT_EXIT();
return child; // return the child</code>
@ -3199,7 +3213,7 @@ QS_BEGIN_PRE_(QS_QF_TICK, 0U)
QS_END_PRE_()
// scan the linked-list of time events at this rate...
uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // iteration hard limit
uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // loop hard limit
for (; limit &gt; 0U; --limit) {
QTimeEvt *e = prev-&gt;next; // advance down the time evt. list

View File

@ -462,17 +462,23 @@ bool QHsm_isIn(QHsm * const me,
bool inState = false; // assume that this HSM is not in 'state'
// scan the state hierarchy bottom-up
QState r;
do {
// do the states match?
if (me->super.temp.fun == state) {
inState = true; // 'true' means that match found
r = Q_RET_IGNORED; // cause breaking out of the loop
QStateHandler s = me->super.state.fun;
int_fast8_t limit = QHSM_MAX_NEST_DEPTH_ + 1; // loop hard limit
QState r = Q_RET_SUPER;
for (; (r != Q_RET_IGNORED) && (limit > 0); --limit) {
if (s == state) { // do the states match?
inState = true; // 'true' means that match found
break; // break out of the for-loop
}
else {
r = QHSM_RESERVED_EVT_(me->super.temp.fun, Q_EMPTY_SIG);
r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG);
s = me->super.temp.fun;
}
} while (r != Q_RET_IGNORED); // QHsm_top() state not reached
}
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, limit > 0);
QF_CRIT_EXIT();
#ifndef Q_UNSAFE
me->super.temp.uint = ~me->super.state.uint;

View File

@ -366,15 +366,23 @@ bool QMsm_isInState(QMsm const * const me,
{
bool inState = false; // assume that this SM is not in 'state'
for (QMState const *s = me->super.state.obj;
s != (QMState *)0;
s = s->superstate)
{
if (s == stateObj) {
inState = true; // match found, return 'true'
QMState const *s = me->super.state.obj;
int_fast8_t limit = 6; // loop hard limit
for (; (s != (QMState *)0) && (limit > 0); --limit) {
if (s == stateObj) { // match found?
inState = true;
break;
}
else {
s = s->superstate; // advance to the superstate
}
}
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ENSURE_INCRIT(690, limit > 0);
QF_CRIT_EXIT();
return inState;
}
@ -410,7 +418,7 @@ QMState const * QMsm_childStateObj(QMsm const * const me,
QF_CRIT_STAT
QF_CRIT_ENTRY();
Q_ASSERT_INCRIT(890, isFound);
Q_ENSURE_INCRIT(890, isFound);
QF_CRIT_EXIT();
return child; // return the child

View File

@ -316,7 +316,7 @@ void QTimeEvt_tick_(
QS_END_PRE_()
// scan the linked-list of time events at this rate...
uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // iteration hard limit
uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // loop hard limit
for (; limit > 0U; --limit) {
QTimeEvt *e = prev->next; // advance down the time evt. list