AVR Libc Home Page AVRs AVR Libc Development Pages
Main Page User Manual Library Reference FAQ Alphabetical Index Example Projects

pgmspace.h
Go to the documentation of this file.
00001 /* Copyright (c) 2002-2007  Marek Michalkiewicz
00002    Copyright (c) 2006, Carlos Lamas
00003    Copyright (c) 2009-2010, Jan Waclawek
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    * Redistributions in binary form must reproduce the above copyright
00012      notice, this list of conditions and the following disclaimer in
00013      the documentation and/or other materials provided with the
00014      distribution.
00015    * Neither the name of the copyright holders nor the names of
00016      contributors may be used to endorse or promote products derived
00017      from this software without specific prior written permission.
00018 
00019   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00020   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00023   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00024   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00025   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00026   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00027   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00028   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00029   POSSIBILITY OF SUCH DAMAGE. */
00030 
00031 /* $Id: pgmspace_8h_source.html,v 1.1.1.4 2012/01/03 16:04:22 joerg_wunsch Exp $ */
00032 
00033 /*
00034    pgmspace.h
00035 
00036    Contributors:
00037      Created by Marek Michalkiewicz <marekm@linux.org.pl>
00038      Eric B. Weddington <eric@ecentral.com>
00039      Wolfgang Haidinger <wh@vmars.tuwien.ac.at> (pgm_read_dword())
00040      Ivanov Anton <anton@arc.com.ru> (pgm_read_float())
00041  */
00042 
00043 /** \file */
00044 /** \defgroup avr_pgmspace <avr/pgmspace.h>: Program Space Utilities
00045     \code
00046     #include <avr/io.h>
00047     #include <avr/pgmspace.h>
00048     \endcode
00049 
00050     The functions in this module provide interfaces for a program to access
00051     data stored in program space (flash memory) of the device.  In order to
00052     use these functions, the target device must support either the \c LPM or
00053     \c ELPM instructions.
00054 
00055     \note These functions are an attempt to provide some compatibility with
00056     header files that come with IAR C, to make porting applications between
00057     different compilers easier.  This is not 100% compatibility though (GCC
00058     does not have full support for multiple address spaces yet).
00059 
00060     \note If you are working with strings which are completely based in ram,
00061     use the standard string functions described in \ref avr_string.
00062 
00063     \note If possible, put your constant tables in the lower 64 KB and use
00064     pgm_read_byte_near() or pgm_read_word_near() instead of
00065     pgm_read_byte_far() or pgm_read_word_far() since it is more efficient that
00066     way, and you can still use the upper 64K for executable code.
00067     All functions that are suffixed with a \c _P \e require their
00068     arguments to be in the lower 64 KB of the flash ROM, as they do
00069     not use ELPM instructions.  This is normally not a big concern as
00070     the linker setup arranges any program space constants declared
00071     using the macros from this header file so they are placed right after
00072     the interrupt vectors, and in front of any executable code.  However,
00073     it can become a problem if there are too many of these constants, or
00074     for bootloaders on devices with more than 64 KB of ROM.
00075     <em>All these functions will not work in that situation.</em>
00076 
00077     \note For <b>Xmega</b> devices, make sure the NVM controller
00078     command register (\c NVM.CMD or \c NVM_CMD) is set to 0x00 (NOP)
00079     before using any of these functions.
00080 */
00081 
00082 #ifndef __PGMSPACE_H_
00083 #define __PGMSPACE_H_ 1
00084 
00085 #define __need_size_t
00086 #include <inttypes.h>
00087 #include <stddef.h>
00088 #include <avr/io.h>
00089 
00090 #ifndef __ATTR_CONST__
00091 #define __ATTR_CONST__ __attribute__((__const__))
00092 #endif
00093 
00094 #ifndef __ATTR_PROGMEM__
00095 #define __ATTR_PROGMEM__ __attribute__((__progmem__))
00096 #endif
00097 
00098 #ifndef __ATTR_PURE__
00099 #define __ATTR_PURE__ __attribute__((__pure__))
00100 #endif
00101 
00102 /**
00103    \ingroup avr_pgmspace
00104    \def PROGMEM
00105 
00106    Attribute to use in order to declare an object being located in
00107    flash ROM.
00108  */
00109 #define PROGMEM __ATTR_PROGMEM__
00110 
00111 #ifdef __cplusplus
00112 extern "C" {
00113 #endif
00114 
00115 #if defined(__DOXYGEN__)
00116 /*
00117  * Doxygen doesn't grok the appended attribute syntax of
00118  * GCC, and confuses the typedefs with function decls, so
00119  * supply a doxygen-friendly view.
00120  */
00121 
00122 /**
00123    \ingroup avr_pgmspace
00124    \typedef prog_void
00125    \note DEPRECATED
00126 
00127    This typedef is now deprecated because the usage of the __progmem__ 
00128    attribute on a type is not supported in GCC. However, the use of the 
00129    __progmem__ attribute on a variable declaration is supported, and this is 
00130    now the recommended usage.
00131 
00132    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00133    has been defined before including <avr/pgmspace.h> (either by a
00134    #define directive, or by a -D compiler option.)
00135 
00136    Type of a "void" object located in flash ROM.  Does not make much
00137    sense by itself, but can be used to declare a "void *" object in
00138    flash ROM.
00139 */
00140 typedef void PROGMEM prog_void;
00141 
00142 /**
00143    \ingroup avr_pgmspace
00144    \typedef prog_char
00145    \note DEPRECATED
00146 
00147    This typedef is now deprecated because the usage of the __progmem__ 
00148    attribute on a type is not supported in GCC. However, the use of the 
00149    __progmem__ attribute on a variable declaration is supported, and this is 
00150    now the recommended usage.
00151 
00152    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00153    has been defined before including <avr/pgmspace.h> (either by a
00154    #define directive, or by a -D compiler option.)
00155 
00156    Type of a "char" object located in flash ROM.
00157 */
00158 typedef char PROGMEM prog_char;
00159 
00160 /**
00161    \ingroup avr_pgmspace
00162    \typedef prog_uchar
00163    \note DEPRECATED
00164 
00165    This typedef is now deprecated because the usage of the __progmem__ 
00166    attribute on a type is not supported in GCC. However, the use of the 
00167    __progmem__ attribute on a variable declaration is supported, and this is 
00168    now the recommended usage.
00169 
00170    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00171    has been defined before including <avr/pgmspace.h> (either by a
00172    #define directive, or by a -D compiler option.)
00173 
00174    Type of an "unsigned char" object located in flash ROM.
00175 */
00176 typedef unsigned char PROGMEM prog_uchar;
00177 
00178 /**
00179    \ingroup avr_pgmspace
00180    \typedef prog_int8_t
00181    \note DEPRECATED
00182 
00183    This typedef is now deprecated because the usage of the __progmem__ 
00184    attribute on a type is not supported in GCC. However, the use of the 
00185    __progmem__ attribute on a variable declaration is supported, and this is 
00186    now the recommended usage.
00187 
00188    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00189    has been defined before including <avr/pgmspace.h> (either by a
00190    #define directive, or by a -D compiler option.)
00191 
00192    Type of an "int8_t" object located in flash ROM.
00193 */
00194 typedef int8_t PROGMEM prog_int8_t;
00195 
00196 /**
00197    \ingroup avr_pgmspace
00198    \typedef prog_uint8_t
00199    \note DEPRECATED
00200 
00201    This typedef is now deprecated because the usage of the __progmem__ 
00202    attribute on a type is not supported in GCC. However, the use of the 
00203    __progmem__ attribute on a variable declaration is supported, and this is 
00204    now the recommended usage.
00205 
00206    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00207    has been defined before including <avr/pgmspace.h> (either by a
00208    #define directive, or by a -D compiler option.)
00209 
00210    Type of an "uint8_t" object located in flash ROM.
00211 */
00212 typedef uint8_t PROGMEM prog_uint8_t;
00213 
00214 /**
00215    \ingroup avr_pgmspace
00216    \typedef prog_int16_t
00217    \note DEPRECATED
00218 
00219    This typedef is now deprecated because the usage of the __progmem__ 
00220    attribute on a type is not supported in GCC. However, the use of the 
00221    __progmem__ attribute on a variable declaration is supported, and this is 
00222    now the recommended usage.
00223 
00224    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00225    has been defined before including <avr/pgmspace.h> (either by a
00226    #define directive, or by a -D compiler option.)
00227 
00228    Type of an "int16_t" object located in flash ROM.
00229 */
00230 typedef int16_t PROGMEM prog_int16_t;
00231 
00232 /**
00233    \ingroup avr_pgmspace
00234    \typedef prog_uint16_t
00235    \note DEPRECATED
00236 
00237    This typedef is now deprecated because the usage of the __progmem__ 
00238    attribute on a type is not supported in GCC. However, the use of the 
00239    __progmem__ attribute on a variable declaration is supported, and this is 
00240    now the recommended usage.
00241 
00242    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00243    has been defined before including <avr/pgmspace.h> (either by a
00244    #define directive, or by a -D compiler option.)
00245 
00246    Type of an "uint16_t" object located in flash ROM.
00247 */
00248 typedef uint16_t PROGMEM prog_uint16_t;
00249 
00250 /**
00251    \ingroup avr_pgmspace
00252    \typedef prog_int32_t
00253    \note DEPRECATED
00254 
00255    This typedef is now deprecated because the usage of the __progmem__ 
00256    attribute on a type is not supported in GCC. However, the use of the 
00257    __progmem__ attribute on a variable declaration is supported, and this is 
00258    now the recommended usage.
00259 
00260    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00261    has been defined before including <avr/pgmspace.h> (either by a
00262    #define directive, or by a -D compiler option.)
00263 
00264    Type of an "int32_t" object located in flash ROM.
00265 */
00266 typedef int32_t PROGMEM prog_int32_t;
00267 
00268 /**
00269    \ingroup avr_pgmspace
00270    \typedef prog_uint32_t
00271    \note DEPRECATED
00272 
00273    This typedef is now deprecated because the usage of the __progmem__ 
00274    attribute on a type is not supported in GCC. However, the use of the 
00275    __progmem__ attribute on a variable declaration is supported, and this is 
00276    now the recommended usage.
00277 
00278    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00279    has been defined before including <avr/pgmspace.h> (either by a
00280    #define directive, or by a -D compiler option.)
00281 
00282    Type of an "uint32_t" object located in flash ROM.
00283 */
00284 typedef uint32_t PROGMEM prog_uint32_t;
00285 
00286 /**
00287    \ingroup avr_pgmspace
00288    \typedef prog_int64_t
00289    \note DEPRECATED
00290 
00291    This typedef is now deprecated because the usage of the __progmem__ 
00292    attribute on a type is not supported in GCC. However, the use of the 
00293    __progmem__ attribute on a variable declaration is supported, and this is 
00294    now the recommended usage.
00295 
00296    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00297    has been defined before including <avr/pgmspace.h> (either by a
00298    #define directive, or by a -D compiler option.)
00299 
00300    Type of an "int64_t" object located in flash ROM.
00301 
00302    \note This type is not available when the compiler
00303    option -mint8 is in effect.
00304 */
00305 typedef int64_t PROGMEM prog_int64_t;
00306 
00307 /**
00308    \ingroup avr_pgmspace
00309    \typedef prog_uint64_t
00310    \note DEPRECATED
00311 
00312    This typedef is now deprecated because the usage of the __progmem__ 
00313    attribute on a type is not supported in GCC. However, the use of the 
00314    __progmem__ attribute on a variable declaration is supported, and this is 
00315    now the recommended usage.
00316 
00317    The typedef is only visible if the macro __PROG_TYPES_COMPAT__
00318    has been defined before including <avr/pgmspace.h> (either by a
00319    #define directive, or by a -D compiler option.)
00320 
00321    Type of an "uint64_t" object located in flash ROM.
00322 
00323    \note This type is not available when the compiler
00324    option -mint8 is in effect.
00325 */
00326 typedef uint64_t PROGMEM prog_uint64_t;
00327 
00328 /** \ingroup avr_pgmspace
00329     \def PGM_P
00330 
00331     Used to declare a variable that is a pointer to a string in program
00332     space. */
00333 
00334 #ifndef PGM_P
00335 #define PGM_P const char *
00336 #endif
00337 
00338 /** \ingroup avr_pgmspace
00339     \def PGM_VOID_P
00340 
00341     Used to declare a generic pointer to an object in program space. */
00342 
00343 #ifndef PGM_VOID_P
00344 #define PGM_VOID_P const void *
00345 #endif
00346 
00347 #elif defined(__PROG_TYPES_COMPAT__)  /* !DOXYGEN */
00348 
00349 typedef void prog_void __attribute__((__progmem__,deprecated("prog_void type is deprecated.")));
00350 typedef char prog_char __attribute__((__progmem__,deprecated("prog_char type is deprecated.")));
00351 typedef unsigned char prog_uchar __attribute__((__progmem__,deprecated("prog_uchar type is deprecated.")));
00352 typedef int8_t    prog_int8_t   __attribute__((__progmem__,deprecated("prog_int8_t type is deprecated.")));
00353 typedef uint8_t   prog_uint8_t  __attribute__((__progmem__,deprecated("prog_uint8_t type is deprecated.")));
00354 typedef int16_t   prog_int16_t  __attribute__((__progmem__,deprecated("prog_int16_t type is deprecated.")));
00355 typedef uint16_t  prog_uint16_t __attribute__((__progmem__,deprecated("prog_uint16_t type is deprecated.")));
00356 typedef int32_t   prog_int32_t  __attribute__((__progmem__,deprecated("prog_int32_t type is deprecated.")));
00357 typedef uint32_t  prog_uint32_t __attribute__((__progmem__,deprecated("prog_uint32_t type is deprecated.")));
00358 #if !__USING_MINT8
00359 typedef int64_t   prog_int64_t  __attribute__((__progmem__,deprecated("prog_int64_t type is deprecated.")));
00360 typedef uint64_t  prog_uint64_t __attribute__((__progmem__,deprecated("prog_uint64_t type is deprecated.")));
00361 #endif
00362 
00363 #ifndef PGM_P
00364 #define PGM_P const prog_char *
00365 #endif
00366 
00367 #ifndef PGM_VOID_P
00368 #define PGM_VOID_P const prog_void *
00369 #endif
00370 
00371 #else /* !defined(__DOXYGEN__), !defined(__PROG_TYPES_COMPAT__) */
00372 
00373 #ifndef PGM_P
00374 #define PGM_P const char *
00375 #endif
00376 
00377 #ifndef PGM_VOID_P
00378 #define PGM_VOID_P const void *
00379 #endif
00380 #endif /* defined(__DOXYGEN__), defined(__PROG_TYPES_COMPAT__) */
00381 
00382 /* Although in C, we can get away with just using __c, it does not work in
00383    C++. We need to use &__c[0] to avoid the compiler puking. Dave Hylands
00384    explaned it thusly,
00385 
00386      Let's suppose that we use PSTR("Test"). In this case, the type returned
00387      by __c is a prog_char[5] and not a prog_char *. While these are
00388      compatible, they aren't the same thing (especially in C++). The type
00389      returned by &__c[0] is a prog_char *, which explains why it works
00390      fine. */
00391 
00392 #if defined(__DOXYGEN__)
00393 /*
00394  * The #define below is just a dummy that serves documentation
00395  * purposes only.
00396  */
00397 /** \ingroup avr_pgmspace
00398     \def PSTR(s)
00399 
00400     Used to declare a static pointer to a string in program space. */
00401 # define PSTR(s) ((const PROGMEM char *)(s))
00402 #else  /* !DOXYGEN */
00403 /* The real thing. */
00404 # define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))
00405 #endif /* DOXYGEN */
00406 
00407 #define __LPM_classic__(addr)   \
00408 (__extension__({                \
00409     uint16_t __addr16 = (uint16_t)(addr); \
00410     uint8_t __result;           \
00411     __asm__                     \
00412     (                           \
00413         "lpm" "\n\t"            \
00414         "mov %0, r0" "\n\t"     \
00415         : "=r" (__result)       \
00416         : "z" (__addr16)        \
00417         : "r0"                  \
00418     );                          \
00419     __result;                   \
00420 }))
00421 
00422 #define __LPM_enhanced__(addr)  \
00423 (__extension__({                \
00424     uint16_t __addr16 = (uint16_t)(addr); \
00425     uint8_t __result;           \
00426     __asm__                     \
00427     (                           \
00428         "lpm %0, Z" "\n\t"      \
00429         : "=r" (__result)       \
00430         : "z" (__addr16)        \
00431     );                          \
00432     __result;                   \
00433 }))
00434 
00435 #define __LPM_word_classic__(addr)          \
00436 (__extension__({                            \
00437     uint16_t __addr16 = (uint16_t)(addr);   \
00438     uint16_t __result;                      \
00439     __asm__                                 \
00440     (                                       \
00441         "lpm"           "\n\t"              \
00442         "mov %A0, r0"   "\n\t"              \
00443         "adiw r30, 1"   "\n\t"              \
00444         "lpm"           "\n\t"              \
00445         "mov %B0, r0"   "\n\t"              \
00446         : "=r" (__result), "=z" (__addr16)  \
00447         : "1" (__addr16)                    \
00448         : "r0"                              \
00449     );                                      \
00450     __result;                               \
00451 }))
00452 
00453 #define __LPM_word_enhanced__(addr)         \
00454 (__extension__({                            \
00455     uint16_t __addr16 = (uint16_t)(addr);   \
00456     uint16_t __result;                      \
00457     __asm__                                 \
00458     (                                       \
00459         "lpm %A0, Z+"   "\n\t"              \
00460         "lpm %B0, Z"    "\n\t"              \
00461         : "=r" (__result), "=z" (__addr16)  \
00462         : "1" (__addr16)                    \
00463     );                                      \
00464     __result;                               \
00465 }))
00466 
00467 #define __LPM_dword_classic__(addr)         \
00468 (__extension__({                            \
00469     uint16_t __addr16 = (uint16_t)(addr);   \
00470     uint32_t __result;                      \
00471     __asm__                                 \
00472     (                                       \
00473         "lpm"           "\n\t"              \
00474         "mov %A0, r0"   "\n\t"              \
00475         "adiw r30, 1"   "\n\t"              \
00476         "lpm"           "\n\t"              \
00477         "mov %B0, r0"   "\n\t"              \
00478         "adiw r30, 1"   "\n\t"              \
00479         "lpm"           "\n\t"              \
00480         "mov %C0, r0"   "\n\t"              \
00481         "adiw r30, 1"   "\n\t"              \
00482         "lpm"           "\n\t"              \
00483         "mov %D0, r0"   "\n\t"              \
00484         : "=r" (__result), "=z" (__addr16)  \
00485         : "1" (__addr16)                    \
00486         : "r0"                              \
00487     );                                      \
00488     __result;                               \
00489 }))
00490 
00491 #define __LPM_dword_enhanced__(addr)        \
00492 (__extension__({                            \
00493     uint16_t __addr16 = (uint16_t)(addr);   \
00494     uint32_t __result;                      \
00495     __asm__                                 \
00496     (                                       \
00497         "lpm %A0, Z+"   "\n\t"              \
00498         "lpm %B0, Z+"   "\n\t"              \
00499         "lpm %C0, Z+"   "\n\t"              \
00500         "lpm %D0, Z"    "\n\t"              \
00501         : "=r" (__result), "=z" (__addr16)  \
00502         : "1" (__addr16)                    \
00503     );                                      \
00504     __result;                               \
00505 }))
00506 
00507 #define __LPM_float_classic__(addr)         \
00508 (__extension__({                            \
00509     uint16_t __addr16 = (uint16_t)(addr);   \
00510     float __result;                         \
00511     __asm__                                 \
00512     (                                       \
00513         "lpm"           "\n\t"              \
00514         "mov %A0, r0"   "\n\t"              \
00515         "adiw r30, 1"   "\n\t"              \
00516         "lpm"           "\n\t"              \
00517         "mov %B0, r0"   "\n\t"              \
00518         "adiw r30, 1"   "\n\t"              \
00519         "lpm"           "\n\t"              \
00520         "mov %C0, r0"   "\n\t"              \
00521         "adiw r30, 1"   "\n\t"              \
00522         "lpm"           "\n\t"              \
00523         "mov %D0, r0"   "\n\t"              \
00524         : "=r" (__result), "=z" (__addr16)  \
00525         : "1" (__addr16)                    \
00526         : "r0"                              \
00527     );                                      \
00528     __result;                               \
00529 }))
00530 
00531 #define __LPM_float_enhanced__(addr)        \
00532 (__extension__({                            \
00533     uint16_t __addr16 = (uint16_t)(addr);   \
00534     float __result;                         \
00535     __asm__                                 \
00536     (                                       \
00537         "lpm %A0, Z+"   "\n\t"              \
00538         "lpm %B0, Z+"   "\n\t"              \
00539         "lpm %C0, Z+"   "\n\t"              \
00540         "lpm %D0, Z"    "\n\t"              \
00541         : "=r" (__result), "=z" (__addr16)  \
00542         : "1" (__addr16)                    \
00543     );                                      \
00544     __result;                               \
00545 }))
00546 
00547 #if defined (__AVR_HAVE_LPMX__)
00548 #define __LPM(addr)         __LPM_enhanced__(addr)
00549 #define __LPM_word(addr)    __LPM_word_enhanced__(addr)
00550 #define __LPM_dword(addr)   __LPM_dword_enhanced__(addr)
00551 #define __LPM_float(addr)   __LPM_float_enhanced__(addr)
00552 #else
00553 #define __LPM(addr)         __LPM_classic__(addr)
00554 #define __LPM_word(addr)    __LPM_word_classic__(addr)
00555 #define __LPM_dword(addr)   __LPM_dword_classic__(addr)
00556 #define __LPM_float(addr)   __LPM_float_classic__(addr)
00557 #endif
00558 
00559 /** \ingroup avr_pgmspace
00560     \def pgm_read_byte_near(address_short)
00561     Read a byte from the program space with a 16-bit (near) address. 
00562     \note The address is a byte address.
00563     The address is in the program space. */
00564 
00565 #define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
00566 
00567 /** \ingroup avr_pgmspace
00568     \def pgm_read_word_near(address_short)
00569     Read a word from the program space with a 16-bit (near) address. 
00570     \note The address is a byte address. 
00571     The address is in the program space. */
00572 
00573 #define pgm_read_word_near(address_short) __LPM_word((uint16_t)(address_short))
00574 
00575 /** \ingroup avr_pgmspace
00576     \def pgm_read_dword_near(address_short)
00577     Read a double word from the program space with a 16-bit (near) address. 
00578     \note The address is a byte address. 
00579     The address is in the program space. */
00580 
00581 #define pgm_read_dword_near(address_short) \
00582     __LPM_dword((uint16_t)(address_short))
00583 
00584 /** \ingroup avr_pgmspace
00585     \def pgm_read_float_near(address_short)
00586     Read a float from the program space with a 16-bit (near) address. 
00587     \note The address is a byte address. 
00588     The address is in the program space. */
00589 
00590 #define pgm_read_float_near(address_short) \
00591     __LPM_float((uint16_t)(address_short))
00592 
00593 #if defined(RAMPZ) || defined(__DOXYGEN__)
00594 
00595 /* Only for devices with more than 64K of program memory.
00596    RAMPZ must be defined (see iom103.h, iom128.h).
00597 */
00598 
00599 /* The classic functions are needed for ATmega103. */
00600 
00601 #define __ELPM_classic__(addr)      \
00602 (__extension__({                    \
00603     uint32_t __addr32 = (uint32_t)(addr); \
00604     uint8_t __result;               \
00605     __asm__                         \
00606     (                               \
00607         "out %2, %C1" "\n\t"        \
00608         "mov r31, %B1" "\n\t"       \
00609         "mov r30, %A1" "\n\t"       \
00610         "elpm" "\n\t"               \
00611         "mov %0, r0" "\n\t"         \
00612         : "=r" (__result)           \
00613         : "r" (__addr32),           \
00614           "I" (_SFR_IO_ADDR(RAMPZ)) \
00615         : "r0", "r30", "r31"        \
00616     );                              \
00617     __result;                       \
00618 }))
00619 
00620 #define __ELPM_enhanced__(addr)     \
00621 (__extension__({                    \
00622     uint32_t __addr32 = (uint32_t)(addr); \
00623     uint8_t __result;               \
00624     __asm__                         \
00625     (                               \
00626         "out %2, %C1" "\n\t"        \
00627         "movw r30, %1" "\n\t"       \
00628         "elpm %0, Z+" "\n\t"        \
00629         : "=r" (__result)           \
00630         : "r" (__addr32),           \
00631           "I" (_SFR_IO_ADDR(RAMPZ)) \
00632         : "r30", "r31"              \
00633     );                              \
00634     __result;                       \
00635 }))
00636 
00637 #define __ELPM_xmega__(addr)        \
00638 (__extension__({                    \
00639     uint32_t __addr32 = (uint32_t)(addr); \
00640     uint8_t __result;               \
00641     __asm__                         \
00642     (                               \
00643         "in __tmp_reg__, %2" "\n\t" \
00644         "out %2, %C1" "\n\t"        \
00645         "movw r30, %1" "\n\t"       \
00646         "elpm %0, Z+" "\n\t"        \
00647         "out %2, __tmp_reg__"       \
00648         : "=r" (__result)           \
00649         : "r" (__addr32),           \
00650           "I" (_SFR_IO_ADDR(RAMPZ)) \
00651         : "r30", "r31"              \
00652     );                              \
00653     __result;                       \
00654 }))
00655 
00656 #define __ELPM_word_classic__(addr)     \
00657 (__extension__({                        \
00658     uint32_t __addr32 = (uint32_t)(addr); \
00659     uint16_t __result;                  \
00660     __asm__                             \
00661     (                                   \
00662         "out %2, %C1"   "\n\t"          \
00663         "mov r31, %B1"  "\n\t"          \
00664         "mov r30, %A1"  "\n\t"          \
00665         "elpm"          "\n\t"          \
00666         "mov %A0, r0"   "\n\t"          \
00667         "in r0, %2"     "\n\t"          \
00668         "adiw r30, 1"   "\n\t"          \
00669         "adc r0, __zero_reg__" "\n\t"   \
00670         "out %2, r0"    "\n\t"          \
00671         "elpm"          "\n\t"          \
00672         "mov %B0, r0"   "\n\t"          \
00673         : "=r" (__result)               \
00674         : "r" (__addr32),               \
00675           "I" (_SFR_IO_ADDR(RAMPZ))     \
00676         : "r0", "r30", "r31"            \
00677     );                                  \
00678     __result;                           \
00679 }))
00680 
00681 #define __ELPM_word_enhanced__(addr)    \
00682 (__extension__({                        \
00683     uint32_t __addr32 = (uint32_t)(addr); \
00684     uint16_t __result;                  \
00685     __asm__                             \
00686     (                                   \
00687         "out %2, %C1"   "\n\t"          \
00688         "movw r30, %1"  "\n\t"          \
00689         "elpm %A0, Z+"  "\n\t"          \
00690         "elpm %B0, Z"   "\n\t"          \
00691         : "=r" (__result)               \
00692         : "r" (__addr32),               \
00693           "I" (_SFR_IO_ADDR(RAMPZ))     \
00694         : "r30", "r31"                  \
00695     );                                  \
00696     __result;                           \
00697 }))
00698 
00699 #define __ELPM_word_xmega__(addr)       \
00700 (__extension__({                        \
00701     uint32_t __addr32 = (uint32_t)(addr); \
00702     uint16_t __result;                  \
00703     __asm__                             \
00704     (                                   \
00705         "in __tmp_reg__, %2" "\n\t"     \
00706         "out %2, %C1"   "\n\t"          \
00707         "movw r30, %1"  "\n\t"          \
00708         "elpm %A0, Z+"  "\n\t"          \
00709         "elpm %B0, Z"   "\n\t"          \
00710         "out %2, __tmp_reg__"           \
00711         : "=r" (__result)               \
00712         : "r" (__addr32),               \
00713           "I" (_SFR_IO_ADDR(RAMPZ))     \
00714         : "r30", "r31"                  \
00715     );                                  \
00716     __result;                           \
00717 }))
00718 
00719 #define __ELPM_dword_classic__(addr)      \
00720 (__extension__({                          \
00721     uint32_t __addr32 = (uint32_t)(addr); \
00722     uint32_t __result;                    \
00723     __asm__                               \
00724     (                                     \
00725         "out %2, %C1"          "\n\t"     \
00726         "mov r31, %B1"         "\n\t"     \
00727         "mov r30, %A1"         "\n\t"     \
00728         "elpm"                 "\n\t"     \
00729         "mov %A0, r0"          "\n\t"     \
00730         "in r0, %2"            "\n\t"     \
00731         "adiw r30, 1"          "\n\t"     \
00732         "adc r0, __zero_reg__" "\n\t"     \
00733         "out %2, r0"           "\n\t"     \
00734         "elpm"                 "\n\t"     \
00735         "mov %B0, r0"          "\n\t"     \
00736         "in r0, %2"            "\n\t"     \
00737         "adiw r30, 1"          "\n\t"     \
00738         "adc r0, __zero_reg__" "\n\t"     \
00739         "out %2, r0"           "\n\t"     \
00740         "elpm"                 "\n\t"     \
00741         "mov %C0, r0"          "\n\t"     \
00742         "in r0, %2"            "\n\t"     \
00743         "adiw r30, 1"          "\n\t"     \
00744         "adc r0, __zero_reg__" "\n\t"     \
00745         "out %2, r0"           "\n\t"     \
00746         "elpm"                 "\n\t"     \
00747         "mov %D0, r0"          "\n\t"     \
00748         : "=r" (__result)                 \
00749         : "r" (__addr32),                 \
00750           "I" (_SFR_IO_ADDR(RAMPZ))       \
00751         : "r0", "r30", "r31"              \
00752     );                                    \
00753     __result;                             \
00754 }))
00755 
00756 #define __ELPM_dword_enhanced__(addr)     \
00757 (__extension__({                          \
00758     uint32_t __addr32 = (uint32_t)(addr); \
00759     uint32_t __result;                    \
00760     __asm__                               \
00761     (                                     \
00762         "out %2, %C1"   "\n\t"            \
00763         "movw r30, %1"  "\n\t"            \
00764         "elpm %A0, Z+"  "\n\t"            \
00765         "elpm %B0, Z+"  "\n\t"            \
00766         "elpm %C0, Z+"  "\n\t"            \
00767         "elpm %D0, Z"   "\n\t"            \
00768         : "=r" (__result)                 \
00769         : "r" (__addr32),                 \
00770           "I" (_SFR_IO_ADDR(RAMPZ))       \
00771         : "r30", "r31"                    \
00772     );                                    \
00773     __result;                             \
00774 }))
00775 
00776 #define __ELPM_dword_xmega__(addr)        \
00777 (__extension__({                          \
00778     uint32_t __addr32 = (uint32_t)(addr); \
00779     uint32_t __result;                    \
00780     __asm__                               \
00781     (                                     \
00782         "in __tmp_reg__, %2" "\n\t"       \
00783         "out %2, %C1"   "\n\t"            \
00784         "movw r30, %1"  "\n\t"            \
00785         "elpm %A0, Z+"  "\n\t"            \
00786         "elpm %B0, Z+"  "\n\t"            \
00787         "elpm %C0, Z+"  "\n\t"            \
00788         "elpm %D0, Z"   "\n\t"            \
00789         "out %2, __tmp_reg__"             \
00790         : "=r" (__result)                 \
00791         : "r" (__addr32),                 \
00792           "I" (_SFR_IO_ADDR(RAMPZ))       \
00793         : "r30", "r31"                    \
00794     );                                    \
00795     __result;                             \
00796 }))
00797 
00798 #define __ELPM_float_classic__(addr)      \
00799 (__extension__({                          \
00800     uint32_t __addr32 = (uint32_t)(addr); \
00801     float __result;                       \
00802     __asm__                               \
00803     (                                     \
00804         "out %2, %C1"          "\n\t"     \
00805         "mov r31, %B1"         "\n\t"     \
00806         "mov r30, %A1"         "\n\t"     \
00807         "elpm"                 "\n\t"     \
00808         "mov %A0, r0"          "\n\t"     \
00809         "in r0, %2"            "\n\t"     \
00810         "adiw r30, 1"          "\n\t"     \
00811         "adc r0, __zero_reg__" "\n\t"     \
00812         "out %2, r0"           "\n\t"     \
00813         "elpm"                 "\n\t"     \
00814         "mov %B0, r0"          "\n\t"     \
00815         "in r0, %2"            "\n\t"     \
00816         "adiw r30, 1"          "\n\t"     \
00817         "adc r0, __zero_reg__" "\n\t"     \
00818         "out %2, r0"           "\n\t"     \
00819         "elpm"                 "\n\t"     \
00820         "mov %C0, r0"          "\n\t"     \
00821         "in r0, %2"            "\n\t"     \
00822         "adiw r30, 1"          "\n\t"     \
00823         "adc r0, __zero_reg__" "\n\t"     \
00824         "out %2, r0"           "\n\t"     \
00825         "elpm"                 "\n\t"     \
00826         "mov %D0, r0"          "\n\t"     \
00827         : "=r" (__result)                 \
00828         : "r" (__addr32),                 \
00829           "I" (_SFR_IO_ADDR(RAMPZ))       \
00830         : "r0", "r30", "r31"              \
00831     );                                    \
00832     __result;                             \
00833 }))
00834 
00835 #define __ELPM_float_enhanced__(addr)     \
00836 (__extension__({                          \
00837     uint32_t __addr32 = (uint32_t)(addr); \
00838     float __result;                       \
00839     __asm__                               \
00840     (                                     \
00841         "out %2, %C1"   "\n\t"            \
00842         "movw r30, %1"  "\n\t"            \
00843         "elpm %A0, Z+"  "\n\t"            \
00844         "elpm %B0, Z+"  "\n\t"            \
00845         "elpm %C0, Z+"  "\n\t"            \
00846         "elpm %D0, Z"   "\n\t"            \
00847         : "=r" (__result)                 \
00848         : "r" (__addr32),                 \
00849           "I" (_SFR_IO_ADDR(RAMPZ))       \
00850         : "r30", "r31"                    \
00851     );                                    \
00852     __result;                             \
00853 }))
00854 
00855 #define __ELPM_float_xmega__(addr)        \
00856 (__extension__({                          \
00857     uint32_t __addr32 = (uint32_t)(addr); \
00858     float __result;                       \
00859     __asm__                               \
00860     (                                     \
00861         "in __tmp_reg__, %2" "\n\t"       \
00862         "out %2, %C1"   "\n\t"            \
00863         "movw r30, %1"  "\n\t"            \
00864         "elpm %A0, Z+"  "\n\t"            \
00865         "elpm %B0, Z+"  "\n\t"            \
00866         "elpm %C0, Z+"  "\n\t"            \
00867         "elpm %D0, Z"   "\n\t"            \
00868         "out %2, __tmp_reg__"             \
00869         : "=r" (__result)                 \
00870         : "r" (__addr32),                 \
00871           "I" (_SFR_IO_ADDR(RAMPZ))       \
00872         : "r30", "r31"                    \
00873     );                                    \
00874     __result;                             \
00875 }))
00876 
00877 /* 
00878 Check for architectures that implement RAMPD (avrxmega3, avrxmega5, 
00879 avrxmega7) as they need to save/restore RAMPZ for ELPM macros so it does
00880 not interfere with data accesses. 
00881 */
00882 #if defined (__AVR_HAVE_RAMPD__)
00883 
00884 #define __ELPM(addr)        __ELPM_xmega__(addr)
00885 #define __ELPM_word(addr)   __ELPM_word_xmega__(addr)
00886 #define __ELPM_dword(addr)  __ELPM_dword_xmega__(addr)
00887 #define __ELPM_float(addr)  __ELPM_float_xmega__(addr)
00888 
00889 #else
00890 
00891 #if defined (__AVR_HAVE_LPMX__)
00892 
00893 #define __ELPM(addr)        __ELPM_enhanced__(addr)
00894 #define __ELPM_word(addr)   __ELPM_word_enhanced__(addr)
00895 #define __ELPM_dword(addr)  __ELPM_dword_enhanced__(addr)
00896 #define __ELPM_float(addr)  __ELPM_float_enhanced__(addr)
00897 
00898 #else
00899 
00900 #define __ELPM(addr)        __ELPM_classic__(addr)
00901 #define __ELPM_word(addr)   __ELPM_word_classic__(addr)
00902 #define __ELPM_dword(addr)  __ELPM_dword_classic__(addr)
00903 #define __ELPM_float(addr)  __ELPM_float_classic__(addr)
00904 
00905 #endif  /* __AVR_HAVE_LPMX__ */
00906 
00907 #endif  /* __AVR_HAVE_RAMPD__ */
00908 
00909 
00910 /** \ingroup avr_pgmspace
00911     \def pgm_read_byte_far(address_long)
00912     Read a byte from the program space with a 32-bit (far) address. 
00913 
00914     \note The address is a byte address. 
00915     The address is in the program space. */
00916 
00917 #define pgm_read_byte_far(address_long)  __ELPM((uint32_t)(address_long))
00918 
00919 /** \ingroup avr_pgmspace
00920     \def pgm_read_word_far(address_long)
00921     Read a word from the program space with a 32-bit (far) address. 
00922 
00923     \note The address is a byte address.
00924     The address is in the program space. */
00925 
00926 #define pgm_read_word_far(address_long)  __ELPM_word((uint32_t)(address_long))
00927 
00928 /** \ingroup avr_pgmspace
00929     \def pgm_read_dword_far(address_long)
00930     Read a double word from the program space with a 32-bit (far) address. 
00931 
00932     \note The address is a byte address.
00933     The address is in the program space. */
00934 
00935 #define pgm_read_dword_far(address_long) __ELPM_dword((uint32_t)(address_long))
00936 
00937 /** \ingroup avr_pgmspace
00938     \def pgm_read_float_far(address_long)
00939     Read a float from the program space with a 32-bit (far) address. 
00940 
00941     \note The address is a byte address.
00942     The address is in the program space. */
00943 
00944 #define pgm_read_float_far(address_long) __ELPM_float((uint32_t)(address_long))
00945 
00946 #endif /* RAMPZ or __DOXYGEN__ */
00947 
00948 /** \ingroup avr_pgmspace
00949     \def pgm_read_byte(address_short)
00950     Read a byte from the program space with a 16-bit (near) address. 
00951 
00952     \note The address is a byte address. 
00953     The address is in the program space. */
00954 
00955 #define pgm_read_byte(address_short)    pgm_read_byte_near(address_short)
00956 
00957 /** \ingroup avr_pgmspace
00958     \def pgm_read_word(address_short)
00959     Read a word from the program space with a 16-bit (near) address. 
00960 
00961     \note The address is a byte address. 
00962     The address is in the program space. */
00963 
00964 #define pgm_read_word(address_short)    pgm_read_word_near(address_short)
00965 
00966 /** \ingroup avr_pgmspace
00967     \def pgm_read_dword(address_short)
00968     Read a double word from the program space with a 16-bit (near) address. 
00969 
00970     \note The address is a byte address. 
00971     The address is in the program space. */
00972 
00973 #define pgm_read_dword(address_short)   pgm_read_dword_near(address_short)
00974 
00975 /** \ingroup avr_pgmspace
00976     \def pgm_read_float(address_short)
00977     Read a float from the program space with a 16-bit (near) address. 
00978 
00979     \note The address is a byte address. 
00980     The address is in the program space. */
00981 
00982 #define pgm_read_float(address_short)   pgm_read_float_near(address_short)
00983 
00984 /* pgm_get_far_address() macro
00985 
00986    This macro facilitates the obtention of a 32 bit "far" pointer (only 24 bits
00987    used) to data even passed the 64KB limit for the 16 bit ordinary pointer. It
00988    is similar to the '&' operator, with some limitations.
00989 
00990    Comments:
00991 
00992    - The overhead is minimal and it's mainly due to the 32 bit size operation.
00993 
00994    - 24 bit sizes guarantees the code compatibility for use in future devices.
00995 
00996    - hh8() is an undocumented feature but seems to give the third significant byte
00997      of a 32 bit data and accepts symbols, complementing the functionality of hi8()
00998      and lo8(). There is not an equivalent assembler function to get the high
00999      significant byte.
01000 
01001    - 'var' has to be resolved at linking time as an existing symbol, i.e, a simple
01002      type variable name, an array name (not an indexed element of the array, if the
01003      index is a constant the compiler does not complain but fails to get the address
01004      if optimization is enabled), a struct name or a struct field name, a function
01005      identifier, a linker defined identifier,...
01006 
01007    - The returned value is the identifier's VMA (virtual memory address) determined
01008      by the linker and falls in the corresponding memory region. The AVR Harvard
01009      architecture requires non overlapping VMA areas for the multiple address spaces
01010      in the processor: Flash ROM, RAM, and EEPROM. Typical offset for this are
01011      0x00000000, 0x00800xx0, and 0x00810000 respectively, derived from the linker
01012          script used and linker options. The value returned can be seen then as a
01013      universal pointer.
01014 
01015 */
01016 
01017 #define pgm_get_far_address(var)                          \
01018 ({                                                    \
01019         uint_farptr_t tmp;                                \
01020                                                       \
01021         __asm__ __volatile__(                             \
01022                                                       \
01023                         "ldi    %A0, lo8(%1)"           "\n\t"    \
01024                         "ldi    %B0, hi8(%1)"           "\n\t"    \
01025                         "ldi    %C0, hh8(%1)"           "\n\t"    \
01026                         "clr    %D0"                    "\n\t"    \
01027                 :                                             \
01028                         "=d" (tmp)                                \
01029                 :                                             \
01030                         "p"  (&(var))                             \
01031         );                                                \
01032         tmp;                                              \
01033 })
01034 
01035 
01036 
01037 extern const void * memchr_P(const void *, int __val, size_t __len) __ATTR_CONST__;
01038 extern int memcmp_P(const void *, const void *, size_t) __ATTR_PURE__;
01039 extern void *memccpy_P(void *, const void *, int __val, size_t);
01040 extern void *memcpy_P(void *, const void *, size_t);
01041 extern void *memmem_P(const void *, size_t, const void *, size_t) __ATTR_PURE__;
01042 extern const void * memrchr_P(const void *, int __val, size_t __len) __ATTR_CONST__;
01043 extern char *strcat_P(char *, const char *);
01044 extern const char * strchr_P(const char *, int __val) __ATTR_CONST__;
01045 extern const char * strchrnul_P(const char *, int __val) __ATTR_CONST__;
01046 extern int strcmp_P(const char *, const char *) __ATTR_PURE__;
01047 extern char *strcpy_P(char *, const char *);
01048 extern int strcasecmp_P(const char *, const char *) __ATTR_PURE__;
01049 extern char *strcasestr_P(const char *, const char *) __ATTR_PURE__;
01050 extern size_t strcspn_P(const char *__s, const char * __reject) __ATTR_PURE__;
01051 extern size_t strlcat_P (char *, const char *, size_t );
01052 extern size_t strlcpy_P (char *, const char *, size_t );
01053 extern size_t __strlen_P(const char *) __ATTR_CONST__;  /* program memory can't change */
01054 extern size_t strnlen_P(const char *, size_t) __ATTR_CONST__; /* program memory can't change */
01055 extern int strncmp_P(const char *, const char *, size_t) __ATTR_PURE__;
01056 extern int strncasecmp_P(const char *, const char *, size_t) __ATTR_PURE__;
01057 extern char *strncat_P(char *, const char *, size_t);
01058 extern char *strncpy_P(char *, const char *, size_t);
01059 extern char *strpbrk_P(const char *__s, const char * __accept) __ATTR_PURE__;
01060 extern const char * strrchr_P(const char *, int __val) __ATTR_CONST__;
01061 extern char *strsep_P(char **__sp, const char * __delim);
01062 extern size_t strspn_P(const char *__s, const char * __accept) __ATTR_PURE__;
01063 extern char *strstr_P(const char *, const char *) __ATTR_PURE__;
01064 extern char *strtok_P(char *__s, const char * __delim);
01065 extern char *strtok_rP(char *__s, const char * __delim, char **__last);
01066 
01067 extern size_t strlen_PF (uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */
01068 extern size_t strnlen_PF (uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */
01069 extern void *memcpy_PF (void *dest, uint_farptr_t src, size_t len);
01070 extern char *strcpy_PF (char *dest, uint_farptr_t src);
01071 extern char *strncpy_PF (char *dest, uint_farptr_t src, size_t len);
01072 extern char *strcat_PF (char *dest, uint_farptr_t src);
01073 extern size_t strlcat_PF (char *dst, uint_farptr_t src, size_t siz);
01074 extern char *strncat_PF (char *dest, uint_farptr_t src, size_t len);
01075 extern int strcmp_PF (const char *s1, uint_farptr_t s2) __ATTR_PURE__;
01076 extern int strncmp_PF (const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
01077 extern int strcasecmp_PF (const char *s1, uint_farptr_t s2) __ATTR_PURE__;
01078 extern int strncasecmp_PF (const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;
01079 extern char *strstr_PF (const char *s1, uint_farptr_t s2);
01080 extern size_t strlcpy_PF (char *dst, uint_farptr_t src, size_t siz);
01081 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;
01082 
01083 
01084 __attribute__((__always_inline__)) static inline size_t strlen_P(const char * s);
01085 static inline size_t strlen_P(const char *s) {
01086   return __builtin_constant_p(__builtin_strlen(s))
01087      ? __builtin_strlen(s) : __strlen_P(s);
01088 } 
01089 
01090 
01091 
01092 #ifdef __cplusplus
01093 }
01094 #endif
01095 
01096 #endif /* __PGMSPACE_H_ */

Automatically generated by Doxygen 1.7.6.1 on Tue Jan 3 2012.