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

sys/ztimer: add auto_adjust module

This commit is contained in:
kaspar030 2022-02-09 14:27:43 +01:00 committed by Francisco Molina
parent 2005ba53f5
commit d758cb93ef
7 changed files with 118 additions and 14 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */
/** @} */

View File

@ -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()"

View File

@ -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

View File

@ -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;
}