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.
This commit is contained in:
Benjamin Valentin 2019-12-25 18:48:38 +01:00 committed by Benjamin Valentin
parent f64511ddb5
commit 8126651009
2 changed files with 37 additions and 0 deletions

View File

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

View File

@ -21,6 +21,7 @@
#include <stdint.h>
#include <string.h>
#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;
}