AVR-LibC  2.2.0
Standard C library for AVR-GCC
 

AVR-LibC Documentation

Logo

AVR-LibC Development Pages

Main Page

User Manual

Library Reference

FAQ

Example Projects

File List

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/* $Id$ */
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# ifndef __ATTR_ALWAYS_INLINE__
44# define __ATTR_ALWAYS_INLINE__ __inline__ __attribute__((__always_inline__))
45# endif
46
47#endif /* __DOXYGEN__ */
48
49#include <stdint.h>
50#include <util/delay_basic.h>
51
52/** \file */
53/** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops
54 \code
55 #define F_CPU 1000000UL // 1 MHz
56 //#define F_CPU 14.7456e6
57 #include <util/delay.h>
58 \endcode
59
60 \note As an alternative method, it is possible to pass the
61 F_CPU macro down to the compiler from the Makefile.
62 Obviously, in that case, no \c \#define statement should be
63 used.
64
65 The functions in this header file are wrappers around the basic
66 busy-wait functions from <tt><util/delay_basic.h></tt>. They are meant as
67 convenience functions where actual time values can be specified
68 rather than a number of cycles to wait for. The idea behind is
69 that compile-time constant expressions will be eliminated by
70 compiler optimization so floating-point expressions can be used
71 to calculate the number of delay cycles needed based on the CPU
72 frequency passed by the macro F_CPU.
73
74 \note In order for these functions to work as intended, compiler
75 optimizations <em>must</em> be enabled, and the delay time
76 <em>must</em> be an expression that is a known constant at
77 compile-time. If these requirements are not met, the resulting
78 delay will be much longer (and basically unpredictable), and
79 applications that otherwise do not use floating-point calculations
80 will experience severe code bloat by the floating-point library
81 routines linked into the application.
82
83 The functions available allow the specification of microsecond, and
84 millisecond delays directly, using the application-supplied macro
85 F_CPU as the CPU clock frequency (in Hertz).
86*/
87
88
89#ifndef F_CPU
90/* prevent compiler error by supplying a default */
91# warning "F_CPU not defined for <util/delay.h>"
92/** \ingroup util_delay
93 \def F_CPU
94 \brief CPU frequency in Hz
95
96 The macro F_CPU specifies the CPU frequency to be considered by
97 the delay macros. This macro is normally supplied by the
98 environment (e.g. from within a project header, or the project's
99 Makefile). The value 1 MHz here is only provided as a "vanilla"
100 fallback if no such user-provided definition could be found.
101
102 In terms of the delay functions, the CPU frequency can be given as
103 a floating-point constant (e.g. 3.6864e6 for 3.6864 MHz).
104 However, the macros in <util/setbaud.h> require it to be an
105 integer value.
106 */
107# define F_CPU 1000000UL
108#endif
109
110#ifndef __OPTIMIZE__
111# warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
112#endif
113
114/**
115 \ingroup util_delay
116
117 Perform a delay of \c __ms milliseconds, using _delay_loop_2().
118
119 The macro #F_CPU is supposed to be defined to a
120 constant defining the CPU clock frequency (in Hertz).
121
122 The maximal possible delay is 262.14 ms / F_CPU in MHz.
123
124 When the user request delay which exceed the maximum possible one,
125 _delay_ms() provides a decreased resolution functionality. In this
126 mode _delay_ms() will work with a resolution of 1/10&nbsp;ms, providing
127 delays up to 6.5535 seconds (independent from CPU frequency). The
128 user will not be informed about decreased resolution.
129
130 If the avr-gcc toolchain has \c __builtin_avr_delay_cycles()
131 support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For
132 values greater than the maximal possible delay, overflow may result in
133 no delay i.e., 0&nbsp;ms.
134
135 Conversion of \c __ms into clock cycles may not always result in
136 an integral value. By default, the clock cycles are rounded up to the next
137 integer. This ensures that the user gets at least \c __ms
138 microseconds of delay.
139
140 Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
141 \c __DELAY_ROUND_CLOSEST__, before including this header file, the
142 algorithm can be made to round down, or round to closest integer,
143 respectively.
144
145 \note The implementation of _delay_ms() based on
146 \c __builtin_avr_delay_cycles() is not backward compatible with older
147 implementations. In order to get functionality backward compatible
148 with previous versions, the macro \c __DELAY_BACKWARD_COMPATIBLE__
149 must be defined before including this header file.
150 */
151static __ATTR_ALWAYS_INLINE__ void _delay_ms(double __ms);
152
153void
154_delay_ms(double __ms)
155{
156 double __tmp ;
157#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) \
158 && !defined(__DELAY_BACKWARD_COMPATIBLE__)
159 uint32_t __ticks_dc;
160 extern void __builtin_avr_delay_cycles(uint32_t);
161 __tmp = ((F_CPU) / 1e3) * __ms;
162
163 #if defined(__DELAY_ROUND_DOWN__)
164 __ticks_dc = (uint32_t)__builtin_fabs(__tmp);
165
166 #elif defined(__DELAY_ROUND_CLOSEST__)
167 __ticks_dc = (uint32_t)(__builtin_fabs(__tmp)+0.5);
168
169 #else
170 //round up by default
171 __ticks_dc = (uint32_t)(__builtin_ceil(__builtin_fabs(__tmp)));
172 #endif
173
174 __builtin_avr_delay_cycles(__ticks_dc);
175
176#else
177 uint16_t __ticks;
178 __tmp = ((F_CPU) / 4e3) * __ms;
179 if (__tmp < 1.0)
180 __ticks = 1;
181 else if (__tmp > 65535)
182 {
183 // __ticks = requested delay in 1/10 ms
184 __ticks = (uint16_t) (__ms * 10.0);
185 while(__ticks)
186 {
187 // wait 1/10 ms
188 _delay_loop_2(((F_CPU) / 4e3) / 10);
189 __ticks --;
190 }
191 return;
192 }
193 else
194 __ticks = (uint16_t)__tmp;
195 _delay_loop_2(__ticks);
196#endif
197}
198
199/**
200 \ingroup util_delay
201
202 Perform a delay of \c __us microseconds, using _delay_loop_1().
203
204 The macro #F_CPU is supposed to be defined to a
205 constant defining the CPU clock frequency (in Hertz).
206
207 The maximal possible delay is 768 &mu;s / F_CPU in MHz.
208
209 If the user requests a delay greater than the maximal possible one,
210 _delay_us() will automatically call _delay_ms() instead. The user
211 will not be informed about this case.
212
213 If the avr-gcc toolchain has __builtin_avr_delay_cycles()
214 support, maximal possible delay is 4294967.295 &mu;s/ F_CPU in MHz. For
215 values greater than the maximal possible delay, overflow may result in
216 no delay i.e., 0&nbsp;&mu;s.
217
218 Conversion of \c __us into clock cycles may not always result in
219 integer. By default, the clock cycles are rounded up to next
220 integer. This ensures that the user gets at least \c __us
221 microseconds of delay.
222
223 Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or
224 \c __DELAY_ROUND_CLOSEST__, before including this header file, the
225 algorithm can be made to round down, or round to closest integer,
226 respectively.
227
228 \note The implementation of _delay_us() based on
229 \c __builtin_avr_delay_cycles() is not backward compatible with older
230 implementations. In order to get functionality backward compatible
231 with previous versions, the macro \c __DELAY_BACKWARD_COMPATIBLE__
232 must be defined before including this header file.
233 */
234static __ATTR_ALWAYS_INLINE__ void _delay_us(double __us);
235
236void
237_delay_us(double __us)
238{
239 double __tmp ;
240#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) \
241 && !defined(__DELAY_BACKWARD_COMPATIBLE__)
242 uint32_t __ticks_dc;
243 extern void __builtin_avr_delay_cycles(uint32_t);
244 __tmp = ((F_CPU) / 1e6) * __us;
245
246 #if defined(__DELAY_ROUND_DOWN__)
247 __ticks_dc = (uint32_t)__builtin_fabs(__tmp);
248
249 #elif defined(__DELAY_ROUND_CLOSEST__)
250 __ticks_dc = (uint32_t)(__builtin_fabs(__tmp)+0.5);
251
252 #else
253 //round up by default
254 __ticks_dc = (uint32_t)(__builtin_ceil(__builtin_fabs(__tmp)));
255 #endif
256
257 __builtin_avr_delay_cycles(__ticks_dc);
258
259#else
260 uint8_t __ticks;
261 double __tmp2 ;
262 __tmp = ((F_CPU) / 3e6) * __us;
263 __tmp2 = ((F_CPU) / 4e6) * __us;
264 if (__tmp < 1.0)
265 __ticks = 1;
266 else if (__tmp2 > 65535)
267 {
268 _delay_ms(__us / 1000.0);
269 return;
270 }
271 else if (__tmp > 255)
272 {
273 uint16_t __ticks=(uint16_t)__tmp2;
274 _delay_loop_2(__ticks);
275 return;
276 }
277 else
278 __ticks = (uint8_t)__tmp;
279 _delay_loop_1(__ticks);
280#endif
281}
282
283
284#endif /* _UTIL_DELAY_H_ */
unsigned int uint16_t
Definition: stdint.h:93
unsigned long int uint32_t
Definition: stdint.h:103
unsigned char uint8_t
Definition: stdint.h:83
void _delay_loop_1(uint8_t __count)
Definition: delay_basic.h:81
void _delay_loop_2(uint16_t __count)
Definition: delay_basic.h:103
#define F_CPU
CPU frequency in Hz.
Definition: delay.h:107
static void _delay_us(double __us)
Definition: delay.h:237
static void _delay_ms(double __ms)
Definition: delay.h:154