Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/sam0_common: implement periph_timer_query_freqs #20147

Merged
merged 1 commit into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cpu/sam0_common/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion cpu/sam0_common/Makefile.features
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
48 changes: 37 additions & 11 deletions cpu/sam0_common/periph/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@

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);
Expand Down Expand Up @@ -94,20 +110,13 @@

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 */
Expand All @@ -130,6 +139,23 @@
#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
*/
Expand Down Expand Up @@ -319,7 +345,7 @@

The problem was observed on SAME54.
*/
while(dev(tim)->CTRLBSET.bit.CMD == TC_CTRLBSET_CMD_READSYNC_Val) {}

Check warning on line 348 in cpu/sam0_common/periph/timer.c

View workflow job for this annotation

GitHub Actions / static-tests

keyword 'while' not followed by a single space
#else
dev(tim)->READREQ.reg = TC_READREQ_RREQ | TC_READREQ_ADDR(TC_COUNT32_COUNT_OFFSET);
#endif
Expand Down
Loading