Loading...
Searching...
No Matches
xtimer_compat.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2019 Kaspar Schleiser <kaspar@schleiser.de>
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#pragma once
10
22
23#include <assert.h>
24#include <stdbool.h>
25#include <stdint.h>
26
27/* make sure to overwrite potentially conflicting XTIMER_WIDTH definition from
28 * board.h by eagerly including it */
29#include "board.h"
30#include "busy_wait.h"
31#include "timex.h"
32#ifdef MODULE_CORE_MSG
33#include "msg.h"
34#endif /* MODULE_CORE_MSG */
35#include "mutex.h"
36#include "sched.h"
37#include "macros/math.h"
38
39#include "ztimer.h"
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45/* the xtimer API is documented elsewhere. This is just an (incomplete) wrapper,
46 * so skip doxygen.
47 */
48#ifndef DOXYGEN
49
50/* ztimer clocks with width lower than 32 bit get extended to 32 bit in software
51 * via ztimer_extend. So no matter what was defined elsewhere, we overwrite it
52 */
53#ifdef XTIMER_WIDTH
54#undef XTIMER_WIDTH
55#endif
56
57#define XTIMER_WIDTH (32)
58#define XTIMER_MASK (0)
59
64
65#ifndef XTIMER_BACKOFF
66#define XTIMER_BACKOFF 1
67#endif
68
73#define _XTIMER_BACKEND_NOT_IMPLEMENTED \
74 extern void xtimer_function_called_but_no_backend_available(void); \
75 xtimer_function_called_but_no_backend_available()
76
77typedef ztimer_t xtimer_t;
78typedef uint32_t xtimer_ticks32_t;
79typedef uint64_t xtimer_ticks64_t;
80
81static inline void xtimer_init(void)
82{
84}
85
86static inline bool xtimer_is_set(const xtimer_t *timer)
87{
88 return ztimer_is_set(ZTIMER_USEC, timer);
89}
90
91static inline xtimer_ticks32_t xtimer_ticks(uint32_t ticks)
92{
93 return ticks;
94}
95
96static inline uint32_t xtimer_usec_from_ticks(xtimer_ticks32_t ticks)
97{
98 return ticks;
99}
100
101static inline uint32_t _div_round_up_u32(uint32_t a, uint32_t b)
102{
103 return (a + b - 1) / b;
104}
105
106static inline uint32_t _div_round_up_u64(uint64_t a, uint32_t b)
107{
108 return (a + b - 1) / b;
109}
110
111static inline uint32_t xtimer_msec_from_ticks(xtimer_ticks32_t ticks)
112{
113 return _div_round_up_u32(ticks, US_PER_MS);
114}
115
116static inline uint64_t xtimer_usec_from_ticks64(xtimer_ticks64_t ticks)
117{
118 return ticks;
119}
120
121static inline xtimer_ticks32_t xtimer_ticks_from_usec(uint32_t usec)
122{
123 return usec;
124}
125
126static inline xtimer_ticks64_t xtimer_ticks_from_usec64(uint64_t usec)
127{
128 return usec;
129}
130
131static inline xtimer_ticks32_t xtimer_now(void)
132{
133 if (IS_USED(MODULE_ZTIMER_USEC)) {
134 return ztimer_now(ZTIMER_USEC);
135 }
136 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
138 }
139 else {
140 _XTIMER_BACKEND_NOT_IMPLEMENTED;
141 return 0;
142 }
143}
144
145static inline uint32_t xtimer_now_usec(void)
146{
147 if (IS_USED(MODULE_ZTIMER_USEC)) {
148 return ztimer_now(ZTIMER_USEC);
149 }
150 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
152 }
153 else {
154 _XTIMER_BACKEND_NOT_IMPLEMENTED;
155 return 0;
156 }
157}
158
159static inline void _ztimer_sleep_scale(ztimer_clock_t *clock, uint32_t time,
160 uint32_t scale)
161{
162 const uint32_t max_sleep = UINT32_MAX / scale;
163
164 while (time > max_sleep) {
165 ztimer_sleep(clock, max_sleep * scale);
166 time -= max_sleep;
167 }
168
169 ztimer_sleep(clock, time * scale);
170}
171
172static inline void xtimer_sleep(uint32_t seconds)
173{
174 /* TODO: use ZTIMER_SEC */
175 if (IS_USED(MODULE_ZTIMER_MSEC)) {
176 _ztimer_sleep_scale(ZTIMER_MSEC, seconds, MS_PER_SEC);
177 }
178 else {
179 _ztimer_sleep_scale(ZTIMER_USEC, seconds, US_PER_SEC);
180 }
181}
182
183static inline void xtimer_msleep(uint32_t milliseconds)
184{
185 if (IS_USED(MODULE_ZTIMER_MSEC)) {
186 ztimer_sleep(ZTIMER_MSEC, milliseconds);
187 }
188 else if (IS_USED(MODULE_ZTIMER_USEC)) {
189 _ztimer_sleep_scale(ZTIMER_USEC, milliseconds, US_PER_MS);
190 }
191 else {
192 busy_wait_us(US_PER_MS * milliseconds);
193 }
194}
195
196static inline void xtimer_usleep(uint32_t microseconds)
197{
198 if (IS_USED(MODULE_ZTIMER_USEC)) {
199 ztimer_sleep(ZTIMER_USEC, microseconds);
200 }
201 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
202 ztimer_sleep(ZTIMER_MSEC, _div_round_up_u32(microseconds, US_PER_MS));
203 }
204 else {
205 busy_wait_us(microseconds);
206 }
207}
208
209static inline void xtimer_nanosleep(uint32_t nanoseconds)
210{
211 xtimer_usleep(nanoseconds / NS_PER_US);
212}
213
214static inline void xtimer_tsleep32(xtimer_ticks32_t ticks)
215{
217}
218
219static inline void xtimer_tsleep64(xtimer_ticks64_t ticks)
220{
221 const uint32_t max_sleep = UINT32_MAX;
222 uint64_t time = xtimer_usec_from_ticks64(ticks);
223
224 while (time > max_sleep) {
225 xtimer_usleep(max_sleep);
226 time -= max_sleep;
227 }
228 xtimer_usleep(time);
229}
230
231static inline void xtimer_set(xtimer_t *timer, uint32_t offset)
232{
233 if (IS_USED(MODULE_ZTIMER_USEC)) {
234 ztimer_set(ZTIMER_USEC, timer, offset);
235 }
236 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
237 ztimer_set(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS));
238 }
239 else {
240 _XTIMER_BACKEND_NOT_IMPLEMENTED;
241 }
242}
243
244static inline void xtimer_remove(xtimer_t *timer)
245{
246 if (IS_USED(MODULE_ZTIMER_USEC)) {
248 }
249 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
251 }
252 else {
253 _XTIMER_BACKEND_NOT_IMPLEMENTED;
254 }
255}
256
257static inline void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg,
258 kernel_pid_t target_pid)
259{
260 if (IS_USED(MODULE_ZTIMER_USEC)) {
261 ztimer_set_msg(ZTIMER_USEC, timer, offset, msg, target_pid);
262 }
263 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
264 ztimer_set_msg(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS),
265 msg, target_pid);
266 }
267 else {
268 _XTIMER_BACKEND_NOT_IMPLEMENTED;
269 }
270}
271
272static inline void xtimer_periodic_wakeup(xtimer_ticks32_t *last_wakeup,
273 uint32_t period)
274{
275 if (IS_USED(MODULE_ZTIMER_USEC)) {
276 ztimer_periodic_wakeup(ZTIMER_USEC, last_wakeup, period);
277 }
278 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
279 ztimer_periodic_wakeup(ZTIMER_MSEC, last_wakeup, _div_round_up_u32(period, US_PER_MS));
280 }
281 else {
282 _XTIMER_BACKEND_NOT_IMPLEMENTED;
283 }
284}
285
286static inline int xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout)
287{
288 if (IS_USED(MODULE_ZTIMER_USEC)) {
289 return ztimer_msg_receive_timeout(ZTIMER_USEC, msg, timeout);
290 }
291 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
292 return ztimer_msg_receive_timeout(ZTIMER_MSEC, msg, _div_round_up_u32(timeout, US_PER_MS));
293 }
294 else {
295 _XTIMER_BACKEND_NOT_IMPLEMENTED;
296 }
297}
298
299static inline void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset,
300 kernel_pid_t pid)
301{
302 if (IS_USED(MODULE_ZTIMER_USEC)) {
303 ztimer_set_wakeup(ZTIMER_USEC, timer, offset, pid);
304 }
305 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
306 ztimer_set_wakeup(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS), pid);
307 }
308 else {
309 _XTIMER_BACKEND_NOT_IMPLEMENTED;
310 }
311}
312
313static inline int xtimer_mutex_lock_timeout(mutex_t *mutex, uint64_t us)
314{
315 int res;
316
317 if (IS_USED(MODULE_ZTIMER_USEC)) {
318 assert(us <= UINT32_MAX);
319 res = ztimer_mutex_lock_timeout(ZTIMER_USEC, mutex, (uint32_t)us);
320 }
321 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
322 us = _div_round_up_u64(us, US_PER_MS);
323 assert(us <= UINT32_MAX);
324 res = ztimer_mutex_lock_timeout(ZTIMER_MSEC, mutex, (uint32_t)us);
325 }
326 else {
327 _XTIMER_BACKEND_NOT_IMPLEMENTED;
328 res = -1;
329 }
330
331 /* Impedance matching required: Convert -ECANCELED error code to -1: */
332 return res ? -1 : 0;
333}
334
335static inline int xtimer_rmutex_lock_timeout(rmutex_t *mutex, uint64_t us)
336{
337 int res;
338
339 if (IS_USED(MODULE_ZTIMER_USEC)) {
340 assert(us <= UINT32_MAX);
341 res = ztimer_rmutex_lock_timeout(ZTIMER_USEC, mutex, (uint32_t)us);
342 }
343 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
344 us = _div_round_up_u64(us, US_PER_MS);
345 assert(us <= UINT32_MAX);
346 res = ztimer_rmutex_lock_timeout(ZTIMER_MSEC, mutex, (uint32_t)us);
347 }
348 else {
349 _XTIMER_BACKEND_NOT_IMPLEMENTED;
350 res = -1;
351 }
352
353 /* Impedance matching required: Convert -ECANCELED error code to -1: */
354 return res ? -1 : 0;
355}
356
357static inline void xtimer_set_timeout_flag(xtimer_t *t, uint32_t timeout)
358{
359 if (IS_USED(MODULE_ZTIMER_USEC)) {
361 }
362 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
363 ztimer_set_timeout_flag(ZTIMER_MSEC, t, _div_round_up_u32(timeout, US_PER_MS));
364 }
365 else {
366 _XTIMER_BACKEND_NOT_IMPLEMENTED;
367 }
368}
369
370static inline void xtimer_set_timeout_flag64(xtimer_t *t, uint64_t timeout)
371{
372 assert(timeout <= UINT32_MAX);
373 xtimer_set_timeout_flag(t, timeout);
374}
375
376static inline void xtimer_spin(xtimer_ticks32_t ticks)
377{
378 if (IS_USED(MODULE_ZTIMER_USEC)) {
380 }
381 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
382 ztimer_spin(ZTIMER_MSEC, xtimer_msec_from_ticks(ticks));
383 }
384 else {
386 }
387}
388
391{
392 return a - b;
393}
394
397{
398 return a - b;
399}
400
403{
404 return (xtimer_ticks32_t)(a - b);
405}
406
407static inline xtimer_ticks64_t xtimer_ticks64(uint64_t ticks)
408{
409 return ticks;
410}
411
412static inline bool xtimer_less(xtimer_ticks32_t a, xtimer_ticks32_t b)
413{
414 return a < b;
415}
416
417static inline bool xtimer_less64(xtimer_ticks64_t a, xtimer_ticks64_t b)
418{
419 return a < b;
420}
421
422/* unsupported due to using ztimer (32Bit):
423 * please use ztimer64_xtimer_compat if need
424
425 xtimer_ticks64_t xtimer_now64(void);
426 uint64_t xtimer_now_usec64(void):
427 void xtimer_now_timex(timex_t *out)
428 void xtimer_set64(xtimer_t *timer, uint64_t offset_us);
429 void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset,
430 kernel_pid_t pid);
431 void xtimer_set_msg64(xtimer_t *timer, uint64_t offset,
432 msg_t *msg, kernel_pid_t target_pid);
433 int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t timeout);
434 */
435
436#endif /* DOXYGEN */
437
438#ifdef __cplusplus
439}
440#endif
441
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:76
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:89
#define US_PER_SEC
The number of microseconds per second.
Definition time_units.h:84
#define MS_PER_SEC
The number of milliseconds per second.
Definition time_units.h:74
#define NS_PER_US
The number of nanoseconds per microsecond.
Definition time_units.h:99
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_nanosleep(uint32_t nanoseconds)
Stop execution of a thread for some time.
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:290
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:742
static ztimer_now_t ztimer_now(ztimer_clock_t *clock)
Get the current time from a clock.
Definition ztimer.h:683
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.
Math helper macros.
#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:192
Mutex structure.
Definition mutex.h:36
Mutex structure.
Definition rmutex.h:34
xtimer timestamp (32 bit)
Definition xtimer.h:91
xtimer timestamp (64 bit)
Definition xtimer.h:82
ztimer structure
Definition ztimer.h:319
Utility library for comparing and computing timestamps.
ztimer API