source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/tools/avr/avr/include/util/delay.h @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 2 years ago

Adding new version

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