util_delay(3)

πŸ“¦ version 2.2.1, in fedora 43, fedora 44, opensuse-leap 16.0

util_delay πŸ’–βœ¨

okay bestie, sit DOWN because we're about to talk about the most ✨aesthetic✨ little corner of avr-libc: util_delay(3). this is the header that lets u just... say "wait 5 milliseconds" instead of counting clock cycles by hand like some kind of medieval peasant. iconic behavior fr. πŸŽ€


NAME 🫢

util_delay β€” no cap, that's the whole name. short, sweet, main character energy. πŸ’…


SYNOPSIS ✨

Macros 🌸

#define F_CPU   1000000UL

Functions πŸ¦‹

void _delay_ms (double __ms)
void _delay_us (double __us)

DETAILED DESCRIPTION πŸ’–

so like. here's the setup. before u can use any of this u gotta do the lil incantation:

#define F_CPU 1000000UL  // 1 MHz
//#define F_CPU 14.7456E6
#include <util/delay.h>
Note: lowkey there's another way β€” u can pass the F_CPU macro down to the compiler straight from the Makefile instead. but obviously, if u do that, do NOT also write a #define statement. pick a lane bestie, don't do both. 😭

the functions in this header file are wrappers around the basic busy-wait functions from <util/delay_basic.h>. they're meant as convenience functions, the whole point being that u get to specify an actual time value instead of a number of cycles to wait for. the idea behind it is that compile-time constant expressions will be eliminated by compiler optimization, so floating-point expressions can be used to calculate the number of delay cycles needed based on the CPU frequency passed by the macro F_CPU. it's giving "let the compiler do ur math homework". 🧚

Note: for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an expression that is a known constant at compile-time. if those requirements aren't met, the resulting delay will be much longer (and basically unpredictable), and applications that otherwise don't use floating-point calculations will experience severe code bloat by the floating-point library routines linked into the application. so like. please. turn on optimizations. i'm begging. πŸ™ˆ

the functions available allow the specification of microsecond and millisecond delays directly, using the application-supplied macro F_CPU as the CPU clock frequency (in Hertz).


MACRO DEFINITION DOCUMENTATION 🌈

#define F_CPU 1000000UL πŸ‘‘

CPU frequency in Hz. the macro F_CPU specifies the CPU frequency to be considered by the delay macros. this macro is normally supplied by the environment (e.g. from within a project header, or the project's Makefile). the value 1 MHz here is only provided as a 'vanilla' fallback if no such user-provided definition could be found. it's the plain little default that's just happy to be here. πŸ“

in terms of the delay functions, the CPU frequency can be given as a floating-point constant (e.g. 3.6864E6 for 3.6864 MHz). however, the macros in <util/setbaud.h> require it to be an integer value. so like, know ur audience. πŸ’€


FUNCTION DOCUMENTATION πŸ’œ

void _delay_ms (double __ms) ⭐

perform a delay of __ms milliseconds, using _delay_loop_2().

the macro F_CPU is supposed to be defined to a constant defining the CPU clock frequency (in Hertz).

the maximal possible delay is 262.14 ms / F_CPU in MHz.

when the user requests a delay which exceeds the maximum possible one, _delay_ms() provides a decreased resolution functionality. in this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). the user will not be informed about decreased resolution. so u just. won't know. it's fine. everything is fine. 😭

if the avr-gcc toolchain has __builtin_avr_delay_cycles() support, maximal possible delay is 4294967.295 ms / F_CPU in MHz. for values greater than the maximal possible delay, overflows results in no delay i.e., 0ms. yeah u read that right, zero. the delay just evaporates. πŸ’€

conversion of __ms into clock cycles may not always result in an integer. by default, the clock cycles are rounded up to the next integer. this ensures that the user gets at least __ms microseconds of delay.

alternatively, by defining the macro __DELAY_ROUND_DOWN__, or __DELAY_ROUND_CLOSEST__, before including this header file, the algorithm can be made to round down, or round to the closest integer, respectively. ur rounding era, ur choice. ✨

Note: the implementation of _delay_ms() based on __builtin_avr_delay_cycles() is not backward compatible with older implementations. in order to get functionality backward compatible with previous versions, the macro '__DELAY_BACKWARD_COMPATIBLE__' must be defined before including this header file. also, the backward compatible algorithm will be chosen if the code is compiled in a freestanding environment (GCC option -ffreestanding), as the math functions required for rounding are not available to the compiler then. no math for u in freestanding land bestie, sorry. 🫢

void _delay_us (double __us) πŸ¦‹

perform a delay of __us microseconds, using _delay_loop_1().

the macro F_CPU is supposed to be defined to a constant defining the CPU clock frequency (in Hertz).

the maximal possible delay is 768 us / F_CPU in MHz.

if the user requests a delay greater than the maximal possible one, _delay_us() will automatically call _delay_ms() instead. the user will not be informed about this case. sneaky lil glow-up, it just upgrades itself. πŸ™ˆ

if the avr-gcc toolchain has __builtin_avr_delay_cycles() support, maximal possible delay is 4294967.295 us / F_CPU in MHz. for values greater than the maximal possible delay, overflow results in no delay i.e., 0us. again. poof. gone. πŸ’€

conversion of __us into clock cycles may not always result in an integer. by default, the clock cycles are rounded up to the next integer. this ensures that the user gets at least __us microseconds of delay.

alternatively, by defining the macro __DELAY_ROUND_DOWN__, or __DELAY_ROUND_CLOSEST__, before including this header file, the algorithm can be made to round down, or round to the closest integer, respectively.

Note: the implementation of _delay_ms() based on __builtin_avr_delay_cycles() is not backward compatible with older implementations. in order to get functionality backward compatible with previous versions, the macro __DELAY_BACKWARD_COMPATIBLE__ must be defined before including this header file. also, the backward compatible algorithm will be chosen if the code is compiled in a freestanding environment (GCC option -ffreestanding), as the math functions required for rounding are not available to the compiler then.

AUTHOR 🌸

generated automatically by Doxygen for avr-libc from the source code. it didn't write itself bestie, a whole robot did it. πŸ€–πŸ’…


and that's the whole page!! Version 2.1.0, dated Sat Jan 29 2022 β€” this was util_delay(3), manual page number 3, part of avr-libc. stay delaying, stay optimized, and remember: known constant at compile-time or it's over for u. mwah. πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from