From 2005ba53f50b712dea62d389c352d1e8ab41fac4 Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Wed, 9 Feb 2022 14:27:13 +0100 Subject: [PATCH 1/4] sys/include/ztimer: document CONFIG_ZTIMER_USEC_ADJUST_% --- sys/include/ztimer/config.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/sys/include/ztimer/config.h b/sys/include/ztimer/config.h index 2240d7e2ee..04a8447151 100644 --- a/sys/include/ztimer/config.h +++ b/sys/include/ztimer/config.h @@ -136,6 +136,30 @@ extern "C" { # endif #endif +/** + * @brief An offset for ZTIMER_USEC allowing to compensate for the offset + * of @ref ztimer_set(). It can be measured with @ref ztimer_overhead_set() + * + * This value should be configured in the board.h. + * + */ +#ifndef CONFIG_ZTIMER_USEC_ADJUST_SET +#define CONFIG_ZTIMER_USEC_ADJUST_SET 0 +#endif + +/** + * @brief An offset for ZTIMER_USEC allowing to compentsate for the offset + * of @ref ztimer_sleep(). + * + * @note As internally @ref ztimer_sleep() uses @ref ztimer_set() + * @ref CONFIG_ZTIMER_USEC_ADJUST_SET should be tuned before. + * + * This value should be configured in the board.h. + */ +#ifndef CONFIG_ZTIMER_USEC_ADJUST_SLEEP +#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 0 +#endif + #ifdef __cplusplus } #endif From d758cb93efdadf8b8dbd11b612bcee1c1c9f4218 Mon Sep 17 00:00:00 2001 From: kaspar030 Date: Wed, 9 Feb 2022 14:27:43 +0100 Subject: [PATCH 2/4] sys/ztimer: add auto_adjust module --- makefiles/default_modules.deps.mk | 4 ++ makefiles/pseudomodules.inc.mk | 14 +++++++ sys/include/ztimer/config.h | 11 +++++ sys/include/ztimer/overhead.h | 17 ++++++-- sys/ztimer/Kconfig | 4 ++ sys/ztimer/init.c | 70 ++++++++++++++++++++++++++----- sys/ztimer/overhead.c | 12 +++++- 7 files changed, 118 insertions(+), 14 deletions(-) diff --git a/makefiles/default_modules.deps.mk b/makefiles/default_modules.deps.mk index fb86b1c6b6..fa98d2c0ae 100644 --- a/makefiles/default_modules.deps.mk +++ b/makefiles/default_modules.deps.mk @@ -6,6 +6,10 @@ ifneq (,$(filter auto_init_ztimer,$(USEMODULE))) USEMODULE += ztimer_init endif +ifneq (,$(filter ztimer_auto_adjust,$(USEMODULE))) + USEMODULE += ztimer_overhead +endif + ifneq (,$(filter auto_init_saul,$(USEMODULE))) USEMODULE += saul_init_devs endif diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 247ee09d48..7c48855a3c 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -258,6 +258,20 @@ PSEUDOMODULES += ztimer PSEUDOMODULES += ztimer_% PSEUDOMODULES += ztimer64_% +## @defgroup pseudomodule_ztimer_auto_adjust ztimer_auto_adjust +## @brief A module to set on init ztimer->adjust_sleep/adjust_set values +## +## When this module is active, then on init if no CONFIG_ZTIMER_USEC_ADJUST_% +## values are set for the BOARD correction values adjust_sleep and adjust_set +## will be calculated in set for the required clocks. +## +## Note that some BOARDs clocks require a startup time to get accuarate values, +## a configurable @ref CONFIG_ZTIMER_AUTO_ADJUST_SETTLE value can be set for this. +## +## Alternatively CONFIG_ZTIMER_USEC_ADJUST_% values can be set in the BOARDs +## configuration header board.h. These can be found out by running tests/ztimer_overhead +PSEUDOMODULES += ztimer_auto_adjust + # ztimer's main module is called "ztimer_core" NO_PSEUDOMODULES += ztimer_core NO_PSEUDOMODULES += netdev_ieee802154_submac diff --git a/sys/include/ztimer/config.h b/sys/include/ztimer/config.h index 04a8447151..36ac9c99af 100644 --- a/sys/include/ztimer/config.h +++ b/sys/include/ztimer/config.h @@ -160,6 +160,17 @@ extern "C" { #define CONFIG_ZTIMER_USEC_ADJUST_SLEEP 0 #endif +/** + * @brief Some MCUs clocks need some warm-up time during which timing is + * inaccurate. This can be a hindrance when using the @ref + * pseudomodule_ztimer_auto_adjust module. + * + * @warning This value will increase the boards start-up time + */ +#ifndef CONFIG_ZTIMER_AUTO_ADJUST_SETTLE +#define CONFIG_ZTIMER_AUTO_ADJUST_SETTLE 0 +#endif + #ifdef __cplusplus } #endif diff --git a/sys/include/ztimer/overhead.h b/sys/include/ztimer/overhead.h index 521667053c..faaef4ba9a 100644 --- a/sys/include/ztimer/overhead.h +++ b/sys/include/ztimer/overhead.h @@ -31,9 +31,9 @@ extern "C" { #endif /** - * @brief Measure ztimer overhead + * @brief Measure overhead for ztimer_set() * - * This function can be used to measure the overhead incurred by ztimer. + * This function can be used to measure the overhead incurred by ztimer_set(). * It will configure a callback to trigger after @p base ticks, then return the * number of ticks that have passed, minus @p base. * @@ -41,7 +41,18 @@ extern "C" { * @param[in] base base interval to use * @return (time from ztimer_set() until callback) - base */ -int32_t ztimer_overhead(ztimer_clock_t *clock, uint32_t base); +int32_t ztimer_overhead_set(ztimer_clock_t *clock, uint32_t base); + +/** + * @brief Measure overhead for ztimer_sleep() + * + * This function can be used to measure the overhead incurred by ztimer_sleep(). + * + * @param[in] clock ztimer clock to operate on + * @param[in] base base interval to use + * @return (time(ztimer_sleep(base))) - base + */ +int32_t ztimer_overhead_sleep(ztimer_clock_t *clock, uint32_t base); #endif /* ZTIMER_OVERHEAD_H */ /** @} */ diff --git a/sys/ztimer/Kconfig b/sys/ztimer/Kconfig index fe92804ca4..7ea3f78dd7 100644 --- a/sys/ztimer/Kconfig +++ b/sys/ztimer/Kconfig @@ -183,6 +183,10 @@ config MODULE_AUTO_INIT_ZTIMER select MODULE_ZTIMER_INIT default y +config MODULE_ZTIMER_AUTO_ADJUST + bool "Auto adjust ztimer set and sleep values" + select MODULE_ZTIMER_OVERHEAD + config MODULE_ZTIMER_NOW64 bool "Use a 64-bits result for ztimer_now()" diff --git a/sys/ztimer/init.c b/sys/ztimer/init.c index 6436103f91..f400644308 100644 --- a/sys/ztimer/init.c +++ b/sys/ztimer/init.c @@ -43,6 +43,7 @@ #include "ztimer/convert_frac.h" #include "ztimer/convert_shift.h" #include "ztimer/convert_muldiv64.h" +#include "ztimer/overhead.h" #include "ztimer/periph_timer.h" #include "ztimer/periph_rtt.h" #include "ztimer/periph_rtc.h" @@ -212,6 +213,29 @@ ztimer_clock_t *const ZTIMER_SEC = &_ztimer_convert_frac_sec.super.super; # endif #endif +#if IS_USED(MODULE_ZTIMER_USEC) +#ifndef CONFIG_ZTIMER_AUTO_ADJUST_BASE_ITVL +#define CONFIG_ZTIMER_AUTO_ADJUST_BASE_ITVL 1000 +#endif +#ifndef CONFIG_ZTIMER_AUTO_ADJUST_ITER +#define CONFIG_ZTIMER_AUTO_ADJUST_ITER 100 +#endif + +static void _ztimer_usec_overhead(unsigned samples, unsigned base, uint16_t *adjust_value, + int32_t (*overhead_fn)(ztimer_clock_t *clock, uint32_t base)) +{ + int32_t min = INT32_MAX; + + for (unsigned i = 0; i < samples; i++) { + int32_t overhead = overhead_fn(ZTIMER_USEC, base); + if (overhead < min) { + min = overhead; + } + } + *adjust_value = min; +} +#endif + void ztimer_init(void) { /* Step 4: initialize used ztimer-periphery */ @@ -266,16 +290,42 @@ void ztimer_init(void) # else LOG_DEBUG("ztimer_init(): ZTIMER_USEC without conversion\n"); # endif -# ifdef CONFIG_ZTIMER_USEC_ADJUST_SET - LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting adjust_set value to %i\n", - CONFIG_ZTIMER_USEC_ADJUST_SET ); - ZTIMER_USEC->adjust_set = CONFIG_ZTIMER_USEC_ADJUST_SET; -# endif -# ifdef CONFIG_ZTIMER_USEC_ADJUST_SLEEP - LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting adjust_sleep value to %i\n", - CONFIG_ZTIMER_USEC_ADJUST_SLEEP ); - ZTIMER_USEC->adjust_sleep = CONFIG_ZTIMER_USEC_ADJUST_SLEEP; -# endif + + /* warm-up time if set and needed */ + if (IS_USED(MODULE_ZTIMER_AUTO_ADJUST) && + !(CONFIG_ZTIMER_USEC_ADJUST_SET && CONFIG_ZTIMER_USEC_ADJUST_SLEEP)) { + if (CONFIG_ZTIMER_AUTO_ADJUST_SETTLE) { + ztimer_sleep(ZTIMER_USEC, CONFIG_ZTIMER_AUTO_ADJUST_SETTLE); + } + } + + /* calculate or set 'adjust_set' */ + if (CONFIG_ZTIMER_USEC_ADJUST_SET) { + ZTIMER_USEC->adjust_set = CONFIG_ZTIMER_USEC_ADJUST_SET; + } + else if (IS_USED(MODULE_ZTIMER_AUTO_ADJUST)) { + _ztimer_usec_overhead(CONFIG_ZTIMER_AUTO_ADJUST_ITER, CONFIG_ZTIMER_AUTO_ADJUST_BASE_ITVL, + &ZTIMER_USEC->adjust_set, ztimer_overhead_set); + } + if (ZTIMER_USEC->adjust_set) { + LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting adjust_set value to %i\n", + ZTIMER_USEC->adjust_set); + } + + /* calculate or set 'adjust_sleep' */ + if (CONFIG_ZTIMER_USEC_ADJUST_SLEEP) { + ZTIMER_USEC->adjust_sleep = CONFIG_ZTIMER_USEC_ADJUST_SLEEP; + } + else if (IS_USED(MODULE_ZTIMER_AUTO_ADJUST)) { + _ztimer_usec_overhead(CONFIG_ZTIMER_AUTO_ADJUST_ITER, + CONFIG_ZTIMER_AUTO_ADJUST_BASE_ITVL, &ZTIMER_USEC->adjust_sleep, + ztimer_overhead_sleep); + } + + if (ZTIMER_USEC->adjust_sleep) { + LOG_DEBUG("ztimer_init(): ZTIMER_USEC setting adjust_sleep value to %i\n", + ZTIMER_USEC->adjust_sleep); + } #endif #if MODULE_ZTIMER_MSEC diff --git a/sys/ztimer/overhead.c b/sys/ztimer/overhead.c index c8d792a0cb..c472a150f0 100644 --- a/sys/ztimer/overhead.c +++ b/sys/ztimer/overhead.c @@ -35,7 +35,7 @@ static void _callback(void *arg) *callback_arg->val = ztimer_now(callback_arg->clock); } -int32_t ztimer_overhead(ztimer_clock_t *clock, uint32_t base) +int32_t ztimer_overhead_set(ztimer_clock_t *clock, uint32_t base) { volatile uint32_t after = 0; uint32_t pre; @@ -48,3 +48,13 @@ int32_t ztimer_overhead(ztimer_clock_t *clock, uint32_t base) while (!after) {} return after - pre - base; } + +int32_t ztimer_overhead_sleep(ztimer_clock_t *clock, uint32_t base) +{ + uint32_t pre = ztimer_now(clock); + + ztimer_sleep(clock, base); + uint32_t after = ztimer_now(clock); + + return after - pre - base; +} From a8006a74f87d4cf60c921983e8fe4d49aa17848e Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Wed, 9 Feb 2022 14:28:09 +0100 Subject: [PATCH 3/4] tests/ztimer_overhead: add ztimer_sleep overhead --- tests/ztimer_overhead/Makefile | 5 ++++- tests/ztimer_overhead/README.md | 19 +++++++++++++++- tests/ztimer_overhead/app.config.test | 1 + tests/ztimer_overhead/main.c | 32 ++++++++++++++++++++++----- tests/ztimer_overhead/tests/01-run.py | 15 +++++++++++++ 5 files changed, 64 insertions(+), 8 deletions(-) diff --git a/tests/ztimer_overhead/Makefile b/tests/ztimer_overhead/Makefile index 9c105c8470..c4e52b629f 100644 --- a/tests/ztimer_overhead/Makefile +++ b/tests/ztimer_overhead/Makefile @@ -1,6 +1,9 @@ DEVELHELP ?= 0 + include ../Makefile.tests_common -USEMODULE += ztimer_overhead ztimer_usec +USEMODULE += ztimer_auto_adjust +USEMODULE += ztimer_overhead +USEMODULE += ztimer_usec include $(RIOTBASE)/Makefile.include diff --git a/tests/ztimer_overhead/README.md b/tests/ztimer_overhead/README.md index 7724edf39d..0bf1ebc09c 100644 --- a/tests/ztimer_overhead/README.md +++ b/tests/ztimer_overhead/README.md @@ -3,5 +3,22 @@ This test application sets up a ztimer_periph at 1MHz, then measures 1024 times how much overhead ztimer adds. -It uses the "ztimer_overhead()" function. See it's documentation for more +It uses the "ztimer_overhead_set()" function. See it's documentation for more information. + +It then sets `adjust_set` parameter and sleeps 1024 times and measure how +much overhead ztimer_sleep adds. + +It uses the "ztimer_overhead_sleep()" function. See it's documentation for more +information. + +At the end of the test `adjust_set` and `adjust_sleep` values are printed +that can be set for the target `BOARD` in `board.h`. + +e.g for dwm1001: + +```shell +ZTIMER_USEC adjust params for dwm1001: + CONFIG_ZTIMER_USEC_ADJUST_SET 6 + CONFIG_ZTIMER_USEC_ADJUST_SLEEP 21 +``` diff --git a/tests/ztimer_overhead/app.config.test b/tests/ztimer_overhead/app.config.test index 1245a93667..a8fe62236a 100644 --- a/tests/ztimer_overhead/app.config.test +++ b/tests/ztimer_overhead/app.config.test @@ -3,3 +3,4 @@ CONFIG_MODULE_ZTIMER=y CONFIG_ZTIMER_USEC=y CONFIG_MODULE_ZTIMER_OVERHEAD=y +CONFIG_MODULE_ZTIMER_AUTO_ADJUST=y diff --git a/tests/ztimer_overhead/main.c b/tests/ztimer_overhead/main.c index 448913dcf0..70bce271df 100644 --- a/tests/ztimer_overhead/main.c +++ b/tests/ztimer_overhead/main.c @@ -23,26 +23,25 @@ #include #include +#include "board.h" #include "ztimer.h" #include "ztimer/overhead.h" #define BASE 1000 #define SAMPLES 1024 -int main(void) +static int32_t _ztimer_usec_overhead(unsigned samples, unsigned base, + int32_t (*overhead_fn)(ztimer_clock_t *clock, uint32_t base)) { uint32_t total = 0; int32_t min = INT32_MAX; int32_t max = INT32_MIN; - /* unset configured adjustment */ - /* ZTIMER_USEC->adjust_set = 0; */ - printf("ZTIMER_USEC->adjust_set = %" PRIu16 "\n", ZTIMER_USEC->adjust_set); + unsigned n = samples; - unsigned n = SAMPLES; while (n--) { - int32_t overhead = ztimer_overhead(ZTIMER_USEC, BASE); + int32_t overhead = overhead_fn(ZTIMER_USEC, base); total += labs(overhead); if (overhead < min) { min = overhead; @@ -55,5 +54,26 @@ int main(void) printf("min=%" PRIi32 " max=%" PRIi32 " avg_diff=%" PRIi32 "\n", min, max, (total / SAMPLES)); + return min; +} + +int main(void) +{ + /* unset configured adjustment */ + printf("ZTIMER_USEC auto_adjust params:\n"); + printf(" ZTIMER_USEC->adjust_set = %" PRIu16 "\n", ZTIMER_USEC->adjust_set); + ZTIMER_USEC->adjust_set = 0; + printf(" ZTIMER_USEC->adjust_sleep = %" PRIu16 "\n", ZTIMER_USEC->adjust_sleep); + ZTIMER_USEC->adjust_sleep = 0; + printf("ZTIMER_USEC auto_adjust params cleared\n"); + + printf("zitmer_overhead_set...\n"); + ZTIMER_USEC->adjust_set = _ztimer_usec_overhead(SAMPLES, BASE, ztimer_overhead_set); + printf("zitmer_overhead_sleep...\n"); + ZTIMER_USEC->adjust_sleep = _ztimer_usec_overhead(SAMPLES, BASE, ztimer_overhead_sleep); + printf("ZTIMER_USEC adjust params for %s:\n", RIOT_BOARD); + printf(" CONFIG_ZTIMER_USEC_ADJUST_SET %" PRIi16 "\n", ZTIMER_USEC->adjust_set); + printf(" CONFIG_ZTIMER_USEC_ADJUST_SLEEP %" PRIi16 "\n", ZTIMER_USEC->adjust_sleep); + return 0; } diff --git a/tests/ztimer_overhead/tests/01-run.py b/tests/ztimer_overhead/tests/01-run.py index d838f7a72d..6b3b0b415a 100755 --- a/tests/ztimer_overhead/tests/01-run.py +++ b/tests/ztimer_overhead/tests/01-run.py @@ -10,8 +10,23 @@ import sys from testrunner import run +ADJUST_SET_MARGIN = 1 +ADJUST_SLEEP_MARGIN = 1 + + def testfunc(child): + child.expect(r"ZTIMER_USEC->adjust_set = (\d+)\r\n") + auto_adjust_set = int(child.match.group(1)) + child.expect(r"ZTIMER_USEC->adjust_sleep = (\d+)\r\n") + auto_adjust_sleep = int(child.match.group(1)) child.expect(r"min=-?\d+ max=-?\d+ avg_diff=\d+\r\n") + child.expect(r"min=-?\d+ max=-?\d+ avg_diff=\d+\r\n") + child.expect(r"CONFIG_ZTIMER_USEC_ADJUST_SET\s+(\d+)\r\n") + adjust_set = int(child.match.group(1)) + child.expect(r"CONFIG_ZTIMER_USEC_ADJUST_SLEEP\s+(\d+)\r\n") + adjust_sleep = int(child.match.group(1)) + assert auto_adjust_set >= adjust_set - ADJUST_SET_MARGIN + assert auto_adjust_sleep >= adjust_sleep - ADJUST_SLEEP_MARGIN if __name__ == "__main__": From 59d069c59dc9ee8ac1b150d67da37b1cae160cfb Mon Sep 17 00:00:00 2001 From: Francisco Molina Date: Thu, 17 Feb 2022 18:26:33 +0100 Subject: [PATCH 4/4] boards: update CONFIG_ZTIMER_USEC_ADJUST% values --- boards/arduino-uno/include/board.h | 10 ++++++++++ boards/atmega256rfr2-xpro/include/board.h | 4 ++-- boards/common/arduino-atmega/include/board_common.h | 8 ++++++-- dist/tools/doccheck/exclude_patterns | 2 ++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/boards/arduino-uno/include/board.h b/boards/arduino-uno/include/board.h index 5f31f42a23..63878510b6 100644 --- a/boards/arduino-uno/include/board.h +++ b/boards/arduino-uno/include/board.h @@ -19,6 +19,16 @@ #ifndef BOARD_H #define BOARD_H +/** + * @name ztimer configuration values + * + * @note Overrides arduino-atmega defaults + * @{ + */ +#define CONFIG_ZTIMER_USEC_ADJUST_SET (128) +#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP (116) +/** @} */ + #include "board_common.h" #ifdef __cplusplus diff --git a/boards/atmega256rfr2-xpro/include/board.h b/boards/atmega256rfr2-xpro/include/board.h index 22b61528af..56833acedf 100644 --- a/boards/atmega256rfr2-xpro/include/board.h +++ b/boards/atmega256rfr2-xpro/include/board.h @@ -46,8 +46,8 @@ extern "C" { * @name ztimer configuration values * @{ */ -#define CONFIG_ZTIMER_USEC_ADJUST_SET (128) -#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP (128) +#define CONFIG_ZTIMER_USEC_ADJUST_SET (132) +#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP (120) /** @} */ /** diff --git a/boards/common/arduino-atmega/include/board_common.h b/boards/common/arduino-atmega/include/board_common.h index e20ed8aa51..d97dab2b55 100644 --- a/boards/common/arduino-atmega/include/board_common.h +++ b/boards/common/arduino-atmega/include/board_common.h @@ -113,8 +113,12 @@ extern "C" { #define CONFIG_ZTIMER_USEC_DEV (TIMER_DEV(0)) #define CONFIG_ZTIMER_USEC_FREQ (250000LU) #define CONFIG_ZTIMER_USEC_WIDTH (16) -#define CONFIG_ZTIMER_USEC_ADJUST_SET (124) -#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP (120) +#ifndef CONFIG_ZTIMER_USEC_ADJUST_SET +#define CONFIG_ZTIMER_USEC_ADJUST_SET (128) +#endif +#ifndef CONFIG_ZTIMER_USEC_ADJUST_SLEEP +#define CONFIG_ZTIMER_USEC_ADJUST_SLEEP (116) +#endif /** @} */ /** diff --git a/dist/tools/doccheck/exclude_patterns b/dist/tools/doccheck/exclude_patterns index bd2ff2310f..65ffa83fbd 100644 --- a/dist/tools/doccheck/exclude_patterns +++ b/dist/tools/doccheck/exclude_patterns @@ -14707,3 +14707,5 @@ drivers/ft5x06/include/ft5x06_constants\.h:[0-9]+: warning: Member FT5X06_G_MODE drivers/ft5x06/include/ft5x06_constants\.h:[0-9]+: warning: Member FT5X06_G_MODE_INTERRUPT_POLLING \(macro definition\) of file ft5x06_constants\.h is not documented\. drivers/ft5x06/include/ft5x06_constants\.h:[0-9]+: warning: Member FT5X06_G_MODE_INTERRUPT_TRIGGER \(macro definition\) of file ft5x06_constants\.h is not documented\. drivers/ft5x06/include/ft5x06_params\.h:[0-9]+: warning: Member FT5X06_PARAM_TYPE \(macro definition\) of file ft5x06_params\.h is not documented\. +boards/arduino\-uno/include/board\.h:[0-9]+: warning: Member CONFIG_ZTIMER_USEC_ADJUST_SET \(macro definition\) of file board\.h is not documented\. +boards/arduino\-uno/include/board\.h:[0-9]+: warning: Member CONFIG_ZTIMER_USEC_ADJUST_SLEEP \(macro definition\) of file board\.h is not documented\.