diff --git a/cpu/lpc23xx/include/periph_cpu.h b/cpu/lpc23xx/include/periph_cpu.h index b70270ca73..d29ba35c31 100644 --- a/cpu/lpc23xx/include/periph_cpu.h +++ b/cpu/lpc23xx/include/periph_cpu.h @@ -128,6 +128,11 @@ typedef struct { */ #define TIMER_CHANNEL_NUMOF (4U) +/** + * @brief Prevent shared timer functions from being used + */ +#define PERIPH_TIMER_PROVIDES_SET + /** * @brief Declare needed generic SPI functions * @{ diff --git a/cpu/lpc23xx/periph/timer.c b/cpu/lpc23xx/periph/timer.c index f1d3e20a40..750f551e23 100644 --- a/cpu/lpc23xx/periph/timer.c +++ b/cpu/lpc23xx/periph/timer.c @@ -21,6 +21,7 @@ #include #include +#include "irq.h" #include "periph_conf.h" #include "periph_cpu.h" #include "periph/timer.h" @@ -167,6 +168,37 @@ int timer_set_absolute(tim_t tim, int channel, unsigned int value) dev->MR[channel] = value; /* Match Interrupt */ dev->MCR |= (1 << (channel * 3)); + + return 0; +} + +int timer_set(tim_t tim, int channel, unsigned int timeout) +{ + if (((unsigned) tim >= TIMER_NUMOF) || ((unsigned) channel >= TIMER_CHANNEL_NUMOF)) { + return -1; + } + + /* Interrupt will only be generated on increment, + so a 0 timeout is not possible */ + if (timeout == 0) { + timeout = 1; + } + + lpc23xx_timer_t *dev = get_dev(tim); + + unsigned state = irq_disable(); + dev->TCR = 0; + + unsigned absolute = timeout + dev->TC; + unsigned mask = 1 << (channel * 3); + + dev->MR[channel] = absolute; + dev->MCR |= mask; + set_oneshot(tim, channel); + + dev->TCR = 1; + irq_restore(state); + return 0; } @@ -226,13 +258,6 @@ void timer_stop(tim_t tim) static inline void chan_handler(lpc23xx_timer_t *dev, unsigned tim_num, unsigned chan_num) { - const uint32_t mask = (1 << chan_num); - - if ((dev->IR & mask) == 0) { - return; - } - - dev->IR |= mask; if (is_oneshot(tim_num, chan_num)) { dev->MCR &= ~(1 << (chan_num * 3)); } @@ -242,8 +267,15 @@ static inline void chan_handler(lpc23xx_timer_t *dev, unsigned tim_num, unsigned static inline void isr_handler(lpc23xx_timer_t *dev, int tim_num) { - for (unsigned i = 0; i < TIMER_CHANNEL_NUMOF; ++i) { - chan_handler(dev, tim_num, i); + uint32_t state = dev->IR; + uint8_t chan = 0; + + /* clear interrupt flags */ + dev->IR = state; + + while (state) { + state = bitarithm_test_and_clear(state, &chan); + chan_handler(dev, tim_num, chan); } /* we must not forget to acknowledge the handling of the interrupt */