Reference Manual For QP/C 8.1.5
Loading...
Searching...
No Matches
qep_hsm.c
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.h" // QP port
31#include "qp_pkg.h" // 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.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_ ((size_t)6U)
45
46//! @cond INTERNAL
47
48// array of immutable events corresponding to the reserved signals
49static QEvt const l_resEvt_[4] = {
54};
55
56//! @endcond
57
58//============================================================================
59//! @cond INTERNAL
60
61// internal helper macro to pass a reserved event into the state handler
62
63#ifdef Q_SPY
64// helper macro to trace state action (entry/exit)
65#define QS_STATE_ACT_(rec_, state_) \
66 QS_CRIT_ENTRY(); \
67 QS_BEGIN_PRE((rec_), qsId) \
68 QS_OBJ_PRE(me); \
69 QS_FUN_PRE(state_); \
70 QS_END_PRE() \
71 QS_CRIT_EXIT()
72
73// internal helper macro to top-most init
74#define QS_TOP_INIT_(rec_, trg_) \
75 QS_CRIT_ENTRY(); \
76 QS_BEGIN_PRE((rec_), qsId) \
77 QS_TIME_PRE(); \
78 QS_OBJ_PRE(me); \
79 QS_FUN_PRE(trg_); \
80 QS_END_PRE() \
81 QS_CRIT_EXIT()
82
83// internal helper macro to trace transition segment
84#define QS_TRAN_SEG_(rec_, src_, trg_) \
85 QS_CRIT_ENTRY(); \
86 QS_BEGIN_PRE((rec_), qsId) \
87 QS_OBJ_PRE(me); \
88 QS_FUN_PRE(src_); \
89 QS_FUN_PRE(trg_); \
90 QS_END_PRE() \
91 QS_CRIT_EXIT()
92
93// internal helper macro to trace transition action
94#define QS_TRAN_ACT_(rec_, state_) \
95 QS_CRIT_ENTRY(); \
96 QS_BEGIN_PRE((rec_), qsId) \
97 QS_SIG_PRE(e->sig); \
98 QS_OBJ_PRE(me); \
99 QS_FUN_PRE(state_); \
100 QS_END_PRE() \
101 QS_CRIT_EXIT()
102
103// internal helper macro to trace transition begin/end
104#define QS_TRAN0_(rec_, trg_) \
105 QS_CRIT_ENTRY(); \
106 QS_BEGIN_PRE((rec_), qsId) \
107 QS_TIME_PRE(); \
108 QS_SIG_PRE(e->sig); \
109 QS_OBJ_PRE(me); \
110 QS_FUN_PRE(trg_); \
111 QS_END_PRE() \
112 QS_CRIT_EXIT()
113
114// internal helper macro to trace regular transition
115#define QS_TRAN_END_(rec_, src_, trg_) \
116 QS_CRIT_ENTRY(); \
117 QS_BEGIN_PRE((rec_), qsId) \
118 QS_TIME_PRE(); \
119 QS_SIG_PRE(e->sig); \
120 QS_OBJ_PRE(me); \
121 QS_FUN_PRE(src_); \
122 QS_FUN_PRE(trg_); \
123 QS_END_PRE() \
124 QS_CRIT_EXIT()
125
126#else
127#define QS_STATE_ACT_(rec_, state_) ((void)0)
128#define QS_TOP_INIT_(rec_, trg_) ((void)0)
129#define QS_TRAN_SEG_(rec_, src_, trg_) ((void)0)
130#define QS_TRAN_ACT_(rec_, state_) ((void)0)
131#define QS_TRAN0_(rec_, trg_) ((void)0)
132#define QS_TRAN_END_(rec_, src_, trg_) ((void)0)
133#endif
134
135//! @endcond
136
137//============================================================================
138//! @protected @memberof QHsm
139void QHsm_ctor(QHsm * const me,
140 QStateHandler const initial)
141{
142 static struct QAsmVtable const vtable = { // QAsm virtual table
143 &QHsm_init_,
145 &QHsm_isIn_,
147 };
148 // no need to call the superclass' constructor QAsm_ctor() here
149 me->super.vptr = &vtable; // QHsm class' VTABLE
150 me->super.state.fun = Q_STATE_CAST(&QHsm_top); // the current state (top)
151 me->super.temp.fun = initial; // the initial tran. handler
152}
153
154//............................................................................
155//! @protected @memberof QHsm
156QState QHsm_top(QHsm const * const me, QEvt const * const e) {
157 // the top state handler implementation
158 Q_UNUSED_PAR(me);
159 Q_UNUSED_PAR(e);
160 return Q_RET_IGNORED; // the top state ignores all events
161}
162
163//............................................................................
164//! @private @memberof QHsm
165void QHsm_init_(QAsm * const me,
166 void const * const e,
167 uint_fast8_t const qsId)
168{
169#ifdef Q_SPY
170 // produce QS dictionary for QHsm_top handler...
171 // NOTE: the QHsm_top dictionary needs to be produced only once
172 // and not every time QHsm_init_() is called.
175 bool toDo = false; // assume that dictionary not produced
176 if ((QS_priv_.flags & 0x01U) == 0U) { // dictionary not produced yet?
177 QS_priv_.flags |= 0x01U; // mark the QHsm_top dictionary as produced
178 toDo = true;
179 }
180 QS_CRIT_EXIT();
181 if (toDo) { // need to produce the dictionary?
182 QS_FUN_DICTIONARY(&QHsm_top);
183 }
184#else
185 Q_UNUSED_PAR(qsId);
186#endif // Q_SPY
187
188 QStateHandler const s = me->state.fun; // current state
189
190 // current state must be initialized to QHsm_top in QHsm_ctor()
191 Q_REQUIRE_LOCAL(200, s == Q_STATE_CAST(&QHsm_top));
192
193 // temp contains the top-most initial tran. handler, which must be valid
194 Q_REQUIRE_LOCAL(210, me->temp.fun != Q_STATE_CAST(0));
195
196 // execute the top-most initial tran.
197 QState const r = (*me->temp.fun)(me, Q_EVT_CAST(QEvt));
198
199 // the top-most initial tran. must be taken
200 Q_ASSERT_LOCAL(240, r == Q_RET_TRAN);
201
202 // the top-most initial tran. must set the target in temp
203 Q_ASSERT_LOCAL(250, me->temp.fun != Q_STATE_CAST(0));
204
205 QS_TRAN_SEG_(QS_QEP_STATE_INIT, s, me->temp.fun); // output QS record
206
207 // drill down into the state hierarchy with initial transitions...
208 QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // entry path array
209
210 size_t ip = 0U; // path index & fixed loop bound
211 do {
212 // the entry path index must not overflow the allocated array
213 Q_INVARIANT_LOCAL(260, ip < QHSM_MAX_NEST_DEPTH_);
214
215 // the initial tran. must set target in temp
216 Q_ASSERT_LOCAL(270, me->temp.fun != Q_STATE_CAST(0));
217
218 path[ip] = me->temp.fun; // store the entry path
219 ++ip;
220
221 // find the superstate of 'm_temp.fun', ignore result
222 (void)(*me->temp.fun)(me, &l_resEvt_[Q_EMPTY_SIG]);
223 } while (me->temp.fun != s);
224
225 // enter the target (possibly recursively) by initial trans.
226 QHsm_enter_target_(me, path, ip, qsId);
227
228 QS_TOP_INIT_(QS_QEP_INIT_TRAN, path[0]); // output QS record
229
230 me->state.fun = path[0]; // change the current active state
231#ifndef Q_UNSAFE
232 // establish stable state configuration
233 me->temp.uint = QP_DIS_UPDATE(uintptr_t, me->state.uint);
234#else
235 Q_UNUSED_PAR(r);
236#endif
237}
238
239//............................................................................
240//! @private @memberof QHsm
241void QHsm_dispatch_(QAsm * const me,
242 QEvt const * const e,
243 uint_fast8_t const qsId)
244{
245#ifndef Q_SPY
246 Q_UNUSED_PAR(qsId);
247#endif
248
249 // this state machine must be in a "stable state configuration"
250 // NOTE: stable state configuration is established after every RTC step.
252 QP_DIS_VERIFY(uintptr_t, me->state.uint, me->temp.uint));
253
254 // the event to be dispatched must be valid
255 Q_REQUIRE_LOCAL(310, e != (QEvt *)0);
256
257 QStateHandler s = me->state.fun; // current state
258#ifndef Q_UNSAFE
259 uintptr_t const state_dis = me->temp.uint; // from invariant-300
260#endif
261 me->temp.fun = Q_STATE_CAST(0); // invalidate "stable state configuration"
262
264 QS_TRAN0_(QS_QEP_DISPATCH, s); // output QS record
265
266 // process the event hierarchically...
267 QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // entry path array
268 me->temp.fun = s;
269 QState r; // state handler return value
270 size_t ip = QHSM_MAX_NEST_DEPTH_; // path index & fixed loop bound
271 do {
272 // the entry path index must stay in range of the path[] array
273 Q_INVARIANT_LOCAL(340, ip != 0U);
274
275 s = me->temp.fun; // set s to the superstate set previously
276 --ip; // build the entry path[] from the end
277 path[ip] = s; // store the path to potential tran. source
278
279 r = (*s)(me, e); // try to handle event e in state s
280
281 if (r == Q_RET_UNHANDLED) { // unhandled due to a guard?
282 QS_TRAN_ACT_(QS_QEP_UNHANDLED, s); // output QS record
283
284 // find the superstate of 's'
285 r = (*s)(me, &l_resEvt_[Q_EMPTY_SIG]);
286 }
287 } while (r == Q_RET_SUPER); // loop as long as superstate returned
288
289 // me->state should not change, so it must match the saved DIS
291 QP_DIS_VERIFY(uintptr_t, me->state.uint, state_dis));
292
293 if (r == Q_RET_IGNORED) { // was event ignored?
294 QS_TRAN0_(QS_QEP_IGNORED, me->state.fun); // output QS record
295 }
296 else if (r == Q_RET_HANDLED) { // did the last handler handle the event?
297 QS_TRAN0_(QS_QEP_INTERN_TRAN, s); // output QS record
298 }
299 else if ((r == Q_RET_TRAN) || (r == Q_RET_TRAN_HIST)) { // tran. taken?
300 // tran. must have set me->temp to the target state
301 Q_ASSERT_LOCAL(360, me->temp.fun != Q_STATE_CAST(0));
302
303#ifdef Q_SPY
304 if (r == Q_RET_TRAN_HIST) { // tran. to history?
305 QS_TRAN_SEG_(QS_QEP_TRAN_HIST, s, me->temp.fun);//output QS record
306 }
307#endif
308
309 path[0] = me->temp.fun; // save tran. target in path[0]
310
311 // exit current state to tran. source (path[0] not used)...
312 for (size_t iq = QHSM_MAX_NEST_DEPTH_ - 1U; iq > ip; --iq) {
313 // exit from 'path[iq]'
314 if ((*path[iq])(me, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
315 QS_STATE_ACT_(QS_QEP_STATE_EXIT, path[iq]); //output QS record
316 }
317 }
318 path[2] = s; // save tran. source in path[2]
319
320 // take the tran...
321 ip = QHsm_tran_simple_(me, path, qsId); // try simple tran. first
322 if (ip > 1U) { // not a simple tran.?
323 ip = QHsm_tran_complex_(me, path, qsId);
324 }
325
326 // enter the target (possibly recursively) by initial trans.
327 QHsm_enter_target_(me, path, ip, qsId);
328 QS_TRAN_END_(QS_QEP_TRAN, s, path[0]); // output QS record
329
330 me->state.fun = path[0]; // change the current active state
331 }
332 else {
333 Q_ERROR_LOCAL(370); // last state handler returned impossible value
334 }
335
336#ifndef Q_UNSAFE
337 // establish "stable state configuration"
338 me->temp.uint = QP_DIS_UPDATE(uintptr_t, me->state.uint);
339#endif
340}
341
342//............................................................................
343//! @private @memberof QHsm
345 QAsm * const me,
346 QStateHandler * const path,
347 uint_fast8_t const qsId)
348{
349#ifndef Q_SPY
350 Q_UNUSED_PAR(qsId);
351#endif
352
353 QStateHandler t = path[0]; // target
354 QStateHandler const s = path[2]; // source
355 size_t ip = 1U; // assume to enter the target
357
358 // (a) check source==target (tran. to self)...
359 if (s == t) {
360 // exit source 's' (external tran. semantics)
361 if ((*s)(me, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
362 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
363 }
364 }
365 else { // not a tran. to self
366 // find superstate of target in 't'
367 QState const r = (*t)(me, &l_resEvt_[Q_EMPTY_SIG]);
368
369 // state handler t must return the superstate for Q_EMPTY_SIG
370 Q_ASSERT_LOCAL(440, r == Q_RET_SUPER);
371
372 // state handler t must set temp to the superstate
373 Q_ASSERT_LOCAL(450, me->temp.fun != Q_STATE_CAST(0));
374#ifdef Q_UNSAFE
375 Q_UNUSED_PAR(r);
376#endif
377
378 // (b) check source==target->super...
379 t = me->temp.fun;
380 if (s != t) {
381 // find superstate of source 's', ignore the result
382 (void)(*s)(me, &l_resEvt_[Q_EMPTY_SIG]);
383
384 // (c) check source->super==target->super...
385 if (me->temp.fun == t) {
386 // exit source 's'
387 if ((*s)(me, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
388 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
389 }
390 }
391 // (d) check source->super==target...
392 else if (me->temp.fun == path[0]) {
393 // exit source 's'
394 if ((*s)(me, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
395 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
396 }
397 ip = 0U; // set entry path index NOT to enter the target
398 }
399 else { // tran. more complex
400 path[1] = t; // save the superstate of target
401 ip = 2U; // need QHsm_tran_complex_()
402 }
403 }
404 }
405 // return: # levels in path[] for QHsm_enter_target_()
406 // or indication to call QHsm_tran_complex_()
407 return ip;
408}
409
410//............................................................................
411//! @private @memberof QHsm
412size_t QHsm_tran_complex_(QAsm * const me,
413 QStateHandler * const path,
414 uint_fast8_t const qsId)
415{
416#ifndef Q_SPY
417 Q_UNUSED_PAR(qsId);
418#endif
419
420 QStateHandler s = path[2]; // tran. source
421 QStateHandler const ss = me->temp.fun; // source->super
422 me->temp.fun = path[1]; // target->super
423 QState r;
424
425 // (e) check rest of source == target->super->super...
426 // and store the target entry path along the way
427 size_t ip = 1U; // path index & fixed loop bound
428 size_t iq = 0U; // assume that LCA is NOT found
429 do {
430 // the entry path index must stay in range of the path[] array
431 Q_INVARIANT_LOCAL(540, ip < QHSM_MAX_NEST_DEPTH_);
432
433 path[ip] = me->temp.fun; // store temp in the entry path array
434 ++ip;
435
436 // find superstate of 'm_temp.fun'
437 r = (*me->temp.fun)(me, &l_resEvt_[Q_EMPTY_SIG]);
438 if (me->temp.fun == s) { // is temp the LCA?
439 iq = 1U; // indicate that LCA is found
440 break;
441 }
442 } while (r == Q_RET_SUPER); // loop as long as superstate reached
443
444 if (iq == 0U) { // the LCA not found yet?
446
447#ifndef Q_SPY
448 // exit the source 's', ignore the result
449 (void)(*s)(me, &l_resEvt_[Q_EXIT_SIG]);
450#else
451 // exit the source 's'
452 if ((*s)(me, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
453 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s); // output QS record
454 }
455#endif // def Q_SPY
456
457 // (f) check the rest of
458 // source->super... == target->super->super...
459 s = ss; // source->super
460 r = Q_RET_IGNORED; // assume that the LCA NOT found
461 iq = ip;
462 while (iq > 0U) {
463 --iq;
464 if (s == path[iq]) { // is this the LCA?
465 r = Q_RET_HANDLED; // indicate the LCA found
466 ip = iq; // do NOT enter the LCA
467 break;
468 }
469 }
470
471 if (r != Q_RET_HANDLED) { // the LCA still not found?
472 // (g) check each source->super->...
473 // for each target->super...
474 do {
475 // exit from 's'
476 if ((*s)(me, &l_resEvt_[Q_EXIT_SIG]) == Q_RET_HANDLED) {
477 QS_STATE_ACT_(QS_QEP_STATE_EXIT, s);
478 // find superstate of 's', ignore the result
479 (void)(*s)(me, &l_resEvt_[Q_EMPTY_SIG]);
480 }
481 s = me->temp.fun; // set to super of s
482 // NOTE: loop bounded per invariant:540
483 iq = ip;
484 while (iq > 0U) {
485 --iq;
486 if (s == path[iq]) { // is this the LCA?
487 ip = iq; // do NOT to enter the LCA
488 r = Q_RET_HANDLED; // cause break from outer loop
489 break;
490 }
491 }
492 } while (r != Q_RET_HANDLED);
493 }
494 }
495 // # levels in path[] for QHsm_enter_target_()
496 return ip;
497}
498
499//............................................................................
500//! @private @memberof QHsm
501void QHsm_enter_target_(QAsm * const me,
502 QStateHandler * const path,
503 size_t const depth,
504 uint_fast8_t const qsId)
505{
506#ifndef Q_SPY
507 Q_UNUSED_PAR(qsId);
508#endif
509
511 size_t ip = depth;
512
513 Q_REQUIRE_LOCAL(600, ip <= QHSM_MAX_NEST_DEPTH_);
514
515 // execute entry actions from LCA to tran target...
516 while (ip > 0U) {
517 --ip;
518 // enter 'path[ip]'
519 if ((*path[ip])(me, &l_resEvt_[Q_ENTRY_SIG]) == Q_RET_HANDLED) {
520 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]); // output QS record
521 }
522 }
523 QStateHandler t = path[0]; // tran. target
524
525 // drill into the target hierarchy with nested initial trans...
526
527 // take initial tran in 't'
528 while ((*t)(me, &l_resEvt_[Q_INIT_SIG]) == Q_RET_TRAN) { // tran. taken?
529 // temp holds the target of initial tran. and must be valid
530 Q_ASSERT_LOCAL(650, me->temp.fun != Q_STATE_CAST(0));
531
532 QS_TRAN_SEG_(QS_QEP_STATE_INIT, t, me->temp.fun); // output QS record
533
534 // find superstate of initial tran. target...
535 ip = 0U; // entry path index and fixed loop bound
536 do {
537 // the entry path index must stay in range of the path[] array
538 Q_INVARIANT_LOCAL(660, ip < QHSM_MAX_NEST_DEPTH_);
539
540 path[ip] = me->temp.fun; // store the entry path
541 ++ip;
542
543 // find superstate of 'temp.fun'
544 QState const r = (*me->temp.fun)(me, &l_resEvt_[Q_EMPTY_SIG]);
545
546 // the temp superstate handler must return superstate
547 Q_ASSERT_LOCAL(680, r == Q_RET_SUPER);
548#ifdef Q_UNSAFE
549 Q_UNUSED_PAR(r);
550#endif
551 } while (me->temp.fun != t); //loop as long as tran.target not reached
552
553 // retrace the entry path in reverse (correct) order...
554 while (ip > 0U) {
555 --ip;
556 // enter 'path[ip]'
557 if ((*path[ip])(me, &l_resEvt_[Q_ENTRY_SIG]) == Q_RET_HANDLED) {
558 QS_STATE_ACT_(QS_QEP_STATE_ENTRY, path[ip]);//output QS record
559 }
560 }
561 t = path[0]; // tran. target becomes the new source
562 }
563}
564
565//............................................................................
566//! @private @memberof QHsm
567bool QHsm_isIn_(QAsm * const me,
568 QStateHandler const stateHndl)
569{
570 // this state machine must be in a stable state configuration
571 // NOTE: stable state configuration is established after every RTC step.
573 QP_DIS_VERIFY(uintptr_t, me->state.uint, me->temp.uint));
574
575 bool inState = false; // assume that this HSM is NOT in 'stateHndl'
576
577 // scan the state hierarchy bottom-up
578 QStateHandler s = me->state.fun;
579 QState r;
580 do {
581 if (s == stateHndl) { // do the states match?
582 inState = true; // 'true' means that match found
583 break; // break out of the do-loop
584 }
585
586 // find superstate of 's'
587 r = (*s)(me, &l_resEvt_[Q_EMPTY_SIG]);
588 s = me->temp.fun;
589 } while (r == Q_RET_SUPER);
590
591#ifndef Q_UNSAFE
592 // restore the invariant (stable state configuration)
593 me->temp.uint = QP_DIS_UPDATE(uintptr_t, me->state.uint);
594#endif
595 return inState; // return the status
596}
597
598//............................................................................
599//! @public @memberof QHsm
601 QStateHandler const parentHndl)
602{
603 // NOTE: this function is designed to be called during an RTC step,
604 // so it does NOT assume to be called in a stable state configuration
605 // and also does NOT establish stable state configuration upon exit.
606
607#ifndef Q_UNSAFE
608 bool isFound = false; // assume the child state NOT found
609#endif
610
611 QStateHandler child = me->super.state.fun; // child state to find
612 me->super.temp.fun = child; // start from the current state
613 QState r = Q_RET_SUPER;
614 do {
615 // have the parent of the current child?
616 if (me->super.temp.fun == parentHndl) {
617#ifndef Q_UNSAFE
618 isFound = true; // indicate that child state was found
619#endif
620 break;
621 }
622 child = me->super.temp.fun;
623
624 // find superstate of 'child' (placed in me->super.temp)
625 r = (*child)(me, &l_resEvt_[Q_EMPTY_SIG]);
626 } while (r == Q_RET_SUPER);
627 Q_ENSURE_LOCAL(890, isFound);
628
629 return child;
630}
631
632//............................................................................
633//! @public @memberof QHsm
634QStateHandler QHsm_state(QHsm const * const me) {
635 // NOTE: this function does NOT apply critical section, so it can
636 // be safely called from an already established critical section.
637 return me->super.state.fun;
638}
639
640//............................................................................
641//! @private @memberof QHsm
643 // NOTE: this function does NOT apply critical section, so it can
644 // be safely called from an already established critical section.
645 return me->state.fun;
646}
Private attributes of the QS software tracing target-resident component (TX channel).
#define Q_UNUSED_PAR(par_)
Helper macro to mark unused parameters of functions.
Definition qp.h:90
#define Q_STATE_CAST(handler_)
Perform cast to QStateHandler.
Definition qp.h:177
#define Q_EXIT_SIG
Reserved signal sent to state handler to execute the exit case. \clearpage .
Definition qp.h:208
#define Q_EVT_CAST(class_)
Perform downcast of an event onto a subclass of QEvt class_.
Definition qp.h:141
#define Q_ENTRY_SIG
Reserved signal sent to state handler to execute the entry case. \clearpage .
Definition qp.h:207
#define Q_INIT_SIG
Reserved signal sent to state handler to execute the initial transition. \clearpage \clearpage .
Definition qp.h:209
#define Q_EMPTY_SIG
Reserved signal sent to state handler to execute the default case. \clearpage .
Definition qp.h:206
QState(*) QStateHandler(void *const me, QEvt const *const e)
Pointer to a state-handler function.
Definition qp.h:147
#define QEVT_INITIALIZER(sig_)
Initializer for QEvt instances (base class).
Definition qp.h:107
uint_fast8_t QState
Type returned from state-handler functions.
Definition qp.h:146
QP/C Framework in C internal (package-scope) interface.
#define QP_DIS_UPDATE(T_, org_)
Update Duplicate Inverse Storage integer variable.
Definition qp_pkg.h:74
#define QP_DIS_VERIFY(T_, org_, dis_)
Verify integer variable against its Duplicate Inverse Storage.
Definition qp_pkg.h:75
Sample QP/C port.
#define QS_CRIT_STAT
Internal QS macro for defining the critical section status \clearpage .
Definition qs.h:403
#define QS_FUN_DICTIONARY(fun_)
Produce function dictionary (typically for state-handler functions).
Definition qs.h:372
@ QS_QEP_STATE_INIT
an initial transition was taken in a state
Definition qs.h:57
@ QS_QEP_TRAN_HIST
a tran. to history was taken
Definition qs.h:135
@ QS_QEP_STATE_EXIT
a state was exited
Definition qs.h:56
@ QS_QEP_INIT_TRAN
the top-most initial transition was taken
Definition qs.h:58
@ QS_QEP_INTERN_TRAN
an internal transition was taken
Definition qs.h:59
@ QS_QEP_STATE_ENTRY
a state was entered
Definition qs.h:55
@ QS_QEP_UNHANDLED
an event was un-handled due to a guard
Definition qs.h:63
@ QS_QEP_TRAN
a regular transition was taken
Definition qs.h:60
@ QS_QEP_DISPATCH
an event was dispatched (begin of RTC step)
Definition qs.h:62
@ QS_QEP_IGNORED
an event was ignored (silently discarded)
Definition qs.h:61
#define QS_CRIT_EXIT()
Internal macro for exiting a critical section \clearpage .
Definition qs.h:411
#define QS_CRIT_ENTRY()
Internal macro for entering a critical section \clearpage .
Definition qs.h:407
QS (QP/Spy software tracing) internal (package-scope) interface. \clearpage .
Sample QS/C port.
QP Functional Safety (FuSa) Subsystem (fault detection).
#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
Abstract State Machine class (state machine interface).
Definition qp.h:183
struct QAsmVtable const * vptr
Virtual pointer inherited by all QAsm subclasses (see also [SAS_QP_TECH_20]).
Definition qp.h:184
union QAsmAttr state
Current state (pointer to the current state-handler function).
Definition qp.h:185
union QAsmAttr temp
Temporary storage for target/act-table etc..
Definition qp.h:186
Virtual table for the QAsm class.
Definition qp.h:213
Event class.
Definition qp.h:100
Hierarchical State Machine class (QHsm-style implementation strategy).
Definition qp.h:244
bool QHsm_isIn_(QAsm *const me, QStateHandler const stateHndl)
Check if a given state is part of the current active state configuration.
Definition qep_hsm.c:567
void QHsm_enter_target_(QAsm *const me, QStateHandler *const path, size_t const depth, uint_fast8_t const qsId)
Implementation of entry to the target state configuration.
Definition qep_hsm.c:501
QStateHandler QHsm_childState(QHsm *const me, QStateHandler const parentHndl)
Obtain the current active child state of a given parent in QHsm.
Definition qep_hsm.c:600
size_t QHsm_tran_simple_(QAsm *const me, QStateHandler *const path, uint_fast8_t const qsId)
Implementation of a simple state transition segment.
Definition qep_hsm.c:344
void QHsm_ctor(QHsm *const me, QStateHandler const initial)
Constructor of the QHsm base class.
Definition qep_hsm.c:139
QStateHandler QHsm_state(QHsm const *const me)
Obtain the current active state from a HSM (read only).
Definition qep_hsm.c:634
QStateHandler QHsm_getStateHandler_(QAsm const *const me)
Implementation of getting the state handler in an QHsm subclass.
Definition qep_hsm.c:642
void QHsm_dispatch_(QAsm *const me, QEvt const *const e, uint_fast8_t const qsId)
Implementation of dispatching events to a QHsm.
Definition qep_hsm.c:241
void QHsm_init_(QAsm *const me, void const *const e, uint_fast8_t const qsId)
Implementation of the top-most initial transition in QHsm.
Definition qep_hsm.c:165
size_t QHsm_tran_complex_(QAsm *const me, QStateHandler *const path, uint_fast8_t const qsId)
Implementation of a complex state transition segment.
Definition qep_hsm.c:412