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 2251 2011-09-14 08:20:33Z joerg_wunsch $ */ 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 uint16_t __ticks; 00145 double __tmp ; 00146 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00147 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00148 __STDC_HOSTED__ 00149 uint32_t __ticks_dc; 00150 extern void __builtin_avr_delay_cycles(unsigned long); 00151 __tmp = ((F_CPU) / 1e3) * __ms; 00152 00153 #if defined(__DELAY_ROUND_DOWN__) 00154 __ticks_dc = (uint32_t)fabs(__tmp); 00155 00156 #elif defined(__DELAY_ROUND_CLOSEST__) 00157 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00158 00159 #else 00160 //round up by default 00161 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00162 #endif 00163 00164 __builtin_avr_delay_cycles(__ticks_dc); 00165 00166 #else 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 uint8_t __ticks; 00227 double __tmp ; 00228 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00229 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00230 __STDC_HOSTED__ 00231 uint32_t __ticks_dc; 00232 extern void __builtin_avr_delay_cycles(unsigned long); 00233 __tmp = ((F_CPU) / 1e6) * __us; 00234 00235 #if defined(__DELAY_ROUND_DOWN__) 00236 __ticks_dc = (uint32_t)fabs(__tmp); 00237 00238 #elif defined(__DELAY_ROUND_CLOSEST__) 00239 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00240 00241 #else 00242 //round up by default 00243 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00244 #endif 00245 00246 __builtin_avr_delay_cycles(__ticks_dc); 00247 00248 #else 00249 __tmp = ((F_CPU) / 3e6) * __us; 00250 if (__tmp < 1.0) 00251 __ticks = 1; 00252 else if (__tmp > 255) 00253 { 00254 _delay_ms(__us / 1000.0); 00255 return; 00256 } 00257 else 00258 __ticks = (uint8_t)__tmp; 00259 _delay_loop_1(__ticks); 00260 #endif 00261 } 00262 00263 00264 #endif /* _UTIL_DELAY_H_ */