From 97ab5ef12ea971d5b0e79ccc7071cc38b47b7b59 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Mon, 4 Dec 2023 15:10:12 +0100 Subject: [PATCH 1/8] drivers/sdmmc: fix placement of #endif --- drivers/sdmmc/sdmmc_sdhc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sdmmc/sdmmc_sdhc.c b/drivers/sdmmc/sdmmc_sdhc.c index 52af812c82fc0..e193ab5803a9f 100644 --- a/drivers/sdmmc/sdmmc_sdhc.c +++ b/drivers/sdmmc/sdmmc_sdhc.c @@ -631,8 +631,8 @@ void _core_init(sdhc_dev_t *sdhc_dev) GCLK->PCHCTRL[SDHC1_GCLK_ID_SLOW].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(SDHC_CLOCK_SLOW); MCLK->AHBMASK.bit.SDHC1_ = 1; -#endif /* SDHC1 */ } +#endif /* SDHC1 */ } static void _init_pins(sdhc_dev_t *sdhc_dev) From 167a70cd0fe72309236f0014a5ec76b5060c8715 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 5 Dec 2023 15:09:01 +0100 Subject: [PATCH 2/8] tests/sys/psa_crytpo_se: disable test on esp32-wroom-32 --- tests/sys/psa_crypto_se/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/sys/psa_crypto_se/Makefile b/tests/sys/psa_crypto_se/Makefile index 4e1286028a79b..21f3365f2fc33 100644 --- a/tests/sys/psa_crypto_se/Makefile +++ b/tests/sys/psa_crypto_se/Makefile @@ -2,6 +2,8 @@ BOARD ?= nrf52840dk include ../Makefile.sys_common +TEST_ON_CI_BLACKLIST += esp32-wroom-32 + USEMODULE += ztimer USEMODULE += ztimer_usec From 5b7a1bed2f0839bf4c006e2d30f8884182319eb9 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 5 Dec 2023 15:48:26 +0100 Subject: [PATCH 3/8] tests/net/gnrc_sixlowpan_frag_sfr_congure_impl: disable test on native This test sporadically failed on multiple machines compiled with both GNU and LLVM toolchains. To not waste more CI time by sporadically failing unrelated CI runs, let's disable the test for now. --- tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile b/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile index 2a90b61b5b5a5..22765e6245f82 100644 --- a/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile +++ b/tests/net/gnrc_sixlowpan_frag_sfr_congure_impl/Makefile @@ -1,5 +1,12 @@ include ../Makefile.net_common +# This tests fails sporadically in the CI on native with both GCC and LLVM +# toolchains. Maybe it just fluke and due to high load on the machines, +# maybe it is an actual race condition. +# +# TODO: Solve the issue and re-enable +TEST_ON_CI_BLACKLIST += native + USEMODULE += auto_init_gnrc_netif USEMODULE += gnrc_ipv6_router_default USEMODULE += gnrc_sixlowpan_frag_sfr From b917807444b7d8b901f7f9735dfbb48eed4a5598 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 19 Apr 2021 21:42:26 +0200 Subject: [PATCH 4/8] 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 6b21d6885f64b..c4c021aba1fa2 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 5c74fa00d3c1b..9778f52535a6b 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 8e657312a88a4..624bbf003f61b 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 8063c3b68a10a..d149f38fd2a94 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 10f90c58fd8f4..77e344a8087f7 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 \ From 3bc6494004cef8991c4ca0ac30f59e773afc929d Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 19 Apr 2021 21:44:16 +0200 Subject: [PATCH 5/8] tests/periph_timer: use periph_timer_query_freqs If the feature periph_timer_query_freqs is provided, use the corresponding function to iterate over all supported frequencies to increase test coverage. --- tests/periph/timer/Kconfig | 11 +++ tests/periph/timer/Makefile | 1 + tests/periph/timer/main.c | 150 +++++++++++++++++++++++------ tests/periph/timer/tests/01-run.py | 11 +-- 4 files changed, 139 insertions(+), 34 deletions(-) create mode 100644 tests/periph/timer/Kconfig diff --git a/tests/periph/timer/Kconfig b/tests/periph/timer/Kconfig new file mode 100644 index 0000000000000..6b18000ec6254 --- /dev/null +++ b/tests/periph/timer/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2020 HAW Hamburg +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +config APPLICATION + bool + default y + depends on TEST_KCONFIG + imply MODULE_PERIPH_TIMER_QUERY_FREQS diff --git a/tests/periph/timer/Makefile b/tests/periph/timer/Makefile index 99274fa4a6578..2eb33079fd09f 100644 --- a/tests/periph/timer/Makefile +++ b/tests/periph/timer/Makefile @@ -1,6 +1,7 @@ include ../Makefile.periph_common FEATURES_REQUIRED = periph_timer +FEATURES_OPTIONAL = periph_timer_query_freqs BOARDS_TIMER_500kHz := \ atxmega-a1-xplained \ diff --git a/tests/periph/timer/main.c b/tests/periph/timer/main.c index 8c1cb8503ed1b..4df051db10151 100644 --- a/tests/periph/timer/main.c +++ b/tests/periph/timer/main.c @@ -23,6 +23,7 @@ #include #include "atomic_utils.h" +#include "architecture.h" #include "clk.h" #include "periph/timer.h" #include "test_utils/expect.h" @@ -35,14 +36,18 @@ #error "TIMER_NUMOF not defined!" #endif -#define MAX_CHANNELS (10U) +/* backward compatibility with legacy drivers */ +#if !defined(TIMER_CHANNEL_NUMOF) && !IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS) +#define TIMER_CHANNEL_NUMOF 10U +#endif + #define CHAN_OFFSET (5000U) /* fire every 5ms */ #define COOKIE (100U) /* for checking if arg is passed */ static uint8_t fired; static uint32_t sw_count; -static uint32_t timeouts[MAX_CHANNELS]; -static unsigned args[MAX_CHANNELS]; +static uint32_t timeouts[TIMER_CHANNEL_NUMOF]; +static unsigned args[TIMER_CHANNEL_NUMOF]; static void cb(void *arg, int chan) { @@ -56,11 +61,19 @@ static void cb_not_to_be_executed(void *arg, int chan) (void)arg; (void)chan; - puts("Spurious timer fired"); - expect(0); + fired = 1; +} + +static uword_t query_channel_numof(tim_t dev) +{ + if (IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) { + return timer_query_channel_numof(dev); + } + + return TIMER_CHANNEL_NUMOF; } -static int test_timer(unsigned num) +static int test_timer(unsigned num, uint32_t speed) { int set = 0; @@ -68,42 +81,54 @@ static int test_timer(unsigned num) atomic_store_u32(&sw_count, 0); atomic_store_u8(&fired, 0); - for (unsigned i = 0; i < MAX_CHANNELS; i++) { + for (unsigned i = 0; i < TIMER_CHANNEL_NUMOF; i++) { timeouts[i] = 0; args[i] = UINT_MAX; } + printf(" - Calling timer_init(%u, %" PRIu32 ")\n ", + num, speed); /* initialize and halt timer */ - if (timer_init(TIMER_DEV(num), TIMER_SPEED, cb, (void *)(COOKIE * num)) < 0) { - printf("TIMER_%u: ERROR on initialization - skipping\n\n", num); + if (timer_init(TIMER_DEV(num), speed, cb, (void *)(COOKIE * num)) != 0) { + printf("ERROR: timer_init() failed\n\n"); return 0; } else { - printf("TIMER_%u: initialization successful\n", num); + printf("initialization successful\n"); } timer_stop(TIMER_DEV(num)); - printf("TIMER_%u: stopped\n", num); + printf(" - timer_stop(%u): stopped\n", num); /* set each available channel */ - for (unsigned i = 0; i < MAX_CHANNELS; i++) { + for (unsigned i = 0; i < query_channel_numof(TIMER_DEV(num)); i++) { unsigned timeout = ((i + 1) * CHAN_OFFSET); + printf(" - timer_set(%u, %u, %u)\n ", num, i, timeout); if (timer_set(TIMER_DEV(num), i, timeout) < 0) { + printf("ERROR: Couldn't set timeout %u for channel %u\n", + timeout, i); + /* If the timer supports the periph_timer_query_freqs feature, we + * expect it to correctly report the number of supported channels + */ + if (IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) { + return 0; + } break; } else { ++set; - printf("TIMER_%u: set channel %u to %u\n", num, i, timeout); + printf("Successfully set timeout %u for channel %u\n", + timeout, i); } } if (set == 0) { - printf("TIMER_%u: ERROR setting any channel\n\n", num); + printf(" ERROR setting timeout failed for *ALL* channels\n\n"); return 0; } /* start the timer */ - printf("TIMER_%u: starting\n", num); + printf(" - timer_start(%u)\n", num); timer_start(TIMER_DEV(num)); /* wait for all channels to fire */ @@ -112,33 +137,41 @@ static int test_timer(unsigned num) } while (atomic_load_u8(&fired) != set); /* collect results */ + printf(" - Results:\n"); for (int i = 0; i < set; i++) { if (args[i] != ((COOKIE * num) + i)) { - printf("TIMER_%u: ERROR callback argument mismatch\n\n", num); + printf(" ERROR: Callback for channel %u on timer %u has incorrect argument\n", + i, num); return 0; } - printf("TIMER_%u: channel %i fired at SW count %8u", - num, i, (unsigned)timeouts[i]); + printf(" - channel %i fired at SW count %8u", + i, (unsigned)timeouts[i]); if (i == 0) { - printf(" - init: %8" PRIu32 "\n", atomic_load_u32(&timeouts[i])); + printf(" - init: %8" PRIu32 "\n", atomic_load_u32(&timeouts[i])); } else { - printf(" - diff: %8" PRIu32 "\n", + printf(" - diff: %8" PRIu32 "\n", atomic_load_u32(&timeouts[i]) - atomic_load_u32(&timeouts[i - 1])); } } /* test for spurious timer IRQs */ - expect(0 == timer_init(TIMER_DEV(num), TIMER_SPEED, cb_not_to_be_executed, NULL)); + printf(" - Validating no spurious IRQs are triggered:\n"); + expect(0 == timer_init(TIMER_DEV(num), speed, cb_not_to_be_executed, NULL)); - const unsigned duration = 2ULL * US_PER_MS * US_PER_SEC / TIMER_SPEED; + const unsigned duration = 2ULL * US_PER_MS * US_PER_SEC / speed; unsigned target = timer_read(TIMER_DEV(num)) + duration; expect(0 == timer_set_absolute(TIMER_DEV(num), 0, target)); expect(0 == timer_clear(TIMER_DEV(num), 0)); + atomic_store_u8(&fired, 0); while (timer_read(TIMER_DEV(num)) < target) { /* busy waiting for the timer to reach it timeout. Timer must not fire, * it was cleared */ } + if (atomic_load_u8(&fired)) { + printf(" ERROR: Spurious timer fired (1/2)\n"); + return 0; + } /* checking again to make sure that any IRQ pending bit that may just was * mask doesn't trigger a timer IRQ on the next set */ @@ -150,25 +183,88 @@ static int test_timer(unsigned num) /* busy waiting for the timer to reach it timeout. Timer must not fire, * it was cleared */ } + if (atomic_load_u8(&fired)) { + printf(" ERROR: Spurious timer fired (2/2)\n"); + return 0; + } + + printf(" OK (no spurious IRQs)\n"); return 1; } -int main(void) +static uword_t query_freq_numof(tim_t dev) { - int res = 0; + if (IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) { + return timer_query_freqs_numof(dev); + } + return 1; +} + +static uint32_t query_freq(tim_t dev, uword_t index) +{ + if (IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) { + return timer_query_freqs(dev, index); + } + + /* Fallback implementation when periph_timer_query_freqs is not + * implemented */ + if (index) { + return 0; + } + + return TIMER_SPEED; +} + +static void print_supported_frequencies(tim_t dev) +{ + if (!IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) { + printf(" - feature periph_timer_query_freqs unsupported\n"); + return; + } + + uword_t end = query_freq_numof(dev); + printf(" - supported frequencies:\n"); + for (uword_t i = 0; i < MIN(end, 3); i++) { + printf(" %u: %" PRIu32 "\n", (unsigned)i, timer_query_freqs(dev, i)); + } + + if (end > 3) { + printf(" ....\n" + " %u: %" PRIu32 "\n", + (unsigned)(end - 1), timer_query_freqs(dev, end - 1)); + } +} + +int main(void) +{ puts("\nTest for peripheral TIMERs\n"); printf("Available timers: %i\n", TIMER_NUMOF); + int failed = 0; /* test all configured timers */ for (unsigned i = 0; i < TIMER_NUMOF; i++) { - printf("\nTesting TIMER_%u:\n", i); - res += test_timer(i); + printf("\nTIMER %u\n" + "=======\n\n", i); + print_supported_frequencies(TIMER_DEV(i)); + uword_t end = query_freq_numof(TIMER_DEV(i)); + + /* Test only up to three frequencies and only the fastest once. + * (Some timers support really low frequencies and even when limiting + * to only three frequencies tested, the test will take ages to + * complete */ + end = MIN(end, 3); + for (uword_t j = 0; j < end; j++) { + if (!test_timer(i, query_freq(TIMER_DEV(i), j))) { + failed = 1; + } + } } + /* draw conclusion */ - if (res == TIMER_NUMOF) { + if (!failed) { puts("\nTEST SUCCEEDED"); } else { diff --git a/tests/periph/timer/tests/01-run.py b/tests/periph/timer/tests/01-run.py index e7fa3e09added..8e4222cf53835 100755 --- a/tests/periph/timer/tests/01-run.py +++ b/tests/periph/timer/tests/01-run.py @@ -11,13 +11,10 @@ def testfunc(child): - child.expect(r'Available timers: (\d+)\r\n') - timers_num = int(child.match.group(1)) - for timer in range(timers_num): - child.expect_exact('Testing TIMER_{}'.format(timer)) - child.expect_exact('TIMER_{}: initialization successful'.format(timer)) - child.expect_exact('TIMER_{}: stopped'.format(timer)) - child.expect_exact('TIMER_{}: starting'.format(timer)) + # Make sure the expected application is actually flashed + child.expect('Test for peripheral TIMERs') + # The C application carefully evaluates the test results, no need to + # re-implement that wheel in python and just check for the test to succeed child.expect('TEST SUCCEEDED') From 754bbe4e6d6392c816243278ab9d8456b42c73ce Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 5 Dec 2023 16:49:30 +0100 Subject: [PATCH 6/8] tests/sys/psa_crypto_se_cipher: disable test on esp32-wroom-32 The test fails systematically on the CI and prevents merging PRs. --- tests/sys/psa_crypto_se_cipher/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/sys/psa_crypto_se_cipher/Makefile b/tests/sys/psa_crypto_se_cipher/Makefile index 61e4949d5b31f..3273963fb0687 100644 --- a/tests/sys/psa_crypto_se_cipher/Makefile +++ b/tests/sys/psa_crypto_se_cipher/Makefile @@ -2,6 +2,9 @@ BOARD ?= nrf52840dk include ../Makefile.sys_common +# Test fails systematically on the CI +TEST_ON_CI_BLACKLIST += esp32-wroom-32 + USEMODULE += ztimer USEMODULE += ztimer_usec From 92dc2d93e681e30058992f2aedd058e545df3ec6 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Tue, 25 Apr 2023 22:13:38 +0200 Subject: [PATCH 7/8] cpu/cc26xx_cc13xx: implement periph_timer_query_freqs --- cpu/cc26xx_cc13xx/Kconfig | 1 + cpu/cc26xx_cc13xx/Makefile.features | 1 + cpu/cc26xx_cc13xx/include/periph_cpu_common.h | 12 ++++++ cpu/cc26xx_cc13xx/periph/timer.c | 42 ++++++++++++++++++- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/cpu/cc26xx_cc13xx/Kconfig b/cpu/cc26xx_cc13xx/Kconfig index 2006e114cba23..cbb6e5bb3c44c 100644 --- a/cpu/cc26xx_cc13xx/Kconfig +++ b/cpu/cc26xx_cc13xx/Kconfig @@ -8,6 +8,7 @@ config CPU_COMMON_CC26XX_CC13XX bool select HAS_PERIPH_CPUID + select HAS_PERIPH_TIMER_QUERY_FREQS select HAS_PERIPH_UART select HAS_PERIPH_UART_MODECFG diff --git a/cpu/cc26xx_cc13xx/Makefile.features b/cpu/cc26xx_cc13xx/Makefile.features index a797d3ba77844..bc1115ad440b8 100644 --- a/cpu/cc26xx_cc13xx/Makefile.features +++ b/cpu/cc26xx_cc13xx/Makefile.features @@ -1,5 +1,6 @@ FEATURES_PROVIDED += periph_cpuid FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_uart_modecfg +FEATURES_PROVIDED += periph_timer_query_freqs -include $(RIOTCPU)/cortexm_common/Makefile.features diff --git a/cpu/cc26xx_cc13xx/include/periph_cpu_common.h b/cpu/cc26xx_cc13xx/include/periph_cpu_common.h index 71e9f2d046783..2951108f7fd86 100644 --- a/cpu/cc26xx_cc13xx/include/periph_cpu_common.h +++ b/cpu/cc26xx_cc13xx/include/periph_cpu_common.h @@ -143,6 +143,18 @@ typedef struct { uint8_t chn; /**< number of channels [1,2] */ } timer_conf_t; +/** + * @brief Maximum number of channels + * + * @note 32 bit timers only support one channel instead of two. But knowing + * the worst case is useful e.g. for static allocation. Users are + * expected to either do proper error handling with `timer_set()` and + * `timer_set_absolute()`, or at least verify with + * @ref timer_query_channel_numof what the actual number of channels + * of a timer is. + */ +#define TIMER_CHANNEL_NUMOF 2 + #define PERIPH_I2C_NEED_READ_REG #define PERIPH_I2C_NEED_READ_REGS #define PERIPH_I2C_NEED_WRITE_REG diff --git a/cpu/cc26xx_cc13xx/periph/timer.c b/cpu/cc26xx_cc13xx/periph/timer.c index 913809148826c..4f913104e5df4 100644 --- a/cpu/cc26xx_cc13xx/periph/timer.c +++ b/cpu/cc26xx_cc13xx/periph/timer.c @@ -20,8 +20,9 @@ * @} */ -#include +#include #include +#include #include "assert.h" #include "board.h" @@ -98,9 +99,44 @@ static inline gpt_reg_t *dev(tim_t tim) return ((gpt_reg_t *)(GPT0_BASE | (((uint32_t)tim) << 12))); } +uword_t timer_query_freqs_numof(tim_t dev) +{ + assert(dev < TIMER_NUMOF); + /* 32 bit timers only work at CPU clock */ + if (timer_config[dev].cfg == GPT_CFG_32T) { + return 1; + } + + return 256; +} + +uword_t timer_query_channel_numof(tim_t dev) +{ + assert(dev < TIMER_NUMOF); + return timer_config[dev].chn; +} + +uint32_t timer_query_freqs(tim_t dev, uword_t index) +{ + assert(dev < TIMER_NUMOF); + + /* 32 bit timers only work at CPU clock */ + if (timer_config[dev].cfg == GPT_CFG_32T) { + if (index) { + return 0; + } + return RCOSC48M_FREQ; + } + + if (index > UINT8_MAX) { + return 0; + } + return RCOSC48M_FREQ / (index + 1); +} + int timer_init(tim_t tim, uint32_t freq, timer_cb_t cb, void *arg) { - DEBUG("timer_init(%u, %lu)\n", tim, freq); + DEBUG("timer_init(%u, %" PRIu32 ")\n", tim, freq); /* make sure given timer is valid */ if (tim >= TIMER_NUMOF) { return -1; @@ -182,6 +218,8 @@ int timer_set_absolute(tim_t tim, int channel, unsigned int value) dev(tim)->TBMATCHR = (timer_config[tim].cfg == GPT_CFG_32T) ? value : (LOAD_VALUE - value); } + + /* unmask IRQ */ dev(tim)->IMR |= chn_isr_cfg[channel].flag; return 0; From c0aed9b62f35b1db5383154b17fa4bdf0a3a3169 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Mon, 4 Dec 2023 09:02:51 +0100 Subject: [PATCH 8/8] cpu/cc26xx_cc13xx: fix spurious IRQs in periph_timer --- cpu/cc26xx_cc13xx/periph/timer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpu/cc26xx_cc13xx/periph/timer.c b/cpu/cc26xx_cc13xx/periph/timer.c index 4f913104e5df4..735be2f996038 100644 --- a/cpu/cc26xx_cc13xx/periph/timer.c +++ b/cpu/cc26xx_cc13xx/periph/timer.c @@ -195,6 +195,10 @@ int timer_init(tim_t tim, uint32_t freq, timer_cb_t cb, void *arg) dev(tim)->TBILR = LOAD_VALUE; dev(tim)->CTL = GPT_CTL_TAEN | GPT_CTL_TBEN; } + + /* clear any left over IRQ flags to avoid spurious IRQs */ + dev(tim)->ICLR = UINT32_MAX; + /* enable timer IRQs */ _irq_enable(tim);