1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

xtimer: Add tick conversion

This commit is contained in:
Joakim Nohlgård 2016-07-05 16:00:48 +02:00
parent 199140e50b
commit 63e91151cd
8 changed files with 451 additions and 116 deletions

View File

@ -40,7 +40,7 @@ typedef enum {
/** @brief Delay to wait between toggling CS pin, on most chips this can probably be
* removed. */
#define NVRAM_SPI_CS_TOGGLE_TICKS 1
#define NVRAM_SPI_CS_TOGGLE_TICKS xtimer_ticks_from_usec(1)
/**
* @brief Copy data from system memory to NVRAM.

View File

@ -40,6 +40,24 @@
extern "C" {
#endif
/**
* @brief xtimer timestamp (64 bit)
*
* @note This is a struct in order to make the xtimer API type strict
*/
typedef struct {
uint64_t ticks64;
} xtimer_ticks64_t;
/**
* @brief xtimer timestamp (32 bit)
*
* @note This is a struct in order to make the xtimer API type strict
*/
typedef struct {
uint32_t ticks32;
} xtimer_ticks32_t;
/**
* @brief xtimer callback type
*/
@ -58,21 +76,21 @@ typedef struct xtimer {
} xtimer_t;
/**
* @brief get the current system time as 32bit microsecond value
* @brief get the current system time as 32bit time stamp value
*
* @note Overflows every ~71minutes, thus returns xtimer_now64() % 32,
* but is more efficient.
* @note Overflows 2**32 ticks, thus returns xtimer_now64() % 32,
* but is cheaper.
*
* @return current time as 32bit microsecond value
* @return current time as 32bit time stamp
*/
static inline uint32_t xtimer_now(void);
static inline xtimer_ticks32_t xtimer_now(void);
/**
* @brief get the current system time as 64bit microsecond value
* @brief get the current system time as 64bit time stamp
*
* @return current time as 64bit microsecond value
* @return current time as 64bit time stamp
*/
uint64_t xtimer_now64(void);
static inline xtimer_ticks64_t xtimer_now64(void);
/**
* @brief get the current system time into a timex_t
@ -98,7 +116,7 @@ void xtimer_init(void);
*
* @param[in] seconds the amount of seconds the thread should sleep
*/
static void xtimer_sleep(uint32_t seconds);
static inline void xtimer_sleep(uint32_t seconds);
/**
* @brief Pause the execution of a thread for some microseconds
@ -109,18 +127,7 @@ static void xtimer_sleep(uint32_t seconds);
*
* @param[in] microseconds the amount of microseconds the thread should sleep
*/
static void xtimer_usleep(uint32_t microseconds);
/**
* @brief Stop execution of a thread for some time, 64bit version
*
* When called from an ISR, this function will spin and thus block the MCU for
* the specified amount in microseconds, so only use it there for *very* short
* periods, e.g., less then XTIMER_BACKOFF.
*
* @param[in] microseconds the amount of microseconds the thread should sleep
*/
static inline void xtimer_usleep64(uint64_t microseconds);
static inline void xtimer_usleep(uint32_t microseconds);
/**
* @brief Stop execution of a thread for some time
@ -133,16 +140,38 @@ static inline void xtimer_usleep64(uint64_t microseconds);
*
* @param[in] nanoseconds the amount of nanoseconds the thread should sleep
*/
static void xtimer_nanosleep(uint32_t nanoseconds);
static inline void xtimer_nanosleep(uint32_t nanoseconds);
/**
* @brief Stop execution of a thread for some time, 32bit version
*
* When called from an ISR, this function will spin and thus block the MCU for
* the specified amount, so only use it there for *very* short periods,
* e.g. less than XTIMER_BACKOFF.
*
* @param[in] ticks number of ticks the thread should sleep
*/
static inline void xtimer_tsleep32(xtimer_ticks32_t ticks);
/**
* @brief Stop execution of a thread for some time, 64bit version
*
* When called from an ISR, this function will spin and thus block the MCU for
* the specified amount, so only use it there for *very* short periods,
* e.g. less than XTIMER_BACKOFF.
*
* @param[in] ticks number of ticks the thread should sleep
*/
static inline void xtimer_tsleep64(xtimer_ticks64_t ticks);
/**
* @brief Stop execution of a thread for some time, blocking
*
* This function will spin-block, so only use it *very* short periods.
*
* @param[in] microseconds the amount of microseconds the thread should spin
* @param[in] ticks the number of xtimer ticks the thread should spin for
*/
static inline void xtimer_spin(uint32_t microseconds);
static inline void xtimer_spin(xtimer_ticks32_t ticks);
/**
* @brief will cause the calling thread to be suspended until the absolute
@ -161,12 +190,12 @@ static inline void xtimer_spin(uint32_t microseconds);
* @param[in] last_wakeup base time stamp for the wakeup
* @param[in] period time in microseconds that will be added to last_wakeup
*/
void xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period);
static inline void xtimer_periodic_wakeup(xtimer_ticks32_t *last_wakeup, uint32_t period);
/**
* @brief Set a timer that sends a message
*
* This function sets a timer that will send a message @p offset microseconds
* This function sets a timer that will send a message @p offset ticks
* from now.
*
* The mesage struct specified by msg parameter will not be copied, e.g., it
@ -179,7 +208,7 @@ void xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period);
* @param[in] msg ptr to msg that will be sent
* @param[in] target_pid pid the message will be sent to
*/
void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid);
static inline void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid);
/**
* @brief Set a timer that sends a message, 64bit version
@ -197,7 +226,7 @@ void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t t
* @param[in] msg ptr to msg that will be sent
* @param[in] target_pid pid the message will be sent to
*/
void xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_t target_pid);
static inline void xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_t target_pid);
/**
* @brief Set a timer that wakes up a thread
@ -211,7 +240,7 @@ void xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_t
* @param[in] offset microseconds from now
* @param[in] pid pid of the thread that will be woken up
*/
void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid);
static inline void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid);
/**
* @brief Set a timer that wakes up a thread, 64bit version
@ -225,7 +254,7 @@ void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid);
* @param[in] offset microseconds from now
* @param[in] pid pid of the thread that will be woken up
*/
void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid);
static inline void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid);
/**
* @brief Set a timer to execute a callback at some time in the future
@ -233,7 +262,7 @@ void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid);
* Expects timer->callback to be set.
*
* The callback specified in the timer struct will be executed @p offset
* microseconds in the future.
* ticks in the future.
*
* @warning BEWARE! Callbacks from xtimer_set() are being executed in interrupt
* context (unless offset < XTIMER_BACKOFF). DON'T USE THIS FUNCTION unless you
@ -245,7 +274,7 @@ void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid);
* @param[in] offset time in microseconds from now specifying that timer's
* callback's execution time
*/
void xtimer_set(xtimer_t *timer, uint32_t offset);
static inline void xtimer_set(xtimer_t *timer, uint32_t offset);
/**
* @brief remove a timer
@ -259,24 +288,78 @@ void xtimer_remove(xtimer_t *timer);
/**
* @brief receive a message blocking but with timeout
*
* @param[out] msg pointer to a msg_t which will be filled in case of
* @param[out] msg pointer to a msg_t which will be filled in case of
* no timeout
* @param[in] us timeout in microseconds relative
* @param[in] timeout timeout in microseconds relative
*
* @return < 0 on error, other value otherwise
* @return < 0 on error, other value otherwise
*/
int xtimer_msg_receive_timeout(msg_t *msg, uint32_t us);
static inline int xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout);
/**
* @brief receive a message blocking but with timeout, 64bit version
*
* @param[out] msg pointer to a msg_t which will be filled in case of no
* @param[out] msg pointer to a msg_t which will be filled in case of no
* timeout
* @param[in] us timeout in microseconds relative
* @param[in] timeout timeout in microseconds relative
*
* @return < 0 on error, other value otherwise
* @return < 0 on error, other value otherwise
*/
int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
static inline int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t timeout);
/**
* @brief Convert microseconds to xtimer ticks
*
* @param[in] usec microseconds
*
* @return xtimer time stamp
*/
static inline xtimer_ticks32_t xtimer_ticks_from_usec(uint32_t usec);
/**
* @brief Convert microseconds to xtimer ticks, 64 bit version
*
* @param[in] usec microseconds
*
* @return xtimer time stamp
*/
static inline xtimer_ticks64_t xtimer_ticks_from_usec64(uint64_t usec);
/**
* @brief Convert xtimer ticks to microseconds
*
* @param[in] ticks xtimer time stamp
*
* @return microseconds
*/
static inline uint32_t xtimer_usec_from_ticks(xtimer_ticks32_t ticks);
/**
* @brief Convert xtimer ticks to microseconds, 64 bit version
*
* @param[in] ticks xtimer time stamp
*
* @return microseconds
*/
static inline uint64_t xtimer_usec_from_ticks64(xtimer_ticks64_t ticks);
/**
* @brief Create an xtimer time stamp
*
* @param[in] ticks number of xtimer ticks
*
* @return xtimer time stamp
*/
static inline xtimer_ticks32_t xtimer_ticks(uint32_t ticks);
/**
* @brief Create an xtimer time stamp, 64 bit version
*
* @param[in] ticks number of xtimer ticks
*
* @return xtimer time stamp
*/
static inline xtimer_ticks64_t xtimer_ticks64(uint64_t ticks);
/**
* @brief xtimer backoff value
@ -291,7 +374,7 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
#endif
/**
* @brief xtimer overhead value
* @brief xtimer overhead value, in hardware ticks
*
* This value specifies the time a timer will be late if uncorrected, e.g.,
* the system-specific xtimer execution time from timer ISR to executing
@ -315,9 +398,9 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
#ifndef XTIMER_ISR_BACKOFF
/**
* @brief xtimer isr backoff time
* @brief xtimer IRQ backoff time, in hardware ticks
*
* When scheduling the next isr, if it is less than the backoff time
* When scheduling the next IRQ, if it is less than the backoff time
* in the future, just spin.
*
* This is supposed to be defined per-device in e.g., periph_conf.h.
@ -352,14 +435,16 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
/**
* @brief xtimer prescaler value
*
* xtimer assumes it is running with an underlying 1MHz timer.
* If the timer is slower by a power of two, XTIMER_SHIFT can be used to
* adjust the difference.
* If the underlying hardware timer is running at a power of two multiple of
* 15625, XTIMER_SHIFT can be used to adjust the difference.
*
* This will also initialize the underlying periph timer with
* us_per_tick == (1<<XTIMER_SHIFT).
* For a 1 MHz hardware timer, set XTIMER_SHIFT to 0.
*
* For example, if the timer is running with 250khz, set XTIMER_SHIFT to 2.
* For a 4 MHz hardware timer, set XTIMER_SHIFT to 2.
* For a 16 MHz hardware timer, set XTIMER_SHIFT to 4.
* For a 250 kHz hardware timer, set XTIMER_SHIFT to 2.
*
* The direction of the shift is handled by the macros in tick_conversion.h
*/
#define XTIMER_SHIFT (0)
#endif
@ -410,7 +495,14 @@ int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t us);
#define XTIMER_MASK (0)
#endif
#define XTIMER_MASK_SHIFTED XTIMER_TICKS_TO_USEC(XTIMER_MASK)
#ifndef XTIMER_HZ
/**
* @brief Frequency of the underlying hardware timer
*/
#define XTIMER_HZ 1000000ul
#endif
#include "xtimer/tick_conversion.h"
#include "xtimer/implementation.h"

View File

@ -33,14 +33,6 @@ extern "C" {
extern volatile uint32_t _xtimer_high_cnt;
#endif
#if (XTIMER_SHIFT < 0)
#define XTIMER_USEC_TO_TICKS(value) ( (value) << -XTIMER_SHIFT )
#define XTIMER_TICKS_TO_USEC(value) ( (value) >> -XTIMER_SHIFT )
#else
#define XTIMER_USEC_TO_TICKS(value) ( (value) >> XTIMER_SHIFT )
#define XTIMER_TICKS_TO_USEC(value) ( (value) << XTIMER_SHIFT )
#endif
/**
* @brief IPC message type for xtimer msg callback
*/
@ -51,11 +43,7 @@ extern volatile uint32_t _xtimer_high_cnt;
*/
static inline uint32_t _xtimer_lltimer_now(void)
{
#if XTIMER_SHIFT
return XTIMER_TICKS_TO_USEC((uint32_t)timer_read(XTIMER_DEV));
#else
return timer_read(XTIMER_DEV);
#endif
}
/**
@ -63,7 +51,7 @@ static inline uint32_t _xtimer_lltimer_now(void)
*/
static inline uint32_t _xtimer_lltimer_mask(uint32_t val)
{
return val & ~XTIMER_MASK_SHIFTED;
return val & ~XTIMER_MASK;
}
/**
@ -71,22 +59,36 @@ static inline uint32_t _xtimer_lltimer_mask(uint32_t val)
* @brief xtimer internal stuff
* @internal
*/
uint64_t _xtimer_now64(void);
int _xtimer_set_absolute(xtimer_t *timer, uint32_t target);
void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset);
void _xtimer_sleep(uint32_t offset, uint32_t long_offset);
void _xtimer_set(xtimer_t *timer, uint32_t offset);
void _xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period);
void _xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid);
void _xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_t target_pid);
void _xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid);
void _xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid);
void _xtimer_set(xtimer_t *timer, uint32_t offset);
int _xtimer_msg_receive_timeout(msg_t *msg, uint32_t ticks);
int _xtimer_msg_receive_timeout64(msg_t *msg, uint64_t ticks);
/**
* @brief Sleep for the given number of ticks
*/
void _xtimer_tsleep(uint32_t offset, uint32_t long_offset);
/** @} */
#ifndef XTIMER_MIN_SPIN
/**
* @brief Minimal value xtimer_spin() can spin
*/
#define XTIMER_MIN_SPIN XTIMER_TICKS_TO_USEC(1)
#define XTIMER_MIN_SPIN _xtimer_usec_from_ticks(1)
#endif
#ifndef DOXYGEN
/* Doxygen warns that these are undocumented, but the documentation can be found in xtimer.h */
static inline uint32_t xtimer_now(void)
static inline uint32_t _xtimer_now(void)
{
#if XTIMER_MASK
uint32_t latched_high_cnt, now;
@ -106,7 +108,19 @@ static inline uint32_t xtimer_now(void)
#endif
}
static inline void xtimer_spin(uint32_t offset) {
static inline xtimer_ticks32_t xtimer_now(void)
{
xtimer_ticks32_t ret = { .ticks32 = _xtimer_now() };
return ret;
}
static inline xtimer_ticks64_t xtimer_now64(void)
{
xtimer_ticks64_t ret = { .ticks64 = _xtimer_now64() };
return ret;
}
static inline void _xtimer_spin(uint32_t offset) {
uint32_t start = _xtimer_lltimer_now();
#if XTIMER_MASK
offset = _xtimer_lltimer_mask(offset);
@ -116,24 +130,122 @@ static inline void xtimer_spin(uint32_t offset) {
#endif
}
static inline void _xtimer_tsleep32(uint32_t ticks)
{
_xtimer_tsleep(ticks, 0);
}
static inline void _xtimer_tsleep64(uint64_t ticks)
{
_xtimer_tsleep((uint32_t)ticks, (uint32_t)(ticks >> 32));
}
static inline void xtimer_spin(xtimer_ticks32_t ticks) {
_xtimer_spin(ticks.ticks32);
}
static inline void xtimer_usleep(uint32_t microseconds)
{
_xtimer_sleep(microseconds, 0);
_xtimer_tsleep32(_xtimer_ticks_from_usec(microseconds));
}
static inline void xtimer_usleep64(uint64_t microseconds)
{
_xtimer_sleep((uint32_t) microseconds, (uint32_t) (microseconds >> 32));
_xtimer_tsleep64(_xtimer_ticks_from_usec64(microseconds));
}
static inline void xtimer_sleep(uint32_t seconds)
{
xtimer_usleep64((uint64_t)seconds * SEC_IN_USEC);
_xtimer_tsleep64(_xtimer_ticks_from_usec64((uint64_t)seconds * SEC_IN_USEC));
}
static inline void xtimer_nanosleep(uint32_t nanoseconds)
{
_xtimer_sleep(nanoseconds / USEC_IN_NS, 0);
_xtimer_tsleep32(_xtimer_ticks_from_usec(nanoseconds / USEC_IN_NS));
}
static inline void xtimer_tsleep32(xtimer_ticks32_t ticks)
{
_xtimer_tsleep32(ticks.ticks32);
}
static inline void xtimer_tsleep64(xtimer_ticks64_t ticks)
{
_xtimer_tsleep64(ticks.ticks64);
}
static inline void xtimer_periodic_wakeup(xtimer_ticks32_t *last_wakeup, uint32_t period)
{
_xtimer_periodic_wakeup(&last_wakeup->ticks32, _xtimer_ticks_from_usec(period));
}
static inline void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid)
{
_xtimer_set_msg(timer, _xtimer_ticks_from_usec(offset), msg, target_pid);
}
static inline void xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_t target_pid)
{
_xtimer_set_msg64(timer, _xtimer_ticks_from_usec64(offset), msg, target_pid);
}
static inline void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid)
{
_xtimer_set_wakeup(timer, _xtimer_ticks_from_usec(offset), pid);
}
static inline void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid)
{
_xtimer_set_wakeup64(timer, _xtimer_ticks_from_usec64(offset), pid);
}
static inline void xtimer_set(xtimer_t *timer, uint32_t offset)
{
_xtimer_set(timer, _xtimer_ticks_from_usec(offset));
}
static inline int xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout)
{
return _xtimer_msg_receive_timeout(msg, _xtimer_ticks_from_usec(timeout));
}
static inline int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t timeout)
{
return _xtimer_msg_receive_timeout64(msg, _xtimer_ticks_from_usec64(timeout));
}
static inline xtimer_ticks32_t xtimer_ticks_from_usec(uint32_t usec)
{
xtimer_ticks32_t ticks = { .ticks32 = _xtimer_ticks_from_usec(usec) };
return ticks;
}
static inline xtimer_ticks64_t xtimer_ticks_from_usec64(uint64_t usec)
{
xtimer_ticks64_t ticks = { .ticks64 = _xtimer_ticks_from_usec64(usec) };
return ticks;
}
static inline uint32_t xtimer_usec_from_ticks(xtimer_ticks32_t ticks)
{
return _xtimer_usec_from_ticks(ticks.ticks32);
}
static inline uint64_t xtimer_usec_from_ticks64(xtimer_ticks64_t ticks)
{
return _xtimer_usec_from_ticks64(ticks.ticks64);
}
static inline xtimer_ticks32_t xtimer_ticks(uint32_t ticks)
{
xtimer_ticks32_t ret = { .ticks32 = ticks };
return ret;
}
static inline xtimer_ticks64_t xtimer_ticks64(uint64_t ticks)
{
xtimer_ticks64_t ret = { .ticks64 = ticks };
return ret;
}
#endif /* !defined(DOXYGEN) */

View File

@ -0,0 +1,138 @@
/*
* Copyright (C) 2016 Eistec AB
*
* 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 sys_xtimer
*
* @{
* @file
* @brief xtimer tick <-> seconds conversions for different values of XTIMER_HZ
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
*/
#ifndef XTIMER_TICK_CONVERSION_H
#define XTIMER_TICK_CONVERSION_H
#ifndef XTIMER_H
#error "Do not include this file directly! Use xtimer.h instead"
#endif
#include "div.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Some optimizations for common timer frequencies */
#if (XTIMER_SHIFT != 0)
#if (XTIMER_HZ % 15625 != 0)
#error XTIMER_HZ must be a multiple of 15625 (5^6) when using XTIMER_SHIFT
#endif
#if (XTIMER_HZ > 1000000ul)
#if (XTIMER_HZ != (1000000ul << XTIMER_SHIFT))
#error XTIMER_HZ != (1000000ul << XTIMER_SHIFT)
#endif
/* XTIMER_HZ is a power-of-two multiple of 1 MHz */
/* e.g. cc2538 uses a 16 MHz timer */
inline static uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
return (usec << XTIMER_SHIFT); /* multiply by power of two */
}
inline static uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
return (usec << XTIMER_SHIFT); /* multiply by power of two */
}
inline static uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
return (ticks >> XTIMER_SHIFT); /* divide by power of two */
}
inline static uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
return (ticks >> XTIMER_SHIFT); /* divide by power of two */
}
#else /* !(XTIMER_HZ > 1000000ul) */
#if ((XTIMER_HZ << XTIMER_SHIFT) != 1000000ul)
#error (XTIMER_HZ << XTIMER_SHIFT) != 1000000ul
#endif
/* 1 MHz is a power-of-two multiple of XTIMER_HZ */
/* e.g. ATmega2560 uses a 250 kHz timer */
inline static uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
return (usec >> XTIMER_SHIFT); /* divide by power of two */
}
inline static uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
return (usec >> XTIMER_SHIFT); /* divide by power of two */
}
inline static uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
return (ticks << XTIMER_SHIFT); /* multiply by power of two */
}
inline static uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
return (ticks << XTIMER_SHIFT); /* multiply by power of two */
}
#endif /* defined(XTIMER_SHIFT) && (XTIMER_SHIFT != 0) */
#elif XTIMER_HZ == (1000000ul)
/* This is the most straightforward as the xtimer API is based around
* microseconds for representing time values. */
inline static uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
return ticks; /* no-op */
}
inline static uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
return ticks; /* no-op */
}
inline static uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
return usec; /* no-op */
}
inline static uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
return usec; /* no-op */
}
#elif XTIMER_HZ == (32768ul)
/* This is a common frequency for RTC crystals. We use the fact that the
* greatest common divisor between 32768 and 1000000 is 64, so instead of
* multiplying by the fraction (32768 / 1000000), we will instead use
* (512 / 15625), which reduces the truncation caused by the integer widths */
inline static uint32_t _xtimer_ticks_from_usec(uint32_t usec) {
return div_u32_by_15625div512(usec);
}
inline static uint64_t _xtimer_ticks_from_usec64(uint64_t usec) {
return div_u64_by_15625div512(usec);
}
inline static uint32_t _xtimer_usec_from_ticks(uint32_t ticks) {
/* return (usec * 15625) / 512; */
/* Using 64 bit multiplication to avoid truncating the top 9 bits */
uint64_t usec = (uint64_t)ticks * 15625ul;
return (usec >> 9); /* equivalent to (usec / 512) */
}
inline static uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) {
/* return (usec * 15625) / 512; */
uint64_t usec = (uint64_t)ticks * 15625ul;
return (usec >> 9); /* equivalent to (usec / 512) */
}
#else
/* No matching implementation found, try to give meaningful error messages */
#if ((XTIMER_HZ % 15625) == 0)
#error Unsupported hardware timer frequency (XTIMER_HZ), missing XTIMER_SHIFT in board.h? See xtimer.h documentation for more info
#else
#error Unknown hardware timer frequency (XTIMER_HZ), check board.h and/or add an implementation in sys/include/xtimer/tick_conversion.h
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -340,7 +340,7 @@ int _gettimeofday_r(struct _reent *r, struct timeval *restrict tp, void *restric
{
(void)tzp;
(void) r;
uint64_t now = xtimer_now64();
uint64_t now = xtimer_usec_from_ticks64(xtimer_now64());
tp->tv_sec = div_u64_by_1000000(now);
tp->tv_usec = now - (tp->tv_sec * SEC_IN_USEC);
return 0;

View File

@ -38,11 +38,11 @@ static void _callback_unlock_mutex(void* arg)
mutex_unlock(mutex);
}
void _xtimer_sleep(uint32_t offset, uint32_t long_offset)
void _xtimer_tsleep(uint32_t offset, uint32_t long_offset)
{
if (irq_is_in()) {
assert(!long_offset);
xtimer_spin(offset);
_xtimer_spin(offset);
return;
}
@ -58,7 +58,7 @@ void _xtimer_sleep(uint32_t offset, uint32_t long_offset)
mutex_lock(&mutex);
}
void xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period) {
void _xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period) {
xtimer_t timer;
mutex_t mutex = MUTEX_INIT;
@ -66,7 +66,7 @@ void xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period) {
timer.arg = (void*) &mutex;
uint32_t target = (*last_wakeup) + period;
uint32_t now = xtimer_now();
uint32_t now = _xtimer_now();
/* make sure we're not setting a value in the past */
if (now < (*last_wakeup)) {
/* base timer overflowed between last_wakeup and now */
@ -103,7 +103,7 @@ void xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period) {
uint32_t offset = target - now;
DEBUG("xps, now: %9" PRIu32 ", tgt: %9" PRIu32 ", off: %9" PRIu32 "\n", now, target, offset);
if (offset < XTIMER_PERIODIC_SPIN) {
xtimer_spin(offset);
_xtimer_spin(offset);
}
else {
if (offset < XTIMER_PERIODIC_RELATIVE) {
@ -112,14 +112,13 @@ void xtimer_periodic_wakeup(uint32_t *last_wakeup, uint32_t period) {
*
* Since interrupts are normally enabled inside this function, this time may
* be undeterministic. */
target = xtimer_now() + offset;
target = _xtimer_now() + offset;
}
mutex_lock(&mutex);
DEBUG("xps, abs: %" PRIu32 "\n", target);
_xtimer_set_absolute(&timer, target);
mutex_lock(&mutex);
}
out:
*last_wakeup = target;
}
@ -139,13 +138,13 @@ static inline void _setup_msg(xtimer_t *timer, msg_t *msg, kernel_pid_t target_p
msg->sender_pid = target_pid;
}
void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid)
void _xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid)
{
_setup_msg(timer, msg, target_pid);
xtimer_set(timer, offset);
_xtimer_set(timer, offset);
}
void xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_t target_pid)
void _xtimer_set_msg64(xtimer_t *timer, uint64_t offset, msg_t *msg, kernel_pid_t target_pid)
{
_setup_msg(timer, msg, target_pid);
_xtimer_set64(timer, offset, offset >> 32);
@ -156,15 +155,15 @@ static void _callback_wakeup(void* arg)
thread_wakeup((kernel_pid_t)((intptr_t)arg));
}
void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid)
void _xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid)
{
timer->callback = _callback_wakeup;
timer->arg = (void*) ((intptr_t)pid);
xtimer_set(timer, offset);
_xtimer_set(timer, offset);
}
void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid)
void _xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid)
{
timer->callback = _callback_wakeup;
timer->arg = (void*) ((intptr_t)pid);
@ -174,7 +173,7 @@ void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset, kernel_pid_t pid)
void xtimer_now_timex(timex_t *out)
{
uint64_t now = xtimer_now64();
uint64_t now = xtimer_usec_from_ticks64(xtimer_now64());
out->seconds = div_u64_by_1000000(now);
out->microseconds = now - (out->seconds * SEC_IN_USEC);
@ -205,19 +204,19 @@ static int _msg_wait(msg_t *m, msg_t *tmsg, xtimer_t *t)
}
}
int xtimer_msg_receive_timeout64(msg_t *m, uint64_t timeout) {
int _xtimer_msg_receive_timeout64(msg_t *m, uint64_t timeout_ticks) {
msg_t tmsg;
xtimer_t t;
_setup_timer_msg(&tmsg, &t);
xtimer_set_msg64(&t, timeout, &tmsg, sched_active_pid);
_xtimer_set_msg64(&t, timeout_ticks, &tmsg, sched_active_pid);
return _msg_wait(m, &tmsg, &t);
}
int xtimer_msg_receive_timeout(msg_t *msg, uint32_t us)
int _xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout_ticks)
{
msg_t tmsg;
xtimer_t t;
_setup_timer_msg(&tmsg, &t);
xtimer_set_msg(&t, us, &tmsg, sched_active_pid);
_xtimer_set_msg(&t, timeout_ticks, &tmsg, sched_active_pid);
return _msg_wait(msg, &tmsg, &t);
}

View File

@ -69,21 +69,21 @@ static inline void xtimer_spin_until(uint32_t target) {
void xtimer_init(void)
{
/* initialize low-level timer */
timer_init(XTIMER_DEV, XTIMER_USEC_TO_TICKS(1000000ul), _periph_timer_callback, NULL);
timer_init(XTIMER_DEV, XTIMER_HZ, _periph_timer_callback, NULL);
/* register initial overflow tick */
_lltimer_set(0xFFFFFFFF);
}
static void _xtimer_now64(uint32_t *short_term, uint32_t *long_term)
static void _xtimer_now_internal(uint32_t *short_term, uint32_t *long_term)
{
uint32_t before, after, long_value;
/* loop to cope with possible overflow of xtimer_now() */
/* loop to cope with possible overflow of _xtimer_now() */
do {
before = xtimer_now();
before = _xtimer_now();
long_value = _long_cnt;
after = xtimer_now();
after = _xtimer_now();
} while(before > after);
@ -91,10 +91,10 @@ static void _xtimer_now64(uint32_t *short_term, uint32_t *long_term)
*long_term = long_value;
}
uint64_t xtimer_now64(void)
uint64_t _xtimer_now64(void)
{
uint32_t short_term, long_term;
_xtimer_now64(&short_term, &long_term);
_xtimer_now_internal(&short_term, &long_term);
return ((uint64_t)long_term<<32) + short_term;
}
@ -104,7 +104,7 @@ void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset)
DEBUG(" _xtimer_set64() offset=%" PRIu32 " long_offset=%" PRIu32 "\n", offset, long_offset);
if (!long_offset) {
/* timer fits into the short timer */
xtimer_set(timer, (uint32_t) offset);
_xtimer_set(timer, (uint32_t) offset);
}
else {
int state = irq_disable();
@ -112,7 +112,7 @@ void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset)
_remove(timer);
}
_xtimer_now64(&timer->target, &timer->long_target);
_xtimer_now_internal(&timer->target, &timer->long_target);
timer->target += offset;
timer->long_target += long_offset;
if (timer->target < offset) {
@ -126,7 +126,7 @@ void _xtimer_set64(xtimer_t *timer, uint32_t offset, uint32_t long_offset)
}
}
void xtimer_set(xtimer_t *timer, uint32_t offset)
void _xtimer_set(xtimer_t *timer, uint32_t offset)
{
DEBUG("timer_set(): offset=%" PRIu32 " now=%" PRIu32 " (%" PRIu32 ")\n", offset, xtimer_now(), _xtimer_lltimer_now());
if (!timer->callback) {
@ -137,11 +137,11 @@ void xtimer_set(xtimer_t *timer, uint32_t offset)
xtimer_remove(timer);
if (offset < XTIMER_BACKOFF) {
xtimer_spin(offset);
_xtimer_spin(offset);
_shoot(timer);
}
else {
uint32_t target = xtimer_now() + offset;
uint32_t target = _xtimer_now() + offset;
_xtimer_set_absolute(timer, target);
}
}
@ -164,18 +164,12 @@ static inline void _lltimer_set(uint32_t target)
return;
}
DEBUG("_lltimer_set(): setting %" PRIu32 "\n", _xtimer_lltimer_mask(target));
#ifdef XTIMER_SHIFT
target = XTIMER_USEC_TO_TICKS(target);
if (!target) {
target++;
}
#endif
timer_set_absolute(XTIMER_DEV, XTIMER_CHAN, _xtimer_lltimer_mask(target));
}
int _xtimer_set_absolute(xtimer_t *timer, uint32_t target)
{
uint32_t now = xtimer_now();
uint32_t now = _xtimer_now();
int res = 0;
DEBUG("timer_set_absolute(): now=%" PRIu32 " target=%" PRIu32 "\n", now, target);
@ -309,7 +303,7 @@ static uint32_t _time_left(uint32_t target, uint32_t reference)
static inline int _this_high_period(uint32_t target) {
#if XTIMER_MASK
return (target & XTIMER_MASK_SHIFTED) == _xtimer_high_cnt;
return (target & XTIMER_MASK) == _xtimer_high_cnt;
#else
(void)target;
return 1;
@ -413,7 +407,7 @@ static void _next_period(void)
{
#if XTIMER_MASK
/* advance <32bit mask register */
_xtimer_high_cnt += ~XTIMER_MASK_SHIFTED + 1;
_xtimer_high_cnt += ~XTIMER_MASK + 1;
if (_xtimer_high_cnt == 0) {
/* high_cnt overflowed, so advance >32bit counter */
_long_cnt++;

View File

@ -79,7 +79,7 @@ void *slacker_thread(void *arg)
tmsg->msg.type = 12345;
tmsg->msg.content.ptr = tmsg;
xtimer_set_msg(&tmsg->timer, tmsg->interval, &tmsg->msg, thread_getpid());
xtimer_set_msg(&tmsg->timer, xtimer_ticks_from_usec(tmsg->interval), &tmsg->msg, thread_getpid());
}
}
@ -96,7 +96,7 @@ void *worker_thread(void *arg)
while (1) {
msg_t m;
msg_receive(&m);
uint32_t now = xtimer_now();
uint32_t now = xtimer_usec_from_ticks(xtimer_now());
if (start == 0) {
start = now;
last = start;
@ -190,9 +190,9 @@ int main(void)
NULL,
"worker");
uint32_t last_wakeup = xtimer_now();
xtimer_ticks32_t last_wakeup = xtimer_now();
while (1) {
xtimer_periodic_wakeup(&last_wakeup, TEST_INTERVAL);
xtimer_periodic_wakeup(&last_wakeup, xtimer_ticks_from_usec(TEST_INTERVAL));
msg_try_send(&m, pid3);
}
}