diff --git a/cpu/cc26xx_cc13xx/Kconfig b/cpu/cc26xx_cc13xx/Kconfig index 2006e114cb..cbb6e5bb3c 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 a797d3ba77..bc1115ad44 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 71e9f2d046..2951108f7f 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 9138091488..4f913104e5 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;