Пример #1
0
/*..........................................................................*/
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_();
}
/*..........................................................................*/
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;
}
Пример #3
0
//............................................................................
// 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_()
    }
Пример #4
0
/* 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;
}
Пример #5
0
/* 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_()
    }
Пример #6
0
/**
* \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_();
}
Пример #7
0
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;
    }
Пример #8
0
/*..........................................................................*/
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;
    }
Пример #9
0
/*..........................................................................*/
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;
}
Пример #10
0
/* 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_();
    }
    else {                                  /* the time event was not armed */
        wasArmed = (uint8_t)0;

        QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS_teObj_, me);
            QS_TIME_();                                        /* timestamp */
            QS_OBJ_(me);                          /* this time event object */
            QS_OBJ_(me->act__);                        /* the active object */
        QS_END_NOLOCK_();
    }
    QF_INT_UNLOCK_();
    return wasArmed;
}
void QF_tick(void const * const sender)
#endif
{
    QTimeEvt *t;
    QTimeEvt *prev = (QTimeEvt *)0;
    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_()

    for (t = QF_timeEvtListHead_; t != (QTimeEvt *)0; t = t->next) {
        if (t->ctr == (QTimeEvtCtr)0) { /* time evt. scheduled for removal? */
            if (t == QF_timeEvtListHead_) {
                QF_timeEvtListHead_ = t->next;
            }
            else {
                Q_ASSERT(prev != (QTimeEvt *)0);
                prev->next = t->next;
            }
            QF_EVT_REF_CTR_DEC_(&t->super);           /* mark as not linked */
        }
        else {
            --t->ctr;
            if (t->ctr == (QTimeEvtCtr)0) { /* is time evt about to expire? */
                if (t->interval != (QTimeEvtCtr)0) {  /* periodic time evt? */
                    t->ctr = t->interval;           /* rearm the time event */
                }
                else {
                    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 posting */
                /* QACTIVE_POST() asserts internally if the queue overflows */
                QACTIVE_POST(t->act, &t->super, sender);
                QF_CRIT_ENTRY_();     /* re-enter crit. section to continue */

                if (t->ctr == (QTimeEvtCtr)0) {  /* still marked to expire? */
                    if (t == QF_timeEvtListHead_) {
                        QF_timeEvtListHead_ = t->next;
                    }
                    else {
                        Q_ASSERT(prev != (QTimeEvt *)0);
                        prev->next = t->next;
                    }
                    QF_EVT_REF_CTR_DEC_(&t->super);      /* mark as removed */
                }
                else {
                    prev = t;
                }
            }
            else {
                prev = t;
            }
        }
    }
Пример #12
0
void QF_tickX_(uint_fast8_t const tickRate, void const * const sender)
#endif
{
    QTimeEvt *prev = &QF_timeEvtHead_[tickRate];
    QF_CRIT_STAT_

    QF_CRIT_ENTRY_();

    QS_BEGIN_NOCRIT_(QS_QF_TICK, (void *)0, (void *)0)
        QS_TEC_((QTimeEvtCtr)(++prev->ctr)); /* tick ctr */
        QS_U8_((uint8_t)tickRate);           /* tick rate */
    QS_END_NOCRIT_()

    /* scan the linked-list of time events at this rate... */
    for (;;) {
        QTimeEvt *t = prev->next;  /* advance down the time evt. list */

        /* end of the list? */
        if (t == (QTimeEvt *)0) {

            /* any new time events armed since the last run of QF_tickX_()? */
            if (QF_timeEvtHead_[tickRate].act != (void *)0) {

                /* sanity check */
                Q_ASSERT_ID(110, prev != (QTimeEvt *)0);
                prev->next = (QTimeEvt *)QF_timeEvtHead_[tickRate].act;
                QF_timeEvtHead_[tickRate].act = (void *)0;
                t = prev->next;  /* switch to the new list */
            }
            else {
                break; /* all currently armed time evts. processed */
            }
        }

        /* time event scheduled for removal? */
        if (t->ctr == (QTimeEvtCtr)0) {
            prev->next = t->next;
            t->super.refCtr_ &= (uint8_t)0x7F; /* mark as unlinked */
            /* do NOT advance the prev pointer */
            QF_CRIT_EXIT_(); /* exit crit. section to reduce latency */

            /* prevent merging critical sections, see NOTE1 below  */
            QF_CRIT_EXIT_NOP();
        }
        else {
            --t->ctr;

            /* is time event about to expire? */
            if (t->ctr == (QTimeEvtCtr)0) {
                QMActive *act = (QMActive *)t->act; /* temp. for volatile */

                /* periodic time evt? */
                if (t->interval != (QTimeEvtCtr)0) {
                    t->ctr = t->interval; /* rearm the time event */
                    prev = t; /* advance to this time event */
                }
                /* one-shot time event: automatically disarm */
                else {
                    prev->next = t->next;
                    t->super.refCtr_ &= (uint8_t)0x7F; /* mark as unlinked */
                    /* do NOT advance the prev pointer */

                    QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_AUTO_DISARM,
                                     QS_priv_.teObjFilter, t)
                        QS_OBJ_(t);            /* this time event object */
                        QS_OBJ_(act);          /* the target AO */
                        QS_U8_((uint8_t)tickRate); /* tick rate */
                    QS_END_NOCRIT_()
                }

                QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_POST, QS_priv_.teObjFilter, t)
                    QS_TIME_();                /* timestamp */
                    QS_OBJ_(t);                /* the time event object */
                    QS_SIG_(t->super.sig);     /* signal of this time event */
                    QS_OBJ_(act);              /* the target AO */
                    QS_U8_((uint8_t)tickRate); /* tick rate */
                QS_END_NOCRIT_()

                QF_CRIT_EXIT_(); /* exit critical section before posting */

                /* QACTIVE_POST() asserts internally if the queue overflows */
                QACTIVE_POST(act, &t->super, sender);
            }
            else {
                prev = t;         /* advance to this time event */
                QF_CRIT_EXIT_();  /* exit crit. section to reduce latency */

                /* prevent merging critical sections, see NOTE1 below  */
                QF_CRIT_EXIT_NOP();
            }
        }