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$ */ 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 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00099 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00100 __STDC_HOSTED__ 00101 # include <math.h> 00102 #endif 00103 00104 /** 00105 \ingroup util_delay 00106 00107 Perform a delay of \c __ms milliseconds, using _delay_loop_2(). 00108 00109 The macro F_CPU is supposed to be defined to a 00110 constant defining the CPU clock frequency (in Hertz). 00111 00112 The maximal possible delay is 262.14 ms / F_CPU in MHz. 00113 00114 When the user request delay which exceed the maximum possible one, 00115 _delay_ms() provides a decreased resolution functionality. In this 00116 mode _delay_ms() will work with a resolution of 1/10 ms, providing 00117 delays up to 6.5535 seconds (independent from CPU frequency). The 00118 user will not be informed about decreased resolution. 00119 00120 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) 00121 support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For 00122 values greater than the maximal possible delay, overflows results in 00123 no delay i.e., 0ms. 00124 00125 Conversion of __us into clock cycles may not always result in integer. 00126 By default, the clock cycles rounded up to next integer. This ensures that 00127 the user gets atleast __us microseconds of delay. 00128 00129 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__ 00130 to round down and round to closest integer. 00131 00132 Note: The new implementation of _delay_ms(double __ms) with 00133 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 00134 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay. 00135 Also, the backward compatible 00136 algorithm will be chosen if the code is compiled in a <em>freestanding 00137 environment</em> (GCC option \c -ffreestanding), as the math functions 00138 required for rounding are not available to the compiler then. 00139 00140 */ 00141 void 00142 _delay_ms(double __ms) 00143 { 00144 double __tmp ; 00145 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00146 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00147 __STDC_HOSTED__ 00148 uint32_t __ticks_dc; 00149 extern void __builtin_avr_delay_cycles(unsigned long); 00150 __tmp = ((F_CPU) / 1e3) * __ms; 00151 00152 #if defined(__DELAY_ROUND_DOWN__) 00153 __ticks_dc = (uint32_t)fabs(__tmp); 00154 00155 #elif defined(__DELAY_ROUND_CLOSEST__) 00156 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00157 00158 #else 00159 //round up by default 00160 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00161 #endif 00162 00163 __builtin_avr_delay_cycles(__ticks_dc); 00164 00165 #else 00166 uint16_t __ticks; 00167 __tmp = ((F_CPU) / 4e3) * __ms; 00168 if (__tmp < 1.0) 00169 __ticks = 1; 00170 else if (__tmp > 65535) 00171 { 00172 // __ticks = requested delay in 1/10 ms 00173 __ticks = (uint16_t) (__ms * 10.0); 00174 while(__ticks) 00175 { 00176 // wait 1/10 ms 00177 _delay_loop_2(((F_CPU) / 4e3) / 10); 00178 __ticks --; 00179 } 00180 return; 00181 } 00182 else 00183 __ticks = (uint16_t)__tmp; 00184 _delay_loop_2(__ticks); 00185 #endif 00186 } 00187 00188 /** 00189 \ingroup util_delay 00190 00191 Perform a delay of \c __us microseconds, using _delay_loop_1(). 00192 00193 The macro F_CPU is supposed to be defined to a 00194 constant defining the CPU clock frequency (in Hertz). 00195 00196 The maximal possible delay is 768 us / F_CPU in MHz. 00197 00198 If the user requests a delay greater than the maximal possible one, 00199 _delay_us() will automatically call _delay_ms() instead. The user 00200 will not be informed about this case. 00201 00202 If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) 00203 support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For 00204 values greater than the maximal possible delay, overflow results in 00205 no delay i.e., 0us. 00206 00207 Conversion of __us into clock cycles may not always result in integer. 00208 By default, the clock cycles rounded up to next integer. This ensures that 00209 the user gets atleast __us microseconds of delay. 00210 00211 Alternatively, user can define __DELAY_ROUND_DOWN__ and __DELAY_ROUND_CLOSEST__ 00212 to round down and round to closest integer. 00213 00214 Note: The new implementation of _delay_us(double __us) with 00215 __builtin_avr_delay_cycles(unsigned long) support is not backward compatible. 00216 User can define __DELAY_BACKWARD_COMPATIBLE__ to get a backward compatible delay. 00217 Also, the backward compatible 00218 algorithm will be chosen if the code is compiled in a <em>freestanding 00219 environment</em> (GCC option \c -ffreestanding), as the math functions 00220 required for rounding are not available to the compiler then. 00221 00222 */ 00223 void 00224 _delay_us(double __us) 00225 { 00226 double __tmp ; 00227 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00228 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00229 __STDC_HOSTED__ 00230 uint32_t __ticks_dc; 00231 extern void __builtin_avr_delay_cycles(unsigned long); 00232 __tmp = ((F_CPU) / 1e6) * __us; 00233 00234 #if defined(__DELAY_ROUND_DOWN__) 00235 __ticks_dc = (uint32_t)fabs(__tmp); 00236 00237 #elif defined(__DELAY_ROUND_CLOSEST__) 00238 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00239 00240 #else 00241 //round up by default 00242 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00243 #endif 00244 00245 __builtin_avr_delay_cycles(__ticks_dc); 00246 00247 #else 00248 uint8_t __ticks; 00249 double __tmp2 ; 00250 __tmp = ((F_CPU) / 3e6) * __us; 00251 __tmp2 = ((F_CPU) / 4e6) * __us; 00252 if (__tmp < 1.0) 00253 __ticks = 1; 00254 else if (__tmp2 > 65535) 00255 { 00256 _delay_ms(__us / 1000.0); 00257 } 00258 else if (__tmp > 255) 00259 { 00260 uint16_t __ticks=(uint16_t)__tmp2; 00261 _delay_loop_2(__ticks); 00262 return; 00263 } 00264 else 00265 __ticks = (uint8_t)__tmp; 00266 _delay_loop_1(__ticks); 00267 #endif 00268 } 00269 00270 00271 #endif /* _UTIL_DELAY_H_ */