mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #17723 from benpicco/periph_timer_periodic-set_stopped
drivers/periph/timer: add TIM_FLAG_SET_STOPPED flag
This commit is contained in:
commit
bae91c1660
@ -224,7 +224,12 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
/* disable CTC mode */
|
||||
ctx[tim].mode &= (1 << 3);
|
||||
}
|
||||
ctx[tim].dev->CRB = ctx[tim].mode;
|
||||
/* enable timer or stop it */
|
||||
if (flags & TIM_FLAG_SET_STOPPED) {
|
||||
ctx[tim].dev->CRB = 0;
|
||||
} else {
|
||||
ctx[tim].dev->CRB = ctx[tim].mode;
|
||||
}
|
||||
} else {
|
||||
assert((flags & TIM_FLAG_RESET_ON_MATCH) == 0);
|
||||
res = -1;
|
||||
|
@ -164,6 +164,10 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & TIM_FLAG_SET_STOPPED) {
|
||||
timer_stop(tim);
|
||||
}
|
||||
|
||||
clear_oneshot(tim, channel);
|
||||
|
||||
if (flags & TIM_FLAG_RESET_ON_SET) {
|
||||
|
@ -208,6 +208,7 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool stop = flags & TIM_FLAG_SET_STOPPED;
|
||||
lpc23xx_timer_t *dev = get_dev(tim);
|
||||
|
||||
if (flags & TIM_FLAG_RESET_ON_SET) {
|
||||
@ -218,7 +219,12 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
* (reason: TCR is volatile control register.
|
||||
Bit 2 will put the timer into Reset
|
||||
Bit 1 will control if the timer is running) */
|
||||
dev->TCR = 1;
|
||||
if (!stop) {
|
||||
dev->TCR = 1;
|
||||
}
|
||||
} else if (stop) {
|
||||
/* stop the timer */
|
||||
dev->TCR = 0;
|
||||
}
|
||||
|
||||
clear_oneshot(tim, channel);
|
||||
|
@ -105,7 +105,7 @@ int timer_init(tim_t dev, uint32_t freq, timer_cb_t cb, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void do_timer_set(tim_t dev, unsigned int offset, bool periodic)
|
||||
static void do_timer_set(unsigned int offset, bool periodic)
|
||||
{
|
||||
DEBUG("%s\n", __func__);
|
||||
|
||||
@ -121,8 +121,6 @@ static void do_timer_set(tim_t dev, unsigned int offset, bool periodic)
|
||||
}
|
||||
|
||||
DEBUG("timer_set(): setting %lu.%06lu\n", itv.it_value.tv_sec, itv.it_value.tv_usec);
|
||||
|
||||
timer_start(dev);
|
||||
}
|
||||
|
||||
int timer_set(tim_t dev, int channel, unsigned int offset)
|
||||
@ -137,7 +135,8 @@ int timer_set(tim_t dev, int channel, unsigned int offset)
|
||||
offset = NATIVE_TIMER_MIN_RES;
|
||||
}
|
||||
|
||||
do_timer_set(dev, offset, false);
|
||||
do_timer_set(offset, false);
|
||||
timer_start(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -156,7 +155,11 @@ int timer_set_periodic(tim_t dev, int channel, unsigned int value, uint8_t flags
|
||||
return -1;
|
||||
}
|
||||
|
||||
do_timer_set(dev, value, true);
|
||||
do_timer_set(value, true);
|
||||
|
||||
if (!(flags & TIM_FLAG_SET_STOPPED)) {
|
||||
timer_start(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -165,7 +168,8 @@ int timer_clear(tim_t dev, int channel)
|
||||
{
|
||||
(void)channel;
|
||||
|
||||
do_timer_set(dev, 0, false);
|
||||
do_timer_set(0, false);
|
||||
timer_start(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -114,6 +114,9 @@ int timer_set_periodic(tim_t tim, int chan, unsigned int value, uint8_t flags)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* stop timer to avoid race condition */
|
||||
dev(tim)->TASKS_STOP = 1;
|
||||
|
||||
ctx[tim].flags |= (1 << chan);
|
||||
ctx[tim].is_periodic |= (1 << chan);
|
||||
dev(tim)->CC[chan] = value;
|
||||
@ -125,7 +128,10 @@ int timer_set_periodic(tim_t tim, int chan, unsigned int value, uint8_t flags)
|
||||
}
|
||||
dev(tim)->INTENSET = (TIMER_INTENSET_COMPARE0_Msk << chan);
|
||||
|
||||
dev(tim)->TASKS_START = 1;
|
||||
/* re-start timer */
|
||||
if (!(flags & TIM_FLAG_SET_STOPPED)) {
|
||||
dev(tim)->TASKS_START = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -183,6 +183,9 @@ int timer_set_periodic(tim_t dev, int channel, unsigned int value, uint8_t flags
|
||||
if (channel < 0 || channel >= timer_config[dev].ch_numof) {
|
||||
return -EINVAL;
|
||||
}
|
||||
if (flags & TIM_FLAG_SET_STOPPED) {
|
||||
timer_stop(dev);
|
||||
}
|
||||
if (flags & TIM_FLAG_RESET_ON_SET) {
|
||||
_timer_reset(dev);
|
||||
}
|
||||
|
@ -110,27 +110,21 @@ static uint8_t _get_prescaler(uint32_t freq_out, uint32_t freq_in)
|
||||
/* TOP value is CC0 */
|
||||
static inline void _set_mfrq(tim_t tim)
|
||||
{
|
||||
timer_stop(tim);
|
||||
wait_synchronization(tim);
|
||||
#ifdef TC_WAVE_WAVEGEN_MFRQ
|
||||
dev(tim)->WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;
|
||||
#else
|
||||
dev(tim)->CTRLA.bit.WAVEGEN = TC_CTRLA_WAVEGEN_MFRQ_Val;
|
||||
#endif
|
||||
timer_start(tim);
|
||||
}
|
||||
|
||||
/* TOP value is MAX timer value */
|
||||
static inline void _set_nfrq(tim_t tim)
|
||||
{
|
||||
timer_stop(tim);
|
||||
wait_synchronization(tim);
|
||||
#ifdef TC_WAVE_WAVEGEN_NFRQ
|
||||
dev(tim)->WAVE.reg = TC_WAVE_WAVEGEN_NFRQ;
|
||||
#else
|
||||
dev(tim)->CTRLA.bit.WAVEGEN = TC_CTRLA_WAVEGEN_NFRQ_Val;
|
||||
#endif
|
||||
timer_start(tim);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,9 +236,12 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
{
|
||||
DEBUG("Setting timer %i channel %i to %i (repeating)\n", tim, channel, value);
|
||||
|
||||
timer_stop(tim);
|
||||
|
||||
/* set timeout value */
|
||||
switch (channel) {
|
||||
case 0:
|
||||
/* clear interrupt */
|
||||
dev(tim)->INTFLAG.reg = TC_INTFLAG_MC0;
|
||||
|
||||
if (flags & TIM_FLAG_RESET_ON_MATCH) {
|
||||
@ -276,6 +273,10 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
dev(tim)->COUNT.reg = 0;
|
||||
}
|
||||
|
||||
if (!(flags & TIM_FLAG_SET_STOPPED)) {
|
||||
timer_start(tim);
|
||||
}
|
||||
|
||||
clear_oneshot(tim, channel);
|
||||
|
||||
return 0;
|
||||
@ -328,10 +329,12 @@ unsigned int timer_read(tim_t tim)
|
||||
void timer_stop(tim_t tim)
|
||||
{
|
||||
dev(tim)->CTRLA.bit.ENABLE = 0;
|
||||
wait_synchronization(tim);
|
||||
}
|
||||
|
||||
void timer_start(tim_t tim)
|
||||
{
|
||||
wait_synchronization(tim);
|
||||
dev(tim)->CTRLA.bit.ENABLE = 1;
|
||||
}
|
||||
|
||||
|
@ -149,6 +149,10 @@ int timer_set_periodic(tim_t tim, int channel, unsigned int value, uint8_t flags
|
||||
|
||||
clear_oneshot(tim, channel);
|
||||
|
||||
if (flags & TIM_FLAG_SET_STOPPED) {
|
||||
timer_stop(tim);
|
||||
}
|
||||
|
||||
if (flags & TIM_FLAG_RESET_ON_SET) {
|
||||
/* setting COUNT gives us an interrupt on all channels */
|
||||
unsigned state = irq_disable();
|
||||
|
@ -177,8 +177,8 @@ static void _dose_watchdog_cb(void *arg, int chan)
|
||||
static void _watchdog_init(unsigned timeout_us)
|
||||
{
|
||||
timer_init(DOSE_TIMER_DEV, US_PER_SEC, _dose_watchdog_cb, NULL);
|
||||
timer_set_periodic(DOSE_TIMER_DEV, 0, timeout_us, TIM_FLAG_RESET_ON_MATCH);
|
||||
timer_stop(DOSE_TIMER_DEV);
|
||||
timer_set_periodic(DOSE_TIMER_DEV, 0, timeout_us,
|
||||
TIM_FLAG_RESET_ON_MATCH | TIM_FLAG_SET_STOPPED);
|
||||
}
|
||||
#else
|
||||
static inline void _watchdog_start(void) {}
|
||||
|
@ -89,6 +89,16 @@ typedef uint_fast8_t tim_t;
|
||||
#define TIM_FLAG_RESET_ON_MATCH (0x02)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Keep the timer stopped after setting alarm.
|
||||
*
|
||||
* When set, the timer will remained stopped after a timer_set_periodic() and
|
||||
* can be started manually with timer_start().
|
||||
*/
|
||||
#ifndef TIM_FLAG_SET_STOPPED
|
||||
#define TIM_FLAG_SET_STOPPED (0x04)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Signature of event callback functions triggered from interrupts
|
||||
*
|
||||
|
@ -93,6 +93,18 @@ static const char* _print_ok(int chan, bool *succeeded)
|
||||
return "ERROR";
|
||||
}
|
||||
|
||||
static void _cb_set_stopped(void *arg, int chan)
|
||||
{
|
||||
(void)chan;
|
||||
|
||||
bool *succeeded = arg;
|
||||
|
||||
*succeeded = false;
|
||||
puts("TIM_FLAG_SET_STOPPED failed");
|
||||
|
||||
timer_stop(TIMER_CYCL);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
mutex_t lock = MUTEX_INIT;
|
||||
@ -144,6 +156,12 @@ int main(void)
|
||||
}
|
||||
}
|
||||
|
||||
expect(timer_init(TIMER_CYCL, timer_hz, _cb_set_stopped, &succeeded) == 0);
|
||||
timer_set_periodic(TIMER_CYCL, 0, 25, TIM_FLAG_RESET_ON_SET | TIM_FLAG_SET_STOPPED);
|
||||
|
||||
/* busy wait */
|
||||
for (volatile uint32_t i = 0; i < CLOCK_CORECLOCK / 10; ++i) {}
|
||||
|
||||
if (succeeded) {
|
||||
puts("TEST SUCCEEDED");
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user