core: remove hwtimer, switch schedstatistics to xtimer

dev/timer
Kaspar Schleiser 8 years ago
parent 067c029f92
commit 085383bfae

@ -2,6 +2,10 @@ ifneq (,$(filter gnrc_%,$(filter-out gnrc_netapi gnrc_netreg gnrc_netif% gnrc_pk
USEMODULE += gnrc
endif
ifneq (,$(filter schedstatistics,$(USEMODULE)))
USEMODULE += xtimer
endif
ifneq (,$(filter gnrc_netif_default,$(USEMODULE)))
USEMODULE += gnrc_netif
endif

@ -13,6 +13,7 @@ PSEUDOMODULES += log
PSEUDOMODULES += log_printfnoformat
PSEUDOMODULES += newlib
PSEUDOMODULES += pktqueue
PSEUDOMODULES += schedstatistics
# include variants of the AT86RF2xx drivers as pseudo modules
PSEUDOMODULES += at86rf23%

@ -1,213 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup core_hwtimer
* @{
*
* @file
* @brief Hardware timer abstraction implementation
*
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Oliver Hahm <oliver.hahm@fu-berlin.de>
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
*
* @}
*/
#include <stdio.h>
#include "kernel.h"
#include "thread.h"
#include "lifo.h"
#include "mutex.h"
#include "irq.h"
#include "board.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "log.h"
#include "hwtimer.h"
#include "hwtimer_cpu.h"
#include "arch/hwtimer_arch.h"
/*---------------------------------------------------------------------------*/
typedef struct hwtimer_t {
void (*callback)(void*);
void *data;
} hwtimer_t;
static hwtimer_t timer[HWTIMER_MAXTIMERS];
static int lifo[HWTIMER_MAXTIMERS + 1];
/*---------------------------------------------------------------------------*/
static void multiplexer(int source)
{
lifo_insert(lifo, source);
lpm_prevent_sleep--;
timer[source].callback(timer[source].data);
}
static void hwtimer_releasemutex(void* mutex) {
mutex_unlock((mutex_t*) mutex);
}
void hwtimer_spin(unsigned long ticks)
{
DEBUG("hwtimer_spin ticks=%lu\n", ticks);
unsigned long start = hwtimer_arch_now();
/* compute destination time, possibly resulting in an overflow */
unsigned long stop = ((start + ticks) & HWTIMER_MAXTICKS);
/*
* If there is an overflow (that is: stop time is inferior to start),
* hwtimer_arch_now needs to spin until it has overflowed as well.
*/
if (stop < start) {
while (hwtimer_arch_now() > start) /* do nothing */;
}
/* wait until we have passed destination (stop) time */
while (hwtimer_arch_now() < stop) /* do nothing again */;
}
/*---------------------------------------------------------------------------*/
void hwtimer_init(void)
{
hwtimer_init_comp(F_CPU);
}
/*---------------------------------------------------------------------------*/
void hwtimer_init_comp(uint32_t fcpu)
{
hwtimer_arch_init(multiplexer, fcpu);
lifo_init(lifo, HWTIMER_MAXTIMERS);
for (int i = 0; i < HWTIMER_MAXTIMERS; i++) {
lifo_insert(lifo, i);
}
}
/*---------------------------------------------------------------------------*/
int hwtimer_active(void)
{
return (!lifo_empty(lifo));
}
/*---------------------------------------------------------------------------*/
unsigned long hwtimer_now(void)
{
return hwtimer_arch_now();
}
/*---------------------------------------------------------------------------*/
void hwtimer_wait(unsigned long ticks)
{
DEBUG("hwtimer_wait ticks=%lu\n", ticks);
if ((ticks <= (HWTIMER_SPIN_BARRIER)) || inISR()) {
hwtimer_spin(ticks);
return;
}
mutex_t mutex = MUTEX_INIT;
mutex_lock(&mutex);
int res = hwtimer_set(ticks - (HWTIMER_WAIT_OVERHEAD), hwtimer_releasemutex, &mutex);
if (res == -1) {
mutex_unlock(&mutex);
hwtimer_spin(ticks);
return;
}
/* try to lock mutex again will cause the thread to go into
* STATUS_MUTEX_BLOCKED until hwtimer fires the releasemutex */
mutex_lock(&mutex);
}
/*---------------------------------------------------------------------------*/
static int _hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr, bool absolute)
{
DEBUG("_hwtimer_set: offset=%lu callback=%p ptr=%p absolute=%d\n", offset, callback, ptr, absolute);
unsigned state;
state = disableIRQ();
int n = lifo_get(lifo);
if (n == -1) {
restoreIRQ(state);
LOG_WARNING("No hwtimer left.\n");
return -1;
}
timer[n].callback = callback;
timer[n].data = ptr;
if (absolute) {
DEBUG("hwtimer_arch_set_absolute n=%d\n", n);
hwtimer_arch_set_absolute(offset, n);
}
else {
DEBUG("hwtimer_arch_set n=%d\n", n);
hwtimer_arch_set(offset, n);
}
lpm_prevent_sleep++;
restoreIRQ(state);
return n;
}
int hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr)
{
return _hwtimer_set(offset, callback, ptr, false);
}
int hwtimer_set_absolute(unsigned long offset, void (*callback)(void*), void *ptr)
{
return _hwtimer_set(offset, callback, ptr, true);
}
/*---------------------------------------------------------------------------*/
int hwtimer_remove(int n)
{
DEBUG("hwtimer_remove n=%d\n", n);
unsigned state = disableIRQ();
hwtimer_arch_unset(n);
lifo_insert(lifo, n);
timer[n].callback = NULL;
lpm_prevent_sleep--;
restoreIRQ(state);
return 1;
}

@ -1,85 +0,0 @@
/*
* Copyright (C) 2014 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup core_arch
* @{
*
* @file
* @brief The kernel's hardware timer abstraction interface
*
* @author Thomas Hillebrandt <hillebra@inf.fu-berlin.de>
* @author Heiko Will <hwill@inf.fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
*/
#ifndef HWTIMER_ARCH_H_
#define HWTIMER_ARCH_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/**
* @brief Initialize architecture dependent kernel timer support
*
* @param[in] handler callback that is called when timer @p offset is reached
* @param[in] fcpu the core CPU-frequency for tick interval calculation
*/
void hwtimer_arch_init(void (*handler)(int), uint32_t fcpu);
/**
* @brief Enable interrupts of hardware timers
*/
void hwtimer_arch_enable_interrupt(void);
/**
* @brief Disable interrupts of hardware timers
*/
void hwtimer_arch_disable_interrupt(void);
/**
* @brief Set a kernel timer to raise an interrupt after @p offset kernel timer
* ticks from now
*
* @param[in] offset number of ticks until the timer fires
* @param[in] timer the channel to set
*/
void hwtimer_arch_set(unsigned long offset, short timer);
/**
* @brief Set a kernel timer to raise an interrupt at specified system time.
*
* @param[in] value absolute timer tick value to set a timer channel to
* @param[in] timer the channel to set
*/
void hwtimer_arch_set_absolute(unsigned long value, short timer);
/**
* @brief Unset the kernel timer with the given timer ID
*
* @param[in] timer the channel to unset
*/
void hwtimer_arch_unset(short timer);
/**
* @brief Get the current tick count of the default hardware timer
*
* @return the current value of the hwtimer
*/
unsigned long hwtimer_arch_now(void);
#ifdef __cplusplus
}
#endif
#endif /* HWTIMER_ARCH_H_ */
/** @} */

@ -1,196 +0,0 @@
/*
* Copyright (C) 2013 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup core_hwtimer Hardware timer
* @ingroup core
* @brief Hardware timer interface
*
* The Hardware timers are directly mapped to hardware timers with minimum
* latency. They are intended for short intervals and to be used in time
* critical low-level drivers (e.g. radio). hwtimer callbacks are run in the
* interrupt context and must use the shortest possible execution time (e.g.
* set a flag and trigger a worker thread).
*
* <b>The hardware timer should not be used (until you know what
* you're doing)</b>, use \ref sys_vtimer instead.
*
* @{
*
* @file
* @brief HW-timer abstraction
*
* @author Heiko Will
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Michael Baar
*/
#ifndef HWTIMER_H
#define HWTIMER_H
#include <stdint.h>
#include "hwtimer_cpu.h"
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Number of kernel timer ticks per second
* @def HWTIMER_SPEED
*/
#ifndef HWTIMER_SPEED
#warning "HWTIMER_SPEED undefined. Set HWTIMER_SPEED to the number of ticks \
per second for the current architecture."
#endif
/**
* @brief Upper bound for hwtimer_spin
*
* @note Barrier starting from which hwtimer_spin is called instead
* of setting a timer and yielding the thread.
*
* Boards should override this.
*
* @def HWTIMER_SPIN_BARRIER
*/
#ifndef HWTIMER_SPIN_BARRIER
#define HWTIMER_SPIN_BARRIER (6)
#endif
/**
* @brief Overhead of the `hwtimer_wait` function
*
* @note This value is used to decrease the number of ticks that
* `hwtimer_wait` uses to set the actual hardware timer.
*
* The goal is to make sure the number of ticks spent in the
* function corresponds to the ticks argument it was given.
*
* Boards should override this.
*
* @def HWTIMER_WAIT_OVERHEAD
*/
#ifndef HWTIMER_WAIT_OVERHEAD
#define HWTIMER_WAIT_OVERHEAD (2)
#endif
/**
* @brief Convert microseconds to kernel timer ticks
* @param[in] us number of microseconds
* @return kernel timer ticks
*/
#if HWTIMER_SPEED > 1000000L
#define HWTIMER_TICKS(us) ((us) * (HWTIMER_SPEED / 1000000L))
#else
#define HWTIMER_TICKS(us) ((us) / (1000000L / HWTIMER_SPEED))
#endif
/**
* @brief Convert ticks to microseconds
* @param[in] ticks number of ticks
* @return microseconds
*/
#if HWTIMER_SPEED > 1000000L
#define HWTIMER_TICKS_TO_US(ticks) ((ticks) / (HWTIMER_SPEED / 1000000L))
#else
#define HWTIMER_TICKS_TO_US(ticks) ((ticks) * (1000000L / HWTIMER_SPEED))
#endif
/**
* @brief Maximum hwtimer tick count (before overflow)
* @def HWTIMER_MAXTICKS
*/
#ifndef HWTIMER_MAXTICKS
#warning "HWTIMER_MAXTICKS undefined. Set HWTIMER_MAXTICKS to the maximum \
number of ticks countable on the current architecture."
#endif
/**
* @brief microseconds before hwtimer overflow
*/
#if HWTIMER_SPEED > 1000000L
#define HWTIMER_OVERFLOW_MICROS() (HWTIMER_MAXTICKS / HWTIMER_SPEED * 1000000L)
#else
#define HWTIMER_OVERFLOW_MICROS() (1000000L / HWTIMER_SPEED * HWTIMER_MAXTICKS)
#endif
typedef uint32_t timer_tick_t; /**< data type for hwtimer ticks */
/**
* @brief initialize the hwtimer module
*/
void hwtimer_init(void);
/**
* @brief Get the hardware time
* @return The current tick count of the hardware timer
*/
unsigned long hwtimer_now(void);
/**
* @brief Set a kernel timer
* @param[in] offset Offset until callback invocation in timer ticks
* @param[in] callback Callback function
* @param[in] ptr Argument to callback function
* @return timer id
*/
int hwtimer_set(unsigned long offset, void (*callback)(void*), void *ptr);
/**
* @brief Set a kernel timer
* @param[in] absolute Absolute timer counter value for invocation
* of handler
* @param[in] callback Callback function
* @param[in] ptr Argument to callback function
* @return timer id
*/
int hwtimer_set_absolute(unsigned long absolute,
void (*callback)(void*), void *ptr);
/**
* @brief Remove a kernel timer
* @param[in] t Id of timer to remove
* @return 1 on success
*/
int hwtimer_remove(int t);
/**
* @brief Delay current thread
* @param[in] ticks Number of kernel ticks to delay
*/
void hwtimer_wait(unsigned long ticks);
/**
* @brief determine if the hwtimer module is initialized
* @return 1 if the hwtimer module is initialized
*/
int hwtimer_active(void);
/**
* @brief initialize hwtimer module data structures and hardware
*
* @param[in] fcpu cpu frequency
*/
void hwtimer_init_comp(uint32_t fcpu);
/**
* @brief Delay current thread, spinning. Use only in interrupts for
* VERY short delays!
*
* @param[in] ticks Number of kernel ticks to delay
*/
void hwtimer_spin(unsigned long ticks);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* HWTIMER_H */

@ -164,7 +164,7 @@ extern volatile kernel_pid_t sched_active_pid;
*/
extern clist_node_t *sched_runqueues[SCHED_PRIO_LEVELS];
#if SCHEDSTATISTICS
#ifdef MODULE_SCHEDSTATISTICS
/**
* Scheduler statistics
*/

@ -29,10 +29,13 @@
#include "cpu.h"
#include "lpm.h"
#include "thread.h"
#include "hwtimer.h"
#include "irq.h"
#include "log.h"
#ifdef MODULE_SCHEDSTATISTICS
#include "sched.h"
#endif
#define ENABLE_DEBUG (0)
#include "debug.h"
@ -51,6 +54,11 @@ static void *main_trampoline(void *arg)
auto_init();
#endif
#ifdef MODULE_SCHEDSTATISTICS
schedstat *stat = &sched_pidlist[thread_getpid()];
stat->laststart = 0;
#endif
LOG_INFO("main(): This is RIOT! (Version: " RIOT_VERSION ")\n");
main();
@ -85,8 +93,6 @@ void kernel_init(void)
{
(void) disableIRQ();
hwtimer_init();
thread_create(idle_stack, sizeof(idle_stack),
THREAD_PRIORITY_IDLE,
CREATE_WOUT_YIELD | CREATE_STACKTEST,

@ -31,8 +31,8 @@
#include "irq.h"
#include "log.h"
#if SCHEDSTATISTICS
#include "hwtimer.h"
#ifdef MODULE_SCHEDSTATISTICS
#include "xtimer.h"
#endif
#define ENABLE_DEBUG (0)
@ -55,7 +55,7 @@ volatile kernel_pid_t sched_active_pid = KERNEL_PID_UNDEF;
clist_node_t *sched_runqueues[SCHED_PRIO_LEVELS];
static uint32_t runqueue_bitcache = 0;
#if SCHEDSTATISTICS
#ifdef MODULE_SCHEDSTATISTICS
static void (*sched_cb) (uint32_t timestamp, uint32_t value) = NULL;
schedstat sched_pidlist[KERNEL_PID_LAST + 1];
#endif
@ -81,8 +81,8 @@ int sched_run(void)
return 0;
}
#ifdef SCHEDSTATISTICS
unsigned long time = hwtimer_now();
#ifdef MODULE_SCHEDSTATISTICS
unsigned long time = xtimer_now();
#endif
if (active_thread) {
@ -96,7 +96,7 @@ int sched_run(void)
}
#endif
#ifdef SCHEDSTATISTICS
#ifdef MODULE_SCHEDSTATISTICS
schedstat *active_stat = &sched_pidlist[active_thread->pid];
if (active_stat->laststart) {
active_stat->runtime_ticks += time - active_stat->laststart;
@ -104,7 +104,7 @@ int sched_run(void)
#endif
}
#if SCHEDSTATISTICS
#ifdef MODULE_SCHEDSTATISTICS
schedstat *next_stat = &sched_pidlist[next_thread->pid];
next_stat->laststart = time;
next_stat->schedules++;
@ -122,7 +122,7 @@ int sched_run(void)
return 1;
}
#if SCHEDSTATISTICS
#ifdef MODULE_SCHEDSTATISTICS
void sched_register_cb(void (*callback)(uint32_t, uint32_t))
{
sched_cb = callback;

@ -29,7 +29,6 @@
#include "debug.h"
#include "kernel_internal.h"
#include "bitarithm.h"
#include "hwtimer.h"
#include "sched.h"
volatile tcb_t *thread_get(kernel_pid_t pid)

Loading…
Cancel
Save