Exemple #1
0
/**
 * @brief   Disables a Virtual Timer.
 * @pre     The timer must be in armed state before calling this function.
 *
 * @param[in] vtp       the @p virtual_timer_t structure pointer
 *
 * @iclass
 */
void chVTDoResetI(virtual_timer_t *vtp) {

  chDbgCheckClassI();
  chDbgCheck(vtp != NULL);
  chDbgAssert(vtp->vt_func != NULL, "timer not set or already triggered");

  /* Removing the element from the delta list.*/
  vtp->vt_next->vt_delta += vtp->vt_delta;
  vtp->vt_prev->vt_next = vtp->vt_next;
  vtp->vt_next->vt_prev = vtp->vt_prev;
  vtp->vt_func = (vtfunc_t)NULL;

  /* The above code changes the value in the header when the removed element
     is the last of the list, restoring it.*/
  ch.vtlist.vt_delta = (systime_t)-1;

#if CH_CFG_ST_TIMEDELTA > 0 || defined(__DOXYGEN__)
  {
    if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.vt_next) {
      /* Just removed the last element in the list, alarm timer stopped.*/
      port_timer_stop_alarm();
    }
    else {
      /* The alarm is set to the next element in the delta list.*/
      port_timer_set_alarm(ch.vtlist.vt_lasttime +
                           ch.vtlist.vt_next->vt_delta);
    }
  }
#endif /* CH_CFG_ST_TIMEDELTA > 0 */
}
Exemple #2
0
/**
 * @brief   Disables a Virtual Timer.
 * @pre     The timer must be in armed state before calling this function.
 *
 * @param[in] vtp       the @p virtual_timer_t structure pointer
 *
 * @iclass
 */
void chVTDoResetI(virtual_timer_t *vtp) {

  chDbgCheckClassI();
  chDbgCheck(vtp != NULL);
  chDbgAssert(vtp->func != NULL, "timer not set or already triggered");

#if CH_CFG_ST_TIMEDELTA == 0

  /* The delta of the timer is added to the next timer.*/
  vtp->next->delta += vtp->delta;

 /* Removing the element from the delta list.*/
  vtp->prev->next = vtp->next;
  vtp->next->prev = vtp->prev;
  vtp->func = NULL;

  /* The above code changes the value in the header when the removed element
     is the last of the list, restoring it.*/
  ch.vtlist.delta = (sysinterval_t)-1;
#else /* CH_CFG_ST_TIMEDELTA > 0 */
  sysinterval_t nowdelta, delta;

  /* If the timer is not the first of the list then it is simply unlinked
     else the operation is more complex.*/
  if (ch.vtlist.next != vtp) {
    /* Removing the element from the delta list.*/
    vtp->prev->next = vtp->next;
    vtp->next->prev = vtp->prev;
    vtp->func = NULL;

    /* Adding delta to the next element, if it is not the last one.*/
    if (&ch.vtlist != (virtual_timers_list_t *)vtp->next)
      vtp->next->delta += vtp->delta;

    return;
  }

  /* Removing the first timer from the list.*/
  ch.vtlist.next = vtp->next;
  ch.vtlist.next->prev = (virtual_timer_t *)&ch.vtlist;
  vtp->func = NULL;

  /* If the list become empty then the alarm timer is stopped and done.*/
  if (&ch.vtlist == (virtual_timers_list_t *)ch.vtlist.next) {
    port_timer_stop_alarm();

    return;
  }

  /* The delta of the removed timer is added to the new first timer.*/
  ch.vtlist.next->delta += vtp->delta;

  /* If the new first timer has a delta of zero then the alarm is not
     modified, the already programmed alarm will serve it.*/
/*  if (ch.vtlist.next->delta == 0) {
    return;
  }*/

  /* Distance in ticks between the last alarm event and current time.*/
  nowdelta = chTimeDiffX(ch.vtlist.lasttime, chVTGetSystemTimeX());

  /* If the current time surpassed the time of the next element in list
     then the event interrupt is already pending, just return.*/
  if (nowdelta >= ch.vtlist.next->delta) {
    return;
  }

  /* Distance from the next scheduled event and now.*/
  delta = ch.vtlist.next->delta - nowdelta;

  /* Making sure to not schedule an event closer than CH_CFG_ST_TIMEDELTA
     ticks from now.*/
  if (delta < (sysinterval_t)CH_CFG_ST_TIMEDELTA) {
    delta = nowdelta + (sysinterval_t)CH_CFG_ST_TIMEDELTA;
  }
  else {
    delta = nowdelta + delta;
#if CH_CFG_INTERVALS_SIZE > CH_CFG_ST_RESOLUTION
    /* The delta could be too large for the physical timer to handle.*/
    if (delta > (sysinterval_t)TIME_MAX_SYSTIME) {
      delta = (sysinterval_t)TIME_MAX_SYSTIME;
    }
#endif
  }
  port_timer_set_alarm(chTimeAddX(ch.vtlist.lasttime, delta));
#endif /* CH_CFG_ST_TIMEDELTA > 0 */
}
Exemple #3
0
/**
 * @brief   Time management handler.
 * @note    This handler has to be invoked by a periodic ISR in order to
 *          reschedule the waiting threads.
 *
 * @iclass
 */
void chSysTimerHandlerI(void) {

#if NIL_CFG_ST_TIMEDELTA == 0
  thread_t *tp = &nil.threads[0];
  nil.systime++;
  do {
    /* Is the thread in a wait state with timeout?.*/
    if (tp->timeout > (systime_t)0) {

      chDbgAssert(!NIL_THD_IS_READY(tp), "is ready");

     /* Did the timer reach zero?*/
      if (--tp->timeout == (systime_t)0) {
        /* Timeout on semaphores requires a special handling because the
           semaphore counter must be incremented.*/
        /*lint -save -e9013 [15.7] There is no else because it is not needed.*/
        if (NIL_THD_IS_WTSEM(tp)) {
          tp->u1.semp->cnt++;
        }
        else if (NIL_THD_IS_SUSP(tp)) {
          *tp->u1.trp = NULL;
        }
        /*lint -restore*/
        (void) chSchReadyI(tp, MSG_TIMEOUT);
      }
    }
    /* Lock released in order to give a preemption chance on those
       architectures supporting IRQ preemption.*/
    chSysUnlockFromISR();
    tp++;
    chSysLockFromISR();
  } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]);
#else
  thread_t *tp = &nil.threads[0];
  systime_t next = (systime_t)0;

  chDbgAssert(nil.nexttime == port_timer_get_alarm(), "time mismatch");

  do {
    /* Is the thread in a wait state with timeout?.*/
    if (tp->timeout > (systime_t)0) {

      chDbgAssert(!NIL_THD_IS_READY(tp), "is ready");
      chDbgAssert(tp->timeout >= (nil.nexttime - nil.lasttime), "skipped one");

      tp->timeout -= nil.nexttime - nil.lasttime;
      if (tp->timeout == (systime_t)0) {
        /* Timeout on semaphores requires a special handling because the
           semaphore counter must be incremented.*/
        /*lint -save -e9013 [15.7] There is no else because it is not needed.*/
       if (NIL_THD_IS_WTSEM(tp)) {
          tp->u1.semp->cnt++;
        }
        else if (NIL_THD_IS_SUSP(tp)) {
          *tp->u1.trp = NULL;
        }
        /*lint -restore*/
        (void) chSchReadyI(tp, MSG_TIMEOUT);
      }
      else {
        if (tp->timeout <= (systime_t)(next - (systime_t)1)) {
          next = tp->timeout;
        }
      }
    }
    /* Lock released in order to give a preemption chance on those
       architectures supporting IRQ preemption.*/
    chSysUnlockFromISR();
    tp++;
    chSysLockFromISR();
  } while (tp < &nil.threads[NIL_CFG_NUM_THREADS]);
  nil.lasttime = nil.nexttime;
  if (next > (systime_t)0) {
    nil.nexttime += next;
    port_timer_set_alarm(nil.nexttime);
  }
  else {
    /* No tick event needed.*/
    port_timer_stop_alarm();
  }
#endif
}