diff --git a/tests/ztimer64_msg/Makefile b/tests/ztimer64_msg/Makefile new file mode 100644 index 0000000000..1a28151454 --- /dev/null +++ b/tests/ztimer64_msg/Makefile @@ -0,0 +1,11 @@ +include ../Makefile.tests_common + +USEMODULE += ztimer64_usec + +# uncomment this to test using ztimer64 msec on rtt +#USEMODULE += ztimer64_msec ztimer_periph_rtt + +# uncomment this to test using ztimer64 sec on rtc +#USEMODULE += ztimer64_sec ztimer_periph_rtc + +include $(RIOTBASE)/Makefile.include diff --git a/tests/ztimer64_msg/Makefile.ci b/tests/ztimer64_msg/Makefile.ci new file mode 100644 index 0000000000..d5368f025e --- /dev/null +++ b/tests/ztimer64_msg/Makefile.ci @@ -0,0 +1,12 @@ +BOARD_INSUFFICIENT_MEMORY := \ + arduino-duemilanove \ + arduino-leonardo \ + arduino-nano \ + arduino-uno \ + atmega328p \ + atmega328p-xplained-mini \ + nucleo-f031k6 \ + nucleo-l011k4 \ + samd10-xmini \ + stm32f030f4-demo \ + # diff --git a/tests/ztimer64_msg/README.md b/tests/ztimer64_msg/README.md new file mode 100644 index 0000000000..11f77be44b --- /dev/null +++ b/tests/ztimer64_msg/README.md @@ -0,0 +1,9 @@ +# Overview + +This test application is a direct translation of ztimer_msg to the ztimer64API. +It is meant mostly as a means to do size comparisons, thus tries to be as close +as possible to the original. + +One notable change is the option to choose a different ztimer clock. +By default, the test will use ZTIMER64_USEC, unless ZTIMER64_MSEC is compiled in, +which will be used in that case. diff --git a/tests/ztimer64_msg/app.config.test b/tests/ztimer64_msg/app.config.test new file mode 100644 index 0000000000..aba183dfcb --- /dev/null +++ b/tests/ztimer64_msg/app.config.test @@ -0,0 +1,3 @@ +# this file enables modules defined in Kconfig. Do not use this file for +# application configuration. This is only needed during migration. +CONFIG_ZTIMER64_USEC=y diff --git a/tests/ztimer64_msg/main.c b/tests/ztimer64_msg/main.c new file mode 100644 index 0000000000..a27dd9cc5d --- /dev/null +++ b/tests/ztimer64_msg/main.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2015-19 Kaspar Schleiser + * 2013 INRIA + * 2017 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 + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief ztimer64_msg test application + * + * @author Kaspar Schleiser + * @author Oliver Hahm + * @author Christian Mehlis + * @author Sebastian Meiling + * @} + */ + +#include + +#include "ztimer64.h" +#include "thread.h" +#include "msg.h" +#include "timex.h" + +#include "test_utils/expect.h" + +#ifdef MODULE_ZTIMER64_SEC +#define ZTIMER64 ZTIMER64_SEC +#define TICKS_PER_SEC 1 +#elif MODULE_ZTIMER64_MSEC +#define ZTIMER64 ZTIMER64_MSEC +#define TICKS_PER_SEC MS_PER_SEC +#else +#define ZTIMER64 ZTIMER64_USEC +#define TICKS_PER_SEC US_PER_SEC +#endif + +char timer_stack[THREAD_STACKSIZE_DEFAULT]; +char timer_stack_local[THREAD_STACKSIZE_DEFAULT]; + +struct timer_msg { + ztimer64_t timer; + uint64_t interval; + char *text; + msg_t msg; +}; + +struct timer_msg msg_a = { .interval = (2 * TICKS_PER_SEC), + .text = "Hello World" }; +struct timer_msg msg_b = { .interval = (5 * TICKS_PER_SEC), + .text = "This is a Test" }; + +void *timer_thread(void *arg) +{ + (void)arg; + + printf("This is thread %" PRIkernel_pid "\n", thread_getpid()); + + /* The queue is required to avoid loss of a 2nd message, when the 1st is + * still processed. The timing ensures that at most 1 message is queued. + */ + msg_t msgq[1]; + + msg_init_queue(msgq, 1); + + while (1) { + msg_t m; + msg_receive(&m); + struct timer_msg *tmsg = m.content.ptr; + uint64_t now = ztimer64_now(ZTIMER64); + /* casts are needed to solve for sometimes TICKS_PER_SEC being UL + * result of / and % of uint32_t will always fit into uint32_t + */ + printf( + "now=%" PRIu32 ":%" PRIu32 " -> every %" PRIu32 ".%" PRIu32 "s: %s\n", + (uint32_t)(now / TICKS_PER_SEC), + (uint32_t)(now % TICKS_PER_SEC), + (uint32_t)(tmsg->interval / TICKS_PER_SEC), + (uint32_t)(tmsg->interval % TICKS_PER_SEC), + tmsg->text); + + tmsg->msg.type = 12345; + tmsg->msg.content.ptr = tmsg; + ztimer64_set_msg(ZTIMER64, &tmsg->timer, tmsg->interval, &tmsg->msg, + thread_getpid()); + } +} + +void *timer_thread_local(void *arg) +{ + (void)arg; + + printf("This is thread %" PRIkernel_pid "\n", thread_getpid()); + + while (1) { + msg_t m; + msg_receive(&m); + + uint64_t now = ztimer64_now(ZTIMER64); + uint32_t sec = now / TICKS_PER_SEC; + uint32_t min = sec / 60; + uint32_t hr = sec / 3600; + printf("sec=%" PRIu32 " min=%" PRIu32 " hour=%" PRIu32 "\n", sec, min, + hr); + } +} + +int main(void) +{ + msg_t m; + kernel_pid_t pid = thread_create( + timer_stack, + sizeof(timer_stack), + THREAD_PRIORITY_MAIN - 1, + THREAD_CREATE_STACKTEST, + timer_thread, + NULL, + "timer"); + + expect(pid_is_valid(pid)); + + puts("sending 1st msg"); + m.content.ptr = &msg_a; + msg_try_send(&m, pid); + + puts("sending 2nd msg"); + m.content.ptr = &msg_b; + msg_try_send(&m, pid); + + kernel_pid_t pid2 = thread_create( + timer_stack_local, + sizeof(timer_stack_local), + THREAD_PRIORITY_MAIN - 1, + THREAD_CREATE_STACKTEST, + timer_thread_local, + NULL, + "timer local"); + + expect(pid_is_valid(pid2)); + + while (1) { + ztimer64_sleep(ZTIMER64, 1LLU * TICKS_PER_SEC); + msg_try_send(&m, pid2); + } +} diff --git a/tests/ztimer64_msg/tests/01-run.py b/tests/ztimer64_msg/tests/01-run.py new file mode 100755 index 0000000000..136b6443a4 --- /dev/null +++ b/tests/ztimer64_msg/tests/01-run.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2017 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 +# directory for more details. + +import sys +from testrunner import run + + +def testfunc(child): + # 1st check for periodic 2s Hello World message, i.e., 2 output + 1 msg + for _ in range(7): + child.expect(r"sec=\d+ min=\d+ hour=\d+") + child.expect(r"sec=\d+ min=\d+ hour=\d+") + child.expect(r"now=\d+:\d+ -> every 2.0s: Hello World") + # 2nd check for periodic 5s test message, i.e., 5 output + 1 msg + for _ in range(3): + child.expect(r"sec=\d+ min=\d+ hour=\d+") + child.expect(r"sec=\d+ min=\d+ hour=\d+") + child.expect(r"sec=\d+ min=\d+ hour=\d+") + child.expect(r"sec=\d+ min=\d+ hour=\d+") + child.expect(r"sec=\d+ min=\d+ hour=\d+") + child.expect(r"now=\d+:\d+ -> every 5.0s: This is a Test") + + +if __name__ == "__main__": + sys.exit(run(testfunc))