void QActive_postFIFO(QActive *me, QEvent const *e) { #else void QActive_postFIFO(QActive *me, QEvent const *e, void const *sender) { #endif QF_INT_LOCK_KEY_ QF_INT_LOCK_(); QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_FIFO, QS_aoObj_, me) QS_TIME_(); /* timestamp */ QS_OBJ_(sender); /* the sender object */ QS_SIG_(e->sig); /* the signal of the event */ QS_OBJ_(me); /* this active object (recipient) */ QS_U8_(EVT_POOL_ID(e)); /* the pool Id of the event */ QS_U8_(EVT_REF_CTR(e)); /* the ref count of the event */ QS_EQC_(0); /* number of free entries (unknown) */ QS_EQC_(0); /* min number of free entries (unknown) */ QS_END_NOLOCK_() if (EVT_POOL_ID(e) != (uint8_t)0) { /* is it a pool event? */ EVT_INC_REF_CTR(e); /* increment the reference counter */ } QF_INT_UNLOCK_(); Q_ALLEGE(OSQPost((OS_EVENT *)me->eQueue, (void *)e) == OS_NO_ERR); }
/*..........................................................................*/ void QFsm_init_(QFsm * const me, QEvt const * const e) { QS_CRIT_STAT_ Q_REQUIRE((me->vptr != (QMsmVtbl const *)0) /* ctor must be executed */ && (me->temp.fun != Q_STATE_CAST(0)) /* ctor must be executed */ && (me->state.fun == Q_STATE_CAST(0)));/*init tran. NOT taken */ QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me) QS_OBJ_(me); /* this state machine object */ QS_FUN_(Q_STATE_CAST(0)); /* source state (not defined for a FSM) */ QS_FUN_(me->temp.fun); /* the target of the transition */ QS_END_() /* execute the top-most initial transition */ Q_ALLEGE((*me->temp.fun)(me, e) == (QState)Q_RET_TRAN);/* must be taken */ (void)QEP_TRIG_(me->temp.fun, Q_ENTRY_SIG); /* enter the target */ me->state.fun = me->temp.fun; /* record the new active state */ QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me) QS_TIME_(); /* time stamp */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(me->state.fun); /* the new active state */ QS_END_() }
/* NOTE: disarm a timer (no harm in disarming an already disarmed timer) */ uint8_t QTimeEvt_disarm(QTimeEvt *me) { uint8_t wasArmed; QF_INT_LOCK_KEY_ QF_INT_LOCK_(); if (me->prev != (QTimeEvt *)0) { /* is the time event actually armed? */ wasArmed = (uint8_t)1; if (me == QF_timeEvtListHead_) { QF_timeEvtListHead_ = me->next; } else { if (me->next != (QTimeEvt *)0) { /* not the last in the list? */ me->next->prev = me->prev; } me->prev->next = me->next; } me->prev = (QTimeEvt *)0; /* mark the time event as disarmed */ QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM, QS_teObj_, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(me->act); /* the active object */ QS_TEC_(me->ctr); /* the number of ticks */ QS_TEC_(me->interval); /* the interval */ QS_END_NOLOCK_() }
void QF_tick(void) { /* see NOTE01 */ #else void QF_tick(void const *sender) { #endif QTimeEvt *t; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); QS_BEGIN_NOCRIT_(QS_QF_TICK, (void *)0, (void *)0) QS_TEC_((QTimeEvtCtr)(++QS_tickCtr_)); /* the tick counter */ QS_END_NOCRIT_() t = QF_timeEvtListHead_; while (t != (QTimeEvt *)0) { --t->ctr; if (t->ctr == (QTimeEvtCtr)0) { /* is time evt about to expire? */ if (t->interval != (QTimeEvtCtr)0) { /* is it periodic timeout? */ t->ctr = t->interval; /* rearm the time event */ } else { /* one-shot timeout, disarm by removing it from the list */ if (t == QF_timeEvtListHead_) { QF_timeEvtListHead_ = t->next; } else { if (t->next != (QTimeEvt *)0) { /* not the last event? */ t->next->prev = t->prev; } t->prev->next = t->next; } t->prev = (QTimeEvt *)0; /* mark the event disarmed */ QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_AUTO_DISARM, QS_teObj_, t) QS_OBJ_(t); /* this time event object */ QS_OBJ_(t->act); /* the active object */ QS_END_NOCRIT_() } QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_POST, QS_teObj_, t) QS_TIME_(); /* timestamp */ QS_OBJ_(t); /* the time event object */ QS_SIG_(t->super.sig); /* signal of this time event */ QS_OBJ_(t->act); /* the active object */ QS_END_NOCRIT_() QF_CRIT_EXIT_();/* exit crit. section before calling QF service */ /* QACTIVE_POST() asserts internally if the queue overflows */ QACTIVE_POST(t->act, &t->super, sender); } else { static uint8_t volatile dummy; QF_CRIT_EXIT_(); dummy = (uint8_t)0; /* execute a few instructions, see NOTE02 */ } QF_CRIT_ENTRY_(); /* enter crit. section again to advance the link */ t = t->next; }
/*..........................................................................*/ void QTimeEvt_arm_(QTimeEvt *me, QActive *act, QTimeEvtCtr nTicks) { QF_CRIT_STAT_ Q_REQUIRE((nTicks > (QTimeEvtCtr)0) /* cannot arm a timer with 0 ticks */ && (me->super.sig >= (QSignal)Q_USER_SIG) /* valid signal */ && (me->prev == (QTimeEvt *)0) /* time evt must NOT be used */ && (act != (QActive *)0)); /* active object must be provided */ me->ctr = nTicks; me->prev = me; /* mark the timer in use */ me->act = act; QF_CRIT_ENTRY_(); QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_ARM, QS_teObj_, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(act); /* the active object */ QS_TEC_(nTicks); /* the number of ticks */ QS_TEC_(me->interval); /* the interval */ QS_END_NOCRIT_() me->next = QF_timeEvtListHead_; if (QF_timeEvtListHead_ != (QTimeEvt *)0) { QF_timeEvtListHead_->prev = me; } QF_timeEvtListHead_ = me; QF_CRIT_EXIT_(); }
bool QActive_post_(QActive * const me, QEvt const * const e, uint_fast16_t const margin, void const * const sender) #endif /* Q_SPY */ { uint_fast16_t nFree; bool status; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); nFree = (uint_fast16_t)(me->eQueue.maxMsg - me->eQueue.nofMsg); if (nFree > margin) { QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS_priv_.aoObjFilter, me) QS_TIME_(); /* timestamp */ QS_OBJ_(sender); /* the sender object */ QS_SIG_(e->sig); /* the signal of the event */ QS_OBJ_(me); /* this active object (recipient) */ QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */ QS_EQC_((QEQueueCtr)nFree); /* # free entries available */ QS_EQC_((QEQueueCtr)0); /* min # free entries (unknown) */ QS_END_NOCRIT_() if (e->poolId_ != (uint8_t)0) { /* is it a pool event? */ QF_EVT_REF_CTR_INC_(e); /* increment the reference counter */ } /* posting to the embOS mailbox must succeed, see NOTE3 */ Q_ALLEGE(OS_PutMailCond(&me->eQueue, (OS_CONST_PTR void *)&e) == (char)0); status = true; /* return success */ }
//............................................................................ void QMsm::dispatch(QEvt const * const e) { QMState const *s = m_state.obj; // store the current state QMState const *t; QState r = Q_RET_HANDLED; QS_CRIT_STAT_ Q_REQUIRE(s != (QMState const *)0); // must be initialized QS_BEGIN_(QS_QEP_DISPATCH, QS::priv_.smObjFilter, this) QS_TIME_(); // time stamp QS_SIG_(e->sig); // the signal of the event QS_OBJ_(this); // this state machine object QS_FUN_(s->stateHandler); // the current state handler QS_END_() for (t = s; t != static_cast<QMState const *>(0); t = t->parent) { r = (*t->stateHandler)(this, e); if (r != Q_RET_SUPER) { if (r == Q_RET_UNHANDLED) { // unhandled due to a guard? QS_BEGIN_(QS_QEP_UNHANDLED, QS::priv_.smObjFilter, this) QS_SIG_(e->sig); // the signal of the event QS_OBJ_(this); // this state machine object QS_FUN_(t->stateHandler); // the current state QS_END_() } else { break; // event handled--break out of the loop } }
/*..........................................................................*/ void QFsm_dispatch(QFsm *me, QEvent const *e) { QStateHandler s = me->state; /* save the current state */ QS_INT_LOCK_KEY_ QState r = (*s)(me, e); /* call the event handler */ if (r == Q_RET_TRAN) { /* transition taken? */ QS_BEGIN_(QS_QEP_TRAN, QS_smObj_, me) QS_TIME_(); /* time stamp */ QS_SIG_(e->sig); /* the signal of the event */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(s); /* the source of the transition */ QS_FUN_(me->state); /* the new active state */ QS_END_() (void)QEP_TRIG_(s, Q_EXIT_SIG); /* exit the source */ (void)QEP_TRIG_(me->state, Q_ENTRY_SIG); /* enter the target */ } else { /* transition not taken */ #ifdef Q_SPY if (r == Q_RET_HANDLED) { QS_BEGIN_(QS_QEP_INTERN_TRAN, QS_smObj_, me) QS_TIME_(); /* time stamp */ QS_SIG_(e->sig); /* the signal of the event */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(s); /* the state that handled the event */ QS_END_() } else {
bool QMActive::post_(QEvt const * const e, uint_fast16_t const margin, void const * const sender) #endif { uint_fast16_t nFree; bool status; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); nFree = static_cast<uint_fast16_t>(m_eQueue.maxMsg - m_eQueue.nofMsg); if (nFree > margin) { QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS::priv_.aoObjFilter, this) QS_TIME_(); // timestamp QS_OBJ_(sender); // the sender object QS_SIG_(e->sig); // the signal of the event QS_OBJ_(this); // this active object (recipient) QS_2U8_(e->poolId_, e->refCtr_); // pool Id & ref Count QS_EQC_(static_cast<QEQueueCtr>(nFree)); // # free entries QS_EQC_(static_cast<QEQueueCtr>(0)); // min # free (unknown) QS_END_NOCRIT_() if (e->poolId_ != static_cast<uint8_t>(0)) { // is it a pool event? QF_EVT_REF_CTR_INC_(e); // increment the reference counter } // posting to the embOS mailbox must succeed, see NOTE3 Q_ALLEGE_ID(710, OS_PutMailCond(&m_eQueue, static_cast<OS_CONST_PTR void *>(&e)) == static_cast<char>(0)); status = true; // return success }
//............................................................................ // NOTE: disarm a time evt (no harm in disarming an already disarmed time evt) uint8_t QTimeEvt::disarm(void) { uint8_t wasArmed; QF_INT_LOCK_KEY_ QF_INT_LOCK_(); if (m_prev != (QTimeEvt *)0) { // is the time event actually armed? wasArmed = (uint8_t)1; if (this == QF_timeEvtListHead_) { QF_timeEvtListHead_ = m_next; } else { if (m_next != (QTimeEvt *)0) { // not the last in the list? m_next->m_prev = m_prev; } m_prev->m_next = m_next; } m_prev = (QTimeEvt *)0; // mark the time event as disarmed QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM, QS::teObj_, this) QS_TIME_(); // timestamp QS_OBJ_(this); // this time event object QS_OBJ_(m_act); // the active object QS_TEC_(m_ctr); // the number of ticks QS_TEC_(m_interval); // the interval QS_END_NOLOCK_() }
/*..........................................................................*/ uint8_t QTimeEvt_rearm(QTimeEvt * const me, QTimeEvtCtr const nTicks) { uint8_t isArmed; QF_CRIT_STAT_ Q_REQUIRE((nTicks != (QTimeEvtCtr)0) /* cannot arm a timer with 0 ticks */ && (me->act != (QActive *)0) /* active object must be valid */ && (me->super.sig >= (QSignal)Q_USER_SIG)); /* valid signal */ QF_CRIT_ENTRY_(); if (me->ctr == (QTimeEvtCtr)0) { /* is the time evt disarmed? */ isArmed = (uint8_t)0; if (QF_EVT_REF_CTR_(&me->super) == (uint8_t)0) { /* not linked? */ me->next = QF_timeEvtListHead_; QF_timeEvtListHead_ = me; QF_EVT_REF_CTR_INC_(&me->super); /* mark as linked */ } } else { /* the time event is armed */ isArmed = (uint8_t)1; } me->ctr = nTicks; /* re-load the tick counter (shift the phasing) */ QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_REARM, QS_teObj_, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(me->act); /* the active object */ QS_TEC_(me->ctr); /* the number of ticks */ QS_TEC_(me->interval); /* the interval */ QS_U8_(isArmed); /* was the timer armed? */ QS_END_NOCRIT_() QF_CRIT_EXIT_(); return isArmed; }
bool GuiQMActive::post_(QEvt const * const e, uint_fast16_t const /*margin*/, void const * const sender) #endif { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS::priv_.aoObjFilter, this) QS_TIME_(); // timestamp QS_OBJ_(sender); // the sender object QS_SIG_(e->sig); // the signal of the event QS_OBJ_(this); // this active object QS_2U8_(QF_EVT_POOL_ID_(e), /* the poolID of the event */ QF_EVT_REF_CTR_(e)); // the ref Ctr of the event QS_EQC_(0); // number of free entries (not used) QS_EQC_(0); // min number of free entries (not used) QS_END_NOCRIT_() // is it a dynamic event? if (QF_EVT_POOL_ID_(e) != static_cast<uint8_t>(0)) { QF_EVT_REF_CTR_INC_(e); // increment the reference counter } QF_CRIT_EXIT_(); // QCoreApplication::postEvent() is thread-safe per Qt documentation QCoreApplication::postEvent(QApplication::instance(), new QP_Event(e)); return true; }
/* NOTE: disarm a timer (no harm in disarming an already disarmed timer) */ uint8_t QTimeEvt_disarm(QTimeEvt * const me) { uint8_t wasArmed; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if (me->ctr != (QTimeEvtCtr)0) { /* is the time evt running? */ wasArmed = (uint8_t)1; QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM, QS_priv_.teObjFilter, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(me->act); /* the target AO */ QS_TEC_(me->ctr); /* the number of ticks */ QS_TEC_(me->interval); /* the interval */ QS_U8_((uint8_t)(me->super.refCtr_ & (uint8_t)0x7F));/*tick rate*/ QS_END_NOCRIT_() me->ctr = (QTimeEvtCtr)0; /* schedule removal from the list */ } else { /* the time event was already not running */ wasArmed = (uint8_t)0; QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS_priv_.teObjFilter, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(me->act); /* the target AO */ QS_U8_((uint8_t)(me->super.refCtr_ & (uint8_t)0x7F));/*tick rate*/ QS_END_NOCRIT_() } QF_CRIT_EXIT_(); return wasArmed; }
/*..........................................................................*/ void QF_tick(void) { /* see NOTE01 */ QTimeEvt *t; QF_INT_LOCK_KEY_ QF_INT_LOCK_(); QS_BEGIN_NOLOCK_(QS_QF_TICK, (void *)0, (void *)0) QS_TEC_(++QS_tickCtr_); /* the tick counter */ QS_END_NOLOCK_() t = QF_timeEvtListHead_; while (t != (QTimeEvt *)0) { --t->ctr; if (t->ctr == (QTimeEvtCtr)0) { /* is time evt about to expire? */ if (t->interval != (QTimeEvtCtr)0) { /* is it periodic timeout? */ t->ctr = t->interval; /* rearm the time event */ } else { /* one-shot timeout, disarm by removing it from the list */ if (t == QF_timeEvtListHead_) { QF_timeEvtListHead_ = t->next; } else { if (t->next != (QTimeEvt *)0) { /* not the last event? */ t->next->prev = t->prev; } t->prev->next = t->next; } t->prev = (QTimeEvt *)0; /* mark the event disarmed */ QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_AUTO_DISARM, QS_teObj_, t) QS_OBJ_(t); /* this time event object */ QS_OBJ_(t->act); /* the active object */ QS_END_NOLOCK_() } QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_POST, QS_teObj_, t) QS_TIME_(); /* timestamp */ QS_OBJ_(t); /* the time event object */ QS_SIG_(t->super.sig); /* signal of this time event */ QS_OBJ_(t->act); /* the active object */ QS_END_NOLOCK_() QF_INT_UNLOCK_();/* unlock interrupts before calling QF service */ /* postFIFO() asserts internally that the event was accepted */ QActive_postFIFO(t->act, (QEvent *)t); } else { static uint8_t volatile dummy; QF_INT_UNLOCK_(); dummy = (uint8_t)0; /* execute a few instructions, see NOTE02 */ } QF_INT_LOCK_(); /* lock interrupts again to advance the link */ t = t->next; }
/** * \description * Arms a time event to fire in a specified number of clock ticks and with * a specified interval. If the interval is zero, the time event is armed for * one shot ('one-shot' time event). The time event gets directly posted * (using the FIFO policy) into the event queue of the host active object. * * \arguments * \arg[in,out] \c me pointer (see \ref derivation) * \arg[in] \c nTicks number of clock ticks (at the associated rate) * to rearm the time event with. * \arg[in] \c interval interval (in clock ticks) for periodic time event. * * \note After posting, a one-shot time event gets automatically disarmed * while a periodic time event (interval != 0) is automatically re-armed. * * \note A time event can be disarmed at any time by calling the * QTimeEvt_disarm() function. Also, a time event can be re-armed to fire * in a different number of clock ticks by calling the QTimeEvt_rearm() * function. * * \usage * The following example shows how to arm a one-shot time event from a state * machine of an active object: * \include qf_state.c */ void QTimeEvt_armX(QTimeEvt * const me, QTimeEvtCtr const nTicks, QTimeEvtCtr const interval) { uint_fast8_t tickRate = (uint_fast8_t)me->super.refCtr_ & (uint_fast8_t)0x7F; QTimeEvtCtr ctr = me->ctr; QF_CRIT_STAT_ /** \pre the host AO must be valid, time evnet must be disarmed, * number of clock ticks cannot be zero, and the signal must be valid. */ Q_REQUIRE_ID(100, (me->act != (void *)0) && (ctr == (QTimeEvtCtr)0) && (nTicks != (QTimeEvtCtr)0) && (tickRate < (uint_fast8_t)QF_MAX_TICK_RATE) && (me->super.sig >= (QSignal)Q_USER_SIG)); QF_CRIT_ENTRY_(); me->ctr = nTicks; me->interval = interval; /* is the time event unlinked? * NOTE: For the duration of a single clock tick of the specified tick * rate a time event can be disarmed and yet still linked into the list, * because un-linking is performed exclusively in the QF_tickX() function. */ if ((me->super.refCtr_ & (uint8_t)0x80) == (uint8_t)0) { me->super.refCtr_ |= (uint8_t)0x80; /* mark as linked */ /* The time event is initially inserted into the separate * "freshly armed" link list based on QF_timeEvtHead_[tickRate].act. * Only later, inside the QF_tickX() function, the "freshly armed" * list is appended to the main list of armed time events based on * QF_timeEvtHead_[tickRate].next. Again, this is to keep any * changes to the main list exclusively inside the QF_tickX() * function. */ me->next = (QTimeEvt *)QF_timeEvtHead_[tickRate].act; QF_timeEvtHead_[tickRate].act = me; } QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_ARM, QS_priv_.teObjFilter, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(me->act); /* the active object */ QS_TEC_(nTicks); /* the number of ticks */ QS_TEC_(interval); /* the interval */ QS_U8_((uint8_t)tickRate); /* tick rate */ QS_END_NOCRIT_() QF_CRIT_EXIT_(); }
/*..........................................................................*/ void QHsm_init(QHsm *me, QEvent const *e) { QHsmState s; /* this state machine must be initialized with QHsm_ctor_() */ Q_REQUIRE(((QFsm *)me)->state__.fsm != (QState)0); s = &QHsm_top; /* an HSM starts in the top state */ /* trigger the initial transition */ (*((QFsm *)me)->state__.fsm)((QFsm *)me, e); do { /* drill into the target... */ QHsmState path[QEP_MAX_NEST_DEPTH_]; int8_t ip = (int8_t)0; /* transition entry path index */ QHsmState t = ((QFsm *)me)->state__.hsm; QS_BEGIN_(QS_QEP_STATE_INIT, QS_smObj_, me); QS_OBJ_(me); /* this state machine object */ QS_FUN_(s); /* the source state */ QS_FUN_(((QFsm *)me)->state__.hsm); /* the target */ QS_END_(); path[0] = t; for (t = QEP_TRIG_(t, QEP_EMPTY_SIG_); t != s; t = QEP_TRIG_(t, QEP_EMPTY_SIG_)) { path[++ip] = t; } /* entry path must not overflow */ Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); do { /* retrace the entry path in reverse (desired) order... */ /* enter path[ip] */ if (QEP_TRIG_(path[ip], Q_ENTRY_SIG) == (QHsmState)0) { QS_BEGIN_(QS_QEP_STATE_ENTRY, QS_smObj_, me); QS_OBJ_(me); /* this state machine object */ QS_FUN_(path[ip]); /* the entered state */ QS_END_(); } } while (--ip >= (int8_t)0); s = ((QFsm *)me)->state__.hsm; } while (QEP_TRIG_(s, Q_INIT_SIG) == (QHsmState)0); QS_BEGIN_(QS_QEP_INIT_TRAN, QS_smObj_, me); QS_TIME_(); /* time stamp */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(((QFsm *)me)->state__.hsm); /* the new active state */ QS_END_(); }
/*..........................................................................*/ void QHsm_init(QHsm * const me, QEvt const * const e) { QStateHandler t = me->state.fun; QS_CRIT_STAT_ Q_REQUIRE((me->vptr != (QMsmVtbl const *)0) /* ctor must be executed */ && (me->temp.fun != Q_STATE_CAST(0)) /* ctor must be executed */ && (t == Q_STATE_CAST(&QHsm_top))); /*initial tran. NOT taken */ /* the top-most initial transition must be taken */ Q_ALLEGE((*me->temp.fun)(me, e) == (QState)Q_RET_TRAN); do { /* drill into the target... */ QStateHandler path[QEP_MAX_NEST_DEPTH_]; int_t ip = (int_t)0; /* transition entry path index */ QS_BEGIN_(QS_QEP_STATE_INIT, QS_priv_.smObjFilter, me) QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the source state */ QS_FUN_(me->temp.fun); /* the target of the initial transition */ QS_END_() path[0] = me->temp.fun; (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_); while (me->temp.fun != t) { ++ip; path[ip] = me->temp.fun; (void)QEP_TRIG_(me->temp.fun, QEP_EMPTY_SIG_); } me->temp.fun = path[0]; /* entry path must not overflow */ Q_ASSERT(ip < (int_t)QEP_MAX_NEST_DEPTH_); do { /* retrace the entry path in reverse (desired) order... */ QEP_ENTER_(path[ip]); /* enter path[ip] */ --ip; } while (ip >= (int_t)0); t = path[0]; /* current state becomes the new source */ } while (QEP_TRIG_(t, Q_INIT_SIG) == (QState)Q_RET_TRAN); QS_BEGIN_(QS_QEP_INIT_TRAN, QS_priv_.smObjFilter, me) QS_TIME_(); /* time stamp */ QS_OBJ_(me); /* this state machine object */ QS_FUN_(t); /* the new active state */ QS_END_() me->state.fun = t; /* change the current active state */ me->temp.fun = t; /* mark the configuration as stable */ }
/*..........................................................................*/ QEvent const *QEQueue_get(QEQueue *me) { QEvent const *e; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if (me->frontEvt == (QEvent *)0) { /* is the queue empty? */ e = (QEvent *)0; /* no event available at this time */ } else { /* the queue is not empty */ e = me->frontEvt; if (me->nFree != me->end) { /* any events in the ring buffer? */ me->frontEvt = QF_PTR_AT_(me->ring, me->tail); /* get from tail */ if (me->tail == (QEQueueCtr)0) { /* need to wrap the tail? */ me->tail = me->end; /* wrap around */ } --me->tail; ++me->nFree; /* one more free event in the ring buffer */ QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET, QS_eqObj_, me) QS_TIME_(); /* timestamp */ QS_SIG_(e->sig); /* the signal of this event */ QS_OBJ_(me); /* this queue object */ QS_U8_(QF_EVT_POOL_ID_(e)); /* the pool Id of the event */ QS_U8_(QF_EVT_REF_CTR_(e)); /* the ref count of the event */ QS_EQC_(me->nFree); /* number of free entries */ QS_END_NOCRIT_() } else {
/*..........................................................................*/ QEvent const *QEQueue_get(QEQueue *me) { QEvent const *e; QF_INT_LOCK_KEY_ QF_INT_LOCK_(); if (me->frontEvt == (QEvent *)0) { /* is the queue empty? */ e = (QEvent const *)0; /* no event available at this time */ } else { /* the queue is not empty */ e = me->frontEvt; if (me->nFree != me->end) { /* any events in the ring buffer? */ me->frontEvt = me->ring[me->tail]; /* remove from the tail */ if (me->tail == (QEQueueCtr)0) { /* need to wrap the tail? */ me->tail = me->end; /* wrap around */ } --me->tail; ++me->nFree; /* one more free event in the ring buffer */ QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_GET, QS_eqObj_, me) QS_TIME_(); /* timestamp */ QS_SIG_(e->sig); /* the signal of this event */ QS_OBJ_(me); /* this queue object */ QS_U8_(e->dynamic_); /* the dynamic attribute of the event */ QS_EQC_(me->nFree); /* number of free entries */ QS_END_NOLOCK_() } else {
/*..........................................................................*/ void QActive_unsubscribeAll(QActive const *me) { uint8_t p = me->prio; uint8_t i; QSignal sig; Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE) && (QF_active_[p] == me)); i = QF_div8Lkup[p]; for (sig = (QSignal)Q_USER_SIG; sig < QF_maxSignal_; ++sig) { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if ((QF_PTR_AT_(QF_subscrList_, sig).bits[i] & Q_ROM_BYTE(QF_pwr2Lkup[p])) != (uint8_t)0) { QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS_aoObj_, me) QS_TIME_(); /* timestamp */ QS_SIG_(sig); /* the signal of this event */ QS_OBJ_(me); /* this active object */ QS_END_NOCRIT_() /* clear the priority bit */ QF_PTR_AT_(QF_subscrList_, sig).bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); } QF_CRIT_EXIT_(); } }
/*..........................................................................*/ QEvent const *QActive_get_(QActive *me) { QEvent const *e; QF_INT_LOCK_KEY_ QF_INT_LOCK_(); QACTIVE_EQUEUE_WAIT_(me); /* wait for event to arrive directly ^#defined as: Q_ASSERT((me_)->eQueue.frontEvt != (QEvent *)0) */ e = me->eQueue.frontEvt; if (me->eQueue.nFree != me->eQueue.end) { /* any events in the buffer? */ /* remove event from the tail */ me->eQueue.frontEvt = me->eQueue.ring[me->eQueue.tail]; if (me->eQueue.tail == (QEQueueCtr)0) { /* need to wrap the tail? */ me->eQueue.tail = me->eQueue.end; /* wrap around */ } --me->eQueue.tail; ++me->eQueue.nFree; /* one more free event in the ring buffer */ QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET, QS_aoObj_, me) QS_TIME_(); /* timestamp */ QS_SIG_(e->sig); /* the signal of this event */ QS_OBJ_(me); /* this active object */ QS_U8_(e->dynamic_); /* the dynamic attribute of the event */ QS_EQC_(me->eQueue.nFree); /* number of free entries */ QS_END_NOLOCK_() }
/*..........................................................................*/ QEvt const *QActive_get_(QActive * const me) { QEQueueCtr nFree; QEvt const *e; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); QACTIVE_EQUEUE_WAIT_(me); /* wait for event to arrive directly */ e = me->eQueue.frontEvt; /* always remove event from the front location */ nFree= me->eQueue.nFree + (QEQueueCtr)1; /* get volatile into tmp */ me->eQueue.nFree = nFree; /* upate the number of free */ if (nFree <= me->eQueue.end) { /* any events in the ring buffer? */ /* remove event from the tail */ me->eQueue.frontEvt = QF_PTR_AT_(me->eQueue.ring, me->eQueue.tail); if (me->eQueue.tail == (QEQueueCtr)0) { /* need to wrap the tail? */ me->eQueue.tail = me->eQueue.end; /* wrap around */ } --me->eQueue.tail; QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_GET, QS_priv_.aoObjFilter, me) QS_TIME_(); /* timestamp */ QS_SIG_(e->sig); /* the signal of this event */ QS_OBJ_(me); /* this active object */ QS_2U8_(e->poolId_, e->refCtr_); /* pool Id & ref Count */ QS_EQC_(nFree); /* number of free entries */ QS_END_NOCRIT_() }
QP_BEGIN_ //Q_DEFINE_THIS_MODULE("qeq_get") //............................................................................ QEvt const *QEQueue::get(void) { QEvt const *e; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if (m_frontEvt == null_evt) { // is the queue empty? e = null_evt; // no event available at this time } else { e = m_frontEvt; if (m_nFree != m_end) { // any events in the the ring buffer? m_frontEvt = QF_PTR_AT_(m_ring, m_tail); // remove from the tail if (m_tail == static_cast<QEQueueCtr>(0)) { // need to wrap? m_tail = m_end; // wrap around } --m_tail; ++m_nFree; // one more free event in the ring buffer QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET, QS::eqObj_, this) QS_TIME_(); // timestamp QS_SIG_(e->sig); // the signal of this event QS_OBJ_(this); // this queue object QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event QS_EQC_(m_nFree); // number of free entries QS_END_NOCRIT_() } else {
//**************************************************************************** /// @description /// This function is part of the Publish-Subscribe event delivery mechanism /// available in QF. Un-subscribing from all events means that the framework /// will stop posting any published events to the event queue of the active /// object. /// /// @note Due to the latency of event queues, an active object should NOT /// assume that no events will ever be dispatched to the state machine of /// the active object after un-subscribing from all events. /// The events might be already in the queue, or just about to be posted /// and the un-subscribe operation will not flush such events. Also, the /// alternative event-delivery mechanisms, such as direct event posting or /// time events, can be still delivered to the event queue of the active /// object. /// /// @sa QP::QF::publish_(), QP::QMActive::subscribe(), and /// QP::QMActive::unsubscribe() /// void QMActive::unsubscribeAll(void) const { uint_fast8_t const p = m_prio; Q_REQUIRE_ID(500, (static_cast<uint_fast8_t>(0) < p) && (p <= static_cast<uint_fast8_t>(QF_MAX_ACTIVE)) && (QF::active_[p] == this)); uint_fast8_t const i = static_cast<uint_fast8_t>(QF_div8Lkup[p]); enum_t sig; for (sig = Q_USER_SIG; sig < QF_maxSignal_; ++sig) { QF_CRIT_STAT_ QF_CRIT_ENTRY_(); if ((QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] & QF_pwr2Lkup[p]) != static_cast<uint8_t>(0)) { QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::priv_.aoObjFilter, this) QS_TIME_(); // timestamp QS_SIG_(sig); // the signal of this event QS_OBJ_(this); // this active object QS_END_NOCRIT_() // clear the priority bit QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] &= QF_invPwr2Lkup[p]; } QF_CRIT_EXIT_(); } }
//............................................................................ void QHsm::init(QEvent const *e) { QStateHandler t; QS_INT_LOCK_KEY_ // the top-most initial transition must be taken Q_ALLEGE((*m_state)(this, e) == Q_RET_TRAN); t = (QStateHandler)&QHsm::top; // HSM starts in the top state do { // drill into the target... QStateHandler path[QEP_MAX_NEST_DEPTH_]; int8_t ip = (int8_t)0; // transition entry path index QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) QS_OBJ_(this); // this state machine object QS_FUN_(t); // the source state QS_FUN_(m_state); // the target of the initial transition QS_END_() path[0] = m_state; (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); while (m_state != t) { ++ip; path[ip] = m_state; (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); } m_state = path[0]; // entry path must not overflow Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); do { // retrace the entry path in reverse (desired) order... QEP_ENTER_(path[ip]); // enter path[ip] --ip; } while (ip >= (int8_t)0); t = path[0]; // current state becomes the new source } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN); m_state = t; QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this) QS_TIME_(); // time stamp QS_OBJ_(this); // this state machine object QS_FUN_(m_state); // the new active state QS_END_() }
void QActive_postFIFO(QActive *me, QEvent const *e) { #else void QActive_postFIFO(QActive *me, QEvent const *e, void const *sender) { #endif QF_INT_LOCK_KEY_ QF_INT_LOCK_(); QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_FIFO, QS_aoObj_, me) QS_TIME_(); /* timestamp */ QS_OBJ_(sender); /* the sender object */ QS_SIG_(e->sig); /* the signal of the event */ QS_OBJ_(me); /* this active object (recipient) */ QS_U8_(EVT_POOL_ID(e)); /* the pool Id of the event */ QS_U8_(EVT_REF_CTR(e)); /* the ref count of the event */ QS_EQC_(me->eQueue.nFree); /* number of free entries */ QS_EQC_(me->eQueue.nMin); /* min number of free entries */ QS_END_NOLOCK_() if (EVT_POOL_ID(e) != (uint8_t)0) { /* is it a pool event? */ EVT_INC_REF_CTR(e); /* increment the reference counter */ } if (me->eQueue.frontEvt == (QEvent *)0) { /* empty queue? */ me->eQueue.frontEvt = e; /* deliver event directly */ QACTIVE_EQUEUE_SIGNAL_(me); /* signal the event queue */ } else { /* queue is not empty, insert event into the ring-buffer */ /* the queue must be able to accept the event (cannot overflow) */ Q_ASSERT(me->eQueue.nFree != (QEQueueCtr)0); /* insert event into the ring buffer (FIFO) */ me->eQueue.ring[me->eQueue.head] = e; if (me->eQueue.head == (QEQueueCtr)0) { /* need to wrap the head? */ me->eQueue.head = me->eQueue.end; /* wrap around */ } --me->eQueue.head; --me->eQueue.nFree; /* update number of free events */ if (me->eQueue.nMin > me->eQueue.nFree) { me->eQueue.nMin = me->eQueue.nFree; /* update min so far */ } } QF_INT_UNLOCK_(); }
void QF_publish_(QEvt const * const e, void const * const sender) #endif { QF_CRIT_STAT_ /* make sure that the published signal is within the configured range */ Q_REQUIRE(e->sig < (QSignal)QF_maxSignal_); QF_CRIT_ENTRY_(); QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, (void *)0, (void *)0) QS_TIME_(); /* the timestamp */ QS_OBJ_(sender); /* the sender object */ QS_SIG_(e->sig); /* the signal of the event */ QS_2U8_(e->poolId_, e->refCtr_);/* pool Id & ref Count of the event */ QS_END_NOCRIT_() if (e->poolId_ != (uint8_t)0) { /* is it a dynamic event? */ QF_EVT_REF_CTR_INC_(e); /* increment reference counter, NOTE01 */ } QF_CRIT_EXIT_(); #if (QF_MAX_ACTIVE <= 8) { uint8_t tmp = QF_subscrList_[e->sig].bits[0]; while (tmp != (uint8_t)0) { uint8_t p = QF_LOG2(tmp); tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); /* clear subscriber bit */ Q_ASSERT(QF_active_[p] != (QActive *)0); /* must be registered */ /* QACTIVE_POST() asserts internally if the queue overflows */ QACTIVE_POST(QF_active_[p], e, sender); } } #else { uint_t i = (uint_t)Q_DIM(QF_subscrList_[0].bits); do { /* go through all bytes in the subscription list */ uint8_t tmp; --i; tmp = QF_PTR_AT_(QF_subscrList_, e->sig).bits[i]; while (tmp != (uint8_t)0) { uint8_t p = QF_LOG2(tmp); tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);/*clear subscriber bit */ p = (uint8_t)(p + (uint8_t)(i << 3));/* adjust the priority */ Q_ASSERT(QF_active_[p] != (QActive *)0);/*must be registered*/ /* QACTIVE_POST() asserts internally if the queue overflows */ QACTIVE_POST(QF_active_[p], e, sender); } } while (i != (uint_t)0); } #endif QF_gc(e); /* run the garbage collector, see NOTE01 */ }
/*..........................................................................*/ QTimeEvtCtr QTimeEvt_ctr(QTimeEvt const * const me) { QTimeEvtCtr ret; QF_CRIT_STAT_ QF_CRIT_ENTRY_(); ret = me->ctr; QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_CTR, QS_priv_.teObjFilter, me) QS_TIME_(); /* timestamp */ QS_OBJ_(me); /* this time event object */ QS_OBJ_(me->act); /* the target AO */ QS_TEC_(ret); /* the current counter */ QS_TEC_(me->interval); /* the interval */ QS_U8_((uint8_t)(me->super.refCtr_ & (uint8_t)0x7F)); /* tick rate */ QS_END_NOCRIT_() QF_CRIT_EXIT_(); return ret; }
/*..........................................................................*/ QEvent const *QActive_get_(QActive *me) { QEvent const *e; QF_INT_LOCK_KEY_ QF_INT_LOCK_(); QACTIVE_OSOBJECT_WAIT_(me); /* wait for event to arrive directly */ e = me->eQueue__.frontEvt__; if (me->eQueue__.nUsed__ != (QEQueueCtr)0) {/*any events in the buffer? */ /* remove from the tail */ me->eQueue__.frontEvt__ = me->eQueue__.ring__[me->eQueue__.tail__]; ++me->eQueue__.tail__; if (me->eQueue__.tail__ == me->eQueue__.end__) { /* wrap around? */ me->eQueue__.tail__ = (QEQueueCtr)0; /* wrap the tail */ } --me->eQueue__.nUsed__; /* one less event in the ring buffer */ QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET, QS_aoObj_, me); QS_TIME_(); /* timestamp */ QS_SIG_(e->sig); /* the signal of this event */ QS_OBJ_(me); /* this active object */ QS_U8_(e->attrQF__); /* the QF attribute of the event */ QS_EQC_(me->eQueue__.nUsed__); /* number of used entries */ QS_END_NOLOCK_(); } else { me->eQueue__.frontEvt__ = (QEvent const *)0; /* queue becomes empty */ QACTIVE_OSOBJECT_ONIDLE_(me); QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET_LAST, QS_aoObj_, me); QS_TIME_(); /* timestamp */ QS_SIG_(e->sig); /* the signal of this event */ QS_OBJ_(me); /* this active object */ QS_U8_(e->attrQF__); /* the QF attribute of the event */ QS_END_NOLOCK_(); } QF_INT_UNLOCK_(); return e; }
/*..........................................................................*/ void QS_obj_dict(void const * const obj, char_t const Q_ROM * const name) { QS_CRIT_STAT_ QS_CRIT_ENTRY_(); QS_beginRec((uint8_t)QS_OBJ_DICT); QS_OBJ_(obj); QS_STR_ROM_(name); QS_endRec(); QS_CRIT_EXIT_(); QS_onFlush(); }