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_tsleep32(xtimer_ticks32_t ticks)
210{
212}
213
214static inline void xtimer_tsleep64(xtimer_ticks64_t ticks)
215{
216 const uint32_t max_sleep = UINT32_MAX;
217 uint64_t time = xtimer_usec_from_ticks64(ticks);
218
219 while (time > max_sleep) {
220 xtimer_usleep(max_sleep);
221 time -= max_sleep;
222 }
223 xtimer_usleep(time);
224}
225
226static inline void xtimer_set(xtimer_t *timer, uint32_t offset)
227{
228 if (IS_USED(MODULE_ZTIMER_USEC)) {
229 ztimer_set(ZTIMER_USEC, timer, offset);
230 }
231 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
232 ztimer_set(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS));
233 }
234 else {
235 _XTIMER_BACKEND_NOT_IMPLEMENTED;
236 }
237}
238
239static inline void xtimer_remove(xtimer_t *timer)
240{
241 if (IS_USED(MODULE_ZTIMER_USEC)) {
243 }
244 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
246 }
247 else {
248 _XTIMER_BACKEND_NOT_IMPLEMENTED;
249 }
250}
251
252static inline void xtimer_set_msg(xtimer_t *timer, uint32_t offset, msg_t *msg,
253 kernel_pid_t target_pid)
254{
255 if (IS_USED(MODULE_ZTIMER_USEC)) {
256 ztimer_set_msg(ZTIMER_USEC, timer, offset, msg, target_pid);
257 }
258 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
259 ztimer_set_msg(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS),
260 msg, target_pid);
261 }
262 else {
263 _XTIMER_BACKEND_NOT_IMPLEMENTED;
264 }
265}
266
267static inline void xtimer_periodic_wakeup(xtimer_ticks32_t *last_wakeup,
268 uint32_t period)
269{
270 if (IS_USED(MODULE_ZTIMER_USEC)) {
271 ztimer_periodic_wakeup(ZTIMER_USEC, last_wakeup, period);
272 }
273 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
274 ztimer_periodic_wakeup(ZTIMER_MSEC, last_wakeup, _div_round_up_u32(period, US_PER_MS));
275 }
276 else {
277 _XTIMER_BACKEND_NOT_IMPLEMENTED;
278 }
279}
280
281static inline int xtimer_msg_receive_timeout(msg_t *msg, uint32_t timeout)
282{
283 if (IS_USED(MODULE_ZTIMER_USEC)) {
284 return ztimer_msg_receive_timeout(ZTIMER_USEC, msg, timeout);
285 }
286 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
287 return ztimer_msg_receive_timeout(ZTIMER_MSEC, msg, _div_round_up_u32(timeout, US_PER_MS));
288 }
289 else {
290 _XTIMER_BACKEND_NOT_IMPLEMENTED;
291 }
292}
293
294static inline void xtimer_set_wakeup(xtimer_t *timer, uint32_t offset,
295 kernel_pid_t pid)
296{
297 if (IS_USED(MODULE_ZTIMER_USEC)) {
298 ztimer_set_wakeup(ZTIMER_USEC, timer, offset, pid);
299 }
300 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
301 ztimer_set_wakeup(ZTIMER_MSEC, timer, _div_round_up_u32(offset, US_PER_MS), pid);
302 }
303 else {
304 _XTIMER_BACKEND_NOT_IMPLEMENTED;
305 }
306}
307
308static inline int xtimer_mutex_lock_timeout(mutex_t *mutex, uint64_t us)
309{
310 int res;
311
312 if (IS_USED(MODULE_ZTIMER_USEC)) {
313 assert(us <= UINT32_MAX);
314 res = ztimer_mutex_lock_timeout(ZTIMER_USEC, mutex, (uint32_t)us);
315 }
316 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
317 us = _div_round_up_u64(us, US_PER_MS);
318 assert(us <= UINT32_MAX);
319 res = ztimer_mutex_lock_timeout(ZTIMER_MSEC, mutex, (uint32_t)us);
320 }
321 else {
322 _XTIMER_BACKEND_NOT_IMPLEMENTED;
323 res = -1;
324 }
325
326 /* Impedance matching required: Convert -ECANCELED error code to -1: */
327 return res ? -1 : 0;
328}
329
330static inline int xtimer_rmutex_lock_timeout(rmutex_t *mutex, uint64_t us)
331{
332 int res;
333
334 if (IS_USED(MODULE_ZTIMER_USEC)) {
335 assert(us <= UINT32_MAX);
336 res = ztimer_rmutex_lock_timeout(ZTIMER_USEC, mutex, (uint32_t)us);
337 }
338 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
339 us = _div_round_up_u64(us, US_PER_MS);
340 assert(us <= UINT32_MAX);
341 res = ztimer_rmutex_lock_timeout(ZTIMER_MSEC, mutex, (uint32_t)us);
342 }
343 else {
344 _XTIMER_BACKEND_NOT_IMPLEMENTED;
345 res = -1;
346 }
347
348 /* Impedance matching required: Convert -ECANCELED error code to -1: */
349 return res ? -1 : 0;
350}
351
352static inline void xtimer_set_timeout_flag(xtimer_t *t, uint32_t timeout)
353{
354 if (IS_USED(MODULE_ZTIMER_USEC)) {
356 }
357 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
358 ztimer_set_timeout_flag(ZTIMER_MSEC, t, _div_round_up_u32(timeout, US_PER_MS));
359 }
360 else {
361 _XTIMER_BACKEND_NOT_IMPLEMENTED;
362 }
363}
364
365static inline void xtimer_set_timeout_flag64(xtimer_t *t, uint64_t timeout)
366{
367 assert(timeout <= UINT32_MAX);
368 xtimer_set_timeout_flag(t, timeout);
369}
370
371static inline void xtimer_spin(xtimer_ticks32_t ticks)
372{
373 if (IS_USED(MODULE_ZTIMER_USEC)) {
375 }
376 else if (IS_USED(MODULE_ZTIMER_MSEC)) {
377 ztimer_spin(ZTIMER_MSEC, xtimer_msec_from_ticks(ticks));
378 }
379 else {
381 }
382}
383
386{
387 return a - b;
388}
389
392{
393 return a - b;
394}
395
398{
399 return (xtimer_ticks32_t)(a - b);
400}
401
402static inline xtimer_ticks64_t xtimer_ticks64(uint64_t ticks)
403{
404 return ticks;
405}
406
407static inline bool xtimer_less(xtimer_ticks32_t a, xtimer_ticks32_t b)
408{
409 return a < b;
410}
411
412static inline bool xtimer_less64(xtimer_ticks64_t a, xtimer_ticks64_t b)
413{
414 return a < b;
415}
416
417/* unsupported due to using ztimer (32Bit):
418 * please use ztimer64_xtimer_compat if need
419
420 xtimer_ticks64_t xtimer_now64(void);
421 uint64_t xtimer_now_usec64(void):
422 void xtimer_now_timex(timex_t *out)
423 void xtimer_set64(xtimer_t *timer, uint64_t offset_us);
424 void xtimer_set_wakeup64(xtimer_t *timer, uint64_t offset,
425 kernel_pid_t pid);
426 void xtimer_set_msg64(xtimer_t *timer, uint64_t offset,
427 msg_t *msg, kernel_pid_t target_pid);
428 int xtimer_msg_receive_timeout64(msg_t *msg, uint64_t timeout);
429 */
430
431#endif /* DOXYGEN */
432
433#ifdef __cplusplus
434}
435#endif
436
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
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: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