Loading...
Searching...
No Matches
xtimer_compat.h
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2019 Kaspar Schleiser <kaspar@schleiser.de>
3 * SPDX-License-Identifier: LGPL-2.1-only
4 */
5
6#pragma once
7
19
20#include <assert.h>
21#include <stdbool.h>
22#include <stdint.h>
23
24/* make sure to overwrite potentially conflicting XTIMER_WIDTH definition from
25 * board.h by eagerly including it */
26#include "board.h"
27#include "busy_wait.h"
28#include "timex.h"
29#ifdef MODULE_CORE_MSG
30#include "msg.h"
31#endif /* MODULE_CORE_MSG */
32#include "mutex.h"
33#include "sched.h"
34
35#include "ztimer.h"
36
37#ifdef __cplusplus
38extern "C" {
39#endif
40
41/* the xtimer API is documented elsewhere. This is just an (incomplete) wrapper,
42 * so skip doxygen.
43 */
44#ifndef DOXYGEN
45
46/* ztimer clocks with width lower than 32 bit get extended to 32 bit in software
47 * via ztimer_extend. So no matter what was defined elsewhere, we overwrite it
48 */
49#ifdef XTIMER_WIDTH
50#undef XTIMER_WIDTH
51#endif
52
53#define XTIMER_WIDTH (32)
54#define XTIMER_MASK (0)
55
60#ifndef XTIMER_BACKOFF
61#define XTIMER_BACKOFF 1
62#endif
63
68#define _XTIMER_BACKEND_NOT_IMPLEMENTED \
69 extern void xtimer_function_called_but_no_backend_available(void); \
70 xtimer_function_called_but_no_backend_available()
71
72typedef ztimer_t xtimer_t;
73typedef uint32_t xtimer_ticks32_t;
74typedef uint64_t xtimer_ticks64_t;
75
76static inline uint32_t _div_round_up_u32(uint32_t a, uint32_t b)
77{
78 return (a + b - 1) / b;
79}
80
81static inline uint32_t _div_round_up_u64(uint64_t a, uint32_t b)
82{
83 return (a + b - 1) / b;
84}
85
86static inline void xtimer_init(void)
87{
89}
90
91static inline xtimer_ticks32_t xtimer_ticks(uint32_t ticks)
92{
93 return ticks;
94}
95
96static inline uint64_t xtimer_usec_from_ticks64(xtimer_ticks64_t ticks)
97{
98 return ticks;
99}
100
101static inline uint32_t xtimer_usec_from_ticks(xtimer_ticks32_t ticks)
102{
103 return ticks;
104}
105
106static inline uint32_t xtimer_msec_from_ticks(xtimer_ticks32_t ticks)
107{
108 return _div_round_up_u32(ticks, US_PER_MS);
109}
110
111static inline xtimer_ticks32_t xtimer_ticks_from_usec(uint32_t usec)
112{
113 return usec;
114}
115
116static inline xtimer_ticks64_t xtimer_ticks_from_usec64(uint64_t usec)
117{
118 return usec;
119}
120
121static inline xtimer_ticks32_t xtimer_now(void)
122{
123 if (IS_USED(MODULE_ZTIMER_USEC)) {
124 return ztimer_now(ZTIMER_USEC);
125 }
126 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
128 }
129 else {
130 _XTIMER_BACKEND_NOT_IMPLEMENTED;
131 return 0;
132 }
133}
134
135static inline uint32_t xtimer_now_usec(void)
136{
137 return xtimer_now();
138}
139
140static inline uint32_t xtimer_now_msec(void)
141{
142 if (IS_USED(MODULE_ZTIMER_MSEC)) {
143 return ztimer_now(ZTIMER_MSEC);
144 }
145 if (IS_USED(MODULE_ZTIMER_USEC)) {
147 }
148 else {
149 _XTIMER_BACKEND_NOT_IMPLEMENTED;
150 return 0;
151 }
152}
153
154static inline void _ztimer_sleep_scale(ztimer_clock_t *clock, uint32_t time,
155 uint32_t scale)
156{
157 const uint32_t max_sleep = UINT32_MAX / scale;
158
159 while (time > max_sleep) {
160 ztimer_sleep(clock, max_sleep * scale);
161 time -= max_sleep;
162 }
163
164 ztimer_sleep(clock, time * scale);
165}
166
167static inline void xtimer_sleep(uint32_t seconds)
168{
169 /* TODO: use ZTIMER_SEC */
170 if (IS_USED(MODULE_ZTIMER_MSEC)) {
171 _ztimer_sleep_scale(ZTIMER_MSEC, seconds, MS_PER_SEC);
172 }
173 else {
174 _ztimer_sleep_scale(ZTIMER_USEC, seconds, US_PER_SEC);
175 }
176}
177
178static inline void xtimer_msleep(uint32_t milliseconds)
179{
180 if (IS_USED(MODULE_ZTIMER_MSEC)) {
181 ztimer_sleep(ZTIMER_MSEC, milliseconds);
182 }
183 else if (IS_USED(MODULE_ZTIMER_USEC)) {
184 _ztimer_sleep_scale(ZTIMER_USEC, milliseconds, US_PER_MS);
185 }
186 else {
187 busy_wait_us(US_PER_MS * milliseconds);
188 }
189}
190
191static inline void xtimer_usleep(uint32_t microseconds)
192{
193 if (IS_USED(MODULE_ZTIMER_USEC)) {
194 ztimer_sleep(ZTIMER_USEC, microseconds);
195 }
196 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
197 ztimer_sleep(ZTIMER_MSEC, _div_round_up_u32(microseconds, US_PER_MS));
198 }
199 else {
200 busy_wait_us(microseconds);
201 }
202}
203
204static inline void xtimer_set(xtimer_t *timer, uint32_t offset)
205{
206 if (IS_USED(MODULE_ZTIMER_USEC)) {
207 ztimer_set(ZTIMER_USEC, timer, offset);
208 }
209 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
210 ztimer_set(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS));
211 }
212 else {
213 _XTIMER_BACKEND_NOT_IMPLEMENTED;
214 }
215}
216
217static inline void xtimer_remove(xtimer_t *timer)
218{
219 if (IS_USED(MODULE_ZTIMER_USEC)) {
221 }
222 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
224 }
225 else {
226 _XTIMER_BACKEND_NOT_IMPLEMENTED;
227 }
228}
229
230static inline bool xtimer_is_set(const xtimer_t *timer)
231{
232 if (IS_USED(MODULE_ZTIMER_USEC)) {
233 return ztimer_is_set(ZTIMER_USEC, timer);
234 }
235 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
236 return ztimer_is_set(ZTIMER_MSEC, timer);
237 }
238 else {
239 _XTIMER_BACKEND_NOT_IMPLEMENTED;
240 return false;
241 }
242}
243
244static inline void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg,
245 kernel_pid_t target_pid)
246{
247 if (IS_USED(MODULE_ZTIMER_USEC)) {
248 ztimer_set_msg(ZTIMER_USEC, timer, offset, msg, target_pid);
249 }
250 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
251 ztimer_set_msg(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS),
252 msg, target_pid);
253 }
254 else {
255 _XTIMER_BACKEND_NOT_IMPLEMENTED;
256 }
257}
258
259static inline void xtimer_periodic_wakeup(xtimer_ticks32_t *last_wakeup,
260 uint32_t period)
261{
262 if (IS_USED(MODULE_ZTIMER_USEC)) {
263 ztimer_periodic_wakeup(ZTIMER_USEC, last_wakeup, period);
264 }
265 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
266 ztimer_periodic_wakeup(ZTIMER_MSEC, last_wakeup, _div_round_up_u32(period, US_PER_MS));
267 }
268 else {
269 _XTIMER_BACKEND_NOT_IMPLEMENTED;
270 }
271}
272
273static inline int xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout)
274{
275 if (IS_USED(MODULE_ZTIMER_USEC)) {
276 return ztimer_msg_receive_timeout(ZTIMER_USEC, msg, timeout);
277 }
278 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
279 return ztimer_msg_receive_timeout(ZTIMER_MSEC, msg, _div_round_up_u32(timeout, US_PER_MS));
280 }
281 else {
282 _XTIMER_BACKEND_NOT_IMPLEMENTED;
283 return 0;
284 }
285}
286
287static inline void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset,
288 kernel_pid_t pid)
289{
290 if (IS_USED(MODULE_ZTIMER_USEC)) {
291 ztimer_set_wakeup(ZTIMER_USEC, timer, offset, pid);
292 }
293 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
294 ztimer_set_wakeup(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS), pid);
295 }
296 else {
297 _XTIMER_BACKEND_NOT_IMPLEMENTED;
298 }
299}
300
301static inline int xtimer_mutex_lock_timeout(mutex_t *mutex, uint64_t us)
302{
303 int res;
304
305 if (IS_USED(MODULE_ZTIMER_USEC)) {
306 assert(us <= UINT32_MAX);
307 res = ztimer_mutex_lock_timeout(ZTIMER_USEC, mutex, (uint32_t)us);
308 }
309 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
310 us = _div_round_up_u64(us, US_PER_MS);
311 assert(us <= UINT32_MAX);
312 res = ztimer_mutex_lock_timeout(ZTIMER_MSEC, mutex, (uint32_t)us);
313 }
314 else {
315 _XTIMER_BACKEND_NOT_IMPLEMENTED;
316 res = -1;
317 }
318
319 /* Impedance matching required: Convert -ECANCELED error code to -1: */
320 return res ? -1 : 0;
321}
322
323static inline int xtimer_rmutex_lock_timeout(rmutex_t *rmutex, uint64_t us)
324{
325 int res;
326
327 if (IS_USED(MODULE_ZTIMER_USEC)) {
328 assert(us <= UINT32_MAX);
329 res = ztimer_rmutex_lock_timeout(ZTIMER_USEC, rmutex, (uint32_t)us);
330 }
331 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
332 us = _div_round_up_u64(us, US_PER_MS);
333 assert(us <= UINT32_MAX);
334 res = ztimer_rmutex_lock_timeout(ZTIMER_MSEC, rmutex, (uint32_t)us);
335 }
336 else {
337 _XTIMER_BACKEND_NOT_IMPLEMENTED;
338 res = -1;
339 }
340
341 /* Impedance matching required: Convert -ECANCELED error code to -1: */
342 return res ? -1 : 0;
343}
344
345static inline void xtimer_set_timeout_flag(xtimer_t *t, uint32_t timeout)
346{
347 if (IS_USED(MODULE_ZTIMER_USEC)) {
349 }
350 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
351 ztimer_set_timeout_flag(ZTIMER_MSEC, t, _div_round_up_u32(timeout, US_PER_MS));
352 }
353 else {
354 _XTIMER_BACKEND_NOT_IMPLEMENTED;
355 }
356}
357
358static inline void xtimer_set_timeout_flag64(xtimer_t *t, uint64_t timeout)
359{
360 assert(timeout <= UINT32_MAX);
361 xtimer_set_timeout_flag(t, timeout);
362}
363
364static inline void xtimer_spin(xtimer_ticks32_t ticks)
365{
366 if (IS_USED(MODULE_ZTIMER_USEC)) {
368 }
369 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
370 ztimer_spin(ZTIMER_MSEC, xtimer_msec_from_ticks(ticks));
371 }
372 else {
374 }
375}
376
379{
380 return a - b;
381}
382
385{
386 return a - b;
387}
388
391{
392 return (xtimer_ticks32_t)(a - b);
393}
394
395static inline xtimer_ticks64_t xtimer_ticks64(uint64_t ticks)
396{
397 return ticks;
398}
399
400static inline bool xtimer_less(xtimer_ticks32_t a, xtimer_ticks32_t b)
401{
402 return a < b;
403}
404
405static inline bool xtimer_less64(xtimer_ticks64_t a, xtimer_ticks64_t b)
406{
407 return a < b;
408}
409
410static inline void xtimer_tsleep32(xtimer_ticks32_t ticks)
411{
413}
414
415static inline void xtimer_tsleep64(xtimer_ticks64_t ticks)
416{
417 const uint32_t max_sleep = UINT32_MAX;
418 uint64_t time = xtimer_usec_from_ticks64(ticks);
419
420 while (time > max_sleep) {
421 xtimer_usleep(max_sleep);
422 time -= max_sleep;
423 }
424 xtimer_usleep(time);
425}
426
427/* unsupported due to using ztimer (32Bit):
428 * please use ztimer64_xtimer_compat if need
429
430 xtimer_ticks64_t xtimer_now64(void);
431 uint64_t xtimer_now_usec64(void):
432 void xtimer_now_timex(timex_t *out)
433 void xtimer_set64(xtimer_t *timer, uint64_t offset_us);
434 void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset,
435 kernel_pid_t pid);
436 void xtimer_set_msg64(xtimer_t *timer, uint64_t offset,
437 msg_t *msg, kernel_pid_t target_pid);
438 int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t timeout);
439 */
440
441#endif /* DOXYGEN */
442
443#ifdef __cplusplus
444}
445#endif
446
POSIX.1-2008 compliant version of the assert macro.
#define assert(cond)
abort the program if assertion is false
Definition assert.h:143
static void busy_wait_us(unsigned usec)
Spin for a number of microseconds.
Definition busy_wait.h:73
int16_t kernel_pid_t
Unique process identifier.
Definition sched.h:134
#define US_PER_MS
The number of microseconds per millisecond.
Definition time_units.h:86
#define US_PER_SEC
The number of microseconds per second.
Definition time_units.h:81
#define MS_PER_SEC
The number of milliseconds per second.
Definition time_units.h:71
void xtimer_set_timeout_flag64(xtimer_t *t, uint64_t timeout)
Set timeout thread flag after timeout.
static void xtimer_usleep(uint32_t microseconds)
Pause the execution of a thread for some microseconds.
static xtimer_ticks32_t xtimer_diff(xtimer_ticks32_t a, xtimer_ticks32_t b)
Compute difference between two xtimer time stamps.
static uint32_t xtimer_now_usec(void)
get the current system time in microseconds since start
static xtimer_ticks64_t xtimer_ticks_from_usec64(uint64_t usec)
Convert microseconds to xtimer ticks, 64 bit version.
void xtimer_remove(xtimer_t *timer)
remove a timer
static bool xtimer_less64(xtimer_ticks64_t a, xtimer_ticks64_t b)
Compare two xtimer time stamps, 64 bit version.
static void xtimer_tsleep32(xtimer_ticks32_t ticks)
Stop execution of a thread for some time, 32bit version.
static void xtimer_msleep(uint32_t milliseconds)
Pause the execution of a thread for some milliseconds.
static void xtimer_sleep(uint32_t seconds)
Pause the execution of a thread for some seconds.
static xtimer_ticks32_t xtimer_diff32_64(xtimer_ticks64_t a, xtimer_ticks64_t b)
Compute 32 bit difference between two 64 bit xtimer time stamps.
int xtimer_rmutex_lock_timeout(rmutex_t *rmutex, uint64_t us)
lock a rmutex but with timeout
static xtimer_ticks64_t xtimer_ticks64(uint64_t ticks)
Create an xtimer time stamp, 64 bit version.
static void xtimer_periodic_wakeup(xtimer_ticks32_t *last_wakeup, uint32_t period)
will cause the calling thread to be suspended until the absolute time (last_wakeup + period).
static void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid)
Set a timer that sends a message.
static bool xtimer_less(xtimer_ticks32_t a, xtimer_ticks32_t b)
Compare two xtimer time stamps.
static uint32_t xtimer_usec_from_ticks(xtimer_ticks32_t ticks)
Convert xtimer ticks to microseconds.
static xtimer_ticks64_t xtimer_diff64(xtimer_ticks64_t a, xtimer_ticks64_t b)
Compute difference between two xtimer time stamps, 64 bit version.
int xtimer_mutex_lock_timeout(mutex_t *mutex, uint64_t us)
lock a mutex but with timeout
static int xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout)
receive a message blocking but with timeout
void xtimer_set_timeout_flag(xtimer_t *t, uint32_t timeout)
Set timeout thread flag after timeout.
static void xtimer_tsleep64(xtimer_ticks64_t ticks)
Stop execution of a thread for some time, 64bit version.
static void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset, kernel_pid_t pid)
Set a timer that wakes up a thread.
void xtimer_init(void)
xtimer initialization function
static void xtimer_spin(xtimer_ticks32_t ticks)
Stop execution of a thread for some time, blocking.
static void xtimer_set(xtimer_t *timer, uint32_t offset)
Set a timer to execute a callback at some time in the future.
static xtimer_ticks32_t xtimer_ticks_from_usec(uint32_t usec)
Convert microseconds to xtimer ticks.
struct xtimer xtimer_t
xtimer timer structure
static xtimer_ticks32_t xtimer_ticks(uint32_t ticks)
Create an xtimer time stamp.
static xtimer_ticks32_t xtimer_now(void)
get the current system time as 32bit time stamp value
static bool xtimer_is_set(const xtimer_t *timer)
state if an xtimer is currently set (waiting to be expired)
static uint64_t xtimer_usec_from_ticks64(xtimer_ticks64_t ticks)
Convert xtimer ticks to microseconds, 64 bit version.
void ztimer_init(void)
Initialize the board-specific default ztimer configuration.
struct ztimer_clock ztimer_clock_t
ztimer_clock_t forward declaration
Definition ztimer.h:287
void ztimer_periodic_wakeup(ztimer_clock_t *clock, uint32_t *last_wakeup, uint32_t period)
Suspend the calling thread until the time (last_wakeup + period)
void ztimer_set_wakeup(ztimer_clock_t *clock, ztimer_t *timer, uint32_t offset, kernel_pid_t pid)
Set a timer that wakes up a thread.
void ztimer_set_msg(ztimer_clock_t *clock, ztimer_t *timer, uint32_t offset, msg_t *msg, kernel_pid_t target_pid)
Post a message after a delay.
uint32_t ztimer_set(ztimer_clock_t *clock, ztimer_t *timer, uint32_t val)
Set a timer on a clock.
ztimer_clock_t *const ZTIMER_USEC
Default ztimer microsecond clock.
static void ztimer_spin(ztimer_clock_t *clock, uint32_t duration)
Busy-wait specified duration.
Definition ztimer.h:739
static ztimer_now_t ztimer_now(ztimer_clock_t *clock)
Get the current time from a clock.
Definition ztimer.h:680
int ztimer_msg_receive_timeout(ztimer_clock_t *clock, msg_t *msg, uint32_t timeout)
receive a message (blocking, with timeout)
unsigned ztimer_is_set(const ztimer_clock_t *clock, const ztimer_t *timer)
Check if a timer is currently active.
int ztimer_rmutex_lock_timeout(ztimer_clock_t *clock, rmutex_t *rmutex, uint32_t timeout)
Try to lock the given rmutex, but give up after timeout.
void ztimer_sleep(ztimer_clock_t *clock, uint32_t duration)
Put the calling thread to sleep for the specified number of ticks.
bool ztimer_remove(ztimer_clock_t *clock, ztimer_t *timer)
Remove a timer from a clock.
void ztimer_set_timeout_flag(ztimer_clock_t *clock, ztimer_t *timer, uint32_t timeout)
Set timeout thread flag after timeout.
int ztimer_mutex_lock_timeout(ztimer_clock_t *clock, mutex_t *mutex, uint32_t timeout)
Try to lock the given mutex, but give up after timeout.
ztimer_clock_t *const ZTIMER_MSEC
Default ztimer millisecond clock.
#define IS_USED(module)
Checks whether a module is being used or not.
Definition modules.h:67
Mutex for thread synchronization.
Describes a message object which can be sent between threads.
Definition msg.h:193
Mutex structure.
Definition mutex.h:36
Mutex structure.
Definition rmutex.h:34
xtimer timestamp (32 bit)
Definition xtimer.h:88
xtimer timestamp (64 bit)
Definition xtimer.h:79
ztimer structure
Definition ztimer.h:316
Utility library for comparing and computing timestamps.
ztimer API