QP/C++ 8.1.1
Real-Time Event Framework
Loading...
Searching...
No Matches
qep_hsm.cpp
Go to the documentation of this file.
1//============================================================================
2// QP/C++ Real-Time Event Framework (RTEF)
3//
4// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
5//
6// Q u a n t u m L e a P s
7// ------------------------
8// Modern Embedded Software
9//
10// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
11//
12// This software is dual-licensed under the terms of the open-source GNU
13// General Public License (GPL) or under the terms of one of the closed-
14// source Quantum Leaps commercial licenses.
15//
16// Redistributions in source code must retain this top-level comment block.
17// Plagiarizing this software to sidestep the license obligations is illegal.
18//
19// NOTE:
20// The GPL does NOT permit the incorporation of this code into proprietary
21// programs. Please contact Quantum Leaps for commercial licensing options,
22// which expressly supersede the GPL and are designed explicitly for
23// closed-source distribution.
24//
25// Quantum Leaps contact information:
26// <www.state-machine.com/licensing>
27// <info@state-machine.com>
28//============================================================================
29#define QP_IMPL // this is QP implementation
30#include "qp_port.hpp" // QP port
31#include "qp_pkg.hpp" // QP package-scope interface
32#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
33#ifdef Q_SPY // QS software tracing enabled?
34 #include "qs_port.hpp" // QS port
35 #include "qs_pkg.hpp" // QS facilities for pre-defined trace records
36#else
37 #include "qs_dummy.hpp" // disable the QS software tracing
38#endif // Q_SPY
39
40// unnamed namespace for local definitions with internal linkage
41namespace {
42
43Q_DEFINE_THIS_MODULE("qep_hsm")
44
45// maximum depth of state nesting in a QHsm (including the top level)
46// must be >= 3
47static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6};
48
49//! @cond INTERNAL
50
51// array of immutable events corresponding to the reserved signals
52static constexpr std::array<QP::QEvt, 4> l_resEvt_ {
57};
58
59//! @endcond
60
61} // unnamed namespace
62
63//============================================================================
64//! @cond INTERNAL
65
66// internal helper macro to pass a reserved event into the state handler
67
68#ifdef Q_SPY
69// helper macro to trace state action (entry/exit)
70#define QS_STATE_ACT_(rec_, state_) \
71 QS_CRIT_ENTRY(); \
72 QS_BEGIN_PRE((rec_), qsId) \
73 QS_OBJ_PRE(this); \
74 QS_FUN_PRE(state_); \
75 QS_END_PRE() \
76 QS_CRIT_EXIT()
77
78// internal helper macro to top-most init
79#define QS_TOP_INIT_(rec_, trg_) \
80 QS_CRIT_ENTRY(); \
81 QS_BEGIN_PRE((rec_), qsId) \
82 QS_TIME_PRE(); \
83 QS_OBJ_PRE(this); \
84 QS_FUN_PRE(trg_); \
85 QS_END_PRE() \
86 QS_CRIT_EXIT()
87
88// internal helper macro to trace transition segment
89#define QS_TRAN_SEG_(rec_, src_, trg_) \
90 QS_CRIT_ENTRY(); \
91 QS_BEGIN_PRE((rec_), qsId) \
92 QS_OBJ_PRE(this); \
93 QS_FUN_PRE(src_); \
94 QS_FUN_PRE(trg_); \
95 QS_END_PRE() \
96 QS_CRIT_EXIT()
97
98// internal helper macro to trace transition action
99#define QS_TRAN_ACT_(rec_, state_) \
100 QS_CRIT_ENTRY(); \
101 QS_BEGIN_PRE((rec_), qsId) \
102 QS_SIG_PRE(e->sig); \
103 QS_OBJ_PRE(this); \
104 QS_FUN_PRE(state_); \
105 QS_END_PRE() \
106 QS_CRIT_EXIT()
107
108// internal helper macro to trace transition begin/end
109#define QS_TRAN0_(rec_, trg_) \
110 QS_CRIT_ENTRY(); \
111 QS_BEGIN_PRE((rec_), qsId) \
112 QS_TIME_PRE(); \
113 QS_SIG_PRE(e->sig); \
114 QS_OBJ_PRE(this); \
115 QS_FUN_PRE(trg_); \
116 QS_END_PRE() \
117 QS_CRIT_EXIT()
118
119// internal helper macro to trace regular transition
120#define QS_TRAN_END_(rec_, src_, trg_) \
121 QS_CRIT_ENTRY(); \
122 QS_BEGIN_PRE((rec_), qsId) \
123 QS_TIME_PRE(); \
124 QS_SIG_PRE(e->sig); \
125 QS_OBJ_PRE(this); \
126 QS_FUN_PRE(src_); \
127 QS_FUN_PRE(trg_); \
128 QS_END_PRE() \
129 QS_CRIT_EXIT()
130
131#else
132#define QS_STATE_ACT_(rec_, state_) (static_cast<void>(0))
133#define QS_TOP_INIT_(rec_, trg_) (static_cast<void>(0))
134#define QS_TRAN_SEG_(rec_, src_, trg_) (static_cast<void>(0))
135#define QS_TRAN_ACT_(rec_, state_) (static_cast<void>(0))
136#define QS_TRAN0_(rec_, trg_) (static_cast<void>(0))
137#define QS_TRAN_END_(rec_, src_, trg_) (static_cast<void>(0))
138#endif
139
140//! @endcond
141
142//============================================================================
143namespace QP {
144
145//............................................................................
146QHsm::QHsm(QStateHandler const initial) noexcept
147 : QAsm()
148{
149 m_state.fun = &top; // the current state (top)
150 m_temp.fun = initial; // the initial tran. handler
151}
152
153//............................................................................
155 void const * const e,
156 std::uint_fast8_t const qsId)
157{
158#ifdef Q_SPY
159 // produce QS dictionary for QHsm_top handler...
160 // NOTE: the QHsm_top dictionary needs to be produced only once
161 // and not every time QHsm_init_() is called.
164 bool toDo = false; // assume that dictionary not produced
165 if ((QS::priv_.flags & 0x01U) == 0U) { // dictionary not produced yet?
166 QS::priv_.flags |= 0x01U; // mark the QHsm::top dictionary as produced
167 toDo = true;
168 }
169 QS_CRIT_EXIT();
170 if (toDo) { // need to produce the dictionary?
172 }
173#else
174 Q_UNUSED_PAR(qsId);
175#endif // Q_SPY
176
177 QStateHandler const s = m_state.fun; // current state
178
179 // current state must be initialized to QHsm_top in QHsm_ctor()
180 Q_REQUIRE_LOCAL(200, s == Q_STATE_CAST(&top));
181
182 // temp contains the top-most initial tran. handler, which must be valid
183 Q_REQUIRE_LOCAL(210, m_temp.fun != nullptr);
184
185 // execute the top-most initial tran.
186 QState const r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt));
187
188 // the top-most initial tran. must be taken
189 Q_ASSERT_LOCAL(240, r == Q_RET_TRAN);
190
191 // the top-most initial tran. must set the target in temp
192 Q_ASSERT_LOCAL(250, m_temp.fun != nullptr);
193
194 QS_TRAN_SEG_(QS_QEP_STATE_INIT, s, m_temp.fun); // output QS record
195
196 // drill down into the state hierarchy with initial transitions...
197 std::array <QStateHandler, QHSM_MAX_NEST_DEPTH_> path; // entry path array
198
199 std::int_fast8_t ip = -1; // path index & fixed loop bound (one below [0])
200 do {
201 ++ip;
202
203 // the entry path index must not overflow the allocated array
204 Q_INVARIANT_LOCAL(260, ip < QHSM_MAX_NEST_DEPTH_);
205
206 // the initial tran. must set target in temp
207 Q_ASSERT_LOCAL(270, m_temp.fun != nullptr);
208
209 path[ip] = m_temp.fun; // store the entry path
210
211 // find the superstate of 'm_temp.fun', ignore result
212 static_cast<void>((*m_temp.fun)(this, &l_resEvt_[Q_EMPTY_SIG]));
213 } while (m_temp.fun != s);
214
215 // enter the target (possibly recursively) by initial trans.
216 enter_target_(&path[0], ip, qsId);
217
218 QS_TOP_INIT_(QS_QEP_INIT_TRAN, path[0]); // output QS record
219
220 m_state.fun = path[0]; // change the current active state
221#ifndef Q_UNSAFE
222 // establish stable state configuration
224#else
225 Q_UNUSED_PAR(r);
226#endif
227}
228
229//............................................................................
231 QEvt const * const e,
232 std::uint_fast8_t const qsId)
233{
234#ifndef Q_SPY
235 Q_UNUSED_PAR(qsId);
236#endif
237
238 // this state machine must be in a stable state configuration
239 // NOTE: stable state configuration is established after every RTC step.
242
243 // the event to be dispatched must be valid
244 Q_REQUIRE_LOCAL(310, e != nullptr);
245
246 QStateHandler s = m_state.fun; // current state
247 m_temp.fun = nullptr; // invalidate
248
250 QS_TRAN0_(QS_QEP_DISPATCH, s); // output QS record
251
252 // process the event hierarchically...
253 std::array <QStateHandler, QHSM_MAX_NEST_DEPTH_> path; // entry path array
254 m_temp.fun = s;
255 QState r; // state handler return value
256 std::int_fast8_t ip = QHSM_MAX_NEST_DEPTH_;//path index & fixed loop bound
257 do {
258 --ip;
259
260 // the entry path index must stay in range of the path[] array
261 Q_INVARIANT_LOCAL(340, ip >= 0);
262
263 s = m_temp.fun; // set s to the superstate set previously
264 path[ip] = s; // store the path to potential tran. source
265
266 r = (*s)(this, e); // try to handle event e in state s
267
268 if (r == Q_RET_UNHANDLED) { // unhandled due to a guard?
269 QS_TRAN_ACT_(QS_QEP_UNHANDLED, s); // output QS record
270
271 // find the superstate of 's'
272 r = (*s)(this, &l_resEvt_[Q_EMPTY_SIG]);
273 }
274 } while (r == Q_RET_SUPER); // loop as long as superstate returned
275
276 if (r == Q_RET_IGNORED) { // was event e ignored?
277 QS_TRAN0_(QS_QEP_IGNORED, m_state.fun); // output QS record
278 }
279 else if (r == Q_RET_HANDLED) { // did the last handler handle event e?
280 QS_TRAN0_(QS_QEP_INTERN_TRAN, s); // output QS record
281 }
282 else if ((r == Q_RET_TRAN) || (r == Q_RET_TRAN_HIST)) { // tran. taken?
283 // tran. must set temp to the target state
284 Q_ASSERT_LOCAL(350, m_temp.fun != nullptr);
285
286#ifdef Q_SPY
287 if (r == Q_RET_TRAN_HIST) { // tran. to history?
288 QS_TRAN_SEG_(QS_QEP_TRAN_HIST, s, m_temp.fun); // output QS record
289 }
290#endif
291
292 path[0] = m_temp.fun; // save tran. target in path[0]
293
294 // exit current state to tran. source (path[0] not used)...
295 for (std::int_fast8_t iq = QHSM_MAX_NEST_DEPTH_ - 1; iq > ip; --iq) {
296 // exit from 'path[iq]'
297 if ((*path[iq])(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
298 QS_STATE_ACT_(QS_QEP_STATE_EXIT, path[iq]); //output QS record
299 }
300 }
301 path[2] = s; // save tran. source in path[2]
302
303 // take the tran...
304 ip = tran_simple_(&path[0], qsId); // try simple tran. first
305 if (ip < -1) { // not a simple tran.?
306 ip = tran_complex_(&path[0], qsId);
307 }
308
309 // enter the target (possibly recursively) by initial trans.
310 enter_target_(&path[0], ip, qsId);
311 QS_TRAN_END_(QS_QEP_TRAN, s, path[0]); // output QS record
312
313 m_state.fun = path[0]; // change the current active state
314 }
315 else {
316 Q_ERROR_LOCAL(360); // last state handler returned impossible value
317 }
318
319#ifndef Q_UNSAFE
320 // establish stable state configuration
322#endif
323}
324
325//............................................................................
326//! @private @memberof QHsm
327std::int_fast8_t QHsm::tran_simple_(
328 QStateHandler * const path,
329 std::uint_fast8_t const qsId)
330{
331#ifndef Q_SPY
332 Q_UNUSED_PAR(qsId);
333#endif
334
335 QStateHandler t = path[0]; // target
336 QStateHandler const s = path[2]; // source
337 std::int_fast8_t ip = 0; // assume to enter the target
339
340 // (a) check source==target (tran. to self)...
341 if (s == t) {
342 // exit source 's' (external tran. semantics)
343 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
344 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
345 }
346 }
347 else { // not a tran. to self
348 // find superstate of target in 't'
349 QState const r = (*t)(this, &l_resEvt_[Q_EMPTY_SIG]);
350
351 // state handler t must return the superstate for Q_EMPTY_SIG
352 Q_ASSERT_LOCAL(440, r == Q_RET_SUPER);
353
354 // state handler t must set temp to the superstate
355 Q_ASSERT_LOCAL(450, m_temp.fun != nullptr);
356#ifdef Q_UNSAFE
357 Q_UNUSED_PAR(r);
358#endif
359
360 // (b) check source==target->super...
361 t = m_temp.fun;
362 if (s != t) {
363 // find superstate of source 's', ignore the result
364 static_cast<void>((*s)(this, &l_resEvt_[Q_EMPTY_SIG]));
365
366 // (c) check source->super==target->super...
367 if (m_temp.fun == t) {
368 // exit source 's'
369 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
370 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
371 }
372 }
373 // (d) check source->super==target...
374 else if (m_temp.fun == path[0]) {
375 // exit source 's'
376 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
377 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
378 }
379 ip = -1; // set entry path index not to enter the target
380 }
381 else {
382 path[1] = t; // save the superstate of target
383 ip = -2; // cause execution of QHsm::tran_complex_()
384 }
385 }
386 }
387 // return: # levels in path[] for QHsm_enter_target_()
388 // or indication to call QHsm_tran_complex_()
389 return ip;
390}
391
392//............................................................................
393//! @private @memberof QHsm
394std::int_fast8_t QHsm::tran_complex_(
395 QStateHandler * const path,
396 std::uint_fast8_t const qsId)
397{
398#ifndef Q_SPY
399 Q_UNUSED_PAR(qsId);
400#endif
401
402 QStateHandler s = path[2]; // tran. source
403 QStateHandler const ss = m_temp.fun; // source->super
404 m_temp.fun = path[1]; // target->super
405 std::int_fast8_t iq = 0; // assume that LCA is NOT found
406 QState r;
407
408 // (e) check rest of source == target->super->super...
409 // and store the target entry path along the way
410 std::int_fast8_t ip = 0; // path index & fixed loop bound (one below [1])
411 do {
412 ++ip;
413
414 // the entry path index must stay in range of the path[] array
415 Q_INVARIANT_LOCAL(540, ip < QHSM_MAX_NEST_DEPTH_);
416
417 path[ip] = m_temp.fun; // store temp in the entry path array
418
419 // find superstate of 'm_temp.fun'
420 r = (*m_temp.fun)(this, &l_resEvt_[Q_EMPTY_SIG]);
421 if (m_temp.fun == s) { // is temp the LCA?
422 iq = 1; // indicate that LCA is found
423 break;
424 }
425 } while (r == Q_RET_SUPER); // loop as long as superstate reached
426
427 if (iq == 0) { // the LCA not found yet?
429
430#ifndef Q_SPY
431 // exit the source 's', ignore the result
432 static_cast<void>((*s)(this, &l_resEvt_[Q_EXIT_SIG]));
433#else
434 // exit the source 's'
435 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
436 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS trace
437 }
438#endif // def Q_SPY
439
440 // (f) check the rest of
441 // source->super... == target->super->super...
442 s = ss; // source->super
443 r = Q_RET_IGNORED; // assume that the LCA NOT found
444 iq = ip; // outside for(;;) to comply with MC:2023 R14.2
445 for (; iq >= 0; --iq) {
446 if (s == path[iq]) { // is this the LCA?
447 r = Q_RET_HANDLED; // indicate the LCA found
448 ip = iq - 1; // do not enter the LCA
449 break;
450 }
451 }
452
453 if (r != Q_RET_HANDLED) { // the LCA still not found?
454 // (g) check each source->super->...
455 // for each target->super...
456 do {
457 // exit from 's'
458 if ((*s)(this, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
459 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
460 // find superstate of 's', ignore the result
461 static_cast<void>((*s)(this, &l_resEvt_[Q_EMPTY_SIG]));
462 }
463 s = m_temp.fun; // set to super of s
464 // NOTE: loop bounded per invariant:540
465 iq = ip; // outside for(;;) to comply with MC:2023 R14.2
466 for (; iq >= 0; --iq) {
467 if (s == path[iq]) { // is this the LCA?
468 ip = iq - 1; // indicate not to enter the LCA
469 r = Q_RET_HANDLED; // cause break from outer loop
470 break;
471 }
472 }
473 } while (r != Q_RET_HANDLED);
474 }
475 }
476 // # levels in path[] for QHsm_enter_target_()
477 return ip;
478}
479
480//............................................................................
481//! @private @memberof QHsm
483 QStateHandler * const path,
484 std::int_fast8_t const depth,
485 std::uint_fast8_t const qsId)
486{
487#ifndef Q_SPY
488 Q_UNUSED_PAR(qsId);
489#endif
490
492 std::int_fast8_t ip = depth;
493 // execute entry actions from LCA to tran target...
494 for (; ip >= 0; --ip) {
495 // enter 'path[ip]'
496 if ((*path[ip])(this, &l_resEvt_[Q_ENTRY_SIG]) == Q_RET_HANDLED) {
497 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]); // output QS trace
498 }
499 }
500 QStateHandler t = path[0]; // tran. target
501
502 // drill into the target hierarchy with nested initial trans...
503
504 // take initial tran in 't'
505 while ((*t)(this, &l_resEvt_[Q_INIT_SIG]) == Q_RET_TRAN) { // tran. taken?
506 // temp holds the target of initial tran. and must be valid
507 Q_ASSERT_LOCAL(650, m_temp.fun != nullptr);
508
509 QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, m_temp.fun); // output QS record
510
511 // find superstate of initial tran. target...
512 ip = -1; // entry path index and fixed loop bound (one below [0])
513 do {
514 ++ip;
515 // the entry path index must stay in range of the path[] array
516 Q_INVARIANT_LOCAL(660, ip < QHSM_MAX_NEST_DEPTH_);
517
518 path[ip] = m_temp.fun; // store the entry path
519
520 // find superstate of 'm_temp.fun'
521 QState const r = (*m_temp.fun)(this, &l_resEvt_[Q_EMPTY_SIG]);
522
523 // the temp superstate handler must return superstate
524 Q_ASSERT_LOCAL(680, r == Q_RET_SUPER);
525#ifdef Q_UNSAFE
526 Q_UNUSED_PAR(r);
527#endif
528 } while (m_temp.fun != t); // loop as long as tran.target not reached
529
530 // retrace the entry path in reverse (correct) order...
531 for (; ip >= 0; --ip) {
532 // enter 'path[ip]'
533 if ((*path[ip])(this, &l_resEvt_[Q_ENTRY_SIG]) == Q_RET_HANDLED) {
534 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]);//output QS record
535 }
536 }
537 t = path[0]; // tran. target becomes the new source
538 }
539}
540
541//............................................................................
542bool QHsm::isIn(QStateHandler const stateHndl) noexcept {
543 // this state machine must be in a stable state configuration
544 // NOTE: stable state configuration is established after every RTC step.
547
548 bool inState = false; // assume that this HSM is NOT in 'stateHndl'
549
550 // scan the state hierarchy bottom-up
551 QStateHandler s = m_state.fun;
552 QState r;
553 do {
554 if (s == stateHndl) { // do the states match?
555 inState = true; // 'true' means that match found
556 break; // break out of the do-loop
557 }
558
559 // find superstate of 's'
560 r = (*s)(this, &l_resEvt_[Q_EMPTY_SIG]);
561 s = m_temp.fun;
562 } while (r == Q_RET_SUPER);
563
564#ifndef Q_UNSAFE
565 // restore the invariant (stable state configuration)
567#endif
568 return inState; // return the status
569}
570
571//............................................................................
572QStateHandler QHsm::childState(QStateHandler const parentHndl) noexcept {
573 // NOTE: this function is designed to be called during an RTC step,
574 // so it does NOT assume to be called in a stable state configuration
575 // and also does NOT establish stable state configuration upon exit.
576
577#ifndef Q_UNSAFE
578 bool isFound = false; // assume the child state NOT found
579#endif
580
581 QStateHandler child = m_state.fun; // child state to find
582 m_temp.fun = child; // start from the current state
584 do {
585 // have the parent of the current child?
586 if (m_temp.fun == parentHndl) {
587#ifndef Q_UNSAFE
588 isFound = true; // indicate that child state was found
589#endif
590 break;
591 }
592 child = m_temp.fun;
593
594 // find superstate of 'child' (placed in m_temp)
595 r = (*child)(this, &l_resEvt_[Q_EMPTY_SIG]);
596 } while (r == Q_RET_SUPER);
597 Q_ENSURE_LOCAL(890, isFound);
598
599 return child;
600}
601
602//............................................................................
604 // NOTE: this function does NOT apply critical section, so it can
605 // be safely called from an already established critical section.
606 return m_state.fun; // public "getter" to the state handler (function)
607}
608
609} // namespace QP
QAsm() noexcept
Constructor of the QP::QAsm base class.
Definition qf_act.cpp:75
static constexpr QState Q_RET_UNHANDLED
Definition qp.hpp:175
static constexpr QState Q_RET_TRAN
Definition qp.hpp:177
QAsmAttr m_temp
Temporary storage for target/act-table etc.
Definition qp.hpp:170
static constexpr QState Q_RET_IGNORED
Definition qp.hpp:181
static constexpr QState Q_RET_SUPER
Definition qp.hpp:174
static constexpr QState Q_RET_TRAN_HIST
Definition qp.hpp:178
static constexpr QSignal Q_INIT_SIG
Definition qp.hpp:193
QAsmAttr m_state
Current state (pointer to the current state-handler function).
Definition qp.hpp:169
static constexpr QSignal Q_ENTRY_SIG
Definition qp.hpp:191
static constexpr QSignal Q_EXIT_SIG
Definition qp.hpp:192
static constexpr QSignal Q_EMPTY_SIG
Definition qp.hpp:190
static constexpr QState Q_RET_HANDLED
Definition qp.hpp:176
static QState top(void *const me, QEvt const *const e) noexcept
Top state handler that ignores all events.
Definition qf_act.cpp:80
Event class.
Definition qp.hpp:101
std::int_fast8_t tran_complex_(QStateHandler *const path, std::uint_fast8_t const qsId)
void dispatch(QEvt const *const e, std::uint_fast8_t const qsId) override
Virtual function to dispatch an event to the state machine.
Definition qep_hsm.cpp:230
std::int_fast8_t tran_simple_(QStateHandler *const path, std::uint_fast8_t const qsId)
QStateHandler childState(QStateHandler const parentHndl) noexcept
Obtain the current active child state of a given parent in QP::QMsm.
Definition qep_hsm.cpp:572
void init(void const *const e, std::uint_fast8_t const qsId) override
Virtual function to take the top-most initial transition in the state machine.
Definition qep_hsm.cpp:154
QHsm(QStateHandler const initial) noexcept
Definition qep_hsm.cpp:146
void enter_target_(QStateHandler *const path, std::int_fast8_t const depth, std::uint_fast8_t const qsId)
bool isIn(QStateHandler const stateHndl) noexcept override
Check whether the HSM is in a given state.
Definition qep_hsm.cpp:542
QStateHandler getStateHandler() const noexcept override
Virtual method for getting the current state handler.
Definition qep_hsm.cpp:603
QP/C++ Framework namespace.
Definition qequeue.hpp:36
@ QS_QEP_DISPATCH
an event was dispatched (begin of RTC step)
Definition qs.hpp:64
@ QS_QEP_STATE_ENTRY
a state was entered
Definition qs.hpp:57
@ QS_QEP_STATE_EXIT
a state was exited
Definition qs.hpp:58
@ QS_QEP_TRAN_HIST
a tran. to history was taken
Definition qs.hpp:137
@ QS_QEP_IGNORED
an event was ignored (silently discarded)
Definition qs.hpp:63
@ QS_QEP_UNHANDLED
an event was un-handled due to a guard
Definition qs.hpp:65
@ QS_QEP_STATE_INIT
an initial transition was taken in a state
Definition qs.hpp:59
@ QS_QEP_TRAN
a regular transition was taken
Definition qs.hpp:62
@ QS_QEP_INIT_TRAN
the top-most initial transition was taken
Definition qs.hpp:60
@ QS_QEP_INTERN_TRAN
an internal transition was taken
Definition qs.hpp:61
static T_ dis_update(T_ const org)
Internal function template to calculate the Duplicate Inverse Storage (DIS).
Definition qp_pkg.hpp:61
static bool dis_verify(T_ const org, T_ const dis)
Internal function template to verify the Duplicate Inverse Storage (DIS).
Definition qp_pkg.hpp:68
std::uint_fast8_t QState
Type returned from state-handler functions.
Definition qp.hpp:134
QState(*)(void *const me, QEvt const *const e) QStateHandler
Pointer to a state-handler function.
Definition qp.hpp:138
std::uint16_t QSignal
The signal of event QP::QEvt.
Definition qp.hpp:98
#define Q_EVT_CAST(subclass_)
Perform downcast of an event onto a subclass of QP::QEvt class_.
Definition qp.hpp:384
#define Q_UNUSED_PAR(par_)
Helper macro to clearly mark unused parameters of functions.
Definition qp.hpp:89
#define Q_STATE_CAST(handler_)
Perform cast to QP::QStateHandler.
Definition qp.hpp:385
QP Framework in C++ internal (package-scope) interface
Sample QP/C++ port.
#define QS_CRIT_STAT
Internal QS macro for defining the critical section status.
Definition qs.hpp:430
#define QS_FUN_DICTIONARY(fun_)
Produce function dictionary (typically for state-handler functions).
Definition qs.hpp:400
#define QS_CRIT_EXIT()
Internal macro for exiting a critical section.
Definition qs.hpp:438
#define QS_CRIT_ENTRY()
Internal macro for entering a critical section.
Definition qs.hpp:434
QS (QP/Spy software tracing) internal (package-scope) interface.
Sample QS/C++ port.
QP Functional Safety (FuSa) Subsystem.
#define Q_REQUIRE_LOCAL(id_, expr_)
Assertion for checking a precondition (local critical section).
Definition qsafe.h:99
#define Q_ERROR_LOCAL(id_)
Assertion with user-specified ID for a wrong path through the code (local critical section).
Definition qsafe.h:111
#define Q_ENSURE_LOCAL(id_, expr_)
Assertion for checking a postcondition (local critical section).
Definition qsafe.h:104
#define Q_ASSERT_LOCAL(id_, expr_)
General-purpose assertion with user-specified ID number (local critical section).
Definition qsafe.h:72
#define Q_INVARIANT_LOCAL(id_, expr_)
Assertion for checking a postcondition (local critical section).
Definition qsafe.h:109
#define Q_INVARIANT_INCRIT(id_, expr_)
Assertion for checking a postcondition (in critical section).
Definition qsafe.h:108