mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-28 22:49:47 +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:
commit
eb2e6983d1
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
for (uint8_t scale = 0; scale < ARRAY_SIZE(_prescaler_shifts); scale++) {
|
||||
if ((freq_in >> _prescaler_shifts[scale]) == freq_out) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
|
||||
/* fail if output frequency can't be derived from input frequency */
|
||||
assert(freq_in == 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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user