diff --git a/sys/include/ztimer/periph_timer.h b/sys/include/ztimer/periph_timer.h index 21b8277a19..5e1a7ed634 100644 --- a/sys/include/ztimer/periph_timer.h +++ b/sys/include/ztimer/periph_timer.h @@ -52,9 +52,11 @@ typedef struct { * @param[in] dev periph timer to use * @param[in] freq frequency to configure * @param[in] max_val maximum value this timer supports + * + * @return The actual frequency the timer has been configured to */ -void ztimer_periph_timer_init(ztimer_periph_timer_t *clock, tim_t dev, - uint32_t freq, uint32_t max_val); +uint32_t ztimer_periph_timer_init(ztimer_periph_timer_t *clock, tim_t dev, + uint32_t freq, uint32_t max_val); #ifdef __cplusplus } diff --git a/sys/ztimer/Makefile.dep b/sys/ztimer/Makefile.dep index e20ba7e2a7..02c31c1d4a 100644 --- a/sys/ztimer/Makefile.dep +++ b/sys/ztimer/Makefile.dep @@ -39,6 +39,7 @@ endif ifneq (,$(filter ztimer_periph_timer,$(USEMODULE))) FEATURES_REQUIRED += periph_timer + FEATURES_OPTIONAL += periph_timer_query_freqs endif ifneq (,$(filter ztimer_periph_rtc,$(USEMODULE))) diff --git a/sys/ztimer/init.c b/sys/ztimer/init.c index 08aa1b4f05..8decf8f712 100644 --- a/sys/ztimer/init.c +++ b/sys/ztimer/init.c @@ -39,7 +39,9 @@ #include "kernel_defines.h" +#include "assert.h" #include "board.h" +#include "compiler_hints.h" #include "ztimer.h" #include "ztimer/convert_frac.h" #include "ztimer/convert_shift.h" @@ -72,6 +74,9 @@ # define ZTIMER_TIMER _ztimer_periph_timer # define ZTIMER_TIMER_CLK _ztimer_periph_timer.super # define ZTIMER_TIMER_FREQ CONFIG_ZTIMER_USEC_BASE_FREQ +# ifndef CONFIG_ZTIMER_PERIPH_TIMER_FORCE_CONVERSION +# define CONFIG_ZTIMER_PERIPH_TIMER_FORCE_CONVERSION 0 +# endif #endif #if MODULE_ZTIMER_PERIPH_LPTIMER @@ -209,9 +214,9 @@ ztimer_clock_t *const ZTIMER_USEC_BASE = &ZTIMER_TIMER_CLK; # else # error No suitable ZTIMER_USEC config. Basic timer configuration missing? # endif -# if ZTIMER_TIMER_FREQ == FREQ_1MHZ +# if (ZTIMER_TIMER_FREQ == FREQ_1MHZ) && !(CONFIG_ZTIMER_PERIPH_TIMER_FORCE_CONVERSION) ztimer_clock_t *const ZTIMER_USEC = &ZTIMER_TIMER_CLK; -# elif ZTIMER_TIMER_FREQ == 250000LU +# elif (ZTIMER_TIMER_FREQ == 250000LU) && !(CONFIG_ZTIMER_PERIPH_TIMER_FORCE_CONVERSION) static ztimer_convert_shift_t _ztimer_convert_shift_usec; ztimer_clock_t *const ZTIMER_USEC = &_ztimer_convert_shift_usec.super.super; # else @@ -290,8 +295,11 @@ void ztimer_init(void) "ztimer_init(): ZTIMER_TIMER using periph timer %u, freq %lu, width %u\n", CONFIG_ZTIMER_USEC_DEV, ZTIMER_TIMER_FREQ, CONFIG_ZTIMER_USEC_WIDTH); - ztimer_periph_timer_init(&ZTIMER_TIMER, CONFIG_ZTIMER_USEC_DEV, - ZTIMER_TIMER_FREQ, WIDTH_TO_MAXVAL(CONFIG_ZTIMER_USEC_WIDTH)); + MAYBE_UNUSED + uint32_t periph_timer_freq = + ztimer_periph_timer_init(&ZTIMER_TIMER, CONFIG_ZTIMER_USEC_DEV, + ZTIMER_TIMER_FREQ, + WIDTH_TO_MAXVAL(CONFIG_ZTIMER_USEC_WIDTH)); # if MODULE_PM_LAYERED && !MODULE_ZTIMER_ONDEMAND LOG_DEBUG("ztimer_init(): ZTIMER_TIMER setting block_pm_mode to %i\n", CONFIG_ZTIMER_TIMER_BLOCK_PM_MODE); @@ -335,19 +343,27 @@ void ztimer_init(void) /* Step 5: initialize ztimers requested */ #if MODULE_ZTIMER_USEC -# if ZTIMER_TIMER_FREQ != FREQ_1MHZ -# if ZTIMER_TIMER_FREQ == FREQ_250KHZ +# if (ZTIMER_TIMER_FREQ != FREQ_1MHZ) || CONFIG_ZTIMER_PERIPH_TIMER_FORCE_CONVERSION +# if (ZTIMER_TIMER_FREQ == FREQ_250KHZ) && !(CONFIG_ZTIMER_PERIPH_TIMER_FORCE_CONVERSION) + if (IS_ACTIVE(DEVELHELP) && ((periph_timer_freq < 237500) || (periph_timer_freq > 262500))) { + LOG_WARNING("ZTIMER_USEC from %" PRIu32 " Hz clock with \"left-shift by 2\" frequency conversion\n", + periph_timer_freq); + } LOG_DEBUG("ztimer_init(): ZTIMER_USEC convert_shift %lu to 1000000\n", - ZTIMER_TIMER_FREQ); + periph_timer_freq); ztimer_convert_shift_up_init(&_ztimer_convert_shift_usec, ZTIMER_USEC_BASE, 2); # else LOG_DEBUG("ztimer_init(): ZTIMER_USEC convert_frac %lu to 1000000\n", ZTIMER_TIMER_FREQ); ztimer_convert_frac_init(&_ztimer_convert_frac_usec, ZTIMER_USEC_BASE, - FREQ_1MHZ, ZTIMER_TIMER_FREQ); + FREQ_1MHZ, periph_timer_freq); # endif # else + if (IS_ACTIVE(DEVELHELP) && ((periph_timer_freq < 950000) || (periph_timer_freq > 1050000))) { + LOG_WARNING("ZTIMER_USEC from %" PRIu32 " Hz clock without frequency conversion\n", + periph_timer_freq); + } LOG_DEBUG("ztimer_init(): ZTIMER_USEC without conversion\n"); # endif diff --git a/sys/ztimer/periph_timer.c b/sys/ztimer/periph_timer.c index 6b00bdce71..f52b7aa66b 100644 --- a/sys/ztimer/periph_timer.c +++ b/sys/ztimer/periph_timer.c @@ -21,7 +21,9 @@ */ #include "assert.h" +#include "compiler_hints.h" #include "irq.h" +#include "modules.h" #include "ztimer/periph_timer.h" #ifndef ZTIMER_PERIPH_TIMER_OFFSET @@ -104,12 +106,16 @@ static const ztimer_ops_t _ztimer_periph_timer_ops = { #endif }; -void ztimer_periph_timer_init(ztimer_periph_timer_t *clock, tim_t dev, - uint32_t freq, uint32_t max_val) +uint32_t ztimer_periph_timer_init(ztimer_periph_timer_t *clock, tim_t dev, + uint32_t freq, uint32_t max_val) { clock->dev = dev; clock->super.ops = &_ztimer_periph_timer_ops; clock->super.max_value = max_val; + + if (IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) { + freq = timer_get_closest_freq(dev, freq); + } int ret = timer_init(dev, freq, _ztimer_periph_timer_callback, clock); (void)ret; @@ -127,4 +133,6 @@ void ztimer_periph_timer_init(ztimer_periph_timer_t *clock, tim_t dev, * the first ztimer_acquire() call starts the peripheral */ timer_stop(dev); #endif + + return freq; }