QP/C  6.1.1
qxk_xthr.c
Go to the documentation of this file.
1 
40 #define QP_IMPL /* this is QP implementation */
41 #include "qf_port.h" /* QF port */
42 #include "qxk_pkg.h" /* QXK package-scope internal interface */
43 #include "qassert.h" /* QP embedded systems-friendly assertions */
44 #ifdef Q_SPY /* QS software tracing enabled? */
45  #include "qs_port.h" /* include QS port */
46 #else
47  #include "qs_dummy.h" /* disable the QS software tracing */
48 #endif /* Q_SPY */
49 
50 /* protection against including this source file in a wrong project */
51 #ifndef qxk_h
52  #error "Source file included in a project NOT based on the QXK kernel"
53 #endif /* qxk_h */
54 
55 Q_DEFINE_THIS_MODULE("qxk_xthr")
56 
57 /****************************************************************************/
58 static void QXThread_init_(QMsm * const me, QEvt const * const e);
59 static void QXThread_dispatch_(QMsm * const me, QEvt const * const e);
60 static void QXThread_start_(QActive * const me, uint_fast8_t prio,
61  QEvt const *qSto[], uint_fast16_t qLen,
62  void *stkSto, uint_fast16_t stkSize,
63  QEvt const *ie);
64 #ifndef Q_SPY
65 static bool QXThread_post_(QActive * const me, QEvt const * const e,
66  uint_fast16_t const margin);
67 #else
68 static bool QXThread_post_(QActive * const me, QEvt const * const e,
69  uint_fast16_t const margin, void const * const sender);
70 #endif
71 static void QXThread_postLIFO_(QActive * const me, QEvt const * const e);
72 
73 
74 /****************************************************************************/
94 void QXThread_ctor(QXThread * const me,
95  QXThreadHandler handler, uint_fast8_t tickRate)
96 {
97  static QXThreadVtbl const vtbl = { /* QXThread virtual table */
98  { &QXThread_init_, /* not used in QXThread */
99  &QXThread_dispatch_ }, /* not used in QXThread */
103  };
104 
105  QActive_ctor(&me->super, Q_STATE_CAST(handler)); /* superclass' ctor */
106  me->super.super.vptr = &vtbl.super; /* set the vptr to QXThread v-table */
107  me->super.super.state.act = Q_ACTION_CAST(0); /*mark as extended thread */
108 
109  /* construct the time event member added in the QXThread class */
110  QTimeEvt_ctorX(&me->timeEvt, &me->super, (enum_t)QXK_DELAY_SIG, tickRate);
111 }
112 
113 /****************************************************************************/
114 /* QXThread virtual function implementations... */
115 static void QXThread_init_(QMsm * const me, QEvt const * const e) {
116  (void)me;
117  (void)e;
118  Q_ERROR_ID(110);
119 }
120 
121 /****************************************************************************/
122 static void QXThread_dispatch_(QMsm * const me, QEvt const * const e) {
123  (void)me;
124  (void)e;
125  Q_ERROR_ID(120);
126 }
127 
128 /****************************************************************************/
153 static void QXThread_start_(QActive * const me, uint_fast8_t prio,
154  QEvt const *qSto[], uint_fast16_t qLen,
155  void *stkSto, uint_fast16_t stkSize,
156  QEvt const *ie)
157 {
159 
166  Q_REQUIRE_ID(200, (!QXK_ISR_CONTEXT_()) /* don't call from an ISR! */
168  && (stkSto != (void *)0) /* stack must be provided */
169  && (stkSize != (uint_fast16_t)0)
170  && (me->super.state.act == (QActionHandler)0));
171 
172  (void)ie; /* parameter not referenced */
173 
174  /* is storage for the queue buffer provided? */
175  if (qSto != (QEvt const **)0) {
176  QEQueue_init(&me->eQueue, qSto, qLen);
177  }
178 
179  /* extended thread constructor puts the thread handler in place of
180  * the top-most initial transition 'me->super.temp.act'
181  */
182  QXK_stackInit_(me, Q_XTHREAD_CAST(me->super.temp.act), stkSto, stkSize);
183 
184  me->prio = (uint8_t)prio;
185  me->startPrio = (uint8_t)prio;
186 
187  /* the new thread is not blocked on any object */
188  me->super.temp.obj = (QMState const *)0;
189 
190  QF_add_(me); /* make QF aware of this extended thread */
191 
192  QF_CRIT_ENTRY_();
193  /* extended-thread becomes ready immediately */
195 
196  /* see if this thread needs to be scheduled in case QXK is running */
197  (void)QXK_sched_();
198  QF_CRIT_EXIT_();
199 }
200 
201 /****************************************************************************/
238 #ifndef Q_SPY
239 static bool QXThread_post_(QActive * const me, QEvt const * const e,
240  uint_fast16_t const margin)
241 #else
242 static bool QXThread_post_(QActive * const me, QEvt const * const e,
243  uint_fast16_t const margin,
244  void const * const sender)
245 #endif
246 {
247  bool status;
249 
250  /* is it the private time event? */
251  if (e == &((QXThread *)me)->timeEvt.super) {
252  QF_CRIT_ENTRY_();
253  /* the private time event is disarmed and not in any queue,
254  * so it is safe to change its signal. The signal of 0 means
255  * that the time event has expired.
256  */
257  ((QXThread *)me)->timeEvt.super.sig = (QSignal)0;
258 
260  QF_CRIT_EXIT_();
261 
262  status = true;
263  }
264  /* is the event queue provided? */
265  else if (me->eQueue.end != (QEQueueCtr)0) {
266  QEQueueCtr nFree; /* temporary to avoid UB for volatile access */
267 
269  Q_REQUIRE_ID(300, e != (QEvt const *)0);
270 
271  QF_CRIT_ENTRY_();
272 
273  nFree = me->eQueue.nFree; /* get volatile into the temporary */
274 
275  /* margin available? */
276  if (((margin == QF_NO_MARGIN) && (nFree > (QEQueueCtr)0))
277  || (nFree > (QEQueueCtr)margin))
278  {
279 
281  QS_priv_.locFilter[AO_OBJ], me)
282  QS_TIME_(); /* timestamp */
283  QS_OBJ_(sender); /* the sender object */
284  QS_SIG_(e->sig); /* the signal of the event */
285  QS_OBJ_(me); /* this active object (recipient) */
286  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
287  QS_EQC_(nFree); /* number of free entries */
288  QS_EQC_(me->eQueue.nMin); /* min number of free entries */
290 
291  /* is it a pool event? */
292  if (e->poolId_ != (uint8_t)0) {
293  QF_EVT_REF_CTR_INC_(e); /* increment the reference counter */
294  }
295 
296  --nFree; /* one free entry just used up */
297  me->eQueue.nFree = nFree; /* update the volatile */
298  if (me->eQueue.nMin > nFree) {
299  me->eQueue.nMin = nFree; /* update minimum so far */
300  }
301 
302  /* queue empty? */
303  if (me->eQueue.frontEvt == (QEvt const *)0) {
304  me->eQueue.frontEvt = e; /* deliver event directly */
305 
306  /* is this thread blocked on the queue? */
307  if (me->super.temp.obj == (QMState const *)&me->eQueue) {
308  (void)QXThread_teDisarm_((QXThread *)me);
310  if (!QXK_ISR_CONTEXT_()) {
311  (void)QXK_sched_();
312  }
313  }
314  }
315  /* queue is not empty, insert event into the ring-buffer */
316  else {
317  /* insert event into the ring buffer (FIFO) */
318  QF_PTR_AT_(me->eQueue.ring, me->eQueue.head) = e;
319  if (me->eQueue.head == (QEQueueCtr)0) { /*need to wrap head?*/
320  me->eQueue.head = me->eQueue.end; /* wrap around */
321  }
322  --me->eQueue.head; /* advance the head (counter clockwise) */
323  }
324  QF_CRIT_EXIT_();
325 
326  status = true; /* event posted successfully */
327  }
328  else {
332  Q_ASSERT_ID(310, margin != QF_NO_MARGIN);
333 
335  QS_priv_.locFilter[AO_OBJ], me)
336  QS_TIME_(); /* timestamp */
337  QS_OBJ_(sender); /* the sender object */
338  QS_SIG_(e->sig); /* the signal of the event */
339  QS_OBJ_(me); /* this active object (recipient) */
340  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
341  QS_EQC_(nFree); /* number of free entries */
342  QS_EQC_((QEQueueCtr)margin); /* margin requested */
344 
345  QF_CRIT_EXIT_();
346 
347  QF_gc(e); /* recycle the event to avoid a leak */
348  status = false; /* event not posted */
349  }
350  }
351  else { /* the queue is not available */
352  QF_gc(e); /* make sure the event is not leaked */
353  status = false;
354  Q_ERROR_ID(320); /* this extended thread cannot accept events */
355  }
356 
357  return status;
358 }
359 
360 /****************************************************************************/
371 static void QXThread_postLIFO_(QActive * const me, QEvt const * const e) {
372  (void)me;
373  (void)e;
374  Q_ERROR_ID(410);
375 }
376 
377 /****************************************************************************/
396 QEvt const *QXThread_queueGet(uint_fast16_t const nTicks) {
397  QXThread *thr;
398  QEQueueCtr nFree;
399  QEvt const *e;
401 
402  QF_CRIT_ENTRY_();
403  thr = (QXThread *)QXK_attr_.curr;
404 
411  Q_REQUIRE_ID(500, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
412  && (thr != (QXThread *)0) /* current thread must be extended */
413  && (QXK_attr_.lockHolder != thr->super.prio) /* not holding a lock */
414  && (thr->super.super.temp.obj == (QMState *)0)); /* not blocked */
415 
416  /* is the queue empty? */
417  if (thr->super.eQueue.frontEvt == (QEvt *)0) {
418 
419  /* remember the blocking object (the thread's queue) */
420  thr->super.super.temp.obj = (QMState const *)&thr->super.eQueue;
421 
422  QXThread_teArm_(thr, (QSignal)QXK_QUEUE_SIG, nTicks);
424  (void)QXK_sched_();
425  QF_CRIT_EXIT_();
426  QF_CRIT_EXIT_NOP(); /* BLOCK here */
427 
428  QF_CRIT_ENTRY_();
429  /* the blocking object must be this queue */
430  Q_ASSERT_ID(510, thr->super.super.temp.obj
431  == (QMState const *)&thr->super.eQueue);
432  thr->super.super.temp.obj = (QMState const *)0; /* clear */
433  }
434 
435  /* is the queue not empty? */
436  if (thr->super.eQueue.frontEvt != (QEvt *)0) {
437  e = thr->super.eQueue.frontEvt; /* always remove from the front */
438  nFree= thr->super.eQueue.nFree +(QEQueueCtr)1; /* volatile into tmp */
439  thr->super.eQueue.nFree = nFree; /* update the number of free */
440 
441  /* any events in the ring buffer? */
442  if (nFree <= thr->super.eQueue.end) {
443 
444  /* remove event from the tail */
445  thr->super.eQueue.frontEvt =
446  QF_PTR_AT_(thr->super.eQueue.ring, thr->super.eQueue.tail);
447  if (thr->super.eQueue.tail == (QEQueueCtr)0) { /* need to wrap? */
448  thr->super.eQueue.tail = thr->super.eQueue.end; /* wrap */
449  }
450  --thr->super.eQueue.tail;
451 
453  QS_priv_.locFilter[AO_OBJ], thr)
454  QS_TIME_(); /* timestamp */
455  QS_SIG_(e->sig); /* the signal of this event */
456  QS_OBJ_(&thr->super); /* this active object */
457  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
458  QS_EQC_(nFree); /* number of free entries */
460  }
461  else {
462  thr->super.eQueue.frontEvt = (QEvt const *)0; /* empty queue */
463 
464  /* all entries in the queue must be free (+1 for fronEvt) */
465  Q_ASSERT_ID(520, nFree == (thr->super.eQueue.end +(QEQueueCtr)1));
466 
468  QS_priv_.locFilter[AO_OBJ], thr)
469  QS_TIME_(); /* timestamp */
470  QS_SIG_(e->sig); /* the signal of this event */
471  QS_OBJ_(&thr->super); /* this active object */
472  QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */
474  }
475  }
476  else { /* the queue is still empty -- the timeout must have fired */
477  e = (QEvt const *)0;
478  }
479  QF_CRIT_EXIT_();
480 
481  return e;
482 }
483 
484 /****************************************************************************/
492 void QXThread_block_(QXThread const * const me) {
494  Q_REQUIRE_ID(600, (QXK_attr_.lockHolder != me->super.prio));
495 
497  (void)QXK_sched_();
498 }
499 
500 /****************************************************************************/
508 void QXThread_unblock_(QXThread const * const me) {
510  if ((!QXK_ISR_CONTEXT_()) /* not inside ISR? */
511  && (QF_active_[0] != (QActive *)0)) /* kernel started? */
512  {
513  (void)QXK_sched_();
514  }
515 }
516 
517 /****************************************************************************/
526 void QXThread_teArm_(QXThread * const me, QSignal sig,
527  uint_fast16_t const nTicks)
528 {
530  Q_REQUIRE_ID(700, me->timeEvt.ctr == (QTimeEvtCtr)0);
531 
532  me->timeEvt.super.sig = sig;
533 
534  if (nTicks != QXTHREAD_NO_TIMEOUT) {
535  me->timeEvt.ctr = (QTimeEvtCtr)nTicks;
536  me->timeEvt.interval = (QTimeEvtCtr)0;
537 
538  /* is the time event unlinked?
539  * NOTE: For the duration of a single clock tick of the specified tick
540  * rate a time event can be disarmed and yet still linked in the list,
541  * because un-linking is performed exclusively in QF_tickX().
542  */
543  if ((me->timeEvt.super.refCtr_ & (uint8_t)0x80) == (uint8_t)0) {
544  uint_fast8_t tickRate = (uint_fast8_t)me->timeEvt.super.refCtr_;
545  me->timeEvt.super.refCtr_ |= (uint8_t)0x80; /* mark as linked */
546 
547  /* The time event is initially inserted into the separate
548  * "freshly armed" list based on QF_timeEvtHead_[tickRate].act.
549  * Only later, inside the QF_tickX() function, the "freshly armed"
550  * list is appended to the main list of armed time events based on
551  * QF_timeEvtHead_[tickRate].next. Again, this is to keep any
552  * changes to the main list exclusively inside QF_tickX().
553  */
554  me->timeEvt.next = (QTimeEvt *)QF_timeEvtHead_[tickRate].act;
555  QF_timeEvtHead_[tickRate].act = &me->timeEvt;
556  }
557  }
558 }
559 
560 /****************************************************************************/
568 bool QXThread_teDisarm_(QXThread * const me) {
569  bool wasArmed;
570  /* is the time evt running? */
571  if (me->timeEvt.ctr != (QTimeEvtCtr)0) {
572  wasArmed = true;
573  me->timeEvt.ctr = (QTimeEvtCtr)0; /* schedule removal from list */
574  }
575  /* the time event was already automatically disarmed */
576  else {
577  wasArmed = false;
578  }
579  return wasArmed;
580 }
581 
582 /****************************************************************************/
584 bool QXThread_delay(uint_fast16_t const nTicks) {
585  QXThread *thr;
587 
588  QF_CRIT_ENTRY_();
589  thr = (QXThread *)QXK_attr_.curr;
590 
597  Q_REQUIRE_ID(800, (!QXK_ISR_CONTEXT_()) /* can't block inside an ISR */
598  && (thr != (QXThread *)0) /* current thread must be extended */
599  && (QXK_attr_.lockHolder != thr->super.prio) /* not holding a lock */
600  && (thr->super.super.temp.obj == (QMState *)0)); /* not blocked */
601 
602  /* remember the blocking object */
603  thr->super.super.temp.obj = (QMState const *)&thr->timeEvt;
604  QXThread_teArm_(thr, (QSignal)QXK_DELAY_SIG, nTicks);
605  QXThread_block_(thr);
606  QF_CRIT_EXIT_();
607  QF_CRIT_EXIT_NOP(); /* BLOCK here */
608 
609  QF_CRIT_ENTRY_();
610  /* the blocking object must be the time event */
611  Q_ENSURE_ID(890, thr->super.super.temp.obj
612  == (QMState const *)&thr->timeEvt);
613  thr->super.super.temp.obj = (QMState const *)0; /* clear */
614  QF_CRIT_EXIT_();
615 
616  /* signal of zero means that the time event was posted without
617  * being canceled.
618  */
619  return (bool)(thr->timeEvt.super.sig == (QSignal)0);
620 }
621 
622 /****************************************************************************/
624 bool QXThread_delayCancel(QXThread * const me) {
625  bool wasArmed;
627 
628  QF_CRIT_ENTRY_();
629  if (me->super.super.temp.obj == (QMState const *)&me->timeEvt) {
630  wasArmed = QXThread_teDisarm_(me);
631  QXThread_unblock_(me);
632  }
633  else {
634  wasArmed = false;
635  }
636  QF_CRIT_EXIT_();
637 
638  return wasArmed;
639 }
640 
641 /****************************************************************************/
652 void QXK_threadRet_(void) {
653  QXThread *thr;
654  uint_fast8_t p;
656 
657  QF_CRIT_ENTRY_();
658  thr = (QXThread *)QXK_attr_.curr;
659 
666  Q_REQUIRE_ID(900, (!QXK_ISR_CONTEXT_()) /* can't be in the ISR context */
667  && (thr != (QXThread *)0) /* current thread must be extended */
668  && (QXK_attr_.lockHolder != thr->super.prio) /* not holding a lock */
669  && (thr->super.super.temp.obj == (QMState *)0)); /* not blocked */
670 
671  p = (uint_fast8_t)thr->super.startPrio;
672 
673  /* remove this thread from the QF */
674  QF_active_[p] = (QActive *)0;
676  (void)QXK_sched_();
677  QF_CRIT_EXIT_();
678 }
#define QS_2U8_(data1_, data2_)
Internal QS macro to output 2 unformatted uint8_t data elements.
Definition: qs.h:708
QXK_Attr QXK_attr_
global attributes of the QXK kernel
Definition: qxk.c:58
#define QF_CRIT_EXIT_NOP()
No-operation for exiting a critical section.
Definition: qf.h:810
uint8_t prio
QF priority (1..QF_MAX_ACTIVE) of this active object.
Definition: qf.h:153
QEvt const * QXThread_queueGet(uint_fast16_t const nTicks)
obtain a message from the private message queue (block if no messages)
Definition: qxk_xthr.c:396
void QF_add_(QActive *const a)
Register an active object to be managed by the framework.
Definition: qf_act.c:69
QSignal sig
signal of the event instance
Definition: qep.h:154
Internal (package scope) QXK/C interface.
void *volatile act
the active object that receives the time events
Definition: qf.h:463
#define Q_ENSURE_ID(id_, test_)
Assertion for checking postconditions with user-specified assertion-id.
Definition: qassert.h:273
uint8_t volatile lockHolder
prio of the lock holder
Definition: qxk.h:86
Time Event structure.
Definition: qf.h:456
#define QF_CRIT_ENTRY_()
This is an internal macro for entering a critical section.
Definition: qf_pkg.h:69
struct QActive *volatile curr
current thread pointer (NULL=basic)
Definition: qxk.h:82
struct QTimeEvt *volatile next
link to the next time event in the list
Definition: qf.h:460
void(* QXThreadHandler)(QXThread *const me)
Thread handler pointer-to-function.
Definition: qxthread.h:107
struct QHsmVtbl const * vptr
virtual pointer
Definition: qep.h:282
AO got an event and its queue is empty.
Definition: qs.h:88
#define QXTHREAD_NO_TIMEOUT
no-timeout special timeout value when blocking on queues or semaphores
Definition: qxthread.h:154
#define Q_XTHREAD_CAST(handler_)
Perform cast to QXThreadHandler.
Definition: qxthread.h:163
#define QXK_ISR_CONTEXT_()
Internal macro that reports the execution context (ISR vs.
Definition: qxk.h:174
void QXThread_teArm_(QXThread *const me, QSignal sig, uint_fast16_t const nTicks)
internal function to arm the private time event for a given thread.
Definition: qxk_xthr.c:526
AO got an event and its queue is not empty.
Definition: qs.h:87
an event was posted (FIFO) directly to AO
Definition: qs.h:85
Virtual table for the QActive class.
Definition: qf.h:166
#define QF_CRIT_STAT_
This is an internal macro for defining the critical section status type.
Definition: qf_pkg.h:57
#define QS_BEGIN_NOCRIT_(rec_, objFilter_, obj_)
Internal macro to begin a QS record without entering critical section.
Definition: qs.h:686
#define Q_DEFINE_THIS_MODULE(name_)
Define the user-specified module name for assertions in this file.
Definition: qassert.h:101
unsigned char uint8_t
exact-width 8-bit unsigned int
Definition: stdint.h:28
void QTimeEvt_ctorX(QTimeEvt *const me, QActive *const act, enum_t const sig, uint_fast8_t tickRate)
The extended "constructor" to initialize a Time Event.
Definition: qf_time.c:232
eXtended (blocking) thread of the QXK preemptive kernel
Definition: qxthread.h:71
uint8_t QEQueueCtr
The data type to store the ring-buffer counters based on the macro QF_EQUEUE_CTR_SIZE.
Definition: qequeue.h:76
#define Q_STATE_CAST(handler_)
Perform cast to QStateHandler.
Definition: qep.h:227
uint_fast8_t QXK_sched_(void)
QXK scheduler finds the highest-priority thread ready to run.
Definition: qxk.c:371
union QHsmAttr state
current active state (state-variable)
Definition: qep.h:283
unsigned int uint_fast8_t
fast at-least 8-bit unsigned int
Definition: stdint.h:35
int enum_t
typedef for enumerations used for event signals
Definition: qep.h:76
uint16_t QSignal
QSignal represents the signal of an event.
Definition: qep.h:130
QPSet readySet
ready-set of basic and extended threads
Definition: qxk.h:89
static bool QXThread_post_(QActive *const me, QEvt const *const e, uint_fast16_t const margin, void const *const sender)
Definition: qxk_xthr.c:242
void QF_gc(QEvt const *const e)
Recycle a dynamic event.
Definition: qf_dyn.c:217
Event structure.
Definition: qep.h:153
void QEQueue_init(QEQueue *const me, QEvt const *qSto[], uint_fast16_t const qLen)
Initialize the native QF event queue.
Definition: qf_qeq.c:70
QHsm super
inherits QHsm
Definition: qf.h:111
#define QPSet_insert(me_, n_)
Insert element n_ into the set me_, n_= 1..32.
Definition: qpset.h:74
uint8_t volatile refCtr_
reference counter
Definition: qep.h:156
State object for the QMsm class (QM State Machine).
Definition: qep.h:402
attempt to post an evt to AO failed
Definition: qs.h:116
uint8_t poolId_
pool ID (0 for static event)
Definition: qep.h:155
QActionHandler act
pointer to an action-handler function
Definition: qep.h:251
bool QXThread_teDisarm_(QXThread *const me)
internal function to disarm the private time event for a given thread.
Definition: qxk_xthr.c:568
#define Q_ASSERT_ID(id_, test_)
General purpose assertion with user-specified assertion-id.
Definition: qassert.h:136
Definition: qep.h:281
void const * locFilter[MAX_OBJ]
local QS filters
Definition: qs.h:1069
static void QXThread_postLIFO_(QActive *const me, QEvt const *const e)
Definition: qxk_xthr.c:371
active object
Definition: qs.h:1058
#define QF_EVT_REF_CTR_INC_(e_)
increment the refCtr of an event e_ casting const away
Definition: qf_pkg.h:108
QTimeEvtCtr interval
the interval for periodic time event (zero for one-shot time event)
Definition: qf.h:481
QState(* QActionHandler)(void *const me)
Pointer to an action-handler function.
Definition: qep.h:215
unsigned int uint_fast16_t
fast at-least 16-bit unsigned int
Definition: stdint.h:37
#define QF_MAX_ACTIVE
The maximum number of active objects in the application.
Definition: qf_port.h:58
void QActive_ctor(QActive *const me, QStateHandler initial)
protected "constructor" of an QActive active object
Definition: qf_qact.c:65
Customizable and memory-efficient assertions for embedded systems.
#define Q_REQUIRE_ID(id_, test_)
Assertion for checking preconditions with user-specified assertion-id.
Definition: qassert.h:254
bool QXThread_delay(uint_fast16_t const nTicks)
delay (timed block) the current extended thread (static, no me-pointer)
Definition: qxk_xthr.c:584
#define QS_OBJ_(obj_)
Internal macro to output an unformatted object pointer data element.
Definition: qs.h:744
QTimeEvt QF_timeEvtHead_[QF_MAX_TICK_RATE]
heads of linked lists of time events, one for every clock tick rate
Definition: qf_time.c:53
#define QF_PTR_AT_(base_, i_)
access element at index i_ from the base pointer base_
Definition: qf_pkg.h:114
union QHsmAttr temp
temporary: tran.
Definition: qep.h:284
#define QPSet_remove(me_, n_)
Remove element n_ from the set me_, n_= 1..32.
Definition: qpset.h:78
struct QHsmVtbl super
inherits QHsmVtbl
Definition: qf.h:167
struct QMState const * obj
pointer to QMState object
Definition: qep.h:252
#define QS_TIME_()
Internal macro to output time stamp to a QS record.
Definition: qs.h:205
bool QXThread_delayCancel(QXThread *const me)
cancel the delay
Definition: qxk_xthr.c:624
void QXK_stackInit_(void *thr, QXThreadHandler handler, void *stkSto, uint_fast16_t stkSize)
initialize the private stack of a given QXThread
void QXThread_unblock_(QXThread const *const me)
internal function to unblock (resume) a given extended thread.
Definition: qxk_xthr.c:508
#define QS_END_NOCRIT_()
Internal QS macro to end a QS record without exiting critical section.
Definition: qs.h:700
void QXK_threadRet_(void)
called when a thread function returns
Definition: qxk_xthr.c:652
#define QF_NO_MARGIN
special value of margin that causes asserting failure in case event allocation or event posting fails...
Definition: qf.h:648
Active Object (based on QHsm implementation)
Definition: qf.h:110
#define Q_ACTION_CAST(action_)
Perform cast to QActionHandler.
Definition: qep.h:236
QActive * QF_active_[QF_MAX_ACTIVE+1]
array of registered active objects
Definition: qf_act.c:53
uint16_t QTimeEvtCtr
type of the Time Event counter, which determines the dynamic range of the time delays measured in clo...
Definition: qf.h:412
QTimeEvtCtr volatile ctr
the internal down-counter of the time event.
Definition: qf.h:472
void QXThread_ctor(QXThread *const me, QXThreadHandler handler, uint_fast8_t tickRate)
constructor of an extended-thread
Definition: qxk_xthr.c:94
void QXThread_block_(QXThread const *const me)
internal functin to block (suspend) a given extended thread
Definition: qxk_xthr.c:492
static void QXThread_start_(QActive *const me, uint_fast8_t prio, QEvt const *qSto[], uint_fast16_t qLen, void *stkSto, uint_fast16_t stkSize, QEvt const *ie)
Definition: qxk_xthr.c:153
#define Q_ERROR_ID(id_)
Assertion with user-specified assertion-id for a wrong path.
Definition: qassert.h:192
#define QF_CRIT_EXIT_()
This is an internal macro for exiting a critical section.
Definition: qf_pkg.h:81