From b917807444b7d8b901f7f9735dfbb48eed4a5598 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 19 Apr 2021 21:42:26 +0200 Subject: [PATCH] drivers/periph_timer: add periph_timer_query_freqs Allow accessing supported timer frequencies with a dedicated API. This API needs to be implemented per platform and is available with the feature periph_timer_query_freqs. --- drivers/include/periph/timer.h | 63 +++++++++++++++++++++++++++++ drivers/periph_common/Kconfig.timer | 4 ++ drivers/periph_common/timer.c | 9 +++++ kconfigs/Kconfig.features | 5 +++ makefiles/features_modules.inc.mk | 1 + 5 files changed, 82 insertions(+) diff --git a/drivers/include/periph/timer.h b/drivers/include/periph/timer.h index 6b21d6885f..c4c021aba1 100644 --- a/drivers/include/periph/timer.h +++ b/drivers/include/periph/timer.h @@ -36,6 +36,7 @@ #include #include +#include "architecture.h" #include "periph_cpu.h" #include "periph_conf.h" @@ -232,6 +233,68 @@ void timer_start(tim_t dev); */ void timer_stop(tim_t dev); +/** + * @brief Get the number of different frequencies supported by the given + * timer + * + * If calling @ref timer_query_freqs_numof for the same timer with an index + * smaller this number, it hence MUST return a frequency (and not zero). + * + * @details This function is marked with attribute pure to tell the compiler + * that this function has no side affects and will return the same + * value when called with the same parameter. (E.g. to not call this + * function in every loop iteration when iterating over all + * supported frequencies.) + */ +__attribute__((pure)) +uword_t timer_query_freqs_numof(tim_t dev); + +/** + * @brief Get the number of timer channels for the given timer + * + * @details This function is marked with attribute pure to tell the compiler + * that this function has no side affects and will return the same + * value when called with the same timer as parameter. + * @details There is a weak default implementation that returns the value of + * `TIMER_CHANNEL_NUMOF`. For some MCUs the number of supported + * channels depends on @p dev - those are expected to provide there + * own implementation of this function. + */ +__attribute__((pure)) +uword_t timer_query_channel_numof(tim_t dev); + +/** + * @brief Iterate over supported frequencies + * + * @param dev Timer to get the next supported frequency of + * @param index Index of the frequency to get + * @return The @p index highest frequency supported by the timer + * @retval 0 @p index is too high + * + * @note Add `FEATURES_REQUIRED += periph_timer_query_freqs` to your `Makefile`. + * + * When called with a value of 0 for @p index, the highest supported frequency + * is returned. For a value 1 the second highest is returned, and so on. For + * values out of range, 0 is returned. A program hence can iterate over all + * supported frequencies using: + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c} + * uint32_t freq: + * for (uword_t i; (freq = timer_query_freqs(dev, i)); i++) { + * work_with_frequency(freq); + * } + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Or alternatively: + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c} + * for (uword_t i; i < timer_query_freqs_numof(dev); i++) { + * work_with_frequency(timer_query_freqs(dev, i)); + * } + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +uint32_t timer_query_freqs(tim_t dev, uword_t index); + #ifdef __cplusplus } #endif diff --git a/drivers/periph_common/Kconfig.timer b/drivers/periph_common/Kconfig.timer index 5c74fa00d3..9778f52535 100644 --- a/drivers/periph_common/Kconfig.timer +++ b/drivers/periph_common/Kconfig.timer @@ -30,6 +30,10 @@ config MODULE_PERIPH_INIT_TIMER_PERIODIC depends on MODULE_PERIPH_TIMER_PERIODIC default y if MODULE_PERIPH_INIT +config MODULE_PERIPH_TIMER_QUERY_FREQS + bool "Support for querying supported timer frequencies" + depends on HAS_PERIPH_TIMER_QUERY_FREQS + endif # MODULE_PERIPH_TIMER endif # TEST_KCONFIG diff --git a/drivers/periph_common/timer.c b/drivers/periph_common/timer.c index 8e657312a8..624bbf003f 100644 --- a/drivers/periph_common/timer.c +++ b/drivers/periph_common/timer.c @@ -30,3 +30,12 @@ int timer_set(tim_t dev, int channel, unsigned int timeout) return res; } #endif + +#ifdef MODULE_PERIPH_TIMER_QUERY_FREQS +__attribute__((weak)) +uword_t timer_query_channel_numof(tim_t dev) +{ + (void)dev; + return TIMER_CHANNEL_NUMOF; +} +#endif diff --git a/kconfigs/Kconfig.features b/kconfigs/Kconfig.features index 8063c3b68a..d149f38fd2 100644 --- a/kconfigs/Kconfig.features +++ b/kconfigs/Kconfig.features @@ -572,6 +572,11 @@ config HAS_PERIPH_TIMER_PERIODIC Indicates that the Timer peripheral provides the periodic timeout functionality. +config HAS_PERIPH_TIMER_QUERY_FREQS + bool + help + Indicates that the driver of the timer supports iterating over supported frequencies. + config HAS_PERIPH_UART bool help diff --git a/makefiles/features_modules.inc.mk b/makefiles/features_modules.inc.mk index 10f90c58fd..77e344a808 100644 --- a/makefiles/features_modules.inc.mk +++ b/makefiles/features_modules.inc.mk @@ -47,6 +47,7 @@ PERIPH_IGNORE_MODULES := \ periph_rtt_hw_rtc \ periph_rtt_hw_sys \ periph_spi_on_qspi \ + periph_timer_query_freqs \ periph_uart_collision \ periph_uart_rxstart_irq \ periph_wdog \