mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #17633 from fjmolinas/pr_ztimer_auto_adjust
sys/ztimer: add auto_adjust module
This commit is contained in:
commit
c6151226ad
@ -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
|
||||
|
@ -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)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
2
dist/tools/doccheck/exclude_patterns
vendored
2
dist/tools/doccheck/exclude_patterns
vendored
@ -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\.
|
||||
|
@ -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
|
||||
|
@ -259,6 +259,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
|
||||
|
@ -136,6 +136,41 @@ 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
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
@ -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 */
|
||||
/** @} */
|
||||
|
@ -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()"
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
```
|
||||
|
@ -3,3 +3,4 @@
|
||||
CONFIG_MODULE_ZTIMER=y
|
||||
CONFIG_ZTIMER_USEC=y
|
||||
CONFIG_MODULE_ZTIMER_OVERHEAD=y
|
||||
CONFIG_MODULE_ZTIMER_AUTO_ADJUST=y
|
||||
|
@ -23,26 +23,25 @@
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -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__":
|
||||
|
Loading…
Reference in New Issue
Block a user