1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/include/busy_wait.h
2024-01-09 19:03:15 +01:00

90 lines
2.1 KiB
C

/*
* Copyright (C) 2024 ML!PA Consulting GmbH
*
* 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.
*/
/**
* @defgroup busy_wait Busy Waiting low-level helpers
* @ingroup sys
*
* @brief This modules provides helper functions for busy waiting
* on short intervals before timers are initialized, e.g.
* in `board_init()`.
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @{
*/
#ifndef BUSY_WAIT_H
#define BUSY_WAIT_H
#include <stdint.h>
#include "periph_conf.h"
#include "time_units.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief CPU cycles per busy wait loop iteration
*
* This can be used to roughly estimate the number of cycles
* for a given wait time.
*/
#ifndef CPU_CYCLES_PER_LOOP
#define CPU_CYCLES_PER_LOOP 3
#endif
/**
* @brief Spin for a number of cycles.
*
* This will not take into account cycles spent on interrupts
* if they are enabled and occur.
*
* @param loops Number of loop iterations to take
*/
static inline void busy_wait(unsigned loops)
{
while (loops) {
/* This empty inline assembly should be enough to convince the
* compiler that the loop cannot be optimized out. Tested with
* GCC 12.2 and clang 16.0.0 successfully. */
__asm__ __volatile__ (
""
: /* no outputs */
: /* no inputs */
: /* no clobbers */
);
loops--;
}
}
/**
* @brief Spin for a number of microseconds.
*
* This will roughly try to match the requested delay time, but don't
* expect high accuracy.
*
* This will not take into account cycles spent on interrupts
* if they are enabled and occur.
*
* @param usec Number of µs to spin for.
*/
static inline void busy_wait_us(unsigned usec)
{
unsigned loops = ((uint64_t)usec * CLOCK_CORECLOCK)
/ (US_PER_SEC * CPU_CYCLES_PER_LOOP);
busy_wait(loops);
}
#ifdef __cplusplus
}
#endif
#endif /* BUSY_WAIT_H */
/** @} */