Merge pull request #14780 from fjmolinas/pr_efm32_lpetimer_cleanup

cpu/efm32/timer: cleanups and improvements
This commit is contained in:
Leandro Lanzieri 2020-08-31 15:41:23 +02:00 committed by GitHub
commit 5c3f7bde0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 175 additions and 138 deletions

View File

@ -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
}
};

View File

@ -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)
/** @} */
/**

View File

@ -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)
/** @} */

View File

@ -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)
/** @} */
/**

View File

@ -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)
/** @} */

View File

@ -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)
/** @} */
/**

View File

@ -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)
/** @} */

View File

@ -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)
/** @} */
/**

View File

@ -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)
/** @} */

View File

@ -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)
/** @} */
/**

View File

@ -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)
/** @} */

View File

@ -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)
/** @} */
/**

View File

@ -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)
/** @} */

View File

@ -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.

View File

@ -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 */

View File

@ -19,6 +19,11 @@ BOARDS_TIMER_32kHz := \
openlabs-kw41z-mini \
frdm-k64f \
frdm-k22f \
slstk3401a \
slstk3402a \
sltb001a \
stk3600 \
stk3700 \
#
BOARDS_TIMER_CLOCK_CORECLOCK := \

View File

@ -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));
}