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

Merge pull request #20147 from maribu/periph_timer_query_freq-sam0

cpu/sam0_common: implement periph_timer_query_freqs
This commit is contained in:
Marian Buschsieweke 2023-12-07 16:24:32 +00:00 committed by GitHub
commit eb2e6983d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 12 deletions

View File

@ -25,6 +25,7 @@ config CPU_COMMON_SAM0
select HAS_PERIPH_SPI_RECONFIGURE
select HAS_PERIPH_SPI_GPIO_MODE
select HAS_PERIPH_TIMER_PERIODIC
select HAS_PERIPH_TIMER_QUERY_FREQS
select HAS_PERIPH_UART_MODECFG
select HAS_PERIPH_UART_NONBLOCKING
select HAS_PERIPH_UART_RECONFIGURE

View File

@ -14,15 +14,17 @@ FEATURES_PROVIDED += periph_flashpage_pagewise
FEATURES_PROVIDED += periph_flashpage_rwee
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
FEATURES_PROVIDED += periph_i2c_reconfigure
FEATURES_PROVIDED += periph_rtt_set_counter
FEATURES_PROVIDED += periph_rtt_overflow
FEATURES_PROVIDED += periph_rtt_set_counter
FEATURES_PROVIDED += periph_sdmmc_auto_cmd12
FEATURES_PROVIDED += periph_sdmmc_hs
FEATURES_PROVIDED += periph_sdmmc_mmc
FEATURES_PROVIDED += periph_sdmmc_sdhc
FEATURES_PROVIDED += periph_spi_reconfigure
FEATURES_PROVIDED += periph_spi_gpio_mode
FEATURES_PROVIDED += periph_spi_reconfigure
FEATURES_PROVIDED += periph_timer_periodic # implements timer_set_periodic()
FEATURES_PROVIDED += periph_timer_query_freqs
FEATURES_PROVIDED += periph_uart_modecfg
FEATURES_PROVIDED += periph_uart_nonblocking
FEATURES_PROVIDED += periph_uart_reconfigure

View File

@ -43,6 +43,22 @@ static timer_isr_ctx_t config[TIMER_NUMOF];
static uint32_t _oneshot;
/* Number of right-shifts to perform on the input frequency to get the output
* frequency the prescaler will divide it down to */
static const uint8_t _prescaler_shifts[] = {
[TC_CTRLA_PRESCALER_DIV1_Val] = 0,
[TC_CTRLA_PRESCALER_DIV2_Val] = 1,
[TC_CTRLA_PRESCALER_DIV4_Val] = 2,
[TC_CTRLA_PRESCALER_DIV8_Val] = 3,
[TC_CTRLA_PRESCALER_DIV16_Val] = 4,
[TC_CTRLA_PRESCALER_DIV64_Val] = 6,
[TC_CTRLA_PRESCALER_DIV256_Val] = 8,
[TC_CTRLA_PRESCALER_DIV1024_Val] = 10,
};
static_assert(ARRAY_SIZE(_prescaler_shifts) == (TC_CTRLA_PRESCALER_DIV1024_Val + 1),
"_prescaler_shifts needs an update for the selected MCU");
static inline void set_oneshot(tim_t tim, int chan)
{
_oneshot |= (1 << chan) << (TIMER_CHANNEL_NUMOF * tim);
@ -94,20 +110,13 @@ static inline void _irq_enable(tim_t tim)
static uint8_t _get_prescaler(uint32_t freq_out, uint32_t freq_in)
{
uint8_t scale = 0;
while (freq_in > freq_out) {
freq_in >>= 1;
/* after DIV16 the prescaler gets more coarse */
if (++scale > TC_CTRLA_PRESCALER_DIV16_Val) {
freq_in >>= 1;
}
}
/* fail if output frequency can't be derived from input frequency */
assert(freq_in == freq_out);
for (uint8_t scale = 0; scale < ARRAY_SIZE(_prescaler_shifts); scale++) {
if ((freq_in >> _prescaler_shifts[scale]) == freq_out) {
return scale;
}
}
return UINT8_MAX;
}
/* TOP value is CC0 */
@ -130,6 +139,23 @@ static inline void _set_nfrq(tim_t tim)
#endif
}
uword_t timer_query_freqs_numof(tim_t dev)
{
assert(dev < TIMER_NUMOF);
(void)dev;
return ARRAY_SIZE(_prescaler_shifts);
}
uint32_t timer_query_freqs(tim_t dev, uword_t index)
{
assert(dev < TIMER_NUMOF);
const tc32_conf_t *cfg = &timer_config[dev];
if (index >= ARRAY_SIZE(_prescaler_shifts)) {
return 0;
}
return sam0_gclk_freq(cfg->gclk_src) >> _prescaler_shifts[index];
}
/**
* @brief Setup the given timer
*/