Skip to content

Commit be13a8c

Browse files
committed
tests: Integrate zero timeout test into timer test
1 parent f76a2f3 commit be13a8c

5 files changed

Lines changed: 82 additions & 183 deletions

File tree

tests/periph/timer/main.c

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/*
22
* Copyright (C) 2015 Freie Universität Berlin
3+
* 2018 Eistec AB
4+
* 2024 HAW Hamburg
35
*
46
* This file is subject to the terms and conditions of the GNU Lesser
57
* General Public License v2.1. See the file LICENSE in the top level
@@ -14,6 +16,8 @@
1416
* @brief Peripheral timer test application
1517
*
1618
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
19+
* Joakim Nohlgård <joakim.nohlgard@eistec.se>
20+
* Bennet Blischke <bennet.blischke@haw-hamburg.de>
1721
*
1822
* @}
1923
*/
@@ -25,6 +29,7 @@
2529
#include "atomic_utils.h"
2630
#include "architecture.h"
2731
#include "clk.h"
32+
#include "mutex.h"
2833
#include "periph/timer.h"
2934
#include "test_utils/expect.h"
3035
#include "time_units.h"
@@ -51,11 +56,36 @@
5156
* e.g. when the timer was about to tick anyway */
5257
#define MINIMUM_TICKS 2
5358

59+
#ifndef TEST_ITERATIONS
60+
#define TEST_ITERATIONS (10000ul)
61+
#endif
62+
5463
static uint8_t fired;
5564
static uint32_t sw_count;
5665
static uint32_t timeouts[TIMER_CHANNEL_NUMOF];
5766
static unsigned args[TIMER_CHANNEL_NUMOF];
5867

68+
typedef struct {
69+
unsigned long counter;
70+
tim_t dev;
71+
mutex_t mtx;
72+
} test_ctx_t;
73+
74+
static void cb_incr(void *arg, int chan)
75+
{
76+
(void)chan;
77+
test_ctx_t *ctx = arg;
78+
79+
ctx->counter++;
80+
if (ctx->counter < TEST_ITERATIONS) {
81+
/* Rescheduling the timer like this will trigger a bug in the lptmr
82+
* implementation in Kinetis */
83+
timer_set(ctx->dev, chan, 20000u);
84+
timer_set(ctx->dev, chan, 0);
85+
}
86+
mutex_unlock(&ctx->mtx);
87+
}
88+
5989
static void cb(void *arg, int chan)
6090
{
6191
timeouts[chan] = sw_count;
@@ -207,6 +237,53 @@ static int test_timer(unsigned num, uint32_t timer_freq)
207237
return 1;
208238
}
209239

240+
241+
/* This test is designed to catch an implementation bug where a timer callback is
242+
* called directly from inside timer_set if the given timeout=0, leading to a
243+
* stack overflow if timer_set is called from within the callback of the same
244+
* timer.
245+
*
246+
* The test will attempt to initialize each timer in the system and set a non-zero
247+
* timeout at first. The callback function provided will then attempt to set a new
248+
* timeout=0 until we have called the callback TEST_ITERATIONS times (default 10000).
249+
* The expected behavior is that the timer will trigger again as soon as the timer
250+
* callback function returns. If the timer driver implementation is broken, then
251+
* the callback will be called again by timer_set, causing a stack overflow after a
252+
* number of iterations. */
253+
static int test_timer_timeout(unsigned num, uint32_t timer_freq)
254+
{
255+
/* initialize and halt timer */
256+
unsigned long switches = 0;
257+
test_ctx_t ctx = {
258+
.counter = 0,
259+
.dev = TIMER_DEV(num),
260+
.mtx = MUTEX_INIT_LOCKED
261+
};
262+
263+
printf(" - Testing timeout=0 in callback:\n");
264+
265+
if (timer_init(ctx.dev, timer_freq, cb_incr, &ctx) < 0) {
266+
printf(" TIMER_DEV(%u) init failed.\n", num);
267+
return 0;
268+
}
269+
/* Send the initial trigger for the timer */
270+
timer_set(ctx.dev, 0, 100);
271+
/* Wait until we have executed the zero timeout callback enough times */
272+
while (ctx.counter < TEST_ITERATIONS) {
273+
mutex_lock(&ctx.mtx);
274+
++switches;
275+
}
276+
277+
/* verify results */
278+
if (ctx.counter != TEST_ITERATIONS) {
279+
printf(" TIMER_DEV(%u) counter mismatch, expected: %lu, actual: %lu\n",
280+
num, TEST_ITERATIONS, ctx.counter);
281+
return 0;
282+
}
283+
printf(" OK (timer timeout successfull)\n");
284+
return 1;
285+
}
286+
210287
static uword_t query_freq_numof(tim_t dev)
211288
{
212289
if (IS_USED(MODULE_PERIPH_TIMER_QUERY_FREQS)) {
@@ -271,7 +348,11 @@ int main(void)
271348
* complete */
272349
end = MIN(end, 3);
273350
for (uword_t j = 0; j < end; j++) {
274-
if (!test_timer(i, query_freq(TIMER_DEV(i), j))) {
351+
uint32_t freq = query_freq(TIMER_DEV(i), j);
352+
if (!test_timer(i, freq)) {
353+
failed = 1;
354+
}
355+
if (!test_timer_timeout(i, freq)) {
275356
failed = 1;
276357
}
277358
}

tests/periph/timer_timeout/Makefile

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/periph/timer_timeout/README.md

Lines changed: 0 additions & 22 deletions
This file was deleted.

tests/periph/timer_timeout/main.c

Lines changed: 0 additions & 132 deletions
This file was deleted.

tests/periph/timer_timeout/tests/01-run.py

Lines changed: 0 additions & 23 deletions
This file was deleted.

0 commit comments

Comments
 (0)