-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sys/xtimer: tick conversion #9026
Closed
Closed
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
9f4eea5
xtimer tick_conversion.h: uncrustify
Josar b8dc65f
xtimer tick_conversion.h: add debug messages
Josar a54e103
fixup! xtimer tick_conversion.h: add debug messages
Josar 1bacc15
fixup! fixup! xtimer tick_conversion.h: add debug messages
Josar 0989d64
fixup! xtimer tick_conversion.h: add debug messages
Josar 2c0a48b
fixup! xtimer tick_conversion.h: uncrustify
Josar deea93b
fixup! fixup! xtimer tick_conversion.h: add debug messages
Josar 9d0cb97
fixup! fixup! xtimer tick_conversion.h: uncrustify
Josar 9ca7ed6
fixup! fixup! fixup! xtimer tick_conversion.h: add debug messages
Josar 66e5975
fixup! fixup! fixup! fixup! xtimer tick_conversion.h: add debug messages
Josar ae8c7ab
fixup! fixup! fixup! fixup! fixup! xtimer tick_conversion.h: add debu…
Josar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
/* | ||
* Copyright (C) 2016 Eistec AB | ||
* 2018 Josua Arndt | ||
* | ||
* 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 | ||
|
@@ -12,9 +13,10 @@ | |
* @{ | ||
* @file | ||
* @brief xtimer tick <-> seconds conversions for different values of XTIMER_HZ | ||
* | ||
* @author Joakim Nohlgård <[email protected]> | ||
* @author Josua Arndt <[email protected]> | ||
*/ | ||
|
||
#ifndef XTIMER_TICK_CONVERSION_H | ||
#define XTIMER_TICK_CONVERSION_H | ||
|
||
|
@@ -23,11 +25,50 @@ | |
#endif | ||
|
||
#include "div.h" | ||
#include "fmt.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/* | ||
* As tick_conversion.h is included in multiple files ENABLE_DEBUG can not be | ||
* used as it gets redefined "[-Werror]" | ||
* Activate the debug print and enable module fmt in the project makefile as follow | ||
* | ||
* USEMODULE += fmt | ||
* CFLAGS += -DENABLE_DEBUG_PRINT_TICK_CONVERSION=1 | ||
*/ | ||
#ifndef ENABLE_DEBUG_PRINT_TICK_CONVERSION | ||
#define ENABLE_DEBUG_PRINT_TICK_CONVERSION (0) | ||
#endif | ||
|
||
#if ENABLE_DEBUG_PRINT_TICK_CONVERSION | ||
#ifndef MODULE_FMT | ||
#error Module fmt is necessary to ENABLE_DEBUG_TICKS | ||
#endif | ||
#endif | ||
|
||
__attribute__((always_inline)) inline void debug_print_ticks(uint32_t clock_hz, | ||
char *sign, uint64_t from, char *base_from, uint64_t to, char *base_to) | ||
{ | ||
if (ENABLE_DEBUG_PRINT_TICK_CONVERSION) { | ||
print_str("64bit "); | ||
print_u32_dec(clock_hz); | ||
print_str(" "); | ||
print_str(sign); | ||
print_str(" 1MHz : "); | ||
print_u64_dec(from); | ||
print_str(" "); | ||
print_str(base_from); | ||
print_str(" = "); | ||
print_u64_dec(to); | ||
print_str(" "); | ||
print_str(base_to); | ||
print_str("\n"); | ||
} | ||
} | ||
|
||
/* Some optimizations for common timer frequencies */ | ||
#if (XTIMER_SHIFT != 0) | ||
#if (XTIMER_HZ % 15625 != 0) | ||
|
@@ -37,97 +78,142 @@ extern "C" { | |
#if (XTIMER_HZ != (1000000ul << XTIMER_SHIFT)) | ||
#error XTIMER_HZ != (1000000ul << XTIMER_SHIFT) | ||
#endif | ||
/* XTIMER_HZ is a power-of-two multiple of 1 MHz */ | ||
/* XTIMER_HZ is a power-of-two multiple of 1 MHz and is bigger than 1MHz */ | ||
/* e.g. cc2538 uses a 16 MHz timer */ | ||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) { | ||
return (usec << XTIMER_SHIFT); /* multiply by power of two */ | ||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, ">", (uint64_t)us, "us", | ||
(uint64_t)(us >> XTIMER_SHIFT), "ticks"); | ||
return (us << XTIMER_SHIFT); /* multiply by power of two */ | ||
} | ||
|
||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) { | ||
return (usec << XTIMER_SHIFT); /* multiply by power of two */ | ||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, ">", us, "us", us >> XTIMER_SHIFT, "ticks"); | ||
return (us << XTIMER_SHIFT); /* multiply by power of two */ | ||
} | ||
|
||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) { | ||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, ">", (uint64_t)ticks, "ticks", | ||
(uint64_t)(ticks >> XTIMER_SHIFT), "us"); | ||
return (ticks >> XTIMER_SHIFT); /* divide by power of two */ | ||
} | ||
|
||
static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) { | ||
static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, ">", ticks, "ticks", ticks >> XTIMER_SHIFT, "us"); | ||
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 */ | ||
/* 1 MHz is a power-of-two multiple of XTIMER_HZ and is smaller than 1MHz */ | ||
/* e.g. ATmega2560 uses a 250 kHz timer */ | ||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) { | ||
return (usec >> XTIMER_SHIFT); /* divide by power of two */ | ||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "<", (uint64_t)us, "us", | ||
(uint64_t)(us >> XTIMER_SHIFT), "ticks"); | ||
return (us >> XTIMER_SHIFT); /* divide by power of two */ | ||
} | ||
|
||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) { | ||
return (usec >> XTIMER_SHIFT); /* divide by power of two */ | ||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "<", us, "us", us >> XTIMER_SHIFT, "ticks"); | ||
return (us >> XTIMER_SHIFT); /* divide by power of two */ | ||
} | ||
|
||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) { | ||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "<", (uint64_t)ticks, "ticks", | ||
(uint64_t)(ticks << XTIMER_SHIFT), "us"); | ||
return (ticks << XTIMER_SHIFT); /* multiply by power of two */ | ||
} | ||
|
||
static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) { | ||
static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "<", ticks, "ticks", ticks << XTIMER_SHIFT, "us"); | ||
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. */ | ||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) { | ||
return ticks; /* no-op */ | ||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "=", (uint64_t)us, "us", (uint64_t)us, "ticks"); | ||
return us; /* no-op */ | ||
} | ||
|
||
static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) { | ||
return ticks; /* no-op */ | ||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "=", us, "us", us, "ticks"); | ||
return us; /* no-op */ | ||
} | ||
|
||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) { | ||
return usec; /* no-op */ | ||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "=", (uint64_t)ticks, "ticks", (uint64_t)ticks, "us"); | ||
return ticks; /* no-op */ | ||
} | ||
|
||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) { | ||
return usec; /* no-op */ | ||
static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "=", ticks, "ticks", ticks, "us"); | ||
return ticks; /* 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 */ | ||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t usec) { | ||
return div_u32_by_15625div512(usec); | ||
static inline uint32_t _xtimer_ticks_from_usec(uint32_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "<", (uint64_t)us, "us", | ||
(uint64_t)div_u64_by_15625div512(us), "ticks"); | ||
return div_u32_by_15625div512(us); | ||
} | ||
|
||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t usec) { | ||
return div_u64_by_15625div512(usec); | ||
static inline uint64_t _xtimer_ticks_from_usec64(uint64_t us) | ||
{ | ||
debug_print_ticks(XTIMER_HZ, "<", us, "us", div_u64_by_15625div512(us), "ticks"); | ||
return div_u64_by_15625div512(us); | ||
} | ||
|
||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) { | ||
/* return (usec * 15625) / 512; */ | ||
static inline uint32_t _xtimer_usec_from_ticks(uint32_t ticks) | ||
{ | ||
/* return (us * 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) */ | ||
uint64_t us = (uint64_t)ticks * 15625ul; | ||
|
||
debug_print_ticks(XTIMER_HZ, "<", (uint64_t)ticks, "ticks", | ||
(uint64_t)(us >> 9), "us"); | ||
return (us >> 9); /* equivalent to (us / 512) */ | ||
} | ||
|
||
static inline 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) */ | ||
static inline uint64_t _xtimer_usec_from_ticks64(uint64_t ticks) | ||
{ | ||
/* return (us * 15625) / 512; */ | ||
uint64_t us = (uint64_t)ticks * 15625ul; | ||
|
||
debug_print_ticks(XTIMER_HZ, "<", ticks, "ticks", (us >> 9), "us"); | ||
return (us >> 9); /* equivalent to (us / 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 | ||
#error Unsupported hardware timer frequency (XTIMER_HZ). | ||
/* Xtimer is not correctly configured maybe missing XTIMER_SHIFT in board.h? | ||
* See xtimer.h documentation for more information! | ||
*/ | ||
#else | ||
#error Unknown hardware timer frequency (XTIMER_HZ), check board.h and/or add an implementation in sys/include/xtimer/tick_conversion.h | ||
#error Unknown hardware timer frequency (XTIMER_HZ). | ||
/* Check board.h and/or add an implementation in | ||
* sys/include/xtimer/tick_conversion.h to convert the hardware ticks | ||
*/ | ||
#endif | ||
#endif | ||
|
||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did you changed this error message (here and below). Now the important info is only in the comments instead of showing it to the developer while compiling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see #9026 (comment)