diff --git a/Makefile.dep b/Makefile.dep index cb6f3d2877..7b73c2e2c8 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -729,6 +729,11 @@ ifneq (,$(filter evtimer,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter evtimer_mbox,$(USEMODULE))) + USEMODULE += evtimer + USEMODULE += core_mbox +endif + ifneq (,$(filter fuzzing,$(USEMODULE))) USEMODULE += netdev_test USEMODULE += gnrc_netif diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index d2b3405bae..31abbf9e59 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -20,6 +20,7 @@ PSEUDOMODULES += devfs_% PSEUDOMODULES += dhcpv6_% PSEUDOMODULES += ecc_% PSEUDOMODULES += event_% +PSEUDOMODULES += evtimer_mbox PSEUDOMODULES += fmt_% PSEUDOMODULES += gnrc_dhcpv6_% PSEUDOMODULES += gnrc_ipv6_default diff --git a/sys/include/evtimer_mbox.h b/sys/include/evtimer_mbox.h new file mode 100644 index 0000000000..37d9507401 --- /dev/null +++ b/sys/include/evtimer_mbox.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 Simon Brummer + * + * 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. + */ + +/** + * @addtogroup sys_evtimer + * @{ + * + * @file + * @brief Message box based evtimer event. + * + * @author Simon Brummer + */ +#ifndef EVTIMER_MBOX_H +#define EVTIMER_MBOX_H + +#include "assert.h" +#include "msg.h" +#include "mbox.h" +#include "evtimer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Message box event definition. + */ +typedef struct { + evtimer_event_t event; /**< event base class */ + msg_t msg; /**< message to store in mbox on event */ + mbox_t *mbox; /**< mbox the IPC message shall be stored */ +} evtimer_mbox_event_t; + +/** + * @brief Adds mbox event to an event timer. + * + * @pre @p evtimer is not NULL. + * @pre @p event is not NULL. + * @pre @p mbox is not NULL. + * + * @param[in] evtimer Timer to add @p event. + * @param[in] event Event to add. + * @param[in] mbox Mbox to store event->msg timer expiration. + */ +static inline void evtimer_add_mbox(evtimer_t *evtimer, evtimer_mbox_event_t *event, mbox_t *mbox) +{ + assert(evtimer); + assert(event); + assert(mbox); + event->mbox = mbox; + evtimer_add(evtimer, &(event->event)); +} + +/** + * @brief Event handler for mbox events. + * + * @pre @p event is not NULL. + * + * @param[in] event The event to handle + */ +static inline void _evtimer_mbox_handler(evtimer_event_t *event) +{ + assert(event); + evtimer_mbox_event_t *mbevent = (evtimer_mbox_event_t *)event; + mbox_try_put(mbevent->mbox, &(mbevent->msg)); +} + +/** + * @brief Initializes event timer for mbox events. + * + * @pre @p evtimer is not NULL. + * + * @param[in] evtimer An event timer + */ +static inline void evtimer_init_mbox(evtimer_t *evtimer) +{ + assert(evtimer); + evtimer_init(evtimer, _evtimer_mbox_handler); +} + +#ifdef __cplusplus +} +#endif + +#endif /* EVTIMER_MBOX_H */ +/** @} */ diff --git a/tests/evtimer_mbox/Makefile b/tests/evtimer_mbox/Makefile new file mode 100644 index 0000000000..9eec34fe9c --- /dev/null +++ b/tests/evtimer_mbox/Makefile @@ -0,0 +1,5 @@ +include ../Makefile.tests_common + +USEMODULE += evtimer_mbox + +include $(RIOTBASE)/Makefile.include diff --git a/tests/evtimer_mbox/main.c b/tests/evtimer_mbox/main.c new file mode 100644 index 0000000000..5241ba72e4 --- /dev/null +++ b/tests/evtimer_mbox/main.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2020 Simon Brummer + * + * 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 evtimer_mbox test application + * + * @author Simon Brummer + * + * @} + */ + +#include + +#include "kernel_defines.h" +#include "msg.h" +#include "thread.h" +#include "evtimer_msg.h" +#include "evtimer_mbox.h" + +#define MBOX_SIZE (4) +#define TIMEOUT_MS (100) +#define TRIGGER_TIMEOUT_MS (TIMEOUT_MS + TIMEOUT_MS * MBOX_SIZE) + +int main(void) +{ + /* Initialize mbox and evtimers */ + msg_t queue[MBOX_SIZE]; + mbox_t mbox; + mbox_init(&mbox, queue, ARRAY_SIZE(queue)); + + evtimer_t timer; + evtimer_t trigger_timer; + evtimer_init_mbox(&timer); + evtimer_init_msg(&trigger_timer); + + /* Initialize mbox events */ + evtimer_mbox_event_t events[MBOX_SIZE]; + + for (unsigned i = 0; i < ARRAY_SIZE(events); ++i) { + evtimer_mbox_event_t *e = events + i; + + e->event.offset = TIMEOUT_MS + TIMEOUT_MS * i; + e->msg.type = i; + } + + /* Initialize trigger event */ + evtimer_msg_event_t trigger; + trigger.event.offset = TRIGGER_TIMEOUT_MS; + + /* Add events in reverse order to their expected timeout expiration */ + for (int i = ARRAY_SIZE(events) - 1; i >= 0; --i) { + evtimer_add_mbox(&timer, events + i, &mbox); + } + evtimer_add_msg(&trigger_timer, &trigger, thread_getpid()); + + /* Wait until trigger event expired.*/ + msg_t msg; + msg_receive(&msg); + + /* Verify mbox content, Expectations are: + * 1) Given mbox is full (always use blocking get) + * 2) All msg.type values are stored in ascending order + */ + int failed = 0; + + for (unsigned i = 0; i < MBOX_SIZE; ++i) { + mbox_get(&mbox, &msg); + + if (msg.type != i) { + failed = 1; + break; + } + } + + if (!failed) { + puts("Test successful\n"); + } +} diff --git a/tests/evtimer_mbox/tests/01-run.py b/tests/evtimer_mbox/tests/01-run.py new file mode 100755 index 0000000000..141f38f1b6 --- /dev/null +++ b/tests/evtimer_mbox/tests/01-run.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2020 Simon Brummer +# +# 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('Test successful') + + +if __name__ == '__main__': + sys.exit(run(testfunc, timeout=1, echo=True))