diff --git a/cpu/stm32_common/include/periph_cpu_common.h b/cpu/stm32_common/include/periph_cpu_common.h index 7c72a5bd50..1e3bae20df 100644 --- a/cpu/stm32_common/include/periph_cpu_common.h +++ b/cpu/stm32_common/include/periph_cpu_common.h @@ -30,6 +30,11 @@ extern "C" { */ #define CPUID_LEN (12U) +/** + * @brief All STM timers have 4 capture-compare channels + */ +#define TIMER_CHAN (4U) + /** * @brief Use the shared SPI functions * @{ diff --git a/cpu/stm32f1/periph/timer.c b/cpu/stm32_common/periph/timer.c similarity index 90% rename from cpu/stm32f1/periph/timer.c rename to cpu/stm32_common/periph/timer.c index e57d9b53cb..8d51c4a092 100644 --- a/cpu/stm32f1/periph/timer.c +++ b/cpu/stm32_common/periph/timer.c @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_stm32f1 + * @ingroup cpu_stm32_common * @{ * * @file @@ -54,9 +54,9 @@ int timer_init(tim_t tim, unsigned long freq, timer_cb_t cb, void *arg) /* configure the timer as upcounter in continuous mode */ dev(tim)->CR1 = 0; dev(tim)->CR2 = 0; - dev(tim)->ARR = TIMER_MAXVAL; + dev(tim)->ARR = timer_config[tim].max; /* set prescaler */ - dev(tim)->PSC = ((CLOCK_CORECLOCK / freq) - 1); + dev(tim)->PSC = ((periph_apb_clk(timer_config[tim].bus) / freq) - 1); /* generate an update event to apply our configuration */ dev(tim)->EGR = TIM_EGR_UG; @@ -76,11 +76,11 @@ int timer_set(tim_t tim, int channel, unsigned int timeout) int timer_set_absolute(tim_t tim, int channel, unsigned int value) { - if (channel >= TIMER_CHANNELS) { + if (channel >= TIMER_CHAN) { return -1; } - dev(tim)->CCR[channel] = (value & TIMER_MAXVAL); + dev(tim)->CCR[channel] = (value & timer_config[tim].max); dev(tim)->SR &= ~(TIM_SR_CC1IF << channel); dev(tim)->DIER |= (TIM_DIER_CC1IE << channel); @@ -89,7 +89,7 @@ int timer_set_absolute(tim_t tim, int channel, unsigned int value) int timer_clear(tim_t tim, int channel) { - if (channel >= TIMER_CHANNELS) { + if (channel >= TIMER_CHAN) { return -1; } @@ -126,7 +126,7 @@ static inline void irq_handler(tim_t tim) { uint32_t status = (dev(tim)->SR & dev(tim)->DIER); - for (unsigned int i = 0; i < TIMER_CHANNELS; i++) { + for (uint8_t i = 0; i < TIMER_CHAN; i++) { if (status & (TIM_SR_CC1IF << i)) { dev(tim)->DIER &= ~(TIM_DIER_CC1IE << i); isr_ctx[tim].cb(isr_ctx[tim].arg, i); diff --git a/cpu/stm32f0/periph/timer.c b/cpu/stm32f0/periph/timer.c deleted file mode 100644 index 4e6896e459..0000000000 --- a/cpu/stm32f0/periph/timer.c +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. - */ - -/** - * @ingroup cpu_stm32f0 - * @{ - * - * @file - * @brief Low-level timer driver implementation - * - * @author Hauke Petersen - * - * @} - */ - -#include - -#include "cpu.h" -#include "board.h" -#include "sched.h" -#include "thread.h" -#include "periph_conf.h" -#include "periph/timer.h" - -/* guard file in case no TIMER devices are defined */ -#if TIMER_0_EN || TIMER_1_EN - -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev); - -/** - * Timer state memory - */ -static timer_isr_ctx_t config[TIMER_NUMOF]; - - -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - TIM_TypeDef *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* enable timer peripheral clock */ - TIMER_0_CLKEN(); - /* set timer's IRQ priority */ - NVIC_SetPriority(TIMER_0_IRQ_CHAN, TIMER_IRQ_PRIO); - /* select timer */ - timer = TIMER_0_DEV; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - /* enable timer peripheral clock */ - TIMER_1_CLKEN(); - /* set timer's IRQ priority */ - NVIC_SetPriority(TIMER_1_IRQ_CHAN, TIMER_IRQ_PRIO); - /* select timer */ - timer = TIMER_1_DEV; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - /* set callback function */ - config[dev].cb = cb; - config[dev].arg = arg; - - /* set timer to run in counter mode */ - timer->CR1 |= TIM_CR1_URS; - - /* set auto-reload and prescaler values and load new values */ - timer->ARR = TIMER_0_MAX_VALUE; - timer->PSC = (TIMER_0_FREQ / freq) - 1; - timer->EGR |= TIM_EGR_UG; - - /* enable the timer's interrupt */ - timer_irq_enable(dev); - - /* start the timer */ - timer_start(dev); - - return 0; -} - -int timer_set(tim_t dev, int channel, unsigned int timeout) -{ - int now = timer_read(dev); - return timer_set_absolute(dev, channel, now + timeout - 1); -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - TIM_TypeDef *timer = NULL; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - timer = TIMER_1_DEV; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - switch (channel) { - case 0: - timer->CCR1 = value; - timer->SR &= ~TIM_SR_CC1IF; - timer->DIER |= TIM_DIER_CC1IE; - break; - case 1: - timer->CCR2 = value; - timer->SR &= ~TIM_SR_CC2IF; - timer->DIER |= TIM_DIER_CC2IE; - break; - case 2: - timer->CCR3 = value; - timer->SR &= ~TIM_SR_CC3IF; - timer->DIER |= TIM_DIER_CC3IE; - break; - case 3: - timer->CCR4 = value; - timer->SR &= ~TIM_SR_CC4IF; - timer->DIER |= TIM_DIER_CC4IE; - break; - default: - return -1; - } - return 0; -} - -int timer_clear(tim_t dev, int channel) -{ - TIM_TypeDef *timer; - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - timer = TIMER_1_DEV; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - switch (channel) { - case 0: - timer->DIER &= ~TIM_DIER_CC1IE; - break; - case 1: - timer->DIER &= ~TIM_DIER_CC2IE; - break; - case 2: - timer->DIER &= ~TIM_DIER_CC3IE; - break; - case 3: - timer->DIER &= ~TIM_DIER_CC4IE; - break; - default: - return -1; - } - return 0; -} - -unsigned int timer_read(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - return TIMER_0_DEV->CNT; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - return TIMER_1_DEV->CNT; - break; -#endif - case TIMER_UNDEFINED: - default: - return 0; - } -} - -void timer_start(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->CR1 |= TIM_CR1_CEN; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->CR1 |= TIM_CR1_CEN; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_stop(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->CR1 &= ~TIM_CR1_CEN; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->CR1 &= ~TIM_CR1_CEN; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_irq_enable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_EnableIRQ(TIMER_0_IRQ_CHAN); - break; -#endif -#if TIMER_1_EN - case TIMER_1: - NVIC_EnableIRQ(TIMER_1_IRQ_CHAN); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_irq_disable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_DisableIRQ(TIMER_0_IRQ_CHAN); - break; -#endif -#if TIMER_1_EN - case TIMER_1: - NVIC_DisableIRQ(TIMER_1_IRQ_CHAN); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -#if TIMER_0_EN -void TIMER_0_ISR(void) -{ - irq_handler(TIMER_0, TIMER_0_DEV); -} -#endif - -#if TIMER_1_EN -void TIMER_1_ISR(void) -{ - irq_handler(TIMER_1, TIMER_1_DEV); -} -#endif - -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev) -{ - if (dev->SR & TIM_SR_CC1IF) { - dev->DIER &= ~TIM_DIER_CC1IE; - dev->SR &= ~TIM_SR_CC1IF; - config[timer].cb(config[timer].arg, 0); - } - else if (dev->SR & TIM_SR_CC2IF) { - dev->DIER &= ~TIM_DIER_CC2IE; - dev->SR &= ~TIM_SR_CC2IF; - config[timer].cb(config[timer].arg, 1); - } - else if (dev->SR & TIM_SR_CC3IF) { - dev->DIER &= ~TIM_DIER_CC3IE; - dev->SR &= ~TIM_SR_CC3IF; - config[timer].cb(config[timer].arg, 2); - } - else if (dev->SR & TIM_SR_CC4IF) { - dev->DIER &= ~TIM_DIER_CC4IE; - dev->SR &= ~TIM_SR_CC4IF; - config[timer].cb(config[timer].arg, 3); - } - if (sched_context_switch_request) { - thread_yield(); - } -} -#endif /* TIMER_0_EN || TIMER_1_EN */ diff --git a/cpu/stm32f1/include/periph_cpu.h b/cpu/stm32f1/include/periph_cpu.h index 66b4c5c806..4ebe15fd98 100644 --- a/cpu/stm32f1/include/periph_cpu.h +++ b/cpu/stm32f1/include/periph_cpu.h @@ -30,16 +30,6 @@ extern "C" { */ #define ADC_DEVS (2U) -/** - * @brief All timers for the STM32F1 have 4 CC channels - */ -#define TIMER_CHANNELS (4U) - -/** - * @brief All timers have a width of 16-bit - */ -#define TIMER_MAXVAL (0xffff) - /** * @brief declare needed generic SPI functions * @{ @@ -136,16 +126,6 @@ typedef struct { uint8_t chan; /**< CPU ADC channel connected to the pin */ } adc_conf_t; -/** - * @brief Timer configuration - */ -typedef struct { - TIM_TypeDef *dev; /**< timer device */ - uint32_t rcc_mask; /**< corresponding bit in the RCC register */ - uint8_t bus; /**< APBx bus the timer is clock from */ - uint8_t irqn; /**< global IRQ channel */ -} timer_conf_t; - /** * @brief UART configuration options */ diff --git a/cpu/stm32f2/include/periph_cpu.h b/cpu/stm32f2/include/periph_cpu.h index 7be5c1a557..730f84ee14 100644 --- a/cpu/stm32f2/include/periph_cpu.h +++ b/cpu/stm32f2/include/periph_cpu.h @@ -113,22 +113,6 @@ typedef struct { uint8_t AF; /**< alternate function */ } pwm_conf_t; - -/** - * @brief Timer configuration - * @{ - */ -typedef struct { - TIM_TypeDef *dev; /**< timer device */ - uint8_t channels; /**< number of channel */ - uint32_t freq; /**< frequency */ - uint32_t rcc_mask; /**< corresponding bit in the RCC register */ - uint8_t bus; /**< APBx bus the timer is clock from */ - uint8_t irqn; /**< global IRQ channel */ - uint8_t priority; /**< priority */ -} timer_conf_t; -/** @} */ - /** * @brief Structure for UART configuration data * @{ diff --git a/cpu/stm32f2/periph/timer.c b/cpu/stm32f2/periph/timer.c deleted file mode 100644 index a09a2e833c..0000000000 --- a/cpu/stm32f2/periph/timer.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * Copyright (C) 2016 OTA keys S.A. - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. - */ - -/** - * @ingroup cpu_stm32f2 - * @{ - * - * @file - * @brief Low-level timer driver implementation - * - * @author Hauke Petersen - * @author Aurelien Gonce - * - * @} - */ - -#include - -#include "cpu.h" -#include "board.h" -#include "sched.h" -#include "thread.h" -#include "periph_conf.h" -#include "periph/timer.h" - -/** Unified IRQ handler for all timers */ -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev); - -/** Timer state memory */ -static timer_isr_ctx_t config[TIMER_NUMOF]; - -/** - * @brief Get the timer device - */ -static inline TIM_TypeDef *get_dev(tim_t tim) -{ - return timer_config[tim].dev; -} - -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - /* check if device is valid */ - if (dev >= TIMER_NUMOF) { - return -1; - } - - /* enable timer peripheral clock */ - periph_clk_en(timer_config[dev].bus, timer_config[dev].rcc_mask); - - /* set timer's IRQ priority */ - NVIC_SetPriority(timer_config[dev].irqn, timer_config[dev].priority); - - /* set prescaler */ - get_dev(dev)->PSC = (timer_config[dev].freq / freq) - 1; - - /* set callback function */ - config[dev].cb = cb; - config[dev].arg = arg; - - /* set timer to run in counter mode */ - get_dev(dev)->CR1 = 0; - get_dev(dev)->CR2 = 0; - - /* set auto-reload and prescaler values and load new values */ - get_dev(dev)->EGR |= TIM_EGR_UG; - - /* enable the timer's interrupt */ - timer_irq_enable(dev); - - /* start the timer */ - timer_start(dev); - - return 0; -} - -int timer_set(tim_t dev, int channel, unsigned int timeout) -{ - int now = timer_read(dev); - return timer_set_absolute(dev, channel, now + timeout); -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - if (channel >= timer_config[dev].channels || dev >= TIMER_NUMOF) { - return -1; - } - - switch (channel) { - case 0: - get_dev(dev)->CCR1 = value; - get_dev(dev)->SR &= ~TIM_SR_CC1IF; - get_dev(dev)->DIER |= TIM_DIER_CC1IE; - break; - case 1: - get_dev(dev)->CCR2 = value; - get_dev(dev)->SR &= ~TIM_SR_CC2IF; - get_dev(dev)->DIER |= TIM_DIER_CC2IE; - break; - case 2: - get_dev(dev)->CCR3 = value; - get_dev(dev)->SR &= ~TIM_SR_CC3IF; - get_dev(dev)->DIER |= TIM_DIER_CC3IE; - break; - case 3: - get_dev(dev)->CCR4 = value; - get_dev(dev)->SR &= ~TIM_SR_CC4IF; - get_dev(dev)->DIER |= TIM_DIER_CC4IE; - break; - default: - return -1; - } - - return 0; -} - -int timer_clear(tim_t dev, int channel) -{ - if (channel >= timer_config[dev].channels || dev >= TIMER_NUMOF) { - return -1; - } - - get_dev(dev)->DIER &= ~(TIM_DIER_CC1IE << channel); - - return 0; -} - -unsigned int timer_read(tim_t dev) -{ - return (unsigned int)get_dev(dev)->CNT; -} - -void timer_start(tim_t dev) -{ - get_dev(dev)->CR1 |= TIM_CR1_CEN; -} - -void timer_stop(tim_t dev) -{ - get_dev(dev)->CR1 &= ~TIM_CR1_CEN; -} - -void timer_irq_enable(tim_t dev) -{ - NVIC_EnableIRQ(timer_config[dev].irqn); -} - -void timer_irq_disable(tim_t dev) -{ - NVIC_DisableIRQ(timer_config[dev].irqn); -} - -void TIMER_0_ISR(void) -{ - irq_handler(TIMER_0, get_dev(TIMER_0)); -} - -void TIMER_1_ISR(void) -{ - irq_handler(TIMER_1, get_dev(TIMER_1)); -} - -void TIMER_2_ISR(void) -{ - irq_handler(TIMER_2, get_dev(TIMER_2)); -} - -void TIMER_3_ISR(void) -{ - irq_handler(TIMER_3, get_dev(TIMER_3)); -} - -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev) -{ - if (dev->SR & TIM_SR_CC1IF) { - dev->DIER &= ~TIM_DIER_CC1IE; - dev->SR &= ~TIM_SR_CC1IF; - config[timer].cb(config[timer].arg, 0); - } - else if (dev->SR & TIM_SR_CC2IF) { - dev->DIER &= ~TIM_DIER_CC2IE; - dev->SR &= ~TIM_SR_CC2IF; - config[timer].cb(config[timer].arg, 1); - } - else if (dev->SR & TIM_SR_CC3IF) { - dev->DIER &= ~TIM_DIER_CC3IE; - dev->SR &= ~TIM_SR_CC3IF; - config[timer].cb(config[timer].arg, 2); - } - else if (dev->SR & TIM_SR_CC4IF) { - dev->DIER &= ~TIM_DIER_CC4IE; - dev->SR &= ~TIM_SR_CC4IF; - config[timer].cb(config[timer].arg, 3); - } - if (sched_context_switch_request) { - thread_yield(); - } -} diff --git a/cpu/stm32f3/periph/timer.c b/cpu/stm32f3/periph/timer.c deleted file mode 100644 index d6a25a26ff..0000000000 --- a/cpu/stm32f3/periph/timer.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. - */ - -/** - * @ingroup cpu_stm32f3 - * @{ - * - * @file - * @brief Low-level timer driver implementation - * - * @author Hauke Petersen - * - * @} - */ - -#include - -#include "cpu.h" -#include "board.h" -#include "sched.h" -#include "thread.h" -#include "periph_conf.h" -#include "periph/timer.h" - -/** Unified IRQ handler for all timers */ -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev); - -/** Timer state memory */ -static timer_isr_ctx_t config[TIMER_NUMOF]; - - -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - TIM_TypeDef *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* enable timer peripheral clock */ - TIMER_0_CLKEN(); - /* set timer's IRQ priority */ - NVIC_SetPriority(TIMER_0_IRQ_CHAN, TIMER_IRQ_PRIO); - /* select timer */ - timer = TIMER_0_DEV; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - /* set callback function */ - config[dev].cb = cb; - config[dev].arg = arg; - - /* set timer to run in counter mode */ - timer->CR1 = 0; - timer->CR2 = 0; - - /* set auto-reload and prescaler values and load new values */ - timer->PSC = (TIMER_0_FREQ / freq) - 1; - timer->EGR |= TIM_EGR_UG; - - /* enable the timer's interrupt */ - timer_irq_enable(dev); - - /* start the timer */ - timer_start(dev); - - return 0; -} - -int timer_set(tim_t dev, int channel, unsigned int timeout) -{ - int now = timer_read(dev); - return timer_set_absolute(dev, channel, now + timeout - 1); -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - TIM_TypeDef *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif - default: - return -1; - } - - switch (channel) { - case 0: - timer->CCR1 = value; - timer->SR &= ~TIM_SR_CC1IF; - timer->DIER |= TIM_DIER_CC1IE; - break; - case 1: - timer->CCR2 = value; - timer->SR &= ~TIM_SR_CC2IF; - timer->DIER |= TIM_DIER_CC2IE; - break; - case 2: - timer->CCR3 = value; - timer->SR &= ~TIM_SR_CC3IF; - timer->DIER |= TIM_DIER_CC3IE; - break; - case 3: - timer->CCR4 = value; - timer->SR &= ~TIM_SR_CC4IF; - timer->DIER |= TIM_DIER_CC4IE; - break; - default: - return -1; - } - - return 0; -} - -int timer_clear(tim_t dev, int channel) -{ - TIM_TypeDef *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - switch (channel) { - case 0: - timer->DIER &= ~TIM_DIER_CC1IE; - break; - case 1: - timer->DIER &= ~TIM_DIER_CC2IE; - break; - case 2: - timer->DIER &= ~TIM_DIER_CC3IE; - break; - case 3: - timer->DIER &= ~TIM_DIER_CC4IE; - break; - default: - return -1; - } - - return 0; -} - -unsigned int timer_read(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - return TIMER_0_DEV->CNT; - break; -#endif - case TIMER_UNDEFINED: - default: - return 0; - } -} - -void timer_start(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->CR1 |= TIM_CR1_CEN; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_stop(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->CR1 &= ~TIM_CR1_CEN; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_irq_enable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_EnableIRQ(TIMER_0_IRQ_CHAN); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_irq_disable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_DisableIRQ(TIMER_0_IRQ_CHAN); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -#if TIMER_0_EN -void TIMER_0_ISR(void) -{ - irq_handler(TIMER_0, TIMER_0_DEV); -} -#endif - -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev) -{ - if (dev->SR & TIM_SR_CC1IF) { - dev->DIER &= ~TIM_DIER_CC1IE; - dev->SR &= ~TIM_SR_CC1IF; - config[timer].cb(config[timer].arg, 0); - } - else if (dev->SR & TIM_SR_CC2IF) { - dev->DIER &= ~TIM_DIER_CC2IE; - dev->SR &= ~TIM_SR_CC2IF; - config[timer].cb(config[timer].arg, 1); - } - else if (dev->SR & TIM_SR_CC3IF) { - dev->DIER &= ~TIM_DIER_CC3IE; - dev->SR &= ~TIM_SR_CC3IF; - config[timer].cb(config[timer].arg, 2); - } - else if (dev->SR & TIM_SR_CC4IF) { - dev->DIER &= ~TIM_DIER_CC4IE; - dev->SR &= ~TIM_SR_CC4IF; - config[timer].cb(config[timer].arg, 3); - } - if (sched_context_switch_request) { - thread_yield(); - } -} diff --git a/cpu/stm32f4/periph/timer.c b/cpu/stm32f4/periph/timer.c deleted file mode 100644 index 6b2db5892d..0000000000 --- a/cpu/stm32f4/periph/timer.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. - */ - -/** - * @ingroup cpu_stm32f4 - * @{ - * - * @file - * @brief Low-level timer driver implementation - * - * @author Hauke Petersen - * - * @} - */ - -#include - -#include "cpu.h" -#include "board.h" -#include "sched.h" -#include "thread.h" -#include "periph_conf.h" -#include "periph/timer.h" - -/** Unified IRQ handler for all timers */ -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev); - -/** Timer state memory */ -static timer_isr_ctx_t config[TIMER_NUMOF]; - - -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - TIM_TypeDef *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - /* enable timer peripheral clock */ - TIMER_0_CLKEN(); - /* set timer's IRQ priority */ - NVIC_SetPriority(TIMER_0_IRQ_CHAN, TIMER_IRQ_PRIO); - /* select timer */ - timer = TIMER_0_DEV; - timer->PSC = (TIMER_0_FREQ / freq) - 1; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - /* enable timer peripheral clock */ - TIMER_1_CLKEN(); - /* set timer's IRQ priority */ - NVIC_SetPriority(TIMER_1_IRQ_CHAN, TIMER_IRQ_PRIO); - /* select timer */ - timer = TIMER_1_DEV; - timer->PSC = (TIMER_1_FREQ / freq) - 1; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - /* set callback function */ - config[dev].cb = cb; - config[dev].arg = arg; - - /* set timer to run in counter mode */ - timer->CR1 = 0; - timer->CR2 = 0; - - /* set auto-reload and prescaler values and load new values */ - timer->EGR |= TIM_EGR_UG; - - /* enable the timer's interrupt */ - timer_irq_enable(dev); - - /* start the timer */ - timer_start(dev); - - return 0; -} - -int timer_set(tim_t dev, int channel, unsigned int timeout) -{ - int now = timer_read(dev); - return timer_set_absolute(dev, channel, now + timeout - 1); -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - TIM_TypeDef *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - timer = TIMER_1_DEV; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - switch (channel) { - case 0: - timer->CCR1 = value; - timer->SR &= ~TIM_SR_CC1IF; - timer->DIER |= TIM_DIER_CC1IE; - break; - case 1: - timer->CCR2 = value; - timer->SR &= ~TIM_SR_CC2IF; - timer->DIER |= TIM_DIER_CC2IE; - break; - case 2: - timer->CCR3 = value; - timer->SR &= ~TIM_SR_CC3IF; - timer->DIER |= TIM_DIER_CC3IE; - break; - case 3: - timer->CCR4 = value; - timer->SR &= ~TIM_SR_CC4IF; - timer->DIER |= TIM_DIER_CC4IE; - break; - default: - return -1; - } - - return 0; -} - -int timer_clear(tim_t dev, int channel) -{ - TIM_TypeDef *timer; - - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - timer = TIMER_0_DEV; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - timer = TIMER_1_DEV; - break; -#endif - case TIMER_UNDEFINED: - default: - return -1; - } - - switch (channel) { - case 0: - timer->DIER &= ~TIM_DIER_CC1IE; - break; - case 1: - timer->DIER &= ~TIM_DIER_CC2IE; - break; - case 2: - timer->DIER &= ~TIM_DIER_CC3IE; - break; - case 3: - timer->DIER &= ~TIM_DIER_CC4IE; - break; - default: - return -1; - } - - return 0; -} - -unsigned int timer_read(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - return TIMER_0_DEV->CNT; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - return TIMER_1_DEV->CNT; - break; -#endif - case TIMER_UNDEFINED: - default: - return 0; - } -} - -void timer_start(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->CR1 |= TIM_CR1_CEN; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->CR1 |= TIM_CR1_CEN; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_stop(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - TIMER_0_DEV->CR1 &= ~TIM_CR1_CEN; - break; -#endif -#if TIMER_1_EN - case TIMER_1: - TIMER_1_DEV->CR1 &= ~TIM_CR1_CEN; - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_irq_enable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_EnableIRQ(TIMER_0_IRQ_CHAN); - break; -#endif -#if TIMER_1_EN - case TIMER_1: - NVIC_EnableIRQ(TIMER_1_IRQ_CHAN); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void timer_irq_disable(tim_t dev) -{ - switch (dev) { -#if TIMER_0_EN - case TIMER_0: - NVIC_DisableIRQ(TIMER_0_IRQ_CHAN); - break; -#endif -#if TIMER_1_EN - case TIMER_1: - NVIC_DisableIRQ(TIMER_1_IRQ_CHAN); - break; -#endif - case TIMER_UNDEFINED: - break; - } -} - -void TIMER_0_ISR(void) -{ - irq_handler(TIMER_0, TIMER_0_DEV); -} - -void TIMER_1_ISR(void) -{ - irq_handler(TIMER_1, TIMER_1_DEV); -} - -static inline void irq_handler(tim_t timer, TIM_TypeDef *dev) -{ - if (dev->SR & TIM_SR_CC1IF) { - dev->DIER &= ~TIM_DIER_CC1IE; - dev->SR &= ~TIM_SR_CC1IF; - config[timer].cb(config[timer].arg, 0); - } - else if (dev->SR & TIM_SR_CC2IF) { - dev->DIER &= ~TIM_DIER_CC2IE; - dev->SR &= ~TIM_SR_CC2IF; - config[timer].cb(config[timer].arg, 1); - } - else if (dev->SR & TIM_SR_CC3IF) { - dev->DIER &= ~TIM_DIER_CC3IE; - dev->SR &= ~TIM_SR_CC3IF; - config[timer].cb(config[timer].arg, 2); - } - else if (dev->SR & TIM_SR_CC4IF) { - dev->DIER &= ~TIM_DIER_CC4IE; - dev->SR &= ~TIM_SR_CC4IF; - config[timer].cb(config[timer].arg, 3); - } - if (sched_context_switch_request) { - thread_yield(); - } -} diff --git a/cpu/stm32l1/include/periph_cpu.h b/cpu/stm32l1/include/periph_cpu.h index 00856683ca..a8be489f2a 100644 --- a/cpu/stm32l1/include/periph_cpu.h +++ b/cpu/stm32l1/include/periph_cpu.h @@ -107,15 +107,6 @@ typedef struct { */ void gpio_init_af(gpio_t pin, gpio_af_t af); -/** - * @brief Timer configuration data structure - */ -typedef struct { - TIM_TypeDef *dev; /**< timer device */ - uint8_t rcc; /**< bit in the RCC register */ - uint8_t irqn; /**< IRQ vector entry number */ -} timer_conf_t; - /** * @brief I2C configuration data structure */ diff --git a/cpu/stm32l1/periph/timer.c b/cpu/stm32l1/periph/timer.c deleted file mode 100644 index 03c074b9b8..0000000000 --- a/cpu/stm32l1/periph/timer.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2014-2015 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. - */ - -/** - * @addtogroup driver_periph - * @{ - * - * @file - * @brief Low-level timer driver implementation - * - * @author Thomas Eichinger - * @author Hauke Petersen - * - * @} - */ - -#include "cpu.h" -#include "sched.h" -#include "thread.h" -#include "periph_conf.h" -#include "periph/timer.h" - -/** - * @brief All timers on this CPU have 4 channels - */ -#define CHANNEL_NUMOF (4U) - -/** - * @brief Interrupt state - */ -static timer_isr_ctx_t isr_ctx[TIMER_NUMOF]; - -/** - * @brief Get the timers base register - */ -static inline TIM_TypeDef *_tim(tim_t dev) -{ - return timer_config[dev].dev; -} - -int timer_init(tim_t dev, unsigned long freq, timer_cb_t cb, void *arg) -{ - TIM_TypeDef *tim; - - /* check if given timer exists */ - if (dev >= TIMER_NUMOF) { - return -1; - } - - /* get base register */ - tim = _tim(dev); - /* save callback */ - isr_ctx[dev].cb = cb; - isr_ctx[dev].arg = arg; - /* enable peripheral clock */ - RCC->APB1ENR |= (1 << timer_config[dev].rcc); - /* reset timer and configure to up-counting mode */ - tim->CR1 = 0; - tim->CR2 = 0; - tim->SR = 0; - /* configure reload and pre-scaler values */ - tim->ARR = 0xffffffff; - tim->PSC = (CLOCK_CORECLOCK / freq) - 1; - /* trigger update event to make pre-scaler value effective */ - tim->EGR = TIM_EGR_UG; - /* enable interrupts and start the timer */ - timer_irq_enable(dev); - timer_start(dev); - return 0; -} - -int timer_set(tim_t dev, int channel, unsigned int timeout) -{ - int now = timer_read(dev); - return timer_set_absolute(dev, channel, now + timeout - 1); -} - -int timer_set_absolute(tim_t dev, int channel, unsigned int value) -{ - TIM_TypeDef *tim; - - if (dev >= TIMER_NUMOF || channel >= CHANNEL_NUMOF || channel < 0) { - return -1; - } - - tim = _tim(dev); - tim->CCR[channel] = value; - tim->SR &= ~(1 << (channel + 1)); - tim->DIER |= (1 << (channel + 1)); - return 0; -} - -int timer_clear(tim_t dev, int channel) -{ - TIM_TypeDef *tim; - - if (dev >= TIMER_NUMOF || channel >= CHANNEL_NUMOF || channel < 0) { - return -1; - } - - tim = _tim(dev); - tim->DIER &= ~(1 << (channel + 1)); - return 0; -} - -unsigned int timer_read(tim_t dev) -{ - return (unsigned int)_tim(dev)->CNT; -} - -void timer_start(tim_t dev) -{ - _tim(dev)->CR1 |= TIM_CR1_CEN; -} - -void timer_stop(tim_t dev) -{ - _tim(dev)->CR1 &= ~(TIM_CR1_CEN); -} - -void timer_irq_enable(tim_t dev) -{ - NVIC_EnableIRQ(timer_config[dev].irqn); -} - -void timer_irq_disable(tim_t dev) -{ - NVIC_DisableIRQ(timer_config[dev].irqn); -} - -static inline void irq_handler(tim_t num, TIM_TypeDef *tim) -{ - for (int i = 0; i < CHANNEL_NUMOF; i++) { - uint16_t bit = (1 << (i + 1)); - if ((tim->SR & bit) && (tim->DIER & bit)) { - tim->SR &= ~(bit); - tim->DIER &= ~(bit); - isr_ctx[num].cb(isr_ctx[num].arg, i); - } - } - if (sched_context_switch_request) { - thread_yield(); - } -} - -#ifdef TIMER_0_ISR -void TIMER_0_ISR(void) -{ - irq_handler(0, timer_config[0].dev); -} -#endif - -#ifdef TIMER_1_ISR -void TIMER_1_ISR(void) -{ - irq_handler(0, timer_config[0].dev); -} -#endif