AVR Libc Home Page | AVR Libc Development Pages | ||||
Main Page | User Manual | Library Reference | FAQ | Alphabetical Index | Example Projects |
00001 /* Copyright (c) 2002, Marek Michalkiewicz 00002 Copyright (c) 2004,2005,2007 Joerg Wunsch 00003 Copyright (c) 2007 Florin-Viorel Petrov 00004 All rights reserved. 00005 00006 Redistribution and use in source and binary forms, with or without 00007 modification, are permitted provided that the following conditions are met: 00008 00009 * Redistributions of source code must retain the above copyright 00010 notice, this list of conditions and the following disclaimer. 00011 00012 * Redistributions in binary form must reproduce the above copyright 00013 notice, this list of conditions and the following disclaimer in 00014 the documentation and/or other materials provided with the 00015 distribution. 00016 00017 * Neither the name of the copyright holders nor the names of 00018 contributors may be used to endorse or promote products derived 00019 from this software without specific prior written permission. 00020 00021 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00022 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00023 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00024 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00025 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00026 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00027 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00030 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 POSSIBILITY OF SUCH DAMAGE. */ 00032 00033 /* $Id: delay.h.in 2189 2010-10-13 09:39:34Z aboyapati $ */ 00034 00035 #ifndef _UTIL_DELAY_H_ 00036 #define _UTIL_DELAY_H_ 1 00037 00038 #ifndef __HAS_DELAY_CYCLES 00039 #define __HAS_DELAY_CYCLES 1 00040 #endif 00041 00042 #include <inttypes.h> 00043 #include <util/delay_basic.h> 00044 00045 /** \file */ 00046 /** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops 00047 \code 00048 #define F_CPU 1000000UL // 1 MHz 00049 //#define F_CPU 14.7456E6 00050 #include <util/delay.h> 00051 \endcode 00052 00053 \note As an alternative method, it is possible to pass the 00054 F_CPU macro down to the compiler from the Makefile. 00055 Obviously, in that case, no \c \#define statement should be 00056 used. 00057 00058 The functions in this header file are wrappers around the basic 00059 busy-wait functions from <util/delay_basic.h>. They are meant as 00060 convenience functions where actual time values can be specified 00061 rather than a number of cycles to wait for. The idea behind is 00062 that compile-time constant expressions will be eliminated by 00063 compiler optimization so floating-point expressions can be used 00064 to calculate the number of delay cycles needed based on the CPU 00065 frequency passed by the macro F_CPU. 00066 00067 \note In order for these functions to work as intended, compiler 00068 optimizations <em>must</em> be enabled, and the delay time 00069 <em>must</em> be an expression that is a known constant at 00070 compile-time. If these requirements are not met, the resulting 00071 delay will be much longer (and basically unpredictable), and 00072 applications that otherwise do not use floating-point calculations 00073 will experience severe code bloat by the floating-point library 00074 routines linked into the application. 00075 00076 The functions available allow the specification of microsecond, and 00077 millisecond delays directly, using the application-supplied macro 00078 F_CPU as the CPU clock frequency (in Hertz). 00079 00080 */ 00081 00082 #if !defined(__DOXYGEN__) 00083 static inline void _delay_us(double __us) __attribute__((always_inline)); 00084 static inline void _delay_ms(double __ms) __attribute__((always_inline)); 00085 #endif 00086 00087 #ifndef F_CPU 00088 /* prevent compiler error by supplying a default */ 00089 # warning "F_CPU not defined for <util/delay.h>" 00090 # define F_CPU 1000000UL 00091 #endif 00092 00093 #ifndef __OPTIMIZE__ 00094 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" 00095 #endif 00096 00097 /** 00098 \ingroup util_delay 00099 00100 Perform a delay of \c __ms milliseconds, using _delay_loop_2(). 00101 00102 The macro F_CPU is supposed to be defined to a 00103 constant defining the CPU clock frequency (in Hertz). 00104 00105 The maximal possible delay is 262.14 ms / F_CPU in MHz. 00106 00107 When the user request delay which exceed the maximum possible one, 00108 _delay_ms() provides a decreased resolution functionality. In this 00109 mode _delay_ms() will work with a resolution of 1/10 ms, providing 00110 delays up to 6.5535 seconds (independent from CPU frequency). The 00111 user will not be informed about decreased resolution. 00112 00113 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) 00114 support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For 00115 values greater than the maximal possible delay, overflows results in 00116 no delay i.e., 0ms. 00117 00118 Conversion of __us into clock cycles may not always result in integer. 00119 By default, the clock cycles rounded up to next integer. This ensures that 00120 the user gets atleast __us microseconds of delay. 00121 00122 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__ 00123 to round down and round to closest integer. 00124 00125 Note: The new implementation of _delay_ms(double __ms) with 00126 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 00127 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay 00128 although this will be deprecated in future. 00129 00130 */ 00131 void 00132 _delay_ms(double __ms) 00133 { 00134 uint16_t __ticks; 00135 double __tmp ; 00136 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && !defined(__DELAY_BACKWARD_COMPATIBLE__) 00137 uint32_t __ticks_dc; 00138 extern void __builtin_avr_delay_cycles(unsigned long); 00139 __tmp = ((F_CPU) / 1e3) * __ms; 00140 00141 #if defined(__DELAY_ROUND_DOWN__) 00142 __ticks_dc = (uint32_t)fabs(__tmp); 00143 00144 #elif defined(__DELAY_ROUND_CLOSEST__) 00145 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00146 00147 #else 00148 //round up by default 00149 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00150 #endif 00151 00152 __builtin_avr_delay_cycles(__ticks_dc); 00153 00154 #elif !__HAS_DELAY_CYCLES || (__HAS_DELAY_CYCLES && !defined(__OPTIMIZE__)) || defined (__DELAY_BACKWARD_COMPATIBLE__) 00155 __tmp = ((F_CPU) / 4e3) * __ms; 00156 if (__tmp < 1.0) 00157 __ticks = 1; 00158 else if (__tmp > 65535) 00159 { 00160 // __ticks = requested delay in 1/10 ms 00161 __ticks = (uint16_t) (__ms * 10.0); 00162 while(__ticks) 00163 { 00164 // wait 1/10 ms 00165 _delay_loop_2(((F_CPU) / 4e3) / 10); 00166 __ticks --; 00167 } 00168 return; 00169 } 00170 else 00171 __ticks = (uint16_t)__tmp; 00172 _delay_loop_2(__ticks); 00173 #endif 00174 } 00175 00176 /** 00177 \ingroup util_delay 00178 00179 Perform a delay of \c __us microseconds, using _delay_loop_1(). 00180 00181 The macro F_CPU is supposed to be defined to a 00182 constant defining the CPU clock frequency (in Hertz). 00183 00184 The maximal possible delay is 768 us / F_CPU in MHz. 00185 00186 If the user requests a delay greater than the maximal possible one, 00187 _delay_us() will automatically call _delay_ms() instead. The user 00188 will not be informed about this case. 00189 00190 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) 00191 support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For 00192 values greater than the maximal possible delay, overflow results in 00193 no delay i.e., 0us. 00194 00195 Conversion of __us into clock cycles may not always result in integer. 00196 By default, the clock cycles rounded up to next integer. This ensures that 00197 the user gets atleast __us microseconds of delay. 00198 00199 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__ 00200 to round down and round to closest integer. 00201 00202 Note: The new implementation of _delay_us(double __us) with 00203 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 00204 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay 00205 although this will be deprecated in future. 00206 00207 */ 00208 void 00209 _delay_us(double __us) 00210 { 00211 uint8_t __ticks; 00212 double __tmp ; 00213 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && !defined(__DELAY_BACKWARD_COMPATIBLE__) 00214 uint32_t __ticks_dc; 00215 extern void __builtin_avr_delay_cycles(unsigned long); 00216 __tmp = ((F_CPU) / 1e6) * __us; 00217 00218 #if defined(__DELAY_ROUND_DOWN__) 00219 __ticks_dc = (uint32_t)fabs(__tmp); 00220 00221 #elif defined(__DELAY_ROUND_CLOSEST__) 00222 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00223 00224 #else 00225 //round up by default 00226 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00227 #endif 00228 00229 __builtin_avr_delay_cycles(__ticks_dc); 00230 00231 #elif !__HAS_DELAY_CYCLES || (__HAS_DELAY_CYCLES && !defined(__OPTIMIZE__)) || defined (__DELAY_BACKWARD_COMPATIBLE__) 00232 __tmp = ((F_CPU) / 3e6) * __us; 00233 if (__tmp < 1.0) 00234 __ticks = 1; 00235 else if (__tmp > 255) 00236 { 00237 _delay_ms(__us / 1000.0); 00238 return; 00239 } 00240 else 00241 __ticks = (uint8_t)__tmp; 00242 _delay_loop_1(__ticks); 00243 #endif 00244 } 00245 00246 00247 #endif /* _UTIL_DELAY_H_ */