From 8126651009315ed0d71aa44ba403b1a91e511fe6 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Wed, 25 Dec 2019 18:48:38 +0100 Subject: [PATCH] cpu/lpc2387: timer: implement timer_set() We can achieve greater accuracy for the relative timer_set() if we don't use the generic implementation. Use the same approach as used by atmega_common to trigger interrupts for too small offsets. tests/periph_timer_short_relative_set should now succeed for all intervals. --- cpu/lpc23xx/include/periph_cpu.h | 5 +++++ cpu/lpc23xx/periph/timer.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) 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..3cda55753b 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; }