AVR-LibC  2.3.0
Standard C library for AVR-GCC
 

AVR-LibC Manual

AVR-LibC Sources

Main Page

User Manual

Lib­rary Refe­rence

FAQ

Exam­ple Pro­jects

Index

Loading...
Searching...
No Matches
delay.h
Go to the documentation of this file.
1/* Copyright (c) 2002, Marek Michalkiewicz
2 Copyright (c) 2004,2005,2007 Joerg Wunsch
3 Copyright (c) 2007 Florin-Viorel Petrov
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
17 * Neither the name of the copyright holders nor the names of
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE. */
32
33/* include/util/delay.h. Generated from delay.h.in by configure. */
34
35#ifndef _UTIL_DELAY_H_
36#define _UTIL_DELAY_H_ 1
37
38#ifndef __DOXYGEN__
39# ifndef __HAS_DELAY_CYCLES
40# define __HAS_DELAY_CYCLES 1
41# endif
42
43#endif /* __DOXYGEN__ */
44
45#include <stdint.h>
46#include <util/delay_basic.h>
47#include <bits/attribs.h>
48
49/** \file */
50/** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
51 \code
52 #define F_CPU 1000000UL // 1 MHz
53 //#define F_CPU 14.7456e6
54 #include <util/delay.h>
55 \endcode
56
57 The functions in this header are meant as convenience functions where
58 actual time values can be specified as a delay time,
59 rather than a number of cycles to wait for.
60
61 This requires that the clock frequency of the device is provided
62 in the \c #F_CPU macro in units of Hertz. The macro must be defined
63 before including the <util/delay.h> header. It can be defined
64 in the source code like indicated above, or it can be defined on the
65 command line / in a Makefile by means of <tt>-D F_CPU=...</tt>
66
67 The functions in this header file are wrappers around the basic
68 busy-wait functions from <tt><util/delay_basic.h></tt>, or, when
69 supported by the compiler, then
70 <a href="https://gcc.gnu.org/onlinedocs/gcc/AVR-Built-in-Functions.html#index-_005f_005fbuiltin_005favr_005fdelay_005fcycles"
71 >__builtin_avr_delay_cycles()</a> is used instead.
72
73 In any case, the delay functions provided by this header will not disable
74 interrupts, which means hat the delay time will be longer than
75 specified when interrupts occur while a delay function is running.
76
77 In order for these functions to work as intended, compiler
78 optimizations <em>must</em> be enabled, and the delay time
79 <em>must</em> be an expression that is a known constant at
80 compile-time. If these requirements are not met, the resulting
81 delay will be much longer (and basically unpredictable), and
82 applications that otherwise do not use floating-point calculations
83 will experience severe code bloat by the floating-point library
84 routines linked into the application.
85 The idea is
86 that compile-time constant expressions will be eliminated by
87 compiler optimization so floating-point expressions can be used
88 to calculate the number of delay cycles needed based on the CPU
89 frequency passed by the macro F_CPU.
90
91 The functions available allow the specification of microsecond, and
92 millisecond delays directly, using the application-supplied macro
93 F_CPU as the CPU clock frequency in Hertz.
94*/
95
96
97#ifndef F_CPU
98/* prevent compiler error by supplying a default */
99# warning "F_CPU not defined for <util/delay.h>"
100/** \ingroup util_delay
101 \def F_CPU
102 \brief CPU frequency in Hz
103
104 The macro F_CPU specifies the CPU frequency in Hertz to be considered by
105 the delay functions. This macro is normally supplied by the
106 environment (e.g. from within a project header, or the project's
107 Makefile). The value 1 MHz here is only provided as a
108 fallback default if no such user-provided definition could be found.
109
110 In terms of the delay functions, the CPU frequency can be given as
111 a floating-point constant (e.g. 3.6864e6 for 3.6864 MHz).
112 However, the macros in <util/setbaud.h> require it to be an
113 integer value.
114 */
115# define F_CPU 1000000UL
116#endif
117
118#ifndef __OPTIMIZE__
119# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
120#endif
121
122/**
123 \ingroup util_delay
124
125 Perform a delay of \c __ms milliseconds.
126
127 The macro #F_CPU is supposed to be defined to a
128 constant defining the CPU clock frequency in Hertz.
129
130- If \c __builtin_avr_delay_cycles() is
131\if GIT_BRANCH_IS_ONLINEDOCS
132 supported
133\else
134 \ref faq_toolchain_support "supported"
135\endif
136 by the compiler, then
137 the maximal possible delay is 4294967.04 / f<sub>CPU</sub> milliseconds
138 where f<sub>CPU</sub> denotes the CPU frequency in units of 1 MHz.
139 This is around 71 minutes / f<sub>CPU</sub>.
140 Values greater than that are saturated to this value.
141
142- Otherwise, _delay_loop_2() is used as a fallback, and the maximal
143 possible delay is 262.14 / f<sub>CPU</sub> milliseconds.
144 When the user requests a delay which exceeds the maximum possible one,
145 _delay_ms() provides a decreased resolution functionality. In this
146 mode _delay_ms() will work with a resolution of 1/10&nbsp;ms, providing
147 delays up to 6.5535 seconds (independent from CPU frequency). The
148 user will not be informed about decreased resolution.
149.
150
151 Conversion of \c __ms into clock cycles may not always result in
152 an integral value. By default, the clock cycles are rounded up to the next
153 integer. This ensures that the user gets at least \c __ms
154 microseconds of delay.
155 Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
156 \c __DELAY_ROUND_CLOSEST__, before including this header file, the
157 algorithm can be made to round down, or round to closest integer,
158 respectively.
159
160 \note The implementation of _delay_ms() based on
161 \c __builtin_avr_delay_cycles() is not backward compatible with older
162 implementations. In order to get a functionality backward compatible
163 with previous versions, the macro \c __DELAY_BACKWARD_COMPATIBLE__
164 must be defined before including this header file.
165 */
166static __ATTR_ALWAYS_INLINE__ void
167_delay_ms(double __ms)
168{
169#if (__HAS_DELAY_CYCLES \
170 && defined(__OPTIMIZE__) \
171 && !defined(__DELAY_BACKWARD_COMPATIBLE__))
172 uint32_t __ticks_dc;
173 double __tmp = ((F_CPU) / 1e3) * __ms;
174
175 #if defined(__DELAY_ROUND_DOWN__)
176 __tmp = __builtin_fabs (__tmp);
177 #elif defined(__DELAY_ROUND_CLOSEST__)
178 __tmp = __builtin_fabs (__tmp) + 0.5;
179 #else
180 /* Round up by default */
181 __tmp = __builtin_ceil (__builtin_fabs (__tmp));
182 #endif
183
184 /* Saturate. Notice that the largest representable float
185 in this context is 0xffffff00. */
186 __ticks_dc = __tmp >= 4294967040.0 ? 0xffffff00 : (uint32_t) __tmp;
187 __builtin_avr_delay_cycles(__ticks_dc);
188#else
189 uint16_t __ticks;
190 double __tmp = ((F_CPU) / 4e3) * __ms;
191 if (__tmp < 1.0)
192 __ticks = 1;
193 else if (__tmp > 65535)
194 {
195 // __ticks = requested delay in 1/10 ms
196 __ticks = (uint16_t) (__ms * 10.0);
197 while(__ticks)
198 {
199 // wait 1/10 ms
200 _delay_loop_2(((F_CPU) / 4e3) / 10);
201 __ticks--;
202 }
203 return;
204 }
205 else
206 __ticks = (uint16_t)__tmp;
207 _delay_loop_2(__ticks);
208#endif
209}
210
211/**
212 \ingroup util_delay
213
214 Perform a delay of \c __us microseconds.
215
216 The macro #F_CPU is supposed to be defined to a
217 constant defining the CPU clock frequency in Hertz.
218
219- If \c __builtin_avr_delay_cycles() is
220\if GIT_BRANCH_IS_ONLINEDOCS
221 supported
222\else
223 \ref faq_toolchain_support "supported"
224\endif
225 by the compiler, then
226 the maximal possible delay is 4294967040 / f<sub>CPU</sub> microseconds
227 where f<sub>CPU</sub> denotes the CPU frequency in units of 1 MHz.
228 This is around 71 minutes / f<sub>CPU</sub>.
229 Values greater than that are saturated to this value.
230
231- Otherwise, _delay_loop_1() is used as a fallback, and the maximal
232 possible delay is 768 / f<sub>CPU</sub> microseconds.
233 If the user requests a delay greater than the maximal possible one,
234 _delay_us() will automatically call _delay_ms() instead. The user
235 will not be informed about this case.
236.
237
238 Conversion of \c __us into clock cycles may not always result in an
239 integral value. By default, the clock cycles are rounded up to next
240 integer. This ensures that the user gets at least \c __us
241 microseconds of delay.
242 Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
243 \c __DELAY_ROUND_CLOSEST__, before including this header file, the
244 algorithm can be made to round down, or round to closest integer,
245 respectively.
246
247 \note The implementation of _delay_us() based on
248 \c __builtin_avr_delay_cycles() is not backward compatible with older
249 implementations. In order to get a functionality backward compatible
250 with previous versions, the macro \c __DELAY_BACKWARD_COMPATIBLE__
251 must be defined before including this header file.
252 */
253static __ATTR_ALWAYS_INLINE__ void
254_delay_us(double __us)
255{
256#if (__HAS_DELAY_CYCLES \
257 && defined(__OPTIMIZE__) \
258 && !defined(__DELAY_BACKWARD_COMPATIBLE__))
259 uint32_t __ticks_dc;
260 double __tmp = ((F_CPU) / 1e6) * __us;
261
262 #if defined(__DELAY_ROUND_DOWN__)
263 __tmp = __builtin_fabs (__tmp);
264 #elif defined(__DELAY_ROUND_CLOSEST__)
265 __tmp = __builtin_fabs (__tmp) + 0.5;
266 #else
267 /* Round up by default */
268 __tmp = __builtin_ceil (__builtin_fabs (__tmp));
269 #endif
270
271 /* Saturate. Notice that the largest representable float
272 in this context is 0xffffff00. */
273 __ticks_dc = __tmp >= 4294967040.0 ? 0xffffff00 : (uint32_t) __tmp;
274 __builtin_avr_delay_cycles(__ticks_dc);
275#else
276 uint8_t __ticks;
277 double __tmp = ((F_CPU) / 3e6) * __us;
278 double __tmp2 = ((F_CPU) / 4e6) * __us;
279 if (__tmp < 1.0)
280 __ticks = 1;
281 else if (__tmp2 > 65535)
282 {
283 _delay_ms(__us / 1000.0);
284 return;
285 }
286 else if (__tmp > 255)
287 {
288 uint16_t __ticks=(uint16_t)__tmp2;
289 _delay_loop_2(__ticks);
290 return;
291 }
292 else
293 __ticks = (uint8_t)__tmp;
294 _delay_loop_1(__ticks);
295#endif
296}
297
298#endif /* _UTIL_DELAY_H_ */
unsigned int uint16_t
Definition: stdint.h:96
unsigned long int uint32_t
Definition: stdint.h:114
unsigned char uint8_t
Definition: stdint.h:88
void _delay_loop_1(uint8_t __count)
Definition: delay_basic.h:84
void _delay_loop_2(uint16_t __count)
Definition: delay_basic.h:111
static void _delay_ms(double __ms)
Definition: delay.h:167
#define F_CPU
CPU frequency in Hz.
Definition: delay.h:115
static void _delay_us(double __us)
Definition: delay.h:254