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 #include <math.h> 00045 00046 /** \file */ 00047 /** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops 00048 \code 00049 #define F_CPU 1000000UL // 1 MHz 00050 //#define F_CPU 14.7456E6 00051 #include <util/delay.h> 00052 \endcode 00053 00054 \note As an alternative method, it is possible to pass the 00055 F_CPU macro down to the compiler from the Makefile. 00056 Obviously, in that case, no \c \#define statement should be 00057 used. 00058 00059 The functions in this header file are wrappers around the basic 00060 busy-wait functions from <util/delay_basic.h>. They are meant as 00061 convenience functions where actual time values can be specified 00062 rather than a number of cycles to wait for. The idea behind is 00063 that compile-time constant expressions will be eliminated by 00064 compiler optimization so floating-point expressions can be used 00065 to calculate the number of delay cycles needed based on the CPU 00066 frequency passed by the macro F_CPU. 00067 00068 \note In order for these functions to work as intended, compiler 00069 optimizations <em>must</em> be enabled, and the delay time 00070 <em>must</em> be an expression that is a known constant at 00071 compile-time. If these requirements are not met, the resulting 00072 delay will be much longer (and basically unpredictable), and 00073 applications that otherwise do not use floating-point calculations 00074 will experience severe code bloat by the floating-point library 00075 routines linked into the application. 00076 00077 The functions available allow the specification of microsecond, and 00078 millisecond delays directly, using the application-supplied macro 00079 F_CPU as the CPU clock frequency (in Hertz). 00080 00081 */ 00082 00083 #if !defined(__DOXYGEN__) 00084 static inline void _delay_us(double __us) __attribute__((always_inline)); 00085 static inline void _delay_ms(double __ms) __attribute__((always_inline)); 00086 #endif 00087 00088 #ifndef F_CPU 00089 /* prevent compiler error by supplying a default */ 00090 # warning "F_CPU not defined for <util/delay.h>" 00091 # define F_CPU 1000000UL 00092 #endif 00093 00094 #ifndef __OPTIMIZE__ 00095 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" 00096 #endif 00097 00098 /** 00099 \ingroup util_delay 00100 00101 Perform a delay of \c __ms milliseconds, using _delay_loop_2(). 00102 00103 The macro F_CPU is supposed to be defined to a 00104 constant defining the CPU clock frequency (in Hertz). 00105 00106 The maximal possible delay is 262.14 ms / F_CPU in MHz. 00107 00108 When the user request delay which exceed the maximum possible one, 00109 _delay_ms() provides a decreased resolution functionality. In this 00110 mode _delay_ms() will work with a resolution of 1/10 ms, providing 00111 delays up to 6.5535 seconds (independent from CPU frequency). The 00112 user will not be informed about decreased resolution. 00113 00114 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) 00115 support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For 00116 values greater than the maximal possible delay, overflows results in 00117 no delay i.e., 0ms. 00118 00119 Conversion of __us into clock cycles may not always result in integer. 00120 By default, the clock cycles rounded up to next integer. This ensures that 00121 the user gets atleast __us microseconds of delay. 00122 00123 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__ 00124 to round down and round to closest integer. 00125 00126 Note: The new implementation of _delay_ms(double __ms) with 00127 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 00128 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay 00129 although this will be deprecated in future. 00130 00131 */ 00132 void 00133 _delay_ms(double __ms) 00134 { 00135 uint16_t __ticks; 00136 double __tmp ; 00137 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && !defined(__DELAY_BACKWARD_COMPATIBLE__) 00138 uint32_t __ticks_dc; 00139 extern void __builtin_avr_delay_cycles(unsigned long); 00140 __tmp = ((F_CPU) / 1e3) * __ms; 00141 00142 #if defined(__DELAY_ROUND_DOWN__) 00143 __ticks_dc = (uint32_t)fabs(__tmp); 00144 00145 #elif defined(__DELAY_ROUND_CLOSEST__) 00146 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00147 00148 #else 00149 //round up by default 00150 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00151 #endif 00152 00153 __builtin_avr_delay_cycles(__ticks_dc); 00154 00155 #elif !__HAS_DELAY_CYCLES || (__HAS_DELAY_CYCLES && !defined(__OPTIMIZE__)) || defined (__DELAY_BACKWARD_COMPATIBLE__) 00156 __tmp = ((F_CPU) / 4e3) * __ms; 00157 if (__tmp < 1.0) 00158 __ticks = 1; 00159 else if (__tmp > 65535) 00160 { 00161 // __ticks = requested delay in 1/10 ms 00162 __ticks = (uint16_t) (__ms * 10.0); 00163 while(__ticks) 00164 { 00165 // wait 1/10 ms 00166 _delay_loop_2(((F_CPU) / 4e3) / 10); 00167 __ticks --; 00168 } 00169 return; 00170 } 00171 else 00172 __ticks = (uint16_t)__tmp; 00173 _delay_loop_2(__ticks); 00174 #endif 00175 } 00176 00177 /** 00178 \ingroup util_delay 00179 00180 Perform a delay of \c __us microseconds, using _delay_loop_1(). 00181 00182 The macro F_CPU is supposed to be defined to a 00183 constant defining the CPU clock frequency (in Hertz). 00184 00185 The maximal possible delay is 768 us / F_CPU in MHz. 00186 00187 If the user requests a delay greater than the maximal possible one, 00188 _delay_us() will automatically call _delay_ms() instead. The user 00189 will not be informed about this case. 00190 00191 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) 00192 support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For 00193 values greater than the maximal possible delay, overflow results in 00194 no delay i.e., 0us. 00195 00196 Conversion of __us into clock cycles may not always result in integer. 00197 By default, the clock cycles rounded up to next integer. This ensures that 00198 the user gets atleast __us microseconds of delay. 00199 00200 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__ 00201 to round down and round to closest integer. 00202 00203 Note: The new implementation of _delay_us(double __us) with 00204 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 00205 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay 00206 although this will be deprecated in future. 00207 00208 */ 00209 void 00210 _delay_us(double __us) 00211 { 00212 uint8_t __ticks; 00213 double __tmp ; 00214 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && !defined(__DELAY_BACKWARD_COMPATIBLE__) 00215 uint32_t __ticks_dc; 00216 extern void __builtin_avr_delay_cycles(unsigned long); 00217 __tmp = ((F_CPU) / 1e6) * __us; 00218 00219 #if defined(__DELAY_ROUND_DOWN__) 00220 __ticks_dc = (uint32_t)fabs(__tmp); 00221 00222 #elif defined(__DELAY_ROUND_CLOSEST__) 00223 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00224 00225 #else 00226 //round up by default 00227 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00228 #endif 00229 00230 __builtin_avr_delay_cycles(__ticks_dc); 00231 00232 #elif !__HAS_DELAY_CYCLES || (__HAS_DELAY_CYCLES && !defined(__OPTIMIZE__)) || defined (__DELAY_BACKWARD_COMPATIBLE__) 00233 __tmp = ((F_CPU) / 3e6) * __us; 00234 if (__tmp < 1.0) 00235 __ticks = 1; 00236 else if (__tmp > 255) 00237 { 00238 _delay_ms(__us / 1000.0); 00239 return; 00240 } 00241 else 00242 __ticks = (uint8_t)__tmp; 00243 _delay_loop_1(__ticks); 00244 #endif 00245 } 00246 00247 00248 #endif /* _UTIL_DELAY_H_ */