Skip to content

Commit

Permalink
Merge #19087
Browse files Browse the repository at this point in the history
19087: cpu/qn908x/periph_timer: Implement timer_set() r=kaspar030 a=maribu

### Contribution description

This fixes test failures in tests/periph_timer_short_relative_set.

Note: This differs a bit from the implementation in e.g. nRF5x or STM32 in that it always briefly pauses the timer. The issue is that when running the timer can take a few ticks to actually react to the new compare target. So even if the previously written target is still in the future, the timer may not fire anyway. Pausing the timer while setting and setting the target at least one higher than the current count reliably triggers the IRQ.

### Testing procedure

Run `tests/periph_timer_short_relative_set` at least a few dozen times (or use #19030 to have a few dozen repetitions of the test case in a single run of the test application). It should now succeed.

### Issues/PRs references

None

Co-authored-by: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
  • Loading branch information
bors[bot] and maribu authored Jan 4, 2023
2 parents 21af247 + 94f9a56 commit 9f396d1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cpu/qn908x/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ typedef uint16_t adc_conf_t;
*/
#define TIMER_CHANNELS (4)
#define TIMER_MAX_VALUE (0xffffffff)
/**
* @brief The nRF5x periph_timer implements timer_set()
*/
#define PERIPH_TIMER_PROVIDES_SET 1
/** @} */

/**
Expand Down
25 changes: 25 additions & 0 deletions cpu/qn908x/periph/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,31 @@ int timer_set_absolute(tim_t tim, int channel, unsigned int value)
return 0;
}

int timer_set(tim_t tim, int channel, unsigned int value)
{
DEBUG("timer_set(%u, %u, %u)\n", tim, channel, value);
if ((tim >= TIMER_NUMOF) || (channel >= TIMER_CHANNELS)) {
return -1;
}
CTIMER_Type* const dev = ctimers[tim];

/* no IRQ will be generated on value == 0, so bump it here */
value = (value != 0) ? value : 1;

unsigned irq_state = irq_disable();

/* briefly pause timer */
ctimers[tim]->TCR &= ~CTIMER_TCR_CEN_MASK;
/* set absolute timeout based on given value and enable IRQ */
dev->MR[channel] = dev->TC + value;
dev->MCR |= (CTIMER_MCR_MR0I_MASK << (channel * 3));
/* and resume timer */
ctimers[tim]->TCR |= CTIMER_TCR_CEN_MASK;
irq_restore(irq_state);

return 0;
}

int timer_clear(tim_t tim, int channel)
{
DEBUG("timer_clear(%u, %d)\n", tim, channel);
Expand Down

0 comments on commit 9f396d1

Please sign in to comment.