QP/C  7.3.4
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qep_hsm.c
Go to the documentation of this file.
1//$file${src::qf::qep_hsm.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qf::qep_hsm.c}
5//
6// This code has been generated by QM 6.1.1 <www.state-machine.com/qm>.
7// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
8//
9// This code is covered by the following QP license:
10// License # : LicenseRef-QL-dual
11// Issued to : Any user of the QP/C real-time embedded framework
12// Framework(s) : qpc
13// Support ends : 2024-12-31
14// License scope:
15//
16// Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
17//
18// Q u a n t u m L e a P s
19// ------------------------
20// Modern Embedded Software
21//
22// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
23//
24// This software is dual-licensed under the terms of the open source GNU
25// General Public License version 3 (or any later version), or alternatively,
26// under the terms of one of the closed source Quantum Leaps commercial
27// licenses.
28//
29// The terms of the open source GNU General Public License version 3
30// can be found at: <www.gnu.org/licenses/gpl-3.0>
31//
32// The terms of the closed source Quantum Leaps commercial licenses
33// can be found at: <www.state-machine.com/licensing>
34//
35// Redistributions in source code must retain this top-level comment block.
36// Plagiarizing this software to sidestep the license obligations is illegal.
37//
38// Contact information:
39// <www.state-machine.com/licensing>
40// <info@state-machine.com>
41//
42//$endhead${src::qf::qep_hsm.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43#define QP_IMPL // this is QP implementation
44#include "qp_port.h" // QP port
45#include "qp_pkg.h" // QP package-scope interface
46#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
47#ifdef Q_SPY // QS software tracing enabled?
48 #include "qs_port.h" // QS port
49 #include "qs_pkg.h" // QS facilities for pre-defined trace records
50#else
51 #include "qs_dummy.h" // disable the QS software tracing
52#endif // Q_SPY
53
54Q_DEFINE_THIS_MODULE("qep_hsm")
55
56//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
57// Check for the minimum required QP version
58#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
59#error qpc version 7.3.0 or higher required
60#endif
61//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
62
63//$define${QEP::QP_versionStr[8]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
64
65//${QEP::QP_versionStr[8]} ...................................................
66char const QP_versionStr[8] = QP_VERSION_STR;
67//$enddef${QEP::QP_versionStr[8]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68
69//============================================================================
70//! @cond INTERNAL
71
72//$define${QEP::QEvt::reserved_[4]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
73QEvt const QEvt_reserved_[4] = {
78};
79
80//$enddef${QEP::QEvt::reserved_[4]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
81
82enum {
83 // maximum depth of state nesting in a QHsm (including the top level),
84 // must be >= 3
85 QHSM_MAX_NEST_DEPTH_ = 6
86};
87
88// helper macro to handle reserved event in an QHsm
89#define QHSM_RESERVED_EVT_(state_, sig_) \
90 ((*(state_))(me, &QEvt_reserved_[(sig_)]))
91
92// helper macro to trace state entry
93#define QS_STATE_ENTRY_(state_, qsId_) \
94 QS_CRIT_ENTRY(); \
95 QS_MEM_SYS(); \
96 QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, (qsId_)) \
97 QS_OBJ_PRE_(me); \
98 QS_FUN_PRE_(state_); \
99 QS_END_PRE_() \
100 QS_MEM_APP(); \
101 QS_CRIT_EXIT()
102
103// helper macro to trace state exit
104#define QS_STATE_EXIT_(state_, qsId_) \
105 QS_CRIT_ENTRY(); \
106 QS_MEM_SYS(); \
107 QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, (qsId_)) \
108 QS_OBJ_PRE_(me); \
109 QS_FUN_PRE_(state_); \
110 QS_END_PRE_() \
111 QS_MEM_APP(); \
112 QS_CRIT_EXIT()
113
114//! @endcond
115
116//$define${QEP::QHsm} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
117
118//${QEP::QHsm} ...............................................................
119
120//${QEP::QHsm::ctor} .........................................................
121//! @protected @memberof QHsm
122void QHsm_ctor(QHsm * const me,
123 QStateHandler const initial)
124{
125 static struct QAsmVtable const vtable = { // QAsm virtual table
126 &QHsm_init_,
127 &QHsm_dispatch_,
128 &QHsm_isIn_
129 #ifdef Q_SPY
130 ,&QHsm_getStateHandler_
131 #endif
132 };
133 // do not call the QAsm_ctor() here
134 me->super.vptr = &vtable;
135 me->super.state.fun = Q_STATE_CAST(&QHsm_top);
136 me->super.temp.fun = initial;
137}
138
139//${QEP::QHsm::init_} ........................................................
140//! @private @memberof QHsm
141void QHsm_init_(
142 QAsm * const me,
143 void const * const e,
144 uint_fast8_t const qsId)
145{
147
148 #ifdef Q_SPY
150 QS_MEM_SYS();
151 if ((QS_priv_.flags & 0x01U) == 0U) {
152 QS_priv_.flags |= 0x01U;
153 QS_MEM_APP();
154 QS_CRIT_EXIT();
155 QS_FUN_DICTIONARY(&QHsm_top);
156 }
157 else {
158 QS_MEM_APP();
159 QS_CRIT_EXIT();
160 }
161 #else
162 Q_UNUSED_PAR(qsId);
163 #endif
164
165 QStateHandler t = me->state.fun;
166
168 Q_REQUIRE_INCRIT(200, (me->vptr != (struct QAsmVtable *)0)
169 && (me->temp.fun != Q_STATE_CAST(0))
170 && (t == Q_STATE_CAST(&QHsm_top)));
171 QF_CRIT_EXIT();
172
173 // execute the top-most initial tran.
174 QState r = (*me->temp.fun)(me, Q_EVT_CAST(QEvt));
175
177 // the top-most initial tran. must be taken
178 Q_ASSERT_INCRIT(210, r == Q_RET_TRAN);
179
180 QS_MEM_SYS();
181 QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId)
182 QS_OBJ_PRE_(me); // this state machine object
183 QS_FUN_PRE_(t); // the source state
184 QS_FUN_PRE_(me->temp.fun); // the target of the initial tran.
185 QS_END_PRE_()
186 QS_MEM_APP();
187
188 QF_CRIT_EXIT();
189
190 // drill down into the state hierarchy with initial transitions...
191 int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit
192 do {
193 QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran entry path array
194 int_fast8_t ip = 0; // tran entry path index
195
196 path[0] = me->temp.fun;
197 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
198 while ((me->temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
199 ++ip;
200 path[ip] = me->temp.fun;
201 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
202 }
204 // The initial transition source state must be reached
205 // Too many state nesting levels or "malformed" HSM.
206 Q_ASSERT_INCRIT(220, me->temp.fun == t);
207 QF_CRIT_EXIT();
208
209 me->temp.fun = path[0];
210
211 // retrace the entry path in reverse (desired) order...
212 do {
213 // enter path[ip]
214 if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
215 == Q_RET_HANDLED)
216 {
217 QS_STATE_ENTRY_(path[ip], qsId);
218 }
219 --ip;
220 } while (ip >= 0);
221
222 t = path[0]; // current state becomes the new source
223
224 r = QHSM_RESERVED_EVT_(t, Q_INIT_SIG); // execute initial tran.
225
226 #ifdef Q_SPY
227 if (r == Q_RET_TRAN) {
229 QS_MEM_SYS();
230 QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId)
231 QS_OBJ_PRE_(me); // this state machine object
232 QS_FUN_PRE_(t); // the source state
233 QS_FUN_PRE_(me->temp.fun); // the target of the initial tran.
234 QS_END_PRE_()
235 QS_MEM_APP();
236 QS_CRIT_EXIT();
237 }
238 #endif // Q_SPY
239
240 --limit;
241 } while ((r == Q_RET_TRAN) && (limit > 0));
242
244 // Loop limit must not be reached.
245 // Too many state nesting levels or likely "malformed" HSM
246 Q_ENSURE_INCRIT(290, limit > 0);
247
248 QS_MEM_SYS();
249 QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId)
250 QS_TIME_PRE_(); // time stamp
251 QS_OBJ_PRE_(me); // this state machine object
252 QS_FUN_PRE_(t); // the new active state
253 QS_END_PRE_()
254 QS_MEM_APP();
255
256 QF_CRIT_EXIT();
257
258 me->state.fun = t; // change the current active state
259 #ifndef Q_UNSAFE
260 me->temp.uint = ~me->state.uint;
261 #endif
262}
263
264//${QEP::QHsm::dispatch_} ....................................................
265//! @private @memberof QHsm
266void QHsm_dispatch_(
267 QAsm * const me,
268 QEvt const * const e,
269 uint_fast8_t const qsId)
270{
271 #ifndef Q_SPY
272 Q_UNUSED_PAR(qsId);
273 #endif
274
275 QStateHandler s = me->state.fun;
276 QStateHandler t = s;
278
280 Q_REQUIRE_INCRIT(300, (s != Q_STATE_CAST(0))
281 && (me->state.uint == (uintptr_t)(~me->temp.uint)));
282 Q_REQUIRE_INCRIT(302, QEvt_verify_(e));
283
284 QS_MEM_SYS();
285 QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId)
286 QS_TIME_PRE_(); // time stamp
287 QS_SIG_PRE_(e->sig); // the signal of the event
288 QS_OBJ_PRE_(me); // this state machine object
289 QS_FUN_PRE_(s); // the current state
290 QS_END_PRE_()
291 QS_MEM_APP();
292
293 QF_CRIT_EXIT();
294
295 // process the event hierarchically...
296 QState r;
297 me->temp.fun = s;
298 int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit
299 do {
300 s = me->temp.fun;
301 r = (*s)(me, e); // invoke state handler s
302
303 if (r == Q_RET_UNHANDLED) { // unhandled due to a guard?
304
306 QS_MEM_SYS();
307 QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qsId)
308 QS_SIG_PRE_(e->sig); // the signal of the event
309 QS_OBJ_PRE_(me); // this state machine object
310 QS_FUN_PRE_(s); // the current state
311 QS_END_PRE_()
312 QS_MEM_APP();
313 QS_CRIT_EXIT();
314
315 r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s
316 }
317
318 --limit;
319 } while ((r == Q_RET_SUPER) && (limit > 0));
320
322 Q_ASSERT_INCRIT(310, limit > 0);
323 QF_CRIT_EXIT();
324
325 if (r >= Q_RET_TRAN) { // regular tran. taken?
326 QStateHandler path[QHSM_MAX_NEST_DEPTH_];
327
328 path[0] = me->temp.fun; // tran. target
329 path[1] = t; // current state
330 path[2] = s; // tran. source
331
332 // exit current state to tran. source s...
333 limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit
334 for (; (t != s) && (limit > 0); t = me->temp.fun) {
335 // exit from t
336 if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) {
337 QS_STATE_EXIT_(t, qsId);
338 // find superstate of t
339 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG);
340 }
341 --limit;
342 }
344 Q_ASSERT_INCRIT(320, limit > 0);
345 QF_CRIT_EXIT();
346
347 int_fast8_t ip = QHsm_tran_(me, path, qsId); // take the tran.
348
349 #ifdef Q_SPY
350 if (r == Q_RET_TRAN_HIST) {
352 QS_MEM_SYS();
353 QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qsId)
354 QS_OBJ_PRE_(me); // this state machine object
355 QS_FUN_PRE_(t); // the source of the tran.
356 QS_FUN_PRE_(path[0]); // the target of the tran. to history
357 QS_END_PRE_()
358 QS_MEM_APP();
359 QS_CRIT_EXIT();
360 }
361 #endif // Q_SPY
362
363 // execute state entry actions in the desired order...
364 for (; ip >= 0; --ip) {
365 // enter path[ip]
366 if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
367 == Q_RET_HANDLED)
368 {
369 QS_STATE_ENTRY_(path[ip], qsId);
370 }
371 }
372 t = path[0]; // stick the target into register
373 me->temp.fun = t; // update the next state
374
375 // drill into the target hierarchy...
376 while (QHSM_RESERVED_EVT_(t, Q_INIT_SIG) == Q_RET_TRAN) {
377
379 QS_MEM_SYS();
380 QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId)
381 QS_OBJ_PRE_(me); // this state machine object
382 QS_FUN_PRE_(t); // the source (pseudo)state
383 QS_FUN_PRE_(me->temp.fun); // the target of the tran.
384 QS_END_PRE_()
385 QS_MEM_APP();
386 QS_CRIT_EXIT();
387
388 ip = 0;
389 path[0] = me->temp.fun;
390
391 // find superstate
392 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
393
394 while ((me->temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) {
395 ++ip;
396 path[ip] = me->temp.fun;
397 // find superstate
398 (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
399 }
401 // The initial transition source state must be reached.
402 // Too many state nesting levels or "malformed" HSM.
403 Q_ASSERT_INCRIT(330, me->temp.fun == t);
404 QF_CRIT_EXIT();
405
406 me->temp.fun = path[0];
407
408 // retrace the entry path in reverse (correct) order...
409 do {
410 // enter path[ip]
411 if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG)
412 == Q_RET_HANDLED)
413 {
414 QS_STATE_ENTRY_(path[ip], qsId);
415 }
416 --ip;
417 } while (ip >= 0);
418
419 t = path[0]; // current state becomes the new source
420 }
421
423 QS_MEM_SYS();
424 QS_BEGIN_PRE_(QS_QEP_TRAN, qsId)
425 QS_TIME_PRE_(); // time stamp
426 QS_SIG_PRE_(e->sig); // the signal of the event
427 QS_OBJ_PRE_(me); // this state machine object
428 QS_FUN_PRE_(s); // the source of the tran.
429 QS_FUN_PRE_(t); // the new active state
430 QS_END_PRE_()
431 QS_MEM_APP();
432 QS_CRIT_EXIT();
433 }
434
435 #ifdef Q_SPY
436 else if (r == Q_RET_HANDLED) {
438 QS_MEM_SYS();
439 QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qsId)
440 QS_TIME_PRE_(); // time stamp
441 QS_SIG_PRE_(e->sig); // the signal of the event
442 QS_OBJ_PRE_(me); // this state machine object
443 QS_FUN_PRE_(s); // the source state
444 QS_END_PRE_()
445 QS_MEM_APP();
446 QS_CRIT_EXIT();
447 }
448 else {
450 QS_MEM_SYS();
451 QS_BEGIN_PRE_(QS_QEP_IGNORED, qsId)
452 QS_TIME_PRE_(); // time stamp
453 QS_SIG_PRE_(e->sig); // the signal of the event
454 QS_OBJ_PRE_(me); // this state machine object
455 QS_FUN_PRE_(me->state.fun); // the current state
456 QS_END_PRE_()
457 QS_MEM_APP();
458 QS_CRIT_EXIT();
459 }
460 #endif // Q_SPY
461
462 me->state.fun = t; // change the current active state
463 #ifndef Q_UNSAFE
464 me->temp.uint = ~me->state.uint;
465 #endif
466}
467
468//${QEP::QHsm::getStateHandler_} .............................................
469#ifdef Q_SPY
470//! @private @memberof QHsm
471QStateHandler QHsm_getStateHandler_(QAsm * const me) {
472 return me->state.fun;
473}
474#endif // def Q_SPY
475
476//${QEP::QHsm::isIn_} ........................................................
477//! @private @memberof QHsm
478bool QHsm_isIn_(
479 QAsm * const me,
480 QStateHandler const state)
481{
485 == (uintptr_t)(~me->temp.uint));
486 QF_CRIT_EXIT();
487
488 bool inState = false; // assume that this HSM is not in 'state'
489
490 // scan the state hierarchy bottom-up
491 QStateHandler s = me->state.fun;
492 int_fast8_t limit = QHSM_MAX_NEST_DEPTH_ + 1; // loop hard limit
494 for (; (r != Q_RET_IGNORED) && (limit > 0); --limit) {
495 if (s == state) { // do the states match?
496 inState = true; // 'true' means that match found
497 break; // break out of the for-loop
498 }
499 else {
500 r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG);
501 s = me->temp.fun;
502 }
503 }
504
506 Q_ENSURE_INCRIT(690, limit > 0);
507 QF_CRIT_EXIT();
508
509 #ifndef Q_UNSAFE
510 me->temp.uint = ~me->state.uint;
511 #endif
512
513 return inState; // return the status
514}
515
516//${QEP::QHsm::childState} ...................................................
517//! @public @memberof QHsm
518QStateHandler QHsm_childState(QHsm * const me,
519 QStateHandler const parent)
520{
521 QStateHandler child = me->super.state.fun; // start with current state
522 bool isFound = false; // start with the child not found
523
524 // establish stable state configuration
525 me->super.temp.fun = child;
526 QState r;
527 do {
528 // is this the parent of the current child?
529 if (me->super.temp.fun == parent) {
530 isFound = true; // child is found
531 r = Q_RET_IGNORED; // break out of the loop
532 }
533 else {
534 child = me->super.temp.fun;
535 r = QHSM_RESERVED_EVT_(me->super.temp.fun, Q_EMPTY_SIG);
536 }
537 } while (r != Q_RET_IGNORED); // the top state not reached
538
539 #ifndef Q_UNSAFE
540 me->super.temp.uint = ~me->super.state.uint;
541 #endif
542
545 Q_ASSERT_INCRIT(890, isFound);
546 QF_CRIT_EXIT();
547
548 return child; // return the child
549}
550
551//${QEP::QHsm::tran_} ........................................................
552//! @private @memberof QHsm
553int_fast8_t QHsm_tran_(
554 QAsm * const me,
555 QStateHandler * const path,
556 uint_fast8_t const qsId)
557{
558 #ifndef Q_SPY
559 Q_UNUSED_PAR(qsId);
560 #endif
561
562 int_fast8_t ip = -1; // tran. entry path index
563 QStateHandler t = path[0];
564 QStateHandler const s = path[2];
566
567 // (a) check source==target (tran. to self)...
568 if (s == t) {
569 // exit source s
570 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
571 QS_STATE_EXIT_(s, qsId);
572 }
573 ip = 0; // enter the target
574 }
575 else {
576 // find superstate of target
577 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG);
578
579 t = me->temp.fun;
580
581 // (b) check source==target->super...
582 if (s == t) {
583 ip = 0; // enter the target
584 }
585 else {
586 // find superstate of src
587 (void)QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG);
588
589 // (c) check source->super==target->super...
590 if (me->temp.fun == t) {
591 // exit source s
592 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
593 QS_STATE_EXIT_(s, qsId);
594 }
595 ip = 0; // enter the target
596 }
597 else {
598 // (d) check source->super==target...
599 if (me->temp.fun == path[0]) {
600 // exit source s
601 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) {
602 QS_STATE_EXIT_(s, qsId);
603 }
604 }
605 else {
606 // (e) check rest of source==target->super->super..
607 // and store the entry path along the way
608 int_fast8_t iq = 0; // indicate that LCA was found
609 ip = 1; // enter target and its superstate
610 path[1] = t; // save the superstate of target
611 t = me->temp.fun; // save source->super
612
613 // find target->super->super...
614 QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG);
615 while ((r == Q_RET_SUPER)
616 && (ip < (QHSM_MAX_NEST_DEPTH_ - 1)))
617 {
618 ++ip;
619 path[ip] = me->temp.fun; // store the entry path
620 if (me->temp.fun == s) { // is it the source?
621 iq = 1; // indicate that the LCA found
622 --ip; // do not enter the source
623 r = Q_RET_HANDLED; // terminate the loop
624 }
625 else { // it is not the source, keep going up
626 r = QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG);
627 }
628 }
630 // Tran. source must be found within the nesting depth
631 // Too many state nesting levels or "malformed" HSM.
632 Q_ASSERT_INCRIT(510, r != Q_RET_SUPER);
633 QF_CRIT_EXIT();
634
635 // the LCA not found yet?
636 if (iq == 0) {
637 // exit source s
638 if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG)
639 == Q_RET_HANDLED)
640 {
641 QS_STATE_EXIT_(s, qsId);
642 }
643
644 // (f) check the rest of source->super
645 // == target->super->super...
646 iq = ip;
647 r = Q_RET_IGNORED; // indicate that the LCA NOT found
648 do {
649 if (t == path[iq]) { // is this the LCA?
650 r = Q_RET_HANDLED; // indicate the LCA found
651 ip = iq - 1; // do not enter the LCA
652 iq = -1; // cause termination of the loop
653 }
654 else {
655 --iq; // try lower superstate of target
656 }
657 } while (iq >= 0);
658
659 // the LCA not found yet?
660 if (r != Q_RET_HANDLED) {
661 // (g) check each source->super->...
662 // for each target->super...
663 r = Q_RET_IGNORED; // keep looping
664 int_fast8_t limit = QHSM_MAX_NEST_DEPTH_;
665 do {
666 // exit from t
667 if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG)
668 == Q_RET_HANDLED)
669 {
670 QS_STATE_EXIT_(t, qsId);
671 // find superstate of t
672 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG);
673 }
674 t = me->temp.fun; // set to super of t
675 iq = ip;
676 do {
677 // is this the LCA?
678 if (t == path[iq]) {
679 ip = iq - 1; // do not enter the LCA
680 iq = -1; // break out of inner loop
681 r = Q_RET_HANDLED; // break outer loop
682 }
683 else {
684 --iq;
685 }
686 } while (iq >= 0);
687
688 --limit;
689 } while ((r != Q_RET_HANDLED) && (limit > 0));
691 Q_ASSERT_INCRIT(530, limit > 0);
692 QF_CRIT_EXIT();
693 }
694 }
695 }
696 }
697 }
698 }
700 Q_ENSURE_INCRIT(590, ip < QHSM_MAX_NEST_DEPTH_);
701 QF_CRIT_EXIT();
702 return ip;
703}
704
705//${QEP::QHsm::top} ..........................................................
706//! @protected @memberof QAsm
707QState QHsm_top(QHsm const * const me,
708 QEvt const * const e)
709{
710 Q_UNUSED_PAR(me);
711 Q_UNUSED_PAR(e);
712 return Q_RET_IGNORED; // the top state ignores all events
713}
714//$enddef${QEP::QHsm} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ Q_RET_HANDLED
event handled (internal transition)
Definition qp.h:202
@ Q_RET_IGNORED
event silently ignored (bubbled up to top)
Definition qp.h:203
@ Q_RET_TRAN
regular transition
Definition qp.h:213
@ Q_RET_UNHANDLED
event unhandled due to a guard
Definition qp.h:199
@ Q_RET_SUPER
event passed to superstate to handle
Definition qp.h:197
@ Q_RET_TRAN_HIST
transition to history of a given state
Definition qp.h:218
QEvt const QEvt_reserved_[4]
#define Q_UNUSED_PAR(par_)
Definition qp.h:532
QState(* QStateHandler)(void *const me, QEvt const *const e)
Definition qp.h:226
#define QP_VERSION_STR
Definition qp.h:48
char const QP_versionStr[8]
the current QP version number string in ROM, based on QP_VERSION_STR
#define Q_STATE_CAST(handler_)
Definition qp.h:526
#define Q_EVT_CAST(class_)
Definition qp.h:523
@ Q_INIT_SIG
signal for coding initial transitions
Definition qp.h:259
@ Q_EMPTY_SIG
signal to execute the default case
Definition qp.h:256
@ Q_EXIT_SIG
signal for coding exit actions
Definition qp.h:258
@ Q_ENTRY_SIG
signal for coding entry actions
Definition qp.h:257
#define QEVT_INITIALIZER(sig_)
Definition qp.h:455
enum QStateRet QState
Definition qp.h:223
Internal (package scope) QP/C interface.
Sample QP/C port.
@ QS_QEP_STATE_INIT
an initial transition was taken in a state
Definition qs.h:84
@ QS_QEP_TRAN_HIST
a tran to history was taken
Definition qs.h:162
#define QS_TIME_PRE_()
Definition qs.h:450
#define QS_FUN_DICTIONARY(fun_)
Definition qs.h:517
@ QS_QEP_INIT_TRAN
the top-most initial transition was taken
Definition qs.h:85
#define QS_MEM_APP()
Definition qs.h:588
@ QS_QEP_INTERN_TRAN
an internal transition was taken
Definition qs.h:86
@ QS_QEP_UNHANDLED
an event was un-handled due to a guard
Definition qs.h:90
@ QS_QEP_TRAN
a regular transition was taken
Definition qs.h:87
@ QS_QEP_DISPATCH
an event was dispatched (begin of RTC step)
Definition qs.h:89
@ QS_QEP_IGNORED
an event was ignored (silently discarded)
Definition qs.h:88
#define QS_CRIT_EXIT()
Definition qs.h:578
#define QS_MEM_SYS()
Definition qs.h:583
#define QS_CRIT_ENTRY()
Definition qs.h:573
QS/C package-scope interface.
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem.
#define QF_CRIT_ENTRY()
Definition qsafe.h:58
#define Q_ASSERT_INCRIT(id_, expr_)
Definition qsafe.h:72
#define Q_ENSURE_INCRIT(id_, expr_)
Definition qsafe.h:145
#define QF_CRIT_EXIT()
Definition qsafe.h:62
#define Q_REQUIRE_INCRIT(id_, expr_)
Definition qsafe.h:136
#define QF_CRIT_STAT
Definition qsafe.h:54
Abstract State Machine class (state machine interface)
Definition qp.h:277
struct QAsmVtable const * vptr
Definition qp.h:281
union QAsmAttr temp
Definition qp.h:289
union QAsmAttr state
Definition qp.h:286
Virtual table for the QAsm class.
Definition qp.h:298
Event class.
Definition qp.h:147
QSignal sig
Definition qp.h:151
Hierarchical State Machine class (QHsm-style state machine implementation strategy)
Definition qp.h:313
QAsm super
Definition qp.h:315
uintptr_t uint
Definition qp.h:271
QStateHandler fun
Definition qp.h:265