QP/C  8.0.2
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qep_hsm.c
Go to the documentation of this file.
1//============================================================================
2// QP/C Real-Time Embedded Framework (RTEF)
3// Version 8.0.2
4//
5// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
6//
7// Q u a n t u m L e a P s
8// ------------------------
9// Modern Embedded Software
10//
11// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
12//
13// This software is dual-licensed under the terms of the open-source GNU
14// General Public License (GPL) or under the terms of one of the closed-
15// source Quantum Leaps commercial licenses.
16//
17// Redistributions in source code must retain this top-level comment block.
18// Plagiarizing this software to sidestep the license obligations is illegal.
19//
20// NOTE:
21// The GPL does NOT permit the incorporation of this code into proprietary
22// programs. Please contact Quantum Leaps for commercial licensing options,
23// which expressly supersede the GPL and are designed explicitly for
24// closed-source distribution.
25//
26// Quantum Leaps contact information:
27// <www.state-machine.com/licensing>
28// <info@state-machine.com>
29//============================================================================
30#define QP_IMPL // this is QP implementation
31#include "qp_port.h" // QP port
32#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
33#ifdef Q_SPY // QS software tracing enabled?
34 #include "qs_port.h" // QS port
35 #include "qs_pkg.h" // QS facilities for pre-defined trace records
36#else
37 #include "qs_dummy.h" // disable the QS software tracing
38#endif // Q_SPY
39
40Q_DEFINE_THIS_MODULE("qep_hsm")
41
42// maximum depth of state nesting in a QHsm (including the top level),
43// must be >= 3
44#define QHSM_MAX_NEST_DEPTH_ 6
45
46static QEvt const l_reservedEvt_[4] = {
51};
52
53//============================================================================
54//! @cond INTERNAL
55
56// internal helper macro to pass a reserved event into the state handler
57#define QHSM_RESERVED_EVT_(state_, sig_) \
58 ((*(state_))(me, &l_reservedEvt_[(sig_)]))
59
60#ifdef Q_SPY
61// helper macro to trace state action (entry/exit)
62#define QS_STATE_ACT_(rec_, state_) \
63 QS_CRIT_ENTRY(); \
64 QS_BEGIN_PRE((rec_), qsId) \
65 QS_OBJ_PRE(me); \
66 QS_FUN_PRE(state_); \
67 QS_END_PRE() \
68 QS_CRIT_EXIT()
69
70// internal helper macro to top-most init
71#define QS_TOP_INIT_(rec_, trg_) \
72 QS_CRIT_ENTRY(); \
73 QS_BEGIN_PRE((rec_), qsId) \
74 QS_TIME_PRE(); \
75 QS_OBJ_PRE(me); \
76 QS_FUN_PRE(trg_); \
77 QS_END_PRE() \
78 QS_CRIT_EXIT()
79
80// internal helper macro to trace transition segment
81#define QS_TRAN_SEG_(rec_, src_, trg_) \
82 QS_CRIT_ENTRY(); \
83 QS_BEGIN_PRE((rec_), qsId) \
84 QS_OBJ_PRE(me); \
85 QS_FUN_PRE(src_); \
86 QS_FUN_PRE(trg_); \
87 QS_END_PRE() \
88 QS_CRIT_EXIT()
89
90// internal helper macro to trace transition action
91#define QS_TRAN_ACT_(rec_, state_) \
92 QS_CRIT_ENTRY(); \
93 QS_BEGIN_PRE((rec_), qsId) \
94 QS_SIG_PRE(e->sig); \
95 QS_OBJ_PRE(me); \
96 QS_FUN_PRE(state_); \
97 QS_END_PRE() \
98 QS_CRIT_EXIT()
99
100// internal helper macro to trace transition begin/end
101#define QS_TRAN0_(rec_, trg_) \
102 QS_CRIT_ENTRY(); \
103 QS_BEGIN_PRE((rec_), qsId) \
104 QS_TIME_PRE(); \
105 QS_SIG_PRE(e->sig); \
106 QS_OBJ_PRE(me); \
107 QS_FUN_PRE(trg_); \
108 QS_END_PRE() \
109 QS_CRIT_EXIT()
110
111// internal helper macro to trace regulsr transition
112#define QS_TRAN_END_(rec_, src_, trg_) \
113 QS_CRIT_ENTRY(); \
114 QS_BEGIN_PRE((rec_), qsId) \
115 QS_TIME_PRE(); \
116 QS_SIG_PRE(e->sig); \
117 QS_OBJ_PRE(me); \
118 QS_FUN_PRE(src_); \
119 QS_FUN_PRE(trg_); \
120 QS_END_PRE() \
121 QS_CRIT_EXIT()
122
123#else
124#define QS_STATE_ACT_(rec_, state_) ((void)0)
125#define QS_TOP_INIT_(rec_, trg_) ((void)0)
126#define QS_TRAN_SEG_(rec_, src_, trg_) ((void)0)
127#define QS_TRAN_ACT_(rec_, state_) ((void)0)
128#define QS_TRAN0_(rec_, trg_) ((void)0)
129#define QS_TRAN_END_(rec_, src_, trg_) ((void)0)
130#endif
131
132//! @endcond
133
134//! @private @memberof QHsm
135static int_fast8_t QHsm_tran_simple_(
136 QAsm * const me,
137 QStateHandler * const path,
138 uint_fast8_t const qsId);
139
140//! @private @memberof QHsm
141static int_fast8_t QHsm_tran_complex_(
142 QAsm * const me,
143 QStateHandler * const path,
144 uint_fast8_t const qsId);
145
146//! @private @memberof QHsm
147static void QHsm_enter_target_(
148 QAsm * const me,
149 QStateHandler * const path,
150 int_fast8_t const depth,
151 uint_fast8_t const qsId);
152
153//............................................................................
154//! @protected @memberof QHsm
155void QHsm_ctor(QHsm * const me,
156 QStateHandler const initial)
157{
158 static struct QAsmVtable const vtable = { // QAsm virtual table
159 &QHsm_init_,
162#ifdef Q_SPY
164#endif
165 };
166 // do not call the QAsm_ctor() here
167 me->super.vptr = &vtable;
169 me->super.temp.fun = initial;
170}
171
172//............................................................................
173//! @private @memberof QHsm
175 QAsm * const me,
176 void const * const e,
177 uint_fast8_t const qsId)
178{
180
181 // produce QS dictionary for QHsm_top()
182#ifdef Q_SPY
184 bool isDone = true;
185 if ((QS_priv_.flags & 0x01U) == 0U) {
186 QS_priv_.flags |= 0x01U;
187 isDone = false;
188 }
189 QS_CRIT_EXIT();
190 if (!isDone) {
192 }
193#else
194 Q_UNUSED_PAR(qsId);
195#endif // def Q_SPY
196
197 QStateHandler t = me->state.fun;
198
200 Q_REQUIRE_INCRIT(200, (me->vptr != (struct QAsmVtable *)0)
201 && (me->temp.fun != Q_STATE_CAST(0))
202 && (t == Q_STATE_CAST(&QHsm_top)));
203 QF_CRIT_EXIT();
204
205 // execute the top-most initial tran.
206 QState const r = (*me->temp.fun)(me, Q_EVT_CAST(QEvt));
207
209 // the top-most initial tran. must be taken
210 Q_ASSERT_INCRIT(210, r == Q_RET_TRAN);
211 QF_CRIT_EXIT();
212
213 QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, me->temp.fun);
214
215 // drill down into the state hierarchy with initial transitions...
216 QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran. entry path array
217 path[0] = me->temp.fun;
218 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
219
220 int_fast8_t ip = 1; // tran. entry path index (also the loop bound)
221 for (; (me->temp.fun != t) && (ip < QHSM_MAX_NEST_DEPTH_); ++ip) {
222 path[ip] = me->temp.fun;
223 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
224 }
226 // must NOT be too many state nesting levels or "malformed" HSM
228 QF_CRIT_EXIT();
229
230 me->temp.fun = path[0];
231 QHsm_enter_target_(me, &path[0], ip - 1, qsId);
232 t = path[0];
233
234 QS_TOP_INIT_(QS_QEP_INIT_TRAN, t);
235
236 me->state.fun = t; // change the current active state
237#ifdef Q_UNSAFE
238 Q_UNUSED_PAR(r);
239#endif
240}
241
242//............................................................................
243//! @private @memberof QHsm
245 QAsm * const me,
246 QEvt const * const e,
247 uint_fast8_t const qsId)
248{
249#ifndef Q_SPY
250 Q_UNUSED_PAR(qsId);
251#endif
252
253 QStateHandler s = me->state.fun;
254 QStateHandler t = s;
256
259 (e != (QEvt *)0)
260 && (s != Q_STATE_CAST(0)));
261 QF_CRIT_EXIT();
262
263 QS_TRAN0_(QS_QEP_DISPATCH, s);
264
266
267 // process the event hierarchically...
268 me->temp.fun = s;
269 int_fast8_t ip = QHSM_MAX_NEST_DEPTH_;
270 // NOTE: ip is the fixed loop upper bound
271 for (; ip > 0; --ip) {
272 s = me->temp.fun;
273 r = (*s)(me, e); // invoke state handler s
274
275 if (r == Q_RET_UNHANDLED) { // unhandled due to a guard?
276 QS_TRAN_ACT_(QS_QEP_UNHANDLED, s);
277 r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s
278 }
279 if (r != Q_RET_SUPER) { // event NOT "bubbled up"
280 break;
281 }
282 }
284 Q_ASSERT_INCRIT(310, ip > 0);
285 QF_CRIT_EXIT();
286
287 if (r >= Q_RET_TRAN) { // tran. (regular or history) taken?
288#ifdef Q_SPY
289 if (r == Q_RET_TRAN_HIST) { // tran. to history?
290 QS_TRAN_SEG_(QS_QEP_TRAN_HIST, s, me->temp.fun);
291 }
292#endif // Q_SPY
293
295 path[0] = me->temp.fun; // tran. target
296 path[1] = t; // current state
297 path[2] = s; // tran. source
298
299 // exit current state to tran. source s...
300 while (t != s) {
301 // exit from t
302 if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {
303 QS_STATE_ACT_(QS_QEP_STATE_EXIT, t);
304 // find superstate of t
305 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG);
306 }
307 t = me->temp.fun;
308 }
309
310 // take the tran...
311 ip = QHsm_tran_simple_(me, &path[0], qsId);
312 if (ip < -1) { // not a simple tran.?
313 ip = QHsm_tran_complex_(me, &path[0], qsId);
314 }
315
316 QHsm_enter_target_(me, &path[0], ip, qsId);
317 t = path[0];
318 QS_TRAN_END_(QS_QEP_TRAN, s, t);
319 }
320#ifdef Q_SPY
321 else if (r == Q_RET_HANDLED) {
322 QS_TRAN0_(QS_QEP_INTERN_TRAN, s);
323 }
324 else {
325 QS_TRAN0_(QS_QEP_IGNORED, me->state.fun);
326 }
327#endif // Q_SPY
328
329 me->state.fun = t; // change the current active state
330}
331
332//............................................................................
333//! @private @memberof QHsm
335 QAsm * const me,
336 QStateHandler const state)
337{
338 bool inState = false; // assume that this HSM is not in 'state'
339
340 // scan the state hierarchy bottom-up
341 QStateHandler s = me->state.fun;
343 while (r != Q_RET_IGNORED) {
344 if (s == state) { // do the states match?
345 inState = true; // 'true' means that match found
346 break; // break out of the for-loop
347 }
348 r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG);
349 s = me->temp.fun;
350 }
351 return inState; // return the status
352}
353
354//............................................................................
355#ifdef Q_SPY
356//! @private @memberof QHsm
358 return me->state.fun;
359}
360#endif // def Q_SPY
361
362//............................................................................
363//! @protected @memberof QHsm
364QState QHsm_top(QHsm const * const me,
365 QEvt const * const e)
366{
367 Q_UNUSED_PAR(me);
368 Q_UNUSED_PAR(e);
369 return Q_RET_IGNORED; // the top state ignores all events
370}
371
372//............................................................................
373//! @public @memberof QHsm
375 QStateHandler const parent)
376{
377#ifndef Q_UNSAFE
378 bool isFound = false; // assume the child state NOT found
379#endif
380
381 QStateHandler child = me->super.state.fun; // start with current state
382 me->super.temp.fun = child; // establish stable state configuration
384 while (r != Q_RET_IGNORED) {
385 // have the parent of the current child?
386 if (me->super.temp.fun == parent) {
387#ifndef Q_UNSAFE
388 isFound = true; // indicate that child state was found
389#endif
390 break;
391 }
392 child = me->super.temp.fun;
393 r = QHSM_RESERVED_EVT_(child, Q_EMPTY_SIG);
394 }
397 Q_ASSERT_INCRIT(590, isFound);
398 QF_CRIT_EXIT();
399
400 return child;
401}
402
403//............................................................................
404//! @private @memberof QHsm
405static int_fast8_t QHsm_tran_simple_(
406 QAsm * const me,
407 QStateHandler * const path,
408 uint_fast8_t const qsId)
409{
410#ifndef Q_SPY
411 Q_UNUSED_PAR(qsId);
412#endif
413
414 QStateHandler t = path[0];
415 QStateHandler const s = path[2];
416 int_fast8_t ip = 0; // tran. entry path index
418
419 // (a) check source==target (tran. to self)...
420 if (s == t) {
421 // exit source s
422 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
423 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
424 }
425 ip = 0; // enter the target
426 }
427 else {
428 // find superstate of target
429 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG);
430
431 t = me->temp.fun;
432
433 // (b) check source==target->super...
434 if (s == t) {
435 ip = 0; // enter the target
436 }
437 else {
438 // find superstate of src
439 (void)QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG);
440
441 // (c) check source->super==target->super...
442 if (me->temp.fun == t) {
443 // exit source s
444 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
445 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
446 }
447 ip = 0; // enter the target
448 }
449 // (d) check source->super==target...
450 else if (me->temp.fun == path[0]) {
451 // exit source s
452 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
453 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
454 }
455 ip = -1; // do not enter the target
456 }
457 else {
458 path[1] = t; // save the superstate of target
459 ip = -2; // cause execution of complex tran.
460 }
461 }
462 }
463 return ip;
464}
465
466//............................................................................
467//! @private @memberof QHsm
468static int_fast8_t QHsm_tran_complex_(
469 QAsm * const me,
470 QStateHandler * const path,
471 uint_fast8_t const qsId)
472{
473#ifndef Q_SPY
474 Q_UNUSED_PAR(qsId);
475#endif
476
477 // (e) check rest of source==target->super->super..
478 // and store the entry path along the way
479 int_fast8_t iq = 0; // indicate that LCA was found
480 int_fast8_t ip = 1; // enter target and its superstate
481 QStateHandler const s = path[2]; // source state
482 QStateHandler t = me->temp.fun; // source->super
484
485 // find target->super->super...
486 // note: ip is the fixed upper loop bound
487 QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG);
488 while ((r == Q_RET_SUPER) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
489 ++ip;
490 path[ip] = me->temp.fun; // store the entry path
491 if (me->temp.fun == s) { // is it the source?
492 iq = 1; // indicate that the LCA found
493 --ip; // do not enter the source
494 break; // terminate the loop
495 }
496 r = QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
497 }
500 QF_CRIT_EXIT();
501
502 // the LCA not found yet?
503 if (iq == 0) {
504
505 // exit source s
506#ifndef Q_SPY
507 (void)QHSM_RESERVED_EVT_(s, Q_EXIT_SIG);
508#else
509 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
510 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
511 }
512#endif // def Q_SPY
513
514 // (f) check the rest of
515 // source->super == target->super->super...
516 iq = ip;
517 r = Q_RET_IGNORED; // indicate that the LCA NOT found
518 // note: iq is the fixed upper loop bound
519 do {
520 if (t == path[iq]) { // is this the LCA?
521 r = Q_RET_HANDLED; // indicate the LCA found
522 ip = iq - 1; // do not enter the LCA
523 break; // terminate the loop
524 }
525 --iq; // try lower superstate of target
526 } while (iq >= 0);
527
528 if (r != Q_RET_HANDLED) { // the LCA still not found?
529 // (g) check each source->super->...
530 // for each target->super...
531 r = Q_RET_SUPER; // keep looping
532 while (r != Q_RET_HANDLED) {
533 // exit from t
534 if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {
535 QS_STATE_ACT_(QS_QEP_STATE_EXIT, t);
536 // find superstate of t
537 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG);
538 }
539 t = me->temp.fun; // set to super of t
540 iq = ip;
541 do {
542 if (t == path[iq]) { // is this the LCA?
543 ip = iq - 1; // do not enter the LCA
544 r = Q_RET_HANDLED; // break outer loop
545 break; // terminate the inner loop
546 }
547 --iq; // try lower superstate of target
548 } while (iq >= 0);
549 }
550 }
551 }
552 return ip;
553}
554
555//............................................................................
556//! @private @memberof QHsm
558 QAsm * const me,
559 QStateHandler * const path,
560 int_fast8_t const depth,
561 uint_fast8_t const qsId)
562{
563#ifndef Q_SPY
564 Q_UNUSED_PAR(qsId);
565#endif
566
568
571 QF_CRIT_EXIT();
572
573 int_fast8_t ip = depth;
574 // execute state entry actions in the desired order...
575 // NOTE: ip is the fixed upper loop bound
576 for (; ip >= 0; --ip) {
577 // enter path[ip]
578 if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
579 == Q_RET_HANDLED)
580 {
581 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]);
582 }
583 }
584 QStateHandler t = path[0];
585 me->temp.fun = t; // update the next state
586
587 // drill into the target hierarchy...
588 while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) {
589
590 QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, me->temp.fun);
591
592 ip = 0;
593 path[0] = me->temp.fun;
594
595 // find superstate
596 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
597
598 // note: ip is the fixed upper loop bound
599 while ((me->temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
600 ++ip;
601 path[ip] = me->temp.fun;
602 // find superstate
603 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
604 }
606 // too many state nesting levels or "malformed" HSM
608 QF_CRIT_EXIT();
609
610 me->temp.fun = path[0];
611
612 // retrace the entry path in reverse (correct) order...
613 // note: ip is the fixed upper loop bound
614 do {
615 // enter path[ip]
616 if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) == Q_RET_HANDLED) {
617 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]);
618 }
619 --ip;
620 } while (ip >= 0);
621
622 t = path[0]; // current state becomes the new source
623 }
624}
#define QHSM_MAX_NEST_DEPTH_
#define Q_RET_UNHANDLED
Definition qp.h:190
#define Q_RET_IGNORED
Definition qp.h:194
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.h:97
#define Q_RET_TRAN_HIST
Definition qp.h:208
#define Q_RET_TRAN
Definition qp.h:204
#define Q_STATE_CAST(handler_)
Perform cast to QStateHandler.
Definition qp.h:175
#define Q_EXIT_SIG
reserved signal sent to state handler to execute the exit case)
Definition qp.h:213
QState(* QStateHandler)(void *const me, QEvt const *const e)
Pointer to a state-handler function.
Definition qp.h:148
#define Q_EVT_CAST(class_)
Perform downcast of an event onto a subclass of QEvt class_
Definition qp.h:142
#define Q_ENTRY_SIG
reserved signal sent to state handler to execute the entry case)
Definition qp.h:212
#define Q_INIT_SIG
reserved signal sent to state handler to execute the initial transition)
Definition qp.h:214
#define Q_EMPTY_SIG
reserved signal sent to state handler to execute the default case)
Definition qp.h:211
#define QEVT_INITIALIZER(sig_)
Initializer for immutable (constant) QEvt instances.
Definition qp.h:121
uint_fast8_t QState
Type returned from state-handler functions.
Definition qp.h:147
#define Q_RET_SUPER
Definition qp.h:189
#define Q_RET_HANDLED
Definition qp.h:193
Sample QP/C port.
#define QF_CRIT_ENTRY()
Definition qp_port.h:64
#define QF_CRIT_EXIT()
Definition qp_port.h:72
#define QF_CRIT_STAT
Definition qp_port.h:55
#define QS_CRIT_STAT
Definition qs_dummy.h:157
#define QS_FUN_DICTIONARY(fun_)
Definition qs_dummy.h:72
#define QS_CRIT_EXIT()
Definition qs_dummy.h:159
#define QS_CRIT_ENTRY()
Definition qs_dummy.h:158
Sample QS/C port.
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:50
#define Q_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:93
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:87
Abstract State Machine class (state machine interface)
Definition qp.h:181
struct QAsmVtable const * vptr
Virtual pointer inherited by all QAsm subclasses (see also Object Orientation)
Definition qp.h:182
union QAsmAttr state
Current state (pointer to the current state-handler function)
Definition qp.h:183
union QAsmAttr temp
Temporary storage for target/act-table etc.
Definition qp.h:184
Virtual table for the QAsm class.
Definition qp.h:224
Event class.
Definition qp.h:115
Hierarchical State Machine class (QHsm-style state machine implementation strategy)
Definition qp.h:254
QAsm super
Definition qp.h:255
QState QHsm_top(QHsm const *const me, QEvt const *const e)
Definition qep_hsm.c:364
static void QHsm_enter_target_(QAsm *const me, QStateHandler *const path, int_fast8_t const depth, uint_fast8_t const qsId)
Definition qep_hsm.c:557
static int_fast8_t QHsm_tran_simple_(QAsm *const me, QStateHandler *const path, uint_fast8_t const qsId)
Definition qep_hsm.c:405
QStateHandler QHsm_getStateHandler_(QAsm *const me)
Definition qep_hsm.c:357
void QHsm_ctor(QHsm *const me, QStateHandler const initial)
Definition qep_hsm.c:155
void QHsm_dispatch_(QAsm *const me, QEvt const *const e, uint_fast8_t const qsId)
Definition qep_hsm.c:244
bool QHsm_isIn_(QAsm *const me, QStateHandler const state)
Definition qep_hsm.c:334
void QHsm_init_(QAsm *const me, void const *const e, uint_fast8_t const qsId)
Definition qep_hsm.c:174
static int_fast8_t QHsm_tran_complex_(QAsm *const me, QStateHandler *const path, uint_fast8_t const qsId)
Definition qep_hsm.c:468
QStateHandler QHsm_childState(QHsm *const me, QStateHandler const parent)
Definition qep_hsm.c:374
QStateHandler fun
Definition qp.h:168