QP/C  7.4.0-rc.2
Real-Time Embedded Framework
Loading...
Searching...
No Matches
qxk.c
Go to the documentation of this file.
1//$file${src::qxk::qxk.c} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
2//
3// Model: qpc.qm
4// File: ${src::qxk::qxk.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::qxk::qxk.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
54// protection against including this source file in a wrong project
55#ifndef QXK_H_
56 #error "Source file included in a project NOT based on the QXK kernel"
57#endif // QXK_H_
58
59Q_DEFINE_THIS_MODULE("qxk")
60
61//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
62// Check for the minimum required QP version
63#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U) % 0x3E8U))
64#error qpc version 7.3.0 or higher required
65#endif
66//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
67
68//$define${QXK::QXK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
69
70//${QXK::QXK-base::priv_} ....................................................
71QXK_Attr QXK_priv_;
72
73//${QXK::QXK-base::schedLock} ................................................
74//! @static @public @memberof QXK
75QSchedStatus QXK_schedLock(uint_fast8_t const ceiling) {
78 QF_MEM_SYS();
79
81
82 QSchedStatus stat; // saved lock status to be returned
83
84 // is the lock ceiling being raised?
85 if (ceiling > QXK_priv_.lockCeil) {
86 QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U)
87 QS_TIME_PRE_(); // timestamp
88 // the previous lock ceiling & new lock ceiling
89 QS_2U8_PRE_((uint8_t)QXK_priv_.lockCeil, (uint8_t)ceiling);
90 QS_END_PRE_()
91
92 // previous status of the lock
93 stat = (QSchedStatus)QXK_priv_.lockHolder;
94 stat |= (QSchedStatus)QXK_priv_.lockCeil << 8U;
95
96 // new status of the lock
97 QXK_priv_.lockHolder = (QXK_priv_.curr != (QActive *)0)
98 ? (uint_fast8_t)QXK_priv_.curr->prio
99 : 0U;
100 QXK_priv_.lockCeil = ceiling;
101 }
102 else {
103 stat = 0xFFU; // scheduler not locked
104 }
105 QF_MEM_APP();
106 QF_CRIT_EXIT();
107
108 return stat; // return the status to be saved in a stack variable
109}
110
111//${QXK::QXK-base::schedUnlock} ..............................................
112//! @static @public @memberof QXK
113void QXK_schedUnlock(QSchedStatus const stat) {
114 // has the scheduler been actually locked by the last QXK_schedLock()?
115 if (stat != 0xFFU) {
116 uint8_t const prevCeil = (uint8_t)(stat >> 8U);
119 QF_MEM_SYS();
120
122 Q_REQUIRE_INCRIT(201, QXK_priv_.lockCeil > prevCeil);
123
124 QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U)
125 QS_TIME_PRE_(); // timestamp
126 // ceiling before unlocking & prio after unlocking
127 QS_2U8_PRE_((uint8_t)QXK_priv_.lockCeil, (uint8_t)prevCeil);
128 QS_END_PRE_()
129
130 // restore the previous lock ceiling and lock holder
131 QXK_priv_.lockCeil = prevCeil;
132 QXK_priv_.lockHolder = (stat & 0xFFU);
133
134 // find if any threads should be run after unlocking the scheduler
135 if (QXK_sched_() != 0U) { // activation needed?
136 QXK_activate_(); // synchronously activate basic-thread(s)
137 }
138
139 QF_MEM_APP();
140 QF_CRIT_EXIT();
141 }
142}
143
144//${QXK::QXK-base::current} ..................................................
145//! @static @public @memberof QXK
146QActive * QXK_current(void) {
149 QF_MEM_SYS();
150
151 Q_REQUIRE_INCRIT(600, QXK_priv_.lockCeil <= QF_MAX_ACTIVE);
152
153 struct QActive *curr = QXK_priv_.curr;
154 if (curr == (QActive *)0) { // basic thread?
155 curr = QActive_registry_[QXK_priv_.actPrio];
156 }
157
158 Q_ASSERT_INCRIT(690, curr != (QActive *)0);
159
160 QF_MEM_APP();
161 QF_CRIT_EXIT();
162
163 return curr;
164}
165
166//${QXK::QXK-base::sched_} ...................................................
167//! @static @private @memberof QXK
168uint_fast8_t QXK_sched_(void) {
169 Q_INVARIANT_INCRIT(402, QPSet_verify_(&QXK_priv_.readySet,
170 &QXK_priv_.readySet_dis));
171
172 QActive const * const curr = QXK_priv_.curr;
173 uint_fast8_t p;
174 if (QPSet_isEmpty(&QXK_priv_.readySet)) {
175 p = 0U; // no activation needed
176 }
177 else {
178 // find the highest-prio thread ready to run
179 p = QPSet_findMax(&QXK_priv_.readySet);
180 if (p <= QXK_priv_.lockCeil) {
181 p = (uint_fast8_t)QActive_registry_[QXK_priv_.lockHolder]->prio;
182 if (p != 0U) {
183 Q_ASSERT_INCRIT(410,
184 QPSet_hasElement(&QXK_priv_.readySet, p));
185 }
186 }
187 }
188 QActive * const next = QActive_registry_[p];
189
190 // is the current thread a basic-thread?
191 if (curr == (QActive *)0) {
192
193 // is the next prio. above the active prio.?
194 if (p > QXK_priv_.actPrio) {
195 QXK_priv_.next = next; // set the next AO to activate
196
197 if (next->osObject != (void *)0) { // is next extended?
199 p = 0U; // no activation needed
200 }
201 }
202 else { // below the active prio.
203 QXK_priv_.next = (QActive *)0;
204 p = 0U; // no activation needed
205 }
206 }
207 else { // currently executing an extended-thread
208 // is the current thread different from the next?
209 if (curr != next) {
210 QXK_priv_.next = next;
212 }
213 else { // current is the same as next
214 QXK_priv_.next = (QActive *)0; // no need to context-switch
215 }
216 p = 0U; // no activation needed
217 }
218 return p;
219}
220
221//${QXK::QXK-base::activate_} ................................................
222//! @static @private @memberof QXK
223void QXK_activate_(void) {
224 uint_fast8_t const prio_in = QXK_priv_.actPrio;
225 QActive *next = QXK_priv_.next; // the next AO (basic-thread) to run
226
227 Q_REQUIRE_INCRIT(500, (next != (QActive *)0)
228 && (prio_in <= QF_MAX_ACTIVE));
229
230 // QXK Context switch callback defined or QS tracing enabled?
231 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
232 QXK_contextSw_(next);
233 #endif // QF_ON_CONTEXT_SW || Q_SPY
234
235 QXK_priv_.next = (QActive *)0; // clear the next AO
236 QXK_priv_.curr = (QActive *)0; // current is basic-thread
237
238 // prio. of the next thread
239 uint_fast8_t p = (uint_fast8_t)next->prio;
240
241 // loop until no more ready-to-run AOs of higher prio than the initial
242 do {
243 QXK_priv_.actPrio = p; // next active prio
244
245 QF_MEM_APP();
246 QF_INT_ENABLE(); // unconditionally enable interrupts
247
248 QEvt const * const e = QActive_get_(next);
249 // NOTE QActive_get_() performs QS_MEM_APP() before return
250
251 // dispatch event (virtual call)
252 (*next->super.vptr->dispatch)(&next->super, e, p);
253 #if (QF_MAX_EPOOL > 0U)
254 QF_gc(e);
255 #endif
256
257 QF_INT_DISABLE(); // unconditionally disable interrupts
258 QF_MEM_SYS();
259
260 // check internal integrity (duplicate inverse storage)
261 Q_INVARIANT_INCRIT(502, QPSet_verify_(&QXK_priv_.readySet,
262 &QXK_priv_.readySet_dis));
263
264 if (next->eQueue.frontEvt == (QEvt *)0) { // empty queue?
265 QPSet_remove(&QXK_priv_.readySet, p);
266 #ifndef Q_UNSAFE
267 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
268 #endif
269 }
270
271 if (QPSet_isEmpty(&QXK_priv_.readySet)) {
272 QXK_priv_.next = (QActive *)0;
273 next = QActive_registry_[0];
274 p = 0U; // no activation needed
275 }
276 else {
277 // find next highest-prio below the lock ceiling
278 p = (uint8_t)QPSet_findMax(&QXK_priv_.readySet);
279 if (p <= QXK_priv_.lockCeil) {
280 p = QXK_priv_.lockHolder; // thread holding lock
281 if (p != 0U) {
282 Q_ASSERT_INCRIT(510,
283 QPSet_hasElement(&QXK_priv_.readySet, p));
284 }
285 }
286
287 // set the next thread and ensure that it is registered
288 next = QActive_registry_[p];
289 Q_ASSERT_INCRIT(520, next != (QActive *)0);
290
291 // is next a basic thread?
292 if (next->osObject == (void *)0) {
293 // is the next prio. above the initial prio.?
294 if (p > QActive_registry_[prio_in]->prio) {
295 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
296 if (p != QXK_priv_.actPrio) { // changing threads?
297 QXK_contextSw_(next);
298 }
299 #endif // QF_ON_CONTEXT_SW || Q_SPY
300 QXK_priv_.next = next;
301 }
302 else {
303 QXK_priv_.next = (QActive *)0;
304 p = 0U; // no activation needed
305 }
306 }
307 else { // next is the extended-thread
308 QXK_priv_.next = next;
310 p = 0U; // no activation needed
311 }
312 }
313 } while (p != 0U); // while activation needed
314
315 // restore the active prio.
316 QXK_priv_.actPrio = prio_in;
317
318 #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY)
319 if (next->osObject == (void *)0) {
320 QXK_contextSw_((prio_in == 0U)
321 ? (QActive *)0
322 : QActive_registry_[prio_in]);
323 }
324 #endif // QF_ON_CONTEXT_SW || Q_SPY
325}
326
327//${QXK::QXK-base::contextSw_} ...............................................
328//! @static @public @memberof QXK
329void QXK_contextSw_(QActive * const next) {
330 #ifdef Q_SPY
331 uint8_t const prev_prio = (QXK_priv_.prev != (QActive *)0)
332 ? QXK_priv_.prev->prio
333 : 0U;
334 if (next != (QActive *)0) { // next is NOT idle?
335 QS_BEGIN_PRE_(QS_SCHED_NEXT, next->prio)
336 QS_TIME_PRE_(); // timestamp
337 QS_2U8_PRE_(next->prio, prev_prio);
338 QS_END_PRE_()
339 }
340 else { // going to idle
341 QS_BEGIN_PRE_(QS_SCHED_IDLE, prev_prio)
342 QS_TIME_PRE_(); // timestamp
343 QS_U8_PRE_(prev_prio);
344 QS_END_PRE_()
345 }
346 #endif // Q_SPY
347
348 #ifdef QF_ON_CONTEXT_SW
349 QF_onContextSw(QXK_priv_.prev, next);
350 #endif // QF_ON_CONTEXT_SW
351
352 QXK_priv_.prev = next; // update the previous thread
353}
354
355//${QXK::QXK-base::threadExit_} ..............................................
356//! @static @private @memberof QXK
357void QXK_threadExit_(void) {
360
361 QXThread const * const thr = QXTHREAD_CAST_(QXK_priv_.curr);
362
364 && (thr != (QXThread *)0)); // current thread must be extended
366 QXK_priv_.lockHolder != (uint_fast8_t)thr->super.prio);
367
368 uint_fast8_t const p = (uint_fast8_t)thr->super.prio;
369
370 QF_MEM_SYS();
371 QActive_registry_[p] = (QActive *)0;
372 QPSet_remove(&QXK_priv_.readySet, p);
373 #ifndef Q_UNSAFE
374 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
375 #endif
376
377 (void)QXK_sched_(); // schedule other threads
378
379 QF_MEM_APP();
380 QF_CRIT_EXIT();
381}
382//$enddef${QXK::QXK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
383
384//$define${QXK::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
385
386//${QXK::QF-cust::init} ......................................................
387//! @static @public @memberof QF
388void QF_init(void) {
389 QF_bzero_(&QF_priv_, sizeof(QF_priv_));
390 QF_bzero_(&QXK_priv_, sizeof(QXK_priv_));
391 QF_bzero_(&QActive_registry_[0], sizeof(QActive_registry_));
392
393 // setup the QXK scheduler as initially locked and not running
394 QXK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked
395
396 #ifndef Q_UNSAFE
397 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
398 #endif
399
400 for (uint_fast8_t tickRate = 0U;
401 tickRate < Q_DIM(QTimeEvt_timeEvtHead_);
402 ++tickRate)
403 {
404 QTimeEvt_ctorX(&QTimeEvt_timeEvtHead_[tickRate],
405 (QActive *)0, (enum_t)Q_USER_SIG, tickRate);
406 }
407
408 // QXK idle AO object (const in ROM)
409 static QActive const idle_ao = { (struct QAsmVtable const *)0 };
410
411 // register the idle AO object (cast 'const' away)
412 QActive_registry_[0] = QACTIVE_CAST_(&idle_ao);
413 QXK_priv_.prev = QActive_registry_[0];
414
415 #ifdef QXK_INIT
416 QXK_INIT(); // port-specific initialization of the QXK kernel
417 #endif
418}
419
420//${QXK::QF-cust::stop} ......................................................
421//! @static @public @memberof QF
422void QF_stop(void) {
423 QF_onCleanup(); // application-specific cleanup callback
424 // nothing else to do for the dual-mode QXK kernel
425}
426
427//${QXK::QF-cust::run} .......................................................
428//! @static @public @memberof QF
429int_t QF_run(void) {
430 #ifdef Q_SPY
433
434 // produce the QS_QF_RUN trace record
436 QF_MEM_SYS();
437 QS_beginRec_((uint_fast8_t)QS_QF_RUN);
438 QS_endRec_();
439 QF_MEM_APP();
441 #endif // Q_SPY
442
443 QF_onStartup(); // application-specific startup callback
444
446 QF_MEM_SYS();
447
448 #ifdef QXK_START
449 QXK_START(); // port-specific startup of the QXK kernel
450 #endif
451
452 QXK_priv_.lockCeil = 0U; // unlock the QXK scheduler
453
454 // activate AOs to process events posted so far
455 if (QXK_sched_() != 0U) {
456 QXK_activate_();
457 }
458
459 QF_MEM_APP();
461
462 for (;;) { // QXK idle loop...
463 QXK_onIdle(); // application-specific QXK idle callback
464 }
465
466 #ifdef __GNUC__ // GNU compiler?
467 return 0;
468 #endif
469}
470//$enddef${QXK::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
471
472//$define${QXK::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
473
474//${QXK::QActive} ............................................................
475
476//${QXK::QActive::start_} ....................................................
477//! @public @memberof QActive
478void QActive_start_(QActive * const me,
479 QPrioSpec const prioSpec,
480 QEvt const * * const qSto,
481 uint_fast16_t const qLen,
482 void * const stkSto,
483 uint_fast16_t const stkSize,
484 void const * const par)
485{
489 && ((prioSpec & 0xFF00U) == 0U));
490 QF_CRIT_EXIT();
491
492 me->prio = (uint8_t)(prioSpec & 0xFFU); // QF-prio. of the AO
493 me->pthre = 0U; // not used
494 QActive_register_(me); // make QF aware of this active object
495
496 if (stkSto == (void *)0) { // starting basic thread (AO)?
497
498 QEQueue_init(&me->eQueue, qSto, qLen); // init the built-in queue
499 me->osObject = (void *)0; // no private stack for AO
500
501 // top-most initial tran. (virtual call)
502 (*me->super.vptr->init)(&me->super, par, me->prio);
503 QS_FLUSH(); // flush the trace buffer to the host
504
505 // see if this AO needs to be scheduled if QXK is already running
507 QF_MEM_SYS();
508 if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) { // scheduler running?
509 if (QXK_sched_() != 0U) { // activation needed?
510 QXK_activate_(); // synchronously activate basic-thread(s)
511 }
512 }
513 QF_MEM_APP();
514 QF_CRIT_EXIT();
515 }
516 else { // starting QXThread
517
518 // is storage for the queue buffer provided?
519 if (qSto != (QEvt const **)0) {
520 QEQueue_init(&me->eQueue, qSto, qLen);
521 }
522
523 // extended thread constructor puts the thread handler in place of
524 // the top-most initial tran. 'me->super.temp.act'
525 QXThread_stackInit_(me, me->super.temp.thr, stkSto, stkSize);
526
527 // the new thread is not blocked on any object
528 me->super.temp.obj = (QMState *)0;
529
531 QF_MEM_SYS();
532
533 // extended-thread becomes ready immediately
534 QPSet_insert(&QXK_priv_.readySet, (uint_fast8_t)me->prio);
535 #ifndef Q_UNSAFE
536 QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis);
537 #endif
538
539 // see if this thread needs to be scheduled in case QXK is running
540 if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) {
541 (void)QXK_sched_(); // schedule other threads
542 }
543 QF_MEM_APP();
544 QF_CRIT_EXIT();
545 }
546}
547//$enddef${QXK::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
QF_Attr QF_priv_
Definition qf_act.c:71
uint_fast8_t QSchedStatus
Definition qk.h:60
#define QF_MEM_APP()
Definition qp.h:1288
@ Q_USER_SIG
offset for the user signals (QP Application)
Definition qp.h:263
#define QF_MEM_SYS()
Definition qp.h:1283
int int_t
Definition qp.h:104
int enum_t
Definition qp.h:107
#define Q_DIM(array_)
Definition qp.h:539
uint16_t QPrioSpec
Definition qp.h:623
#define QF_MAX_ACTIVE
Maximum # Active Objects in the system (1..64)
Definition qp_config.h:113
Internal (package scope) QP/C interface.
#define QACTIVE_CAST_(ptr_)
Definition qp_pkg.h:96
Sample QP/C port.
#define QXK_ISR_CONTEXT_()
Check if the code executes in the ISR context.
Definition qp_port.h:131
#define QXK_CONTEXT_SWITCH_()
Trigger context switch (used internally in QXK only)
Definition qp_port.h:134
#define QF_INT_DISABLE()
Disable interrupts.
Definition qp_port.h:37
#define QF_INT_ENABLE()
Enable interrupts.
Definition qp_port.h:40
@ QS_QF_RUN
QF_run() was entered.
Definition qs.h:179
#define QS_TIME_PRE_()
Definition qs.h:450
@ QS_SCHED_IDLE
scheduler restored the idle task
Definition qs.h:156
#define QS_SIG_DICTIONARY(sig_, obj_)
Definition qs.h:505
@ QS_SCHED_LOCK
scheduler was locked
Definition qs.h:153
@ QS_SCHED_UNLOCK
scheduler was unlocked
Definition qs.h:154
#define QS_FLUSH()
Definition qs.h:363
@ QS_SCHED_NEXT
scheduler started next task
Definition qs.h:155
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_INVARIANT_INCRIT(id_, expr_)
Definition qsafe.h:154
#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
int_t QF_run(void)
Definition qutest.c:191
void QF_init(void)
Definition qutest.c:172
void QF_stop(void)
Definition qutest.c:186
uint_fast16_t QSchedStatus
Definition qxk.h:60
#define QXTHREAD_CAST_(ptr_)
Definition qxk.h:366
@ QXK_TIMEOUT_SIG
Definition qxk.h:392
@ QXK_DELAY_SIG
Definition qxk.h:391
Active object class (based on the QHsm implementation strategy)
Definition qp.h:804
QEvt const * QActive_get_(QActive *const me)
Definition qf_actq.c:323
QACTIVE_OS_OBJ_TYPE osObject
Definition qp.h:821
QACTIVE_EQUEUE_TYPE eQueue
Definition qp.h:826
QAsm super
Definition qp.h:806
QActive * QActive_registry_[QF_MAX_ACTIVE+1U]
Definition qp.h:843
uint8_t prio
Definition qp.h:809
uint8_t pthre
Definition qp.h:812
struct QAsmVtable const * vptr
Definition qp.h:284
union QAsmAttr temp
Definition qp.h:292
Virtual table for the QAsm class.
Definition qp.h:301
void(* init)(QAsm *const me, void const *const e, uint_fast8_t const qsId)
Definition qp.h:302
void(* dispatch)(QAsm *const me, QEvt const *const e, uint_fast8_t const qsId)
Definition qp.h:304
Event class.
Definition qp.h:145
State object for the QMsm class (QM State Machine).
Definition qp.h:242
Private attributes of the QXK kernel.
Definition qxk.h:73
eXtended (blocking) thread of the QXK preemptive kernel
Definition qxk.h:145
QActive super
Definition qxk.h:147
QXThreadHandler thr
Definition qp.h:270
struct QMState const * obj
Definition qp.h:272