Exemple #1
0
/**
 * Main function of the timer task. This function is in charge of
 *    calling the callbacks associated with the timers.
 *
 *    This function is run in a high priority task on microkernel builds.
 *    This function is run in a high priority fiber on nanokernel builds.
 *    It implements an infinite loop that waits for any of the semaphores from
 *    g_TimerSem.
 *    When a semaphore is signaled, this function fetches the pointer to the
 *    associated callback in g_TimerDesc, then calls it.
 *
 * @param dummy1 not used (required by ZEPHYR API)
 * @param dummy2 not used (required by ZEPHYR API) *
 *
 */
void timer_task(int dummy1, int dummy2)
{
	int32_t timeout = UINT32_MAX;
	uint32_t now;

	UNUSED(dummy1);
	UNUSED(dummy2);

	while (1) { /* the Timer task shall never stop */
		/* Before waiting for next timeout, publish it to warn QUARK cpu */
		publish_cpu_timeout(timeout);
		/* block until g_TimerSem is signaled or until the next timeout expires */
#ifdef CONFIG_MICROKERNEL
		(void)task_sem_take(g_TimerSem, CONVERT_MS_TO_TICKS(timeout));
#else
		nano_sem_take(&g_TimerSem, CONVERT_MS_TO_TICKS(timeout));
#endif
		now = get_uptime_ms();
		/* task is unblocked: check for expired timers */
		while (g_CurrentTimerHead &&
		       is_after_expiration(now, &(g_CurrentTimerHead->desc))) {
			execute_callback(g_CurrentTimerHead);
			now = get_uptime_ms();
		}
		/* Compute timeout until the expiration of the next timer */
		if (g_CurrentTimerHead != NULL) {
			/* In micro kernel context, timeout = 0 or timeout < 0 works.
			 * In nano kernel context timeout must be a positive value.
			 */
			timeout = g_CurrentTimerHead->desc.expiration - now;
			if (timeout < 0) panic(E_OS_ERR_OVERFLOW);
		} else {
			timeout = UINT32_MAX;
		}

#ifdef __DEBUG_OS_ABSTRACTION_TIMER
		if (NULL != g_CurrentTimerHead)
			_log(
				"\nINFO : timer_task : now = %u, next timer expires at %u, timeout = %u",
				get_uptime_ms(),
				g_CurrentTimerHead->desc.expiration,
				timeout);
		else
			_log(
				"\nINFO : timer_task : now = %u, no next timer, timeout = OS_WAIT_FOREVER",
				get_uptime_ms());
#endif
	} /* end while(1) */
}
Exemple #2
0
/**
 * Insert a timer in the list of active timer,
 *    according to its expiration date.
 *
 * @param newTimer pointer on the timer to insert
 *
 * WARNING: newTimer MUST NOT be null (rem: static function )
 *
 */
static void add_timer(T_TIMER_LIST_ELT *newTimer)
{
	T_TIMER_LIST_ELT *insertionPoint;
	T_TIMER_LIST_ELT *listTail;
	bool found;

#ifdef __DEBUG_OS_ABSTRACTION_TIMER
	_log(
		"\nINFO : add_timer - start: adding 0x%x to expire at %d (now = %d - delay = %d - ticktime = %d)",
		(uint32_t)newTimer, newTimer->desc.expiration,
		get_uptime_ms(), newTimer->desc.delay, sys_clock_us_per_tick);
	display_list();
#endif


	if (NULL == g_CurrentTimerHead) {
		/* there is no active timer, make newTimer the head timer */
		g_CurrentTimerHead = newTimer;
		newTimer->prev = NULL;
		newTimer->next = NULL;
	} else {
		/* find the next timer to expire after newTimer->desc.expiration */
		insertionPoint = g_CurrentTimerHead;
		listTail = g_CurrentTimerHead;
		found = false;
		while ((NULL != insertionPoint) && (false == found)) {
			if (!is_after_expiration(newTimer->desc.expiration,
						 &(insertionPoint->desc))) { /* newTimer is due to expire before insertionPoint */
				if (g_CurrentTimerHead == insertionPoint) { /*  insert newTimer before the head timer  */
					g_CurrentTimerHead->prev = newTimer;
					newTimer->prev = NULL;
					newTimer->next = g_CurrentTimerHead;
					g_CurrentTimerHead = newTimer;
				} else { /* insert newTimer between insertionPoint and insertionPoint->prev */
					newTimer->prev = insertionPoint->prev;
					newTimer->next = insertionPoint;
					insertionPoint->prev = newTimer;
					newTimer->prev->next = newTimer;
				}
				/* done */
				found = true;
			} else { /* newTimer is due to expire after insertionPoint, continue searching */
				listTail = insertionPoint; /* update list head marker = last non null insertionPoint */
				/* move downward */
				insertionPoint = insertionPoint->next;
			}
		}

		if ((false == found) && (NULL != listTail)) {
			/* newTimer is due to expire after all others have expired */
			listTail->next = newTimer;
			newTimer->prev = listTail;
		}
	}

	newTimer->desc.status = E_TIMER_RUNNING;

#ifdef __DEBUG_OS_ABSTRACTION_TIMER
	_log("\nINFO : add_timer - end "); display_list();
	display_list();
#endif
}
Exemple #3
0
/**
 * Main function of the timer task. This function is in charge of
 *    calling the callbacks associated with the timers.
 *
 *    This function is run in a high priority task on microkernel builds.
 *    This function is run in a high priority fiber on nanokernel builds.
 *    It implements an infinite loop that waits for any of the semaphores from
 *    g_TimerSem.
 *    When a semaphore is signaled, this function fetches the pointer to the
 *    associated callback in g_TimerDesc, then calls it.
 *
 * @param dummy1 not used (required by ZEPHYR API)
 * @param dummy2 not used (required by ZEPHYR API) *
 *
 */
void timer_task(int dummy1, int dummy2)
{
    uint32_t timeout;
    uint32_t now;

    UNUSED(dummy1);
    UNUSED(dummy2);

    timeout = OS_WAIT_FOREVER;

    while (1) /* the Timer task shall never stop */
    {
#ifdef CONFIG_MICROKERNEL /********************** MICRO KERNEL SPECIFIC:  */
        /* block until g_TimerSem is signaled or until the next timeout expires */
        (void) task_sem_take_wait_timeout(g_TimerSem, timeout);
#else
        if (NULL == g_CurrentTimerHead)
        {
            /* Start a background timer with max positive delay */
            nano_fiber_timer_start (&g_NanoTimer, 0x7FFFFFFF);
            /* wait until the next timer expires or one is added or removed */
            nano_fiber_timer_wait (&g_NanoTimer);
        }
#endif
        now = _GET_TICK();
        /* task is unblocked: check for expired timers */
        while (is_after_expiration (now, &(g_CurrentTimerHead->desc)))
        {
            execute_callback(g_CurrentTimerHead);
        }
        /* Compute timeout until the expiration of the next timer */
        if ( NULL != g_CurrentTimerHead )
        {
            now = _GET_TICK();
            /* In micro kernel context, timeout = 0 or timeout < 0 works.
             * In nano kernel context timeout must be a positive value.
            */
#ifdef CONFIG_NANOKERNEL
            if (g_CurrentTimerHead->desc.expiration > now)
            {
#endif
                timeout = g_CurrentTimerHead->desc.expiration - now;
                if (OS_WAIT_FOREVER == timeout)
                { /* cannot have timeout = OS_WAIT_FOREVER while there is
                    still at least one active timer */
                    timeout++;
                }
#ifdef CONFIG_NANOKERNEL
                nano_fiber_timer_start (&g_NanoTimer, timeout);
                /* wait until the next timer expires or one is added or removed */
                nano_fiber_timer_wait (&g_NanoTimer);
                /* nano_fiber_timer_wait will wait until "natural" timer
                * expiration, or until nano_fiber_timer_stop(&g_NanoTimer)
                * is called by the timer_callback or by timer_stop() */
            }
#endif
        }
#ifdef CONFIG_MICROKERNEL
        else
        {
            timeout = OS_WAIT_FOREVER;
        }
#endif

#ifdef __DEBUG_OS_ABSTRACTION_TIMER
        if (NULL != g_CurrentTimerHead )
            _log ("\nINFO : timer_task : now = %u, next timer expires at %u, timeout = %u", _GET_TICK() , g_CurrentTimerHead->desc.expiration, timeout );
        else
            _log ("\nINFO : timer_task : now = %u, no next timer, timeout = OS_WAIT_FOREVER", _GET_TICK() );
#endif

    } /* end while(1) */
}