Skip to content

Commit ae804c1

Browse files
DanielLockau-MLPAbenpicco
authored andcommitted
sys/bus: implement time change notification
1 parent 423a85c commit ae804c1

File tree

7 files changed

+223
-0
lines changed

7 files changed

+223
-0
lines changed

sys/Makefile.dep

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,10 @@ ifneq (,$(filter tiny_strerror_as_strerror,$(USEMODULE)))
626626
USEMODULE += tiny_strerror
627627
endif
628628

629+
ifneq (,$(filter sys_bus_rtc, $(USEMODULE)))
630+
USEMODULE += periph_rtc_setter_callback
631+
endif
632+
629633
# include ztimer dependencies
630634
ifneq (,$(filter ztimer ztimer_% %ztimer,$(USEMODULE)))
631635
include $(RIOTBASE)/sys/ztimer/Makefile.dep

sys/bus/sys_bus_rtc.c

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (C) 2021 ML!PA Consulting GmbH
3+
*
4+
* This file is subject to the terms and conditions of the GNU Lesser
5+
* General Public License v2.1. See the file LICENSE in the top level
6+
* directory for more details.
7+
*/
8+
9+
/**
10+
* @ingroup sys_bus
11+
* @{
12+
*
13+
* @file
14+
* @brief RTC event bus
15+
*
16+
* @author Daniel Lockau <[email protected]>
17+
* @}
18+
*/
19+
20+
#include "periph/rtc.h"
21+
#include "sys/bus.h"
22+
#include "timex.h"
23+
24+
/**
25+
* @brief Compute millisecond difference between two time stamps
26+
*
27+
* Internal function.
28+
*/
29+
int32_t sys_bus_rtc_compute_diff_ms(
30+
struct tm *tm_before, uint32_t us_before,
31+
struct tm *tm_after, uint32_t us_after)
32+
{
33+
assert(us_before < US_PER_SEC);
34+
assert(us_after < US_PER_SEC);
35+
36+
uint32_t s_before = rtc_mktime(tm_before);
37+
uint32_t s_after = rtc_mktime(tm_after);
38+
39+
/* default content is out of range special value INT32_MIN */
40+
int32_t diff_ms = RTC_EVENT_OUT_OF_RANGE;
41+
42+
/* calculate time difference if in range */
43+
if (((s_after > s_before) ? (s_after - s_before) : (s_before - s_after))
44+
< (INT32_MAX / MS_PER_SEC)) {
45+
diff_ms = ((int32_t)(s_after - s_before) * (int32_t)MS_PER_SEC)
46+
+ ((int32_t)(us_after - us_before) / (int32_t)US_PER_MS);
47+
}
48+
49+
return diff_ms;
50+
}
51+
52+
#ifdef MODULE_SYS_BUS_RTC
53+
54+
/**
55+
* @brief Setter callback for use with @ref rtc_set_time_with_callback
56+
*
57+
* Internal function.
58+
*/
59+
void rtc_setter_callback(
60+
struct tm *tm_before, uint32_t us_before,
61+
struct tm *tm_after, uint32_t us_after)
62+
{
63+
int32_t diff_ms = sys_bus_rtc_compute_diff_ms(tm_before, us_before,
64+
tm_after, us_after);
65+
66+
/* post result on a non-zero millisecond difference */
67+
if (diff_ms != 0) {
68+
msg_bus_post(sys_bus_get(SYS_BUS_RTC), SYS_BUS_RTC_EVENT_TIME_CHANGE,
69+
(void *)(uintptr_t)diff_ms);
70+
}
71+
}
72+
73+
#endif /* MODULE_SYS_BUS_RTC */

sys/include/sys/bus.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ typedef enum {
5454
/* add more if needed, but not more than 32 */
5555
} sys_bus_power_event_t;
5656

57+
/**
58+
* @brief Indicates positive or negative out-of-range event
59+
*/
60+
#define RTC_EVENT_OUT_OF_RANGE INT32_MIN
61+
5762
/**
5863
* @brief RTC Bus Events
5964
*/
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include $(RIOTBASE)/Makefile.base
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
USEMODULE += sys_bus_rtc
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (C) 2021 ML!PA Consulting GmbH
3+
*
4+
* This file is subject to the terms and conditions of the GNU Lesser
5+
* General Public License v2.1. See the file LICENSE in the top level
6+
* directory for more details.
7+
*/
8+
9+
/**
10+
* @{
11+
*
12+
* @file
13+
*/
14+
15+
#include "embUnit.h"
16+
17+
#include "periph/rtc.h"
18+
19+
extern int32_t sys_bus_rtc_compute_diff_ms(
20+
const struct tm *tm_before, uint32_t us_before,
21+
const struct tm *tm_after, uint32_t us_after);
22+
23+
static void test_sys_bus_rtc_compute_diff_ms(void)
24+
{
25+
/* zero */
26+
struct tm tm_before;
27+
struct tm tm_after;
28+
rtc_localtime(1000, &tm_before);
29+
rtc_localtime(1000, &tm_after);
30+
TEST_ASSERT_EQUAL_INT(0, sys_bus_rtc_compute_diff_ms(
31+
&tm_before, 0, &tm_after, 0));
32+
rtc_localtime(0, &tm_before);
33+
rtc_localtime(0, &tm_after);
34+
TEST_ASSERT_EQUAL_INT(0, sys_bus_rtc_compute_diff_ms(
35+
&tm_before, 1234, &tm_after, 1234));
36+
37+
/* positive, within range */
38+
rtc_localtime(100, &tm_before);
39+
rtc_localtime(10000, &tm_after);
40+
TEST_ASSERT_EQUAL_INT(9900000, sys_bus_rtc_compute_diff_ms(
41+
&tm_before, 1234, &tm_after, 1234));
42+
TEST_ASSERT_EQUAL_INT(9899999, sys_bus_rtc_compute_diff_ms(
43+
&tm_before, 1234, &tm_after, 0));
44+
TEST_ASSERT_EQUAL_INT(9900001, sys_bus_rtc_compute_diff_ms(
45+
&tm_before, 0, &tm_after, 1234));
46+
TEST_ASSERT_EQUAL_INT(9900123, sys_bus_rtc_compute_diff_ms(
47+
&tm_before, 0, &tm_after, 123400));
48+
rtc_localtime((INT32_MAX / 1000) + 99, &tm_after);
49+
TEST_ASSERT_EQUAL_INT(2147482123, sys_bus_rtc_compute_diff_ms(
50+
&tm_before, 0, &tm_after, 123400));
51+
52+
/* negative, within range */
53+
rtc_localtime(10000, &tm_before);
54+
rtc_localtime(100, &tm_after);
55+
TEST_ASSERT_EQUAL_INT(-9900000, sys_bus_rtc_compute_diff_ms(
56+
&tm_before, 1234, &tm_after, 1234));
57+
TEST_ASSERT_EQUAL_INT(-9899999, sys_bus_rtc_compute_diff_ms(
58+
&tm_before, 0, &tm_after, 1234));
59+
TEST_ASSERT_EQUAL_INT(-9900001, sys_bus_rtc_compute_diff_ms(
60+
&tm_before, 1234, &tm_after, 0));
61+
TEST_ASSERT_EQUAL_INT(-9900123, sys_bus_rtc_compute_diff_ms(
62+
&tm_before, 123400, &tm_after, 0));
63+
rtc_localtime((INT32_MAX / 1000) + 99, &tm_before);
64+
TEST_ASSERT_EQUAL_INT(-2147482123, sys_bus_rtc_compute_diff_ms(
65+
&tm_before, 123400, &tm_after, 0));
66+
67+
/* positive, out of range */
68+
rtc_localtime(100, &tm_before);
69+
rtc_localtime((INT32_MAX / 1000) + 100, &tm_after);
70+
TEST_ASSERT_EQUAL_INT(RTC_EVENT_OUT_OF_RANGE, sys_bus_rtc_compute_diff_ms(
71+
&tm_before, 0, &tm_after, 123400));
72+
rtc_localtime(0, &tm_before);
73+
TEST_ASSERT_EQUAL_INT(RTC_EVENT_OUT_OF_RANGE, sys_bus_rtc_compute_diff_ms(
74+
&tm_before, 0, &tm_after, 123400));
75+
76+
/* negative, out of range */
77+
rtc_localtime((INT32_MAX / 1000) + 100, &tm_before);
78+
rtc_localtime(100, &tm_after);
79+
TEST_ASSERT_EQUAL_INT(RTC_EVENT_OUT_OF_RANGE, sys_bus_rtc_compute_diff_ms(
80+
&tm_before, 123400, &tm_after, 0));
81+
rtc_localtime(0, &tm_after);
82+
TEST_ASSERT_EQUAL_INT(RTC_EVENT_OUT_OF_RANGE, sys_bus_rtc_compute_diff_ms(
83+
&tm_before, 123400, &tm_after, 0));
84+
}
85+
86+
Test *tests_sys_bus_tests(void)
87+
{
88+
EMB_UNIT_TESTFIXTURES(fixtures) {
89+
new_TestFixture(test_sys_bus_rtc_compute_diff_ms),
90+
};
91+
92+
EMB_UNIT_TESTCALLER(sys_bus_tests, NULL, NULL, fixtures);
93+
94+
return (Test *)&sys_bus_tests;
95+
}
96+
97+
void tests_sys_bus(void)
98+
{
99+
TESTS_RUN(tests_sys_bus_tests());
100+
}
101+
/** @} */
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (C) 2021 ML!PA Consulting GmbH
3+
*
4+
* This file is subject to the terms and conditions of the GNU Lesser
5+
* General Public License v2.1. See the file LICENSE in the top level
6+
* directory for more details.
7+
*/
8+
9+
/**
10+
* @addtogroup unittests
11+
* @{
12+
*
13+
* @file
14+
* @brief Unittests for the ``sys_bus`` module
15+
*
16+
* @author Daniel Lockau <[email protected]>
17+
*/
18+
19+
#ifndef TESTS_SYS_BUS_H
20+
#define TESTS_SYS_BUS_H
21+
22+
#include "embUnit.h"
23+
24+
#ifdef __cplusplus
25+
extern "C" {
26+
#endif
27+
28+
/**
29+
* @brief The entry point of this test suite.
30+
*/
31+
void tests_sys_bus(void);
32+
33+
#ifdef __cplusplus
34+
}
35+
#endif
36+
37+
#endif /* TESTS_SYS_BUS_H */
38+
/** @} */

0 commit comments

Comments
 (0)