diff --git a/boards/common/slwstk6000b/include/periph_conf.h b/boards/common/slwstk6000b/include/periph_conf.h index e30471fd76..7f74dd90b9 100644 --- a/boards/common/slwstk6000b/include/periph_conf.h +++ b/boards/common/slwstk6000b/include/periph_conf.h @@ -147,7 +147,8 @@ static const timer_conf_t timer_config[] = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, - .irq = TIMER1_IRQn + .irq = TIMER1_IRQn, + .channel_numof = 3 } }; diff --git a/boards/ikea-tradfri/include/board.h b/boards/ikea-tradfri/include/board.h index 108f827236..27af510a54 100644 --- a/boards/ikea-tradfri/include/board.h +++ b/boards/ikea-tradfri/include/board.h @@ -34,12 +34,15 @@ extern "C" { * The timer runs at 250 kHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ -#ifdef EFM32_USE_LETIMER +#if IS_ACTIVE(CONFIG_EFM32_XTIMER_USE_LETIMER) +#define XTIMER_DEV (TIMER_DEV(1)) #define XTIMER_HZ (32768UL) #else +#define XTIMER_DEV (TIMER_DEV(0)) #define XTIMER_HZ (250000UL) #endif #define XTIMER_WIDTH (16) +#define XTIMER_CHAN (0) /** @} */ /** diff --git a/boards/ikea-tradfri/include/periph_conf.h b/boards/ikea-tradfri/include/periph_conf.h index 77e72a3f9c..98122ea566 100644 --- a/boards/ikea-tradfri/include/periph_conf.h +++ b/boards/ikea-tradfri/include/periph_conf.h @@ -85,19 +85,6 @@ static const spi_dev_t spi_config[] = { * 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 = { @@ -108,12 +95,25 @@ static const timer_conf_t timer_config[] = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, - .irq = TIMER1_IRQn - } + .irq = TIMER1_IRQn, + .channel_numof = 3 + }, + { + .prescaler = { + .dev = NULL, + .cmu = cmuClock_LETIMER0 + }, + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn, + .channel_numof = 2 + }, }; -#define TIMER_0_ISR isr_timer1 -#endif /* EFM32_USE_LETIMER */ +#define TIMER_0_ISR isr_timer1 +#define TIMER_1_ISR isr_letimer0 #define TIMER_NUMOF ARRAY_SIZE(timer_config) /** @} */ diff --git a/boards/slstk3401a/include/board.h b/boards/slstk3401a/include/board.h index 40a9157694..6894b13576 100644 --- a/boards/slstk3401a/include/board.h +++ b/boards/slstk3401a/include/board.h @@ -35,12 +35,15 @@ extern "C" { * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ -#ifdef EFM32_USE_LETIMER +#if IS_ACTIVE(CONFIG_EFM32_XTIMER_USE_LETIMER) +#define XTIMER_DEV (TIMER_DEV(1)) #define XTIMER_HZ (32768UL) #else +#define XTIMER_DEV (TIMER_DEV(0)) #define XTIMER_HZ (250000UL) #endif #define XTIMER_WIDTH (16) +#define XTIMER_CHAN (0) /** @} */ /** diff --git a/boards/slstk3401a/include/periph_conf.h b/boards/slstk3401a/include/periph_conf.h index 2a3ad6ba5f..dc034e4f16 100644 --- a/boards/slstk3401a/include/periph_conf.h +++ b/boards/slstk3401a/include/periph_conf.h @@ -145,19 +145,6 @@ static const spi_dev_t spi_config[] = { * 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 = { @@ -168,12 +155,25 @@ static const timer_conf_t timer_config[] = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, - .irq = TIMER1_IRQn - } + .irq = TIMER1_IRQn, + .channel_numof = 3 + }, + { + .prescaler = { + .dev = NULL, + .cmu = cmuClock_LETIMER0 + }, + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn, + .channel_numof = 2 + }, }; -#define TIMER_0_ISR isr_timer1 -#endif /* EFM32_USE_LETIMER */ +#define TIMER_0_ISR isr_timer1 +#define TIMER_1_ISR isr_letimer0 #define TIMER_NUMOF ARRAY_SIZE(timer_config) /** @} */ diff --git a/boards/slstk3402a/include/board.h b/boards/slstk3402a/include/board.h index b4149c1f00..3b3c6e12dd 100644 --- a/boards/slstk3402a/include/board.h +++ b/boards/slstk3402a/include/board.h @@ -33,13 +33,16 @@ extern "C" { * @name Xtimer configuration * @{ */ -#ifdef EFM32_USE_LETIMER +#if IS_ACTIVE(CONFIG_EFM32_XTIMER_USE_LETIMER) +#define XTIMER_DEV (TIMER_DEV(1)) #define XTIMER_HZ (32768UL) #define XTIMER_WIDTH (16) #else +#define XTIMER_DEV (TIMER_DEV(0)) #define XTIMER_HZ (1000000UL) #define XTIMER_WIDTH (32) #endif +#define XTIMER_CHAN (0) /** @} */ /** diff --git a/boards/slstk3402a/include/periph_conf.h b/boards/slstk3402a/include/periph_conf.h index dfefe0bd5c..866be39ede 100644 --- a/boards/slstk3402a/include/periph_conf.h +++ b/boards/slstk3402a/include/periph_conf.h @@ -136,19 +136,6 @@ static const spi_dev_t spi_config[] = { * 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 = { @@ -159,12 +146,25 @@ static const timer_conf_t timer_config[] = { .dev = WTIMER1, .cmu = cmuClock_WTIMER1 }, - .irq = WTIMER1_IRQn - } + .irq = WTIMER1_IRQn, + .channel_numof = 3 + }, + { + .prescaler = { + .dev = NULL, + .cmu = cmuClock_LETIMER0 + }, + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn, + .channel_numof = 2 + }, }; -#define TIMER_0_ISR isr_wtimer1 -#endif /* EFM32_USE_LETIMER */ +#define TIMER_0_ISR isr_wtimer1 +#define TIMER_1_ISR isr_letimer0 #define TIMER_NUMOF ARRAY_SIZE(timer_config) /** @} */ diff --git a/boards/sltb001a/include/board.h b/boards/sltb001a/include/board.h index 1291ca66e9..aced867dc1 100644 --- a/boards/sltb001a/include/board.h +++ b/boards/sltb001a/include/board.h @@ -35,13 +35,16 @@ extern "C" { * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ -#ifdef EFM32_USE_LETIMER +#if IS_ACTIVE(CONFIG_EFM32_XTIMER_USE_LETIMER) +#define XTIMER_DEV (TIMER_DEV(1)) #define XTIMER_HZ (32768UL) #define XTIMER_WIDTH (16) #else +#define XTIMER_DEV (TIMER_DEV(0)) #define XTIMER_HZ (250000UL) #define XTIMER_WIDTH (16) #endif +#define XTIMER_CHAN (0) /** @} */ /** diff --git a/boards/sltb001a/include/periph_conf.h b/boards/sltb001a/include/periph_conf.h index ddc13e9645..7662a53bff 100644 --- a/boards/sltb001a/include/periph_conf.h +++ b/boards/sltb001a/include/periph_conf.h @@ -145,19 +145,6 @@ static const spi_dev_t spi_config[] = { * 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 = { @@ -168,12 +155,25 @@ static const timer_conf_t timer_config[] = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, - .irq = TIMER1_IRQn - } + .irq = TIMER1_IRQn, + .channel_numof = 3 + }, + { + .prescaler = { + .dev = NULL, + .cmu = cmuClock_LETIMER0 + }, + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn, + .channel_numof = 2 + }, }; -#define TIMER_0_ISR isr_timer1 -#endif /* EFM32_USE_LETIMER */ +#define TIMER_0_ISR isr_timer1 +#define TIMER_1_ISR isr_letimer0 #define TIMER_NUMOF ARRAY_SIZE(timer_config) /** @} */ diff --git a/boards/stk3600/include/board.h b/boards/stk3600/include/board.h index 52e0869e08..60822e884b 100644 --- a/boards/stk3600/include/board.h +++ b/boards/stk3600/include/board.h @@ -35,13 +35,16 @@ extern "C" { * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ -#ifdef EFM32_USE_LETIMER +#if IS_ACTIVE(CONFIG_EFM32_XTIMER_USE_LETIMER) +#define XTIMER_DEV (TIMER_DEV(1)) #define XTIMER_HZ (32768UL) #define XTIMER_WIDTH (16) #else +#define XTIMER_DEV (TIMER_DEV(0)) #define XTIMER_HZ (250000UL) #define XTIMER_WIDTH (16) #endif +#define XTIMER_CHAN (0) /** @} */ /** diff --git a/boards/stk3600/include/periph_conf.h b/boards/stk3600/include/periph_conf.h index bbef6a9327..42a6493cd8 100644 --- a/boards/stk3600/include/periph_conf.h +++ b/boards/stk3600/include/periph_conf.h @@ -199,19 +199,6 @@ static const spi_dev_t spi_config[] = { * 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 = { @@ -222,12 +209,25 @@ static const timer_conf_t timer_config[] = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, - .irq = TIMER1_IRQn - } + .irq = TIMER1_IRQn, + .channel_numof = 3 + }, + { + .prescaler = { + .dev = NULL, + .cmu = cmuClock_LETIMER0 + }, + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn, + .channel_numof = 2 + }, }; -#define TIMER_0_ISR isr_timer1 -#endif /* EFM32_USE_LETIMER */ +#define TIMER_0_ISR isr_timer1 +#define TIMER_1_ISR isr_letimer0 #define TIMER_NUMOF ARRAY_SIZE(timer_config) /** @} */ diff --git a/boards/stk3700/include/board.h b/boards/stk3700/include/board.h index 973c6b2399..58fc3f02cd 100644 --- a/boards/stk3700/include/board.h +++ b/boards/stk3700/include/board.h @@ -35,13 +35,16 @@ extern "C" { * The timer runs at 250 KHz to increase accuracy or 32768 Hz for LETIMER. * @{ */ -#ifdef EFM32_USE_LETIMER +#if IS_ACTIVE(CONFIG_EFM32_XTIMER_USE_LETIMER) +#define XTIMER_DEV (TIMER_DEV(1)) #define XTIMER_HZ (32768UL) #define XTIMER_WIDTH (16) #else +#define XTIMER_DEV (TIMER_DEV(0)) #define XTIMER_HZ (250000UL) #define XTIMER_WIDTH (16) #endif +#define XTIMER_CHAN (0) /** @} */ /** diff --git a/boards/stk3700/include/periph_conf.h b/boards/stk3700/include/periph_conf.h index 01829e99a9..e63f566fa0 100644 --- a/boards/stk3700/include/periph_conf.h +++ b/boards/stk3700/include/periph_conf.h @@ -199,19 +199,6 @@ static const spi_dev_t spi_config[] = { * 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 = { @@ -222,12 +209,25 @@ static const timer_conf_t timer_config[] = { .dev = TIMER1, .cmu = cmuClock_TIMER1 }, - .irq = TIMER1_IRQn - } + .irq = TIMER1_IRQn, + .channel_numof = 3 + }, + { + .prescaler = { + .dev = NULL, + .cmu = cmuClock_LETIMER0 + }, + .timer = { + .dev = LETIMER0, + .cmu = cmuClock_LETIMER0 + }, + .irq = LETIMER0_IRQn, + .channel_numof = 2 + }, }; -#define TIMER_0_ISR isr_timer1 -#endif /* EFM32_USE_LETIMER */ +#define TIMER_0_ISR isr_timer1 +#define TIMER_1_ISR isr_letimer0 #define TIMER_NUMOF ARRAY_SIZE(timer_config) /** @} */ diff --git a/cpu/efm32/include/periph_cpu.h b/cpu/efm32/include/periph_cpu.h index 6ef3507a33..963a87f7dc 100644 --- a/cpu/efm32/include/periph_cpu.h +++ b/cpu/efm32/include/periph_cpu.h @@ -20,6 +20,7 @@ #ifndef PERIPH_CPU_H #define PERIPH_CPU_H +#include "kernel_defines.h" #include "mutex.h" #include "cpu_conf.h" @@ -356,28 +357,18 @@ typedef struct { timer_dev_t prescaler; /**< the lower neighboring timer (not initialized for LETIMER) */ timer_dev_t timer; /**< the higher numbered timer */ IRQn_Type irq; /**< number of the higher timer IRQ channel */ + uint8_t channel_numof; /**< number of channels per timer */ } timer_conf_t; /** @} */ /** - * @brief The implementation can use one LETIMER or two regular timers cascaded + * @brief Use LETIMER as the base timer for XTIMER */ -#ifndef EFM32_USE_LETIMER -#define EFM32_USE_LETIMER 0 +#ifndef CONFIG_EFM32_XTIMER_USE_LETIMER +#define CONFIG_EFM32_XTIMER_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 ff291340f9..08fd27f17b 100644 --- a/cpu/efm32/periph/timer.c +++ b/cpu/efm32/periph/timer.c @@ -111,8 +111,7 @@ static void _timer_init(tim_t dev, unsigned long freq) TIMER_Init_TypeDef init_pre = TIMER_INIT_DEFAULT; TIMER_Init_TypeDef init_tim = TIMER_INIT_DEFAULT; - /* leave the prescaler enabled and toggle only the primary timer */ - init_pre.enable = true; + init_pre.enable = false; init_pre.prescale = timerPrescale1; init_tim.enable = false; init_tim.clkSel = timerClkSelCascade; @@ -166,7 +165,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 >= TIMER_CHANNEL_NUMOF) { + if (channel < 0 || channel >= timer_config[dev].channel_numof) { return -1; } @@ -256,6 +255,7 @@ void timer_stop(tim_t dev) pm_unblock(EFM32_TIMER_PM_BLOCKER); } TIMER_Enable(timer_config[dev].timer.dev, false); + TIMER_Enable(timer_config[dev].prescaler.dev, false); } } @@ -274,18 +274,16 @@ void timer_start(tim_t dev) pm_block(EFM32_TIMER_PM_BLOCKER); } TIMER_Enable(timer_config[dev].timer.dev, true); + TIMER_Enable(timer_config[dev].prescaler.dev, true); } } -#ifdef TIMER_0_ISR -void TIMER_0_ISR(void) +static void _timer_isr(tim_t dev) { - tim_t dev = 0; - if (_is_letimer(dev)) { LETIMER_TypeDef *tim = timer_config[dev].timer.dev; - for (int i = 0; i < TIMER_CHANNEL_NUMOF; i++) { + for (int i = 0; i < timer_config[dev].channel_numof; i++) { if (tim->IF & (LETIMER_IF_COMP0 << i)) { LETIMER_IntDisable(tim, LETIMER_IEN_COMP0 << i); @@ -297,7 +295,7 @@ void TIMER_0_ISR(void) else { TIMER_TypeDef *tim = timer_config[dev].timer.dev; - for (int i = 0; i < TIMER_CHANNEL_NUMOF; i++) { + for (int i = 0; i < timer_config[dev].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); @@ -307,4 +305,17 @@ void TIMER_0_ISR(void) } cortexm_isr_end(); } + +#ifdef TIMER_0_ISR +void TIMER_0_ISR(void) +{ + _timer_isr(0); +} #endif /* TIMER_0_ISR */ + +#ifdef TIMER_1_ISR +void TIMER_1_ISR(void) +{ + _timer_isr(1); +} +#endif /* TIMER_1_ISR */ diff --git a/tests/periph_timer/Makefile b/tests/periph_timer/Makefile index d86e686a82..94a4ea9b08 100644 --- a/tests/periph_timer/Makefile +++ b/tests/periph_timer/Makefile @@ -19,6 +19,11 @@ BOARDS_TIMER_32kHz := \ openlabs-kw41z-mini \ frdm-k64f \ frdm-k22f \ + slstk3401a \ + slstk3402a \ + sltb001a \ + stk3600 \ + stk3700 \ # BOARDS_TIMER_CLOCK_CORECLOCK := \ diff --git a/tests/periph_timer_periodic/main.c b/tests/periph_timer_periodic/main.c index 09fc0c2580..640b057a80 100644 --- a/tests/periph_timer_periodic/main.c +++ b/tests/periph_timer_periodic/main.c @@ -37,11 +37,16 @@ * as xtimer is not used in this test, we can use it and the fact that every board * provides a configuration for it. */ -#define TIMER_CYCL XTIMER_DEV -#define CYCLE_MS 25UL -#define CYCLES_MAX 10 +#define TIMER_CYCL (XTIMER_DEV) +#define CYCLE_MS (25UL) +#define CYCLES_MAX (10) +#ifdef TIMER_CHANNEL_NUMOF +#define MAX_CHANNELS (TIMER_CHANNEL_NUMOF) +#else +#define MAX_CHANNELS (10) +#endif -static unsigned count[TIMER_CHANNEL_NUMOF]; +static unsigned count[MAX_CHANNELS]; static void cb(void *arg, int chan) { @@ -85,7 +90,13 @@ int main(void) /* Only the first channel should trigger and reset the counter */ /* If subsequent channels trigger this is an error. */ - timer_set_periodic(TIMER_CYCL, 1, 2 * steps, TIM_FLAG_RESET_ON_SET); + unsigned channel_numof = 1; + for(unsigned i = 1; i < MAX_CHANNELS; i++) { + if(!timer_set_periodic(TIMER_CYCL, i, (1 + i) * steps, TIM_FLAG_RESET_ON_SET)) { + channel_numof = i; + break; + } + } timer_set_periodic(TIMER_CYCL, 0, steps, TIM_FLAG_RESET_ON_MATCH); mutex_lock(&lock); @@ -93,7 +104,7 @@ int main(void) puts("\nCycles:"); bool succeeded = true; - for (unsigned i = 0; i < TIMER_CHANNEL_NUMOF; ++i) { + for (unsigned i = 0; i < channel_numof; ++i) { printf("channel %u = %02u\t[%s]\n", i, count[i], _print_ok(i, &succeeded)); }