From 754d790b3fa73b960dde97851eb1dcd68eb1ae7d Mon Sep 17 00:00:00 2001 From: Thomas Stilwell Date: Thu, 30 Jan 2020 01:59:06 -0600 Subject: [PATCH] boards: efm32 boards: add support for LETIMER --- boards/ikea-tradfri/include/board.h | 6 +++++- boards/ikea-tradfri/include/periph_conf.h | 25 ++++++++++++++++++----- boards/slstk3401a/include/board.h | 6 +++++- boards/slstk3401a/include/periph_conf.h | 24 ++++++++++++++++++---- boards/slstk3402a/include/board.h | 5 +++++ boards/slstk3402a/include/periph_conf.h | 24 ++++++++++++++++++---- boards/sltb001a/include/board.h | 7 ++++++- boards/sltb001a/include/periph_conf.h | 24 ++++++++++++++++++---- boards/stk3600/include/board.h | 7 ++++++- boards/stk3600/include/periph_conf.h | 25 ++++++++++++++++++----- boards/stk3700/include/board.h | 7 ++++++- boards/stk3700/include/periph_conf.h | 25 ++++++++++++++++++----- cpu/efm32/include/periph_cpu.h | 20 ++++++++++++++++++ cpu/efm32/periph/timer.c | 16 +++------------ 14 files changed, 176 insertions(+), 45 deletions(-) diff --git a/boards/ikea-tradfri/include/board.h b/boards/ikea-tradfri/include/board.h index 6ca31bb52fb0..108f82723671 100644 --- a/boards/ikea-tradfri/include/board.h +++ b/boards/ikea-tradfri/include/board.h @@ -31,10 +31,14 @@ extern "C" { /** * @name Xtimer configuration * - * The timer runs at 250 KHz to increase accuracy. + * The timer runs at 250 kHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ +#ifdef EFM32_USE_LETIMER +#define XTIMER_HZ (32768UL) +#else #define XTIMER_HZ (250000UL) +#endif #define XTIMER_WIDTH (16) /** @} */ diff --git a/boards/ikea-tradfri/include/periph_conf.h b/boards/ikea-tradfri/include/periph_conf.h index 2e8b22c79470..77e72a3f9c1f 100644 --- a/boards/ikea-tradfri/include/periph_conf.h +++ b/boards/ikea-tradfri/include/periph_conf.h @@ -48,7 +48,6 @@ extern "C" { #endif /** @} */ - /** * @name RTT configuration * @{ @@ -82,25 +81,41 @@ static const spi_dev_t spi_config[] = { /** * @name Timer configuration * - * The implementation uses two timers in cascade mode. + * The implementation can use one low-energy timer + * or two regular timers in cascade mode. * @{ */ +#if EFM32_USE_LETIMER +static const timer_conf_t timer_config[] = { + { + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn + } +}; +#define TIMER_0_ISR isr_letimer0 + +#else static const timer_conf_t timer_config[] = { { - { + .prescaler = { .dev = TIMER0, .cmu = cmuClock_TIMER0 }, - { + .timer = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, .irq = TIMER1_IRQn } }; +#define TIMER_0_ISR isr_timer1 + +#endif /* EFM32_USE_LETIMER */ #define TIMER_NUMOF ARRAY_SIZE(timer_config) -#define TIMER_0_ISR isr_timer1 /** @} */ /** diff --git a/boards/slstk3401a/include/board.h b/boards/slstk3401a/include/board.h index 645149e122ea..40a9157694b1 100644 --- a/boards/slstk3401a/include/board.h +++ b/boards/slstk3401a/include/board.h @@ -32,10 +32,14 @@ extern "C" { /** * @name Xtimer configuration * - * The timer runs at 250 KHz to increase accuracy. + * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ +#ifdef EFM32_USE_LETIMER +#define XTIMER_HZ (32768UL) +#else #define XTIMER_HZ (250000UL) +#endif #define XTIMER_WIDTH (16) /** @} */ diff --git a/boards/slstk3401a/include/periph_conf.h b/boards/slstk3401a/include/periph_conf.h index 77201b0b7ff3..2a3ad6ba5fa5 100644 --- a/boards/slstk3401a/include/periph_conf.h +++ b/boards/slstk3401a/include/periph_conf.h @@ -141,25 +141,41 @@ static const spi_dev_t spi_config[] = { /** * @name Timer configuration * - * The implementation uses two timers in cascade mode. + * The implementation can use one low-energy timer + * or two regular timers in cascade mode. * @{ */ +#if EFM32_USE_LETIMER static const timer_conf_t timer_config[] = { { - { + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn + } +}; +#define TIMER_0_ISR isr_letimer0 + +#else +static const timer_conf_t timer_config[] = { + { + .prescaler = { .dev = TIMER0, .cmu = cmuClock_TIMER0 }, - { + .timer = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, .irq = TIMER1_IRQn } }; +#define TIMER_0_ISR isr_timer1 + +#endif /* EFM32_USE_LETIMER */ #define TIMER_NUMOF ARRAY_SIZE(timer_config) -#define TIMER_0_ISR isr_timer1 /** @} */ /** diff --git a/boards/slstk3402a/include/board.h b/boards/slstk3402a/include/board.h index 5ebff1cb2ddf..b4149c1f007e 100644 --- a/boards/slstk3402a/include/board.h +++ b/boards/slstk3402a/include/board.h @@ -33,8 +33,13 @@ extern "C" { * @name Xtimer configuration * @{ */ +#ifdef EFM32_USE_LETIMER +#define XTIMER_HZ (32768UL) +#define XTIMER_WIDTH (16) +#else #define XTIMER_HZ (1000000UL) #define XTIMER_WIDTH (32) +#endif /** @} */ /** diff --git a/boards/slstk3402a/include/periph_conf.h b/boards/slstk3402a/include/periph_conf.h index a93391a9f8f9..dfefe0bd5c98 100644 --- a/boards/slstk3402a/include/periph_conf.h +++ b/boards/slstk3402a/include/periph_conf.h @@ -132,25 +132,41 @@ static const spi_dev_t spi_config[] = { /** * @name Timer configuration * - * The implementation uses two timers in cascade mode. + * The implementation can use one low-energy timer + * or two regular timers in cascade mode. * @{ */ +#if EFM32_USE_LETIMER static const timer_conf_t timer_config[] = { { - { + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn + } +}; +#define TIMER_0_ISR isr_letimer0 + +#else +static const timer_conf_t timer_config[] = { + { + .prescaler = { .dev = WTIMER0, .cmu = cmuClock_WTIMER0 }, - { + .timer = { .dev = WTIMER1, .cmu = cmuClock_WTIMER1 }, .irq = WTIMER1_IRQn } }; +#define TIMER_0_ISR isr_wtimer1 + +#endif /* EFM32_USE_LETIMER */ #define TIMER_NUMOF ARRAY_SIZE(timer_config) -#define TIMER_0_ISR isr_wtimer1 /** @} */ /** diff --git a/boards/sltb001a/include/board.h b/boards/sltb001a/include/board.h index dc59748dbcee..1291ca66e979 100644 --- a/boards/sltb001a/include/board.h +++ b/boards/sltb001a/include/board.h @@ -32,11 +32,16 @@ extern "C" { /** * @name Xtimer configuration * - * The timer runs at 250 KHz to increase accuracy. + * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ +#ifdef EFM32_USE_LETIMER +#define XTIMER_HZ (32768UL) +#define XTIMER_WIDTH (16) +#else #define XTIMER_HZ (250000UL) #define XTIMER_WIDTH (16) +#endif /** @} */ /** diff --git a/boards/sltb001a/include/periph_conf.h b/boards/sltb001a/include/periph_conf.h index f43a84b353d5..ddc13e964581 100644 --- a/boards/sltb001a/include/periph_conf.h +++ b/boards/sltb001a/include/periph_conf.h @@ -141,25 +141,41 @@ static const spi_dev_t spi_config[] = { /** * @name Timer configuration * - * The implementation uses two timers in cascade mode. + * The implementation can use one low-energy timer + * or two regular timers in cascade mode. * @{ */ +#if EFM32_USE_LETIMER static const timer_conf_t timer_config[] = { { - { + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn + } +}; +#define TIMER_0_ISR isr_letimer0 + +#else +static const timer_conf_t timer_config[] = { + { + .prescaler = { .dev = TIMER0, .cmu = cmuClock_TIMER0 }, - { + .timer = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, .irq = TIMER1_IRQn } }; +#define TIMER_0_ISR isr_timer1 + +#endif /* EFM32_USE_LETIMER */ #define TIMER_NUMOF ARRAY_SIZE(timer_config) -#define TIMER_0_ISR isr_timer1 /** @} */ /** diff --git a/boards/stk3600/include/board.h b/boards/stk3600/include/board.h index e692bd8dcaca..52e0869e088a 100644 --- a/boards/stk3600/include/board.h +++ b/boards/stk3600/include/board.h @@ -32,11 +32,16 @@ extern "C" { /** * @name Xtimer configuration * - * The timer runs at 250 KHz to increase accuracy. + * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ +#ifdef EFM32_USE_LETIMER +#define XTIMER_HZ (32768UL) +#define XTIMER_WIDTH (16) +#else #define XTIMER_HZ (250000UL) #define XTIMER_WIDTH (16) +#endif /** @} */ /** diff --git a/boards/stk3600/include/periph_conf.h b/boards/stk3600/include/periph_conf.h index 9d6e3a4e1872..bbef6a9327fc 100644 --- a/boards/stk3600/include/periph_conf.h +++ b/boards/stk3600/include/periph_conf.h @@ -155,7 +155,6 @@ static const pwm_conf_t pwm_config[] = { #define PWM_NUMOF ARRAY_SIZE(pwm_channel_config) /** @} */ - /** * @name RTT configuration * @{ @@ -196,25 +195,41 @@ static const spi_dev_t spi_config[] = { /** * @name Timer configuration * - * The implementation uses two timers in cascade mode. + * The implementation can use one low-energy timer + * or two regular timers in cascade mode. * @{ */ +#if EFM32_USE_LETIMER +static const timer_conf_t timer_config[] = { + { + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn + } +}; +#define TIMER_0_ISR isr_letimer0 + +#else static const timer_conf_t timer_config[] = { { - { + .prescaler = { .dev = TIMER0, .cmu = cmuClock_TIMER0 }, - { + .timer = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, .irq = TIMER1_IRQn } }; +#define TIMER_0_ISR isr_timer1 + +#endif /* EFM32_USE_LETIMER */ #define TIMER_NUMOF ARRAY_SIZE(timer_config) -#define TIMER_0_ISR isr_timer1 /** @} */ /** diff --git a/boards/stk3700/include/board.h b/boards/stk3700/include/board.h index 6d7931231046..973c6b2399b5 100644 --- a/boards/stk3700/include/board.h +++ b/boards/stk3700/include/board.h @@ -32,11 +32,16 @@ extern "C" { /** * @name Xtimer configuration * - * The timer runs at 250 KHz to increase accuracy. + * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ +#ifdef EFM32_USE_LETIMER +#define XTIMER_HZ (32768UL) +#define XTIMER_WIDTH (16) +#else #define XTIMER_HZ (250000UL) #define XTIMER_WIDTH (16) +#endif /** @} */ /** diff --git a/boards/stk3700/include/periph_conf.h b/boards/stk3700/include/periph_conf.h index ee54dec5727c..01829e99a9ac 100644 --- a/boards/stk3700/include/periph_conf.h +++ b/boards/stk3700/include/periph_conf.h @@ -155,7 +155,6 @@ static const pwm_conf_t pwm_config[] = { #define PWM_NUMOF ARRAY_SIZE(pwm_channel_config) /** @} */ - /** * @name RTT configuration * @{ @@ -196,25 +195,41 @@ static const spi_dev_t spi_config[] = { /** * @name Timer configuration * - * The implementation uses two timers in cascade mode. + * The implementation can use one low-energy timer + * or two regular timers in cascade mode. * @{ */ +#if EFM32_USE_LETIMER +static const timer_conf_t timer_config[] = { + { + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn + } +}; +#define TIMER_0_ISR isr_letimer0 + +#else static const timer_conf_t timer_config[] = { { - { + .prescaler = { .dev = TIMER0, .cmu = cmuClock_TIMER0 }, - { + .timer = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, .irq = TIMER1_IRQn } }; +#define TIMER_0_ISR isr_timer1 + +#endif /* EFM32_USE_LETIMER */ #define TIMER_NUMOF ARRAY_SIZE(timer_config) -#define TIMER_0_ISR isr_timer1 /** @} */ /** diff --git a/cpu/efm32/include/periph_cpu.h b/cpu/efm32/include/periph_cpu.h index b8c8867a15ab..6ef3507a33d2 100644 --- a/cpu/efm32/include/periph_cpu.h +++ b/cpu/efm32/include/periph_cpu.h @@ -359,6 +359,26 @@ typedef struct { } timer_conf_t; /** @} */ + +/** + * @brief The implementation can use one LETIMER or two regular timers cascaded + */ +#ifndef EFM32_USE_LETIMER +#define EFM32_USE_LETIMER 0 +#endif + +#ifdef EFM32_USE_LETIMER +/** + * @brief This timer implementation has two available channels + */ +#define TIMER_CHANNEL_NUMOF (2) +#else +/** + * @brief This timer implementation has three available channels + */ +#define TIMER_CHANNEL_NUMOF (3) +#endif + /** * @brief UART device configuration. */ diff --git a/cpu/efm32/periph/timer.c b/cpu/efm32/periph/timer.c index 1da1101aadda..ff291340f9f9 100644 --- a/cpu/efm32/periph/timer.c +++ b/cpu/efm32/periph/timer.c @@ -32,16 +32,6 @@ #include "em_timer_utils.h" #include "em_letimer.h" -/** - * @brief This timer implementation has three available channels - */ -#define CC_CHANNELS (3U) - -/** - * @brief The LETIMER implementation has two available channels - */ -#define LE_CC_CHANNELS (2U) - /** * @brief These power modes will be blocked while the timer is running */ @@ -176,7 +166,7 @@ int timer_set_absolute(tim_t dev, int channel, unsigned int value) if (!_is_letimer(dev)) { TIMER_TypeDef *tim = timer_config[dev].timer.dev; - if (channel < 0 || channel >= (int) CC_CHANNELS) { + if (channel < 0 || channel >= TIMER_CHANNEL_NUMOF) { return -1; } @@ -295,7 +285,7 @@ void TIMER_0_ISR(void) if (_is_letimer(dev)) { LETIMER_TypeDef *tim = timer_config[dev].timer.dev; - for (int i = 0; i < (int) LE_CC_CHANNELS; i++) { + for (int i = 0; i < TIMER_CHANNEL_NUMOF; i++) { if (tim->IF & (LETIMER_IF_COMP0 << i)) { LETIMER_IntDisable(tim, LETIMER_IEN_COMP0 << i); @@ -307,7 +297,7 @@ void TIMER_0_ISR(void) else { TIMER_TypeDef *tim = timer_config[dev].timer.dev; - for (int i = 0; i < (int) CC_CHANNELS; i++) { + for (int i = 0; i < TIMER_CHANNEL_NUMOF; i++) { if (tim->IF & (TIMER_IF_CC0 << i)) { tim->CC[i].CTRL = _TIMER_CC_CTRL_MODE_OFF; tim->IFC = (TIMER_IFC_CC0 << i);