Merge pull request #16507 from fjmolinas/pr_event_timeout_periodic
sys/event: add periodic timeout event
This commit is contained in:
commit
cfb10db9b7
@ -478,6 +478,11 @@ ifneq (,$(filter event_timeout_ztimer,$(USEMODULE)))
|
|||||||
USEMODULE += event_timeout
|
USEMODULE += event_timeout
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter event_periodic_timeout,$(USEMODULE)))
|
||||||
|
USEMODULE += event_timeout
|
||||||
|
USEMODULE += ztimer_periodic
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter event_timeout,$(USEMODULE)))
|
ifneq (,$(filter event_timeout,$(USEMODULE)))
|
||||||
ifneq (,$(filter event_timeout_ztimer,$(USEMODULE)))
|
ifneq (,$(filter event_timeout_ztimer,$(USEMODULE)))
|
||||||
USEMODULE += ztimer_usec
|
USEMODULE += ztimer_usec
|
||||||
|
|||||||
42
sys/event/periodic.c
Normal file
42
sys/event/periodic.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Inria
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sys_event
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Periodic Event Implementation
|
||||||
|
*
|
||||||
|
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#include "kernel_defines.h"
|
||||||
|
#include "ztimer.h"
|
||||||
|
#include "ztimer/periodic.h"
|
||||||
|
#include "event/periodic.h"
|
||||||
|
|
||||||
|
static int _event_periodic_callback(void *arg)
|
||||||
|
{
|
||||||
|
event_periodic_t *event_periodic = (event_periodic_t *)arg;
|
||||||
|
|
||||||
|
event_post(event_periodic->queue, event_periodic->event);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void event_periodic_init(event_periodic_t *event_periodic,
|
||||||
|
ztimer_clock_t *clock,
|
||||||
|
event_queue_t *queue, event_t *event)
|
||||||
|
{
|
||||||
|
ztimer_periodic_init(clock, &event_periodic->timer, _event_periodic_callback,
|
||||||
|
event_periodic, 0);
|
||||||
|
event_periodic->queue = queue;
|
||||||
|
event_periodic->event = event;
|
||||||
|
}
|
||||||
105
sys/include/event/periodic.h
Normal file
105
sys/include/event/periodic.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Inria
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup sys_event
|
||||||
|
* @brief Provides functionality to trigger periodic events
|
||||||
|
*
|
||||||
|
* event_periodic intentionally doesn't extend event structures in order to
|
||||||
|
* support events that are integrated in larger structs intrusively.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
||||||
|
* event_periodic_t event_periodic;
|
||||||
|
*
|
||||||
|
* printf("posting timed callback every 1sec\n");
|
||||||
|
* event_periodic_init(&event_periodic, ZTIMER_USEC, &queue, (event_t*)&event);
|
||||||
|
* event_periodic_start(&event_periodic, 1000000);
|
||||||
|
* [...]
|
||||||
|
* ~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Event Periodic API
|
||||||
|
*
|
||||||
|
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EVENT_PERIODIC_H
|
||||||
|
#define EVENT_PERIODIC_H
|
||||||
|
|
||||||
|
#include "event.h"
|
||||||
|
#include "ztimer/periodic.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Timeout Event structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
ztimer_periodic_t timer; /**< ztimer object used for timeout */
|
||||||
|
event_queue_t *queue; /**< event queue to post event to */
|
||||||
|
event_t *event; /**< event to post after timeout */
|
||||||
|
} event_periodic_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a periodic event timeout
|
||||||
|
*
|
||||||
|
* @param[in] event_periodic event_periodic object to initialize
|
||||||
|
* @param[in] clock the clock to configure this timer on
|
||||||
|
* @param[in] queue queue that the timed-out event will be
|
||||||
|
* added to
|
||||||
|
* @param[in] event event to add to queue after timeout
|
||||||
|
*/
|
||||||
|
void event_periodic_init(event_periodic_t *event_periodic, ztimer_clock_t *clock,
|
||||||
|
event_queue_t *queue, event_t *event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts a periodic timeout
|
||||||
|
*
|
||||||
|
* This will make the event as configured in @p event_periodic be triggered
|
||||||
|
* at every interval ticks (based on event_periodic->clock).
|
||||||
|
*
|
||||||
|
* @note: the used event_periodic struct must stay valid until after the timeout
|
||||||
|
* event has been processed!
|
||||||
|
*
|
||||||
|
* @param[in] event_periodic event_timout context object to use
|
||||||
|
* @param[in] interval period length for the event
|
||||||
|
*/
|
||||||
|
static inline void event_periodic_start(event_periodic_t *event_periodic,
|
||||||
|
uint32_t interval)
|
||||||
|
{
|
||||||
|
event_periodic->timer.interval = interval;
|
||||||
|
ztimer_periodic_start(&event_periodic->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop a periodic timeout event
|
||||||
|
*
|
||||||
|
* Calling this function will cancel the timeout by removing its underlying
|
||||||
|
* timer. If the timer has already fired before calling this function, the
|
||||||
|
* connected event will be put already into the given event queue and this
|
||||||
|
* function does not have any effect.
|
||||||
|
*
|
||||||
|
* @param[in] event_periodic event_periodic_timeout context object to use
|
||||||
|
*/
|
||||||
|
static inline void event_periodic_stop(event_periodic_t *event_periodic)
|
||||||
|
{
|
||||||
|
ztimer_periodic_stop(&event_periodic->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* EVENT_PERIODIC_H */
|
||||||
|
/** @} */
|
||||||
@ -62,7 +62,7 @@ typedef struct {
|
|||||||
event_t *event; /**< event to post after timeout */
|
event_t *event; /**< event to post after timeout */
|
||||||
} event_timeout_t;
|
} event_timeout_t;
|
||||||
|
|
||||||
#if IS_USED(MODULE_EVENT_TIMEOUT_ZTIMER)
|
#if IS_USED(MODULE_EVENT_TIMEOUT_ZTIMER) || DOXYGEN
|
||||||
/**
|
/**
|
||||||
* @brief Initialize timeout event object
|
* @brief Initialize timeout event object
|
||||||
*
|
*
|
||||||
|
|||||||
9
tests/event_ztimer/Makefile
Normal file
9
tests/event_ztimer/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
include ../Makefile.tests_common
|
||||||
|
|
||||||
|
FORCE_ASSERTS = 1
|
||||||
|
USEMODULE += event_thread
|
||||||
|
USEMODULE += event_callback
|
||||||
|
USEMODULE += event_timeout_ztimer
|
||||||
|
USEMODULE += event_periodic
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.include
|
||||||
9
tests/event_ztimer/Makefile.ci
Normal file
9
tests/event_ztimer/Makefile.ci
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
BOARD_INSUFFICIENT_MEMORY := \
|
||||||
|
arduino-duemilanove \
|
||||||
|
arduino-leonardo \
|
||||||
|
arduino-nano \
|
||||||
|
arduino-uno \
|
||||||
|
atmega328p \
|
||||||
|
atmega328p-xplained-mini \
|
||||||
|
nucleo-l011k4 \
|
||||||
|
#
|
||||||
124
tests/event_ztimer/main.c
Normal file
124
tests/event_ztimer/main.c
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Inria
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup tests
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief event_timeout application using ztimer
|
||||||
|
*
|
||||||
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
|
* @author Francisco Molina <francois-xavier.molina@inria.fr>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "atomic_utils.h"
|
||||||
|
#include "test_utils/expect.h"
|
||||||
|
#include "timex.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "mutex.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "event/timeout.h"
|
||||||
|
#include "event/periodic.h"
|
||||||
|
#include "event/thread.h"
|
||||||
|
#include "event/callback.h"
|
||||||
|
#include "ztimer.h"
|
||||||
|
#include "ztimer/periodic.h"
|
||||||
|
|
||||||
|
#define EVENT_TIMEOUT_TIME (1 * US_PER_SEC)
|
||||||
|
|
||||||
|
static void callback_never(void *arg);
|
||||||
|
static void callback_timed(void *arg);
|
||||||
|
static void callback_4times(void *arg);
|
||||||
|
|
||||||
|
static uint8_t iter;
|
||||||
|
static event_timeout_t event_timeout;
|
||||||
|
static event_timeout_t event_timeout_cleared;
|
||||||
|
static event_periodic_t event_periodic;
|
||||||
|
static event_callback_t event_4times = EVENT_CALLBACK_INIT(callback_4times, &iter);
|
||||||
|
static event_callback_t event_timed = EVENT_CALLBACK_INIT(callback_timed, &iter);
|
||||||
|
static event_callback_t event_never = EVENT_CALLBACK_INIT(callback_never, 0);
|
||||||
|
static uint32_t before;
|
||||||
|
static mutex_t lock = MUTEX_INIT_LOCKED;
|
||||||
|
|
||||||
|
static void callback_timed(void *arg)
|
||||||
|
{
|
||||||
|
expect(arg == event_timed.arg);
|
||||||
|
uint32_t now = ztimer_now(ZTIMER_USEC);
|
||||||
|
expect((now - before) >= 1 * US_PER_SEC);
|
||||||
|
printf("triggered timed callback after %" PRIu32 "us\n", now - before);
|
||||||
|
mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void callback_4times(void *arg)
|
||||||
|
{
|
||||||
|
uint8_t *count = (uint8_t *)arg;
|
||||||
|
|
||||||
|
*count = *count + 1;
|
||||||
|
uint32_t now = event_periodic.timer.last;
|
||||||
|
uint32_t elapsed = now - before;
|
||||||
|
before = now;
|
||||||
|
expect((elapsed) >= 1 * US_PER_SEC);
|
||||||
|
if (*count <= 4) {
|
||||||
|
printf("trigger %d of periodic timeout, elapsed time: %" PRIu32 " us\n",
|
||||||
|
*count, elapsed);
|
||||||
|
}
|
||||||
|
if (*count == 4) {
|
||||||
|
event_periodic_stop(&event_periodic);
|
||||||
|
mutex_unlock(&lock);
|
||||||
|
}
|
||||||
|
else if (*count > 4) {
|
||||||
|
/* this callback should never be called */
|
||||||
|
puts("this should only be called 4 times");
|
||||||
|
puts("[FAILED]");
|
||||||
|
while (1) {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void callback_never(void *arg)
|
||||||
|
{
|
||||||
|
(void)arg;
|
||||||
|
/* this callback should never be called */
|
||||||
|
puts("this should never happen");
|
||||||
|
puts("[FAILED]");
|
||||||
|
while (1) {
|
||||||
|
expect(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
iter = 0;
|
||||||
|
puts("posting periodic timed callback with timeout 1sec");
|
||||||
|
event_periodic_init(&event_periodic, ZTIMER_USEC, EVENT_PRIO_MEDIUM,
|
||||||
|
&event_4times.super);
|
||||||
|
event_periodic_start(&event_periodic, EVENT_TIMEOUT_TIME);
|
||||||
|
before = event_periodic.timer.last;
|
||||||
|
puts("waiting for periodic callback to be triggered 4 times");
|
||||||
|
mutex_lock(&lock);
|
||||||
|
puts("posting timed callback with timeout 0.5sec, clear right after");
|
||||||
|
event_timeout_ztimer_init(&event_timeout_cleared, ZTIMER_USEC,
|
||||||
|
EVENT_PRIO_MEDIUM, &event_never.super);
|
||||||
|
event_timeout_set(&event_timeout_cleared, EVENT_TIMEOUT_TIME / 2);
|
||||||
|
event_timeout_clear(&event_timeout_cleared);
|
||||||
|
puts("posting timed callback with timeout 1sec");
|
||||||
|
event_timeout_ztimer_init(&event_timeout, ZTIMER_USEC, EVENT_PRIO_MEDIUM,
|
||||||
|
&event_timed.super);
|
||||||
|
before = ztimer_now(ZTIMER_USEC);
|
||||||
|
event_timeout_set(&event_timeout, EVENT_TIMEOUT_TIME);
|
||||||
|
puts("waiting for timed callback to trigger");
|
||||||
|
mutex_lock(&lock);
|
||||||
|
puts("[SUCCESS]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
19
tests/event_ztimer/tests/01-run.py
Executable file
19
tests/event_ztimer/tests/01-run.py
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Copyright (C) 2016 Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
|
# 2017 Sebastian Meiling <s@mlng.net>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# directory for more details.
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from testrunner import run
|
||||||
|
|
||||||
|
|
||||||
|
def testfunc(child):
|
||||||
|
child.expect_exact(u"[SUCCESS]")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(run(testfunc))
|
||||||
Loading…
x
Reference in New Issue
Block a user