Skip to content

Commit

Permalink
tests: Integrate zero timeout test into timer test
Browse files Browse the repository at this point in the history
  • Loading branch information
Teufelchen1 committed May 7, 2024
1 parent 77b8db1 commit 8f00189
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 186 deletions.
93 changes: 89 additions & 4 deletions tests/periph/timer/main.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
* 2018 Eistec AB
* 2024 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand All @@ -14,6 +16,8 @@
* @brief Peripheral timer test application
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* Joakim Nohlgård <joakim.nohlgard@eistec.se>
* Bennet Blischke <bennet.blischke@haw-hamburg.de>
*
* @}
*/
Expand All @@ -25,6 +29,7 @@
#include "atomic_utils.h"
#include "architecture.h"
#include "clk.h"
#include "mutex.h"
#include "periph/timer.h"
#include "test_utils/expect.h"
#include "time_units.h"
Expand All @@ -51,11 +56,36 @@
* e.g. when the timer was about to tick anyway */
#define MINIMUM_TICKS 2

#ifndef TEST_ITERATIONS
#define TEST_ITERATIONS (10000ul)
#endif

static uint8_t fired;
static uint32_t sw_count;
static uint32_t timeouts[TIMER_CHANNEL_NUMOF];
static unsigned args[TIMER_CHANNEL_NUMOF];

typedef struct {
unsigned long counter;
tim_t dev;
mutex_t mtx;
} test_ctx_t;

static void cb_incr(void *arg, int chan)
{
(void)chan;
test_ctx_t *ctx = arg;

ctx->counter++;
if (ctx->counter < TEST_ITERATIONS) {
/* Rescheduling the timer like this will trigger a bug in the lptmr
* implementation in Kinetis */
timer_set(ctx->dev, chan, 20000u);
timer_set(ctx->dev, chan, 0);
}
mutex_unlock(&ctx->mtx);
}

static void cb(void *arg, int chan)
{
timeouts[chan] = sw_count;
Expand Down Expand Up @@ -84,6 +114,7 @@ static unsigned milliseconds_to_ticks(uint32_t timer_freq, unsigned millisecs)
{
/* Use 64 bit arithmetic to avoid overflows for high frequencies. */
unsigned result = ((uint64_t)millisecs * US_PER_MS * timer_freq) / US_PER_SEC;

/* Never return less than MINIMUM_TICKS ticks */
return (result >= MINIMUM_TICKS) ? result : MINIMUM_TICKS;
}
Expand All @@ -102,7 +133,7 @@ static int test_timer(unsigned num, uint32_t timer_freq)
}

printf(" - Calling timer_init(%u, %" PRIu32 ")\n ",
num, timer_freq);
num, timer_freq);
/* initialize and halt timer */
if (timer_init(TIMER_DEV(num), timer_freq, cb, (void *)(COOKIE * num)) != 0) {
printf("ERROR: timer_init() failed\n\n");
Expand Down Expand Up @@ -177,6 +208,7 @@ static int test_timer(unsigned num, uint32_t timer_freq)

const unsigned duration = milliseconds_to_ticks(timer_freq, MINIMUM_TIMEOUT_MS);
unsigned target = timer_read(TIMER_DEV(num)) + duration;

expect(0 == timer_set_absolute(TIMER_DEV(num), 0, target));
expect(0 == timer_clear(TIMER_DEV(num), 0));
atomic_store_u8(&fired, 0);
Expand Down Expand Up @@ -207,6 +239,53 @@ static int test_timer(unsigned num, uint32_t timer_freq)
return 1;
}


Check warning on line 242 in tests/periph/timer/main.c

View workflow job for this annotation

GitHub Actions / static-tests

too many consecutive empty lines
/* This test is designed to catch an implementation bug where a timer callback is
* called directly from inside timer_set if the given timeout=0, leading to a
* stack overflow if timer_set is called from within the callback of the same
* timer.
*
* The test will attempt to initialize each timer in the system and set a non-zero
* timeout at first. The callback function provided will then attempt to set a new
* timeout=0 until we have called the callback TEST_ITERATIONS times (default 10000).
* The expected behavior is that the timer will trigger again as soon as the timer
* callback function returns. If the timer driver implementation is broken, then
* the callback will be called again by timer_set, causing a stack overflow after a
* number of iterations. */
static int test_timer_timeout(unsigned num, uint32_t timer_freq)
{
/* initialize and halt timer */
unsigned long switches = 0;
test_ctx_t ctx = {
.counter = 0,
.dev = TIMER_DEV(num),
.mtx = MUTEX_INIT_LOCKED
};

printf(" - Testing timeout=0 in callback:\n");

if (timer_init(ctx.dev, timer_freq, cb_incr, &ctx) < 0) {
printf(" TIMER_DEV(%u) init failed.\n", num);
return 0;
}
/* Send the initial trigger for the timer */
timer_set(ctx.dev, 0, 100);
/* Wait until we have executed the zero timeout callback enough times */
while (ctx.counter < TEST_ITERATIONS) {
mutex_lock(&ctx.mtx);
++switches;
}

/* verify results */
if (ctx.counter != TEST_ITERATIONS) {
printf(" TIMER_DEV(%u) counter mismatch, expected: %lu, actual: %lu\n",
num, TEST_ITERATIONS, ctx.counter);
return 0;
}
printf(" OK (timer timeout successful)\n");
return 1;
}

static uword_t query_freq_numof(tim_t dev)
{
if (IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) {
Expand Down Expand Up @@ -239,7 +318,8 @@ static void print_supported_frequencies(tim_t dev)
}

uword_t end = query_freq_numof(dev);
printf(" - supported frequencies:\n");

printf(" - supported frequencies:\n");
for (uword_t i = 0; i < MIN(end, 3); i++) {
printf(" %u: %" PRIu32 "\n", (unsigned)i, timer_query_freqs(dev, i));
}
Expand All @@ -258,10 +338,11 @@ int main(void)
printf("Available timers: %i\n", TIMER_NUMOF);

int failed = 0;

/* test all configured timers */
for (unsigned i = 0; i < TIMER_NUMOF; i++) {
printf("\nTIMER %u\n"
"=======\n\n", i);
"=======\n\n", i);
print_supported_frequencies(TIMER_DEV(i));
uword_t end = query_freq_numof(TIMER_DEV(i));

Expand All @@ -271,7 +352,11 @@ int main(void)
* complete */
end = MIN(end, 3);
for (uword_t j = 0; j < end; j++) {
if (!test_timer(i, query_freq(TIMER_DEV(i), j))) {
uint32_t freq = query_freq(TIMER_DEV(i), j);
if (!test_timer(i, freq)) {
failed = 1;
}
if (!test_timer_timeout(i, freq)) {
failed = 1;
}
}
Expand Down
5 changes: 0 additions & 5 deletions tests/periph/timer_timeout/Makefile

This file was deleted.

22 changes: 0 additions & 22 deletions tests/periph/timer_timeout/README.md

This file was deleted.

132 changes: 0 additions & 132 deletions tests/periph/timer_timeout/main.c

This file was deleted.

23 changes: 0 additions & 23 deletions tests/periph/timer_timeout/tests/01-run.py

This file was deleted.

0 comments on commit 8f00189

Please sign in to comment.