$treeview $search $mathjax $extrastylesheet
avr-libc
2.0.0
$projectbrief
|
$projectbrief
|
$searchbox |
AVR Libc Home Page |
AVR Libc Development Pages |
||||
Main Page |
User Manual |
Library Reference |
FAQ |
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 __DOXYGEN__ 00039 # ifndef __HAS_DELAY_CYCLES 00040 # define __HAS_DELAY_CYCLES 1 00041 # endif 00042 #endif /* __DOXYGEN__ */ 00043 00044 #include <inttypes.h> 00045 #include <util/delay_basic.h> 00046 #include <math.h> 00047 00048 /** \file */ 00049 /** \defgroup util_delay <util/delay.h>: Convenience functions for busy-wait delay loops 00050 \code 00051 #define F_CPU 1000000UL // 1 MHz 00052 //#define F_CPU 14.7456E6 00053 #include <util/delay.h> 00054 \endcode 00055 00056 \note As an alternative method, it is possible to pass the 00057 F_CPU macro down to the compiler from the Makefile. 00058 Obviously, in that case, no \c \#define statement should be 00059 used. 00060 00061 The functions in this header file are wrappers around the basic 00062 busy-wait functions from <util/delay_basic.h>. They are meant as 00063 convenience functions where actual time values can be specified 00064 rather than a number of cycles to wait for. The idea behind is 00065 that compile-time constant expressions will be eliminated by 00066 compiler optimization so floating-point expressions can be used 00067 to calculate the number of delay cycles needed based on the CPU 00068 frequency passed by the macro F_CPU. 00069 00070 \note In order for these functions to work as intended, compiler 00071 optimizations <em>must</em> be enabled, and the delay time 00072 <em>must</em> be an expression that is a known constant at 00073 compile-time. If these requirements are not met, the resulting 00074 delay will be much longer (and basically unpredictable), and 00075 applications that otherwise do not use floating-point calculations 00076 will experience severe code bloat by the floating-point library 00077 routines linked into the application. 00078 00079 The functions available allow the specification of microsecond, and 00080 millisecond delays directly, using the application-supplied macro 00081 F_CPU as the CPU clock frequency (in Hertz). 00082 00083 */ 00084 00085 #if !defined(__DOXYGEN__) 00086 static __inline__ void _delay_us(double __us) __attribute__((__always_inline__)); 00087 static __inline__ void _delay_ms(double __ms) __attribute__((__always_inline__)); 00088 #endif 00089 00090 #ifndef F_CPU 00091 /* prevent compiler error by supplying a default */ 00092 # warning "F_CPU not defined for <util/delay.h>" 00093 /** \ingroup util_delay 00094 \def F_CPU 00095 \brief CPU frequency in Hz 00096 00097 The macro F_CPU specifies the CPU frequency to be considered by 00098 the delay macros. This macro is normally supplied by the 00099 environment (e.g. from within a project header, or the project's 00100 Makefile). The value 1 MHz here is only provided as a "vanilla" 00101 fallback if no such user-provided definition could be found. 00102 00103 In terms of the delay functions, the CPU frequency can be given as 00104 a floating-point constant (e.g. 3.6864E6 for 3.6864 MHz). 00105 However, the macros in <util/setbaud.h> require it to be an 00106 integer value. 00107 */ 00108 # define F_CPU 1000000UL 00109 #endif 00110 00111 #ifndef __OPTIMIZE__ 00112 # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" 00113 #endif 00114 00115 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00116 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00117 __STDC_HOSTED__ 00118 # include <math.h> 00119 #endif 00120 00121 /** 00122 \ingroup util_delay 00123 00124 Perform a delay of \c __ms milliseconds, using _delay_loop_2(). 00125 00126 The macro F_CPU is supposed to be defined to a 00127 constant defining the CPU clock frequency (in Hertz). 00128 00129 The maximal possible delay is 262.14 ms / F_CPU in MHz. 00130 00131 When the user request delay which exceed the maximum possible one, 00132 _delay_ms() provides a decreased resolution functionality. In this 00133 mode _delay_ms() will work with a resolution of 1/10 ms, providing 00134 delays up to 6.5535 seconds (independent from CPU frequency). The 00135 user will not be informed about decreased resolution. 00136 00137 If the avr-gcc toolchain has __builtin_avr_delay_cycles() 00138 support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For 00139 values greater than the maximal possible delay, overflows results in 00140 no delay i.e., 0ms. 00141 00142 Conversion of \c __ms into clock cycles may not always result in 00143 integer. By default, the clock cycles rounded up to next 00144 integer. This ensures that the user gets at least \c __ms 00145 microseconds of delay. 00146 00147 Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or 00148 \c __DELAY_ROUND_CLOSEST__, before including this header file, the 00149 algorithm can be made to round down, or round to closest integer, 00150 respectively. 00151 00152 \note 00153 00154 The implementation of _delay_ms() based on 00155 __builtin_avr_delay_cycles() is not backward compatible with older 00156 implementations. In order to get functionality backward compatible 00157 with previous versions, the macro \c "__DELAY_BACKWARD_COMPATIBLE__" 00158 must be defined before including this header file. Also, the 00159 backward compatible algorithm will be chosen if the code is 00160 compiled in a <em>freestanding environment</em> (GCC option 00161 \c -ffreestanding), as the math functions required for rounding are 00162 not available to the compiler then. 00163 00164 */ 00165 void 00166 _delay_ms(double __ms) 00167 { 00168 double __tmp ; 00169 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00170 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00171 __STDC_HOSTED__ 00172 uint32_t __ticks_dc; 00173 extern void __builtin_avr_delay_cycles(unsigned long); 00174 __tmp = ((F_CPU) / 1e3) * __ms; 00175 00176 #if defined(__DELAY_ROUND_DOWN__) 00177 __ticks_dc = (uint32_t)fabs(__tmp); 00178 00179 #elif defined(__DELAY_ROUND_CLOSEST__) 00180 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00181 00182 #else 00183 //round up by default 00184 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00185 #endif 00186 00187 __builtin_avr_delay_cycles(__ticks_dc); 00188 00189 #else 00190 uint16_t __ticks; 00191 __tmp = ((F_CPU) / 4e3) * __ms; 00192 if (__tmp < 1.0) 00193 __ticks = 1; 00194 else if (__tmp > 65535) 00195 { 00196 // __ticks = requested delay in 1/10 ms 00197 __ticks = (uint16_t) (__ms * 10.0); 00198 while(__ticks) 00199 { 00200 // wait 1/10 ms 00201 _delay_loop_2(((F_CPU) / 4e3) / 10); 00202 __ticks --; 00203 } 00204 return; 00205 } 00206 else 00207 __ticks = (uint16_t)__tmp; 00208 _delay_loop_2(__ticks); 00209 #endif 00210 } 00211 00212 /** 00213 \ingroup util_delay 00214 00215 Perform a delay of \c __us microseconds, using _delay_loop_1(). 00216 00217 The macro F_CPU is supposed to be defined to a 00218 constant defining the CPU clock frequency (in Hertz). 00219 00220 The maximal possible delay is 768 us / F_CPU in MHz. 00221 00222 If the user requests a delay greater than the maximal possible one, 00223 _delay_us() will automatically call _delay_ms() instead. The user 00224 will not be informed about this case. 00225 00226 If the avr-gcc toolchain has __builtin_avr_delay_cycles() 00227 support, maximal possible delay is 4294967.295 us/ F_CPU in MHz. For 00228 values greater than the maximal possible delay, overflow results in 00229 no delay i.e., 0us. 00230 00231 Conversion of \c __us into clock cycles may not always result in 00232 integer. By default, the clock cycles rounded up to next 00233 integer. This ensures that the user gets at least \c __us 00234 microseconds of delay. 00235 00236 Alternatively, by defining the macro \c __DELAY_ROUND_DOWN__, or 00237 \c __DELAY_ROUND_CLOSEST__, before including this header file, the 00238 algorithm can be made to round down, or round to closest integer, 00239 respectively. 00240 00241 \note 00242 00243 The implementation of _delay_ms() based on 00244 __builtin_avr_delay_cycles() is not backward compatible with older 00245 implementations. In order to get functionality backward compatible 00246 with previous versions, the macro \c __DELAY_BACKWARD_COMPATIBLE__ 00247 must be defined before including this header file. Also, the 00248 backward compatible algorithm will be chosen if the code is 00249 compiled in a <em>freestanding environment</em> (GCC option 00250 \c -ffreestanding), as the math functions required for rounding are 00251 not available to the compiler then. 00252 00253 */ 00254 void 00255 _delay_us(double __us) 00256 { 00257 double __tmp ; 00258 #if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \ 00259 !defined(__DELAY_BACKWARD_COMPATIBLE__) && \ 00260 __STDC_HOSTED__ 00261 uint32_t __ticks_dc; 00262 extern void __builtin_avr_delay_cycles(unsigned long); 00263 __tmp = ((F_CPU) / 1e6) * __us; 00264 00265 #if defined(__DELAY_ROUND_DOWN__) 00266 __ticks_dc = (uint32_t)fabs(__tmp); 00267 00268 #elif defined(__DELAY_ROUND_CLOSEST__) 00269 __ticks_dc = (uint32_t)(fabs(__tmp)+0.5); 00270 00271 #else 00272 //round up by default 00273 __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); 00274 #endif 00275 00276 __builtin_avr_delay_cycles(__ticks_dc); 00277 00278 #else 00279 uint8_t __ticks; 00280 double __tmp2 ; 00281 __tmp = ((F_CPU) / 3e6) * __us; 00282 __tmp2 = ((F_CPU) / 4e6) * __us; 00283 if (__tmp < 1.0) 00284 __ticks = 1; 00285 else if (__tmp2 > 65535) 00286 { 00287 _delay_ms(__us / 1000.0); 00288 } 00289 else if (__tmp > 255) 00290 { 00291 uint16_t __ticks=(uint16_t)__tmp2; 00292 _delay_loop_2(__ticks); 00293 return; 00294 } 00295 else 00296 __ticks = (uint8_t)__tmp; 00297 _delay_loop_1(__ticks); 00298 #endif 00299 } 00300 00301 00302 #endif /* _UTIL_DELAY_H_ */