$extrastylesheet
avr-libc
2.0.0
Standard C library for AVR-GCC
|
AVR Libc Home Page |
![]() |
AVR Libc Development Pages |
|||
Main Page |
User Manual |
Library Reference |
FAQ |
Example Projects |
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.h 2503 2016-02-07 22:59:47Z joerg_wunsch $ */ 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 #ifndef __DOXYGEN__ 00086 #define __need_size_t 00087 #endif 00088 #include <inttypes.h> 00089 #include <stddef.h> 00090 #include <avr/io.h> 00091 00092 #ifndef __DOXYGEN__ 00093 #ifndef __ATTR_CONST__ 00094 #define __ATTR_CONST__ __attribute__((__const__)) 00095 #endif 00096 00097 #ifndef __ATTR_PROGMEM__ 00098 #define __ATTR_PROGMEM__ __attribute__((__progmem__)) 00099 #endif 00100 00101 #ifndef __ATTR_PURE__ 00102 #define __ATTR_PURE__ __attribute__((__pure__)) 00103 #endif 00104 #endif /* !__DOXYGEN__ */ 00105 00106 /** 00107 \ingroup avr_pgmspace 00108 \def PROGMEM 00109 00110 Attribute to use in order to declare an object being located in 00111 flash ROM. 00112 */ 00113 #define PROGMEM __ATTR_PROGMEM__ 00114 00115 #ifdef __cplusplus 00116 extern "C" { 00117 #endif 00118 00119 #if defined(__DOXYGEN__) 00120 /* 00121 * Doxygen doesn't grok the appended attribute syntax of 00122 * GCC, and confuses the typedefs with function decls, so 00123 * supply a doxygen-friendly view. 00124 */ 00125 00126 /** 00127 \ingroup avr_pgmspace 00128 \typedef prog_void 00129 \note DEPRECATED 00130 00131 This typedef is now deprecated because the usage of the __progmem__ 00132 attribute on a type is not supported in GCC. However, the use of the 00133 __progmem__ attribute on a variable declaration is supported, and this is 00134 now the recommended usage. 00135 00136 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00137 has been defined before including <avr/pgmspace.h> (either by a 00138 \c \#define directive, or by a -D compiler option.) 00139 00140 Type of a "void" object located in flash ROM. Does not make much 00141 sense by itself, but can be used to declare a "void *" object in 00142 flash ROM. 00143 */ 00144 typedef void PROGMEM prog_void; 00145 00146 /** 00147 \ingroup avr_pgmspace 00148 \typedef prog_char 00149 \note DEPRECATED 00150 00151 This typedef is now deprecated because the usage of the __progmem__ 00152 attribute on a type is not supported in GCC. However, the use of the 00153 __progmem__ attribute on a variable declaration is supported, and this is 00154 now the recommended usage. 00155 00156 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00157 has been defined before including <avr/pgmspace.h> (either by a 00158 \c \#define directive, or by a -D compiler option.) 00159 00160 Type of a "char" object located in flash ROM. 00161 */ 00162 typedef char PROGMEM prog_char; 00163 00164 /** 00165 \ingroup avr_pgmspace 00166 \typedef prog_uchar 00167 \note DEPRECATED 00168 00169 This typedef is now deprecated because the usage of the __progmem__ 00170 attribute on a type is not supported in GCC. However, the use of the 00171 __progmem__ attribute on a variable declaration is supported, and this is 00172 now the recommended usage. 00173 00174 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00175 has been defined before including <avr/pgmspace.h> (either by a 00176 \c \#define directive, or by a -D compiler option.) 00177 00178 Type of an "unsigned char" object located in flash ROM. 00179 */ 00180 typedef unsigned char PROGMEM prog_uchar; 00181 00182 /** 00183 \ingroup avr_pgmspace 00184 \typedef prog_int8_t 00185 \note DEPRECATED 00186 00187 This typedef is now deprecated because the usage of the __progmem__ 00188 attribute on a type is not supported in GCC. However, the use of the 00189 __progmem__ attribute on a variable declaration is supported, and this is 00190 now the recommended usage. 00191 00192 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00193 has been defined before including <avr/pgmspace.h> (either by a 00194 \c \#define directive, or by a -D compiler option.) 00195 00196 Type of an "int8_t" object located in flash ROM. 00197 */ 00198 typedef int8_t PROGMEM prog_int8_t; 00199 00200 /** 00201 \ingroup avr_pgmspace 00202 \typedef prog_uint8_t 00203 \note DEPRECATED 00204 00205 This typedef is now deprecated because the usage of the __progmem__ 00206 attribute on a type is not supported in GCC. However, the use of the 00207 __progmem__ attribute on a variable declaration is supported, and this is 00208 now the recommended usage. 00209 00210 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00211 has been defined before including <avr/pgmspace.h> (either by a 00212 \c \#define directive, or by a -D compiler option.) 00213 00214 Type of an "uint8_t" object located in flash ROM. 00215 */ 00216 typedef uint8_t PROGMEM prog_uint8_t; 00217 00218 /** 00219 \ingroup avr_pgmspace 00220 \typedef prog_int16_t 00221 \note DEPRECATED 00222 00223 This typedef is now deprecated because the usage of the __progmem__ 00224 attribute on a type is not supported in GCC. However, the use of the 00225 __progmem__ attribute on a variable declaration is supported, and this is 00226 now the recommended usage. 00227 00228 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00229 has been defined before including <avr/pgmspace.h> (either by a 00230 \c \#define directive, or by a -D compiler option.) 00231 00232 Type of an "int16_t" object located in flash ROM. 00233 */ 00234 typedef int16_t PROGMEM prog_int16_t; 00235 00236 /** 00237 \ingroup avr_pgmspace 00238 \typedef prog_uint16_t 00239 \note DEPRECATED 00240 00241 This typedef is now deprecated because the usage of the __progmem__ 00242 attribute on a type is not supported in GCC. However, the use of the 00243 __progmem__ attribute on a variable declaration is supported, and this is 00244 now the recommended usage. 00245 00246 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00247 has been defined before including <avr/pgmspace.h> (either by a 00248 \c \#define directive, or by a -D compiler option.) 00249 00250 Type of an "uint16_t" object located in flash ROM. 00251 */ 00252 typedef uint16_t PROGMEM prog_uint16_t; 00253 00254 /** 00255 \ingroup avr_pgmspace 00256 \typedef prog_int32_t 00257 \note DEPRECATED 00258 00259 This typedef is now deprecated because the usage of the __progmem__ 00260 attribute on a type is not supported in GCC. However, the use of the 00261 __progmem__ attribute on a variable declaration is supported, and this is 00262 now the recommended usage. 00263 00264 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00265 has been defined before including <avr/pgmspace.h> (either by a 00266 \c \#define directive, or by a -D compiler option.) 00267 00268 Type of an "int32_t" object located in flash ROM. 00269 */ 00270 typedef int32_t PROGMEM prog_int32_t; 00271 00272 /** 00273 \ingroup avr_pgmspace 00274 \typedef prog_uint32_t 00275 \note DEPRECATED 00276 00277 This typedef is now deprecated because the usage of the __progmem__ 00278 attribute on a type is not supported in GCC. However, the use of the 00279 __progmem__ attribute on a variable declaration is supported, and this is 00280 now the recommended usage. 00281 00282 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00283 has been defined before including <avr/pgmspace.h> (either by a 00284 \c \#define directive, or by a -D compiler option.) 00285 00286 Type of an "uint32_t" object located in flash ROM. 00287 */ 00288 typedef uint32_t PROGMEM prog_uint32_t; 00289 00290 /** 00291 \ingroup avr_pgmspace 00292 \typedef prog_int64_t 00293 \note DEPRECATED 00294 00295 This typedef is now deprecated because the usage of the __progmem__ 00296 attribute on a type is not supported in GCC. However, the use of the 00297 __progmem__ attribute on a variable declaration is supported, and this is 00298 now the recommended usage. 00299 00300 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00301 has been defined before including <avr/pgmspace.h> (either by a 00302 \c \#define directive, or by a -D compiler option.) 00303 00304 Type of an "int64_t" object located in flash ROM. 00305 00306 \note This type is not available when the compiler 00307 option -mint8 is in effect. 00308 */ 00309 typedef int64_t PROGMEM prog_int64_t; 00310 00311 /** 00312 \ingroup avr_pgmspace 00313 \typedef prog_uint64_t 00314 \note DEPRECATED 00315 00316 This typedef is now deprecated because the usage of the __progmem__ 00317 attribute on a type is not supported in GCC. However, the use of the 00318 __progmem__ attribute on a variable declaration is supported, and this is 00319 now the recommended usage. 00320 00321 The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 00322 has been defined before including <avr/pgmspace.h> (either by a 00323 \c \#define directive, or by a -D compiler option.) 00324 00325 Type of an "uint64_t" object located in flash ROM. 00326 00327 \note This type is not available when the compiler 00328 option -mint8 is in effect. 00329 */ 00330 typedef uint64_t PROGMEM prog_uint64_t; 00331 00332 /** \ingroup avr_pgmspace 00333 \def PGM_P 00334 00335 Used to declare a variable that is a pointer to a string in program 00336 space. */ 00337 00338 #ifndef PGM_P 00339 #define PGM_P const char * 00340 #endif 00341 00342 /** \ingroup avr_pgmspace 00343 \def PGM_VOID_P 00344 00345 Used to declare a generic pointer to an object in program space. */ 00346 00347 #ifndef PGM_VOID_P 00348 #define PGM_VOID_P const void * 00349 #endif 00350 00351 #elif defined(__PROG_TYPES_COMPAT__) /* !DOXYGEN */ 00352 00353 typedef void prog_void __attribute__((__progmem__,deprecated("prog_void type is deprecated."))); 00354 typedef char prog_char __attribute__((__progmem__,deprecated("prog_char type is deprecated."))); 00355 typedef unsigned char prog_uchar __attribute__((__progmem__,deprecated("prog_uchar type is deprecated."))); 00356 typedef int8_t prog_int8_t __attribute__((__progmem__,deprecated("prog_int8_t type is deprecated."))); 00357 typedef uint8_t prog_uint8_t __attribute__((__progmem__,deprecated("prog_uint8_t type is deprecated."))); 00358 typedef int16_t prog_int16_t __attribute__((__progmem__,deprecated("prog_int16_t type is deprecated."))); 00359 typedef uint16_t prog_uint16_t __attribute__((__progmem__,deprecated("prog_uint16_t type is deprecated."))); 00360 typedef int32_t prog_int32_t __attribute__((__progmem__,deprecated("prog_int32_t type is deprecated."))); 00361 typedef uint32_t prog_uint32_t __attribute__((__progmem__,deprecated("prog_uint32_t type is deprecated."))); 00362 #if !__USING_MINT8 00363 typedef int64_t prog_int64_t __attribute__((__progmem__,deprecated("prog_int64_t type is deprecated."))); 00364 typedef uint64_t prog_uint64_t __attribute__((__progmem__,deprecated("prog_uint64_t type is deprecated."))); 00365 #endif 00366 00367 #ifndef PGM_P 00368 #define PGM_P const prog_char * 00369 #endif 00370 00371 #ifndef PGM_VOID_P 00372 #define PGM_VOID_P const prog_void * 00373 #endif 00374 00375 #else /* !defined(__DOXYGEN__), !defined(__PROG_TYPES_COMPAT__) */ 00376 00377 #ifndef PGM_P 00378 #define PGM_P const char * 00379 #endif 00380 00381 #ifndef PGM_VOID_P 00382 #define PGM_VOID_P const void * 00383 #endif 00384 #endif /* defined(__DOXYGEN__), defined(__PROG_TYPES_COMPAT__) */ 00385 00386 /* Although in C, we can get away with just using __c, it does not work in 00387 C++. We need to use &__c[0] to avoid the compiler puking. Dave Hylands 00388 explaned it thusly, 00389 00390 Let's suppose that we use PSTR("Test"). In this case, the type returned 00391 by __c is a prog_char[5] and not a prog_char *. While these are 00392 compatible, they aren't the same thing (especially in C++). The type 00393 returned by &__c[0] is a prog_char *, which explains why it works 00394 fine. */ 00395 00396 #if defined(__DOXYGEN__) 00397 /* 00398 * The #define below is just a dummy that serves documentation 00399 * purposes only. 00400 */ 00401 /** \ingroup avr_pgmspace 00402 \def PSTR(s) 00403 00404 Used to declare a static pointer to a string in program space. */ 00405 # define PSTR(s) ((const PROGMEM char *)(s)) 00406 #else /* !DOXYGEN */ 00407 /* The real thing. */ 00408 # define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) 00409 #endif /* DOXYGEN */ 00410 00411 #ifndef __DOXYGEN__ /* Internal macros, not documented. */ 00412 #define __LPM_classic__(addr) \ 00413 (__extension__({ \ 00414 uint16_t __addr16 = (uint16_t)(addr); \ 00415 uint8_t __result; \ 00416 __asm__ __volatile__ \ 00417 ( \ 00418 "lpm" "\n\t" \ 00419 "mov %0, r0" "\n\t" \ 00420 : "=r" (__result) \ 00421 : "z" (__addr16) \ 00422 : "r0" \ 00423 ); \ 00424 __result; \ 00425 })) 00426 00427 #define __LPM_enhanced__(addr) \ 00428 (__extension__({ \ 00429 uint16_t __addr16 = (uint16_t)(addr); \ 00430 uint8_t __result; \ 00431 __asm__ __volatile__ \ 00432 ( \ 00433 "lpm %0, Z" "\n\t" \ 00434 : "=r" (__result) \ 00435 : "z" (__addr16) \ 00436 ); \ 00437 __result; \ 00438 })) 00439 00440 #define __LPM_word_classic__(addr) \ 00441 (__extension__({ \ 00442 uint16_t __addr16 = (uint16_t)(addr); \ 00443 uint16_t __result; \ 00444 __asm__ __volatile__ \ 00445 ( \ 00446 "lpm" "\n\t" \ 00447 "mov %A0, r0" "\n\t" \ 00448 "adiw r30, 1" "\n\t" \ 00449 "lpm" "\n\t" \ 00450 "mov %B0, r0" "\n\t" \ 00451 : "=r" (__result), "=z" (__addr16) \ 00452 : "1" (__addr16) \ 00453 : "r0" \ 00454 ); \ 00455 __result; \ 00456 })) 00457 00458 #define __LPM_word_enhanced__(addr) \ 00459 (__extension__({ \ 00460 uint16_t __addr16 = (uint16_t)(addr); \ 00461 uint16_t __result; \ 00462 __asm__ __volatile__ \ 00463 ( \ 00464 "lpm %A0, Z+" "\n\t" \ 00465 "lpm %B0, Z" "\n\t" \ 00466 : "=r" (__result), "=z" (__addr16) \ 00467 : "1" (__addr16) \ 00468 ); \ 00469 __result; \ 00470 })) 00471 00472 #define __LPM_dword_classic__(addr) \ 00473 (__extension__({ \ 00474 uint16_t __addr16 = (uint16_t)(addr); \ 00475 uint32_t __result; \ 00476 __asm__ __volatile__ \ 00477 ( \ 00478 "lpm" "\n\t" \ 00479 "mov %A0, r0" "\n\t" \ 00480 "adiw r30, 1" "\n\t" \ 00481 "lpm" "\n\t" \ 00482 "mov %B0, r0" "\n\t" \ 00483 "adiw r30, 1" "\n\t" \ 00484 "lpm" "\n\t" \ 00485 "mov %C0, r0" "\n\t" \ 00486 "adiw r30, 1" "\n\t" \ 00487 "lpm" "\n\t" \ 00488 "mov %D0, r0" "\n\t" \ 00489 : "=r" (__result), "=z" (__addr16) \ 00490 : "1" (__addr16) \ 00491 : "r0" \ 00492 ); \ 00493 __result; \ 00494 })) 00495 00496 #define __LPM_dword_enhanced__(addr) \ 00497 (__extension__({ \ 00498 uint16_t __addr16 = (uint16_t)(addr); \ 00499 uint32_t __result; \ 00500 __asm__ __volatile__ \ 00501 ( \ 00502 "lpm %A0, Z+" "\n\t" \ 00503 "lpm %B0, Z+" "\n\t" \ 00504 "lpm %C0, Z+" "\n\t" \ 00505 "lpm %D0, Z" "\n\t" \ 00506 : "=r" (__result), "=z" (__addr16) \ 00507 : "1" (__addr16) \ 00508 ); \ 00509 __result; \ 00510 })) 00511 00512 #define __LPM_float_classic__(addr) \ 00513 (__extension__({ \ 00514 uint16_t __addr16 = (uint16_t)(addr); \ 00515 float __result; \ 00516 __asm__ __volatile__ \ 00517 ( \ 00518 "lpm" "\n\t" \ 00519 "mov %A0, r0" "\n\t" \ 00520 "adiw r30, 1" "\n\t" \ 00521 "lpm" "\n\t" \ 00522 "mov %B0, r0" "\n\t" \ 00523 "adiw r30, 1" "\n\t" \ 00524 "lpm" "\n\t" \ 00525 "mov %C0, r0" "\n\t" \ 00526 "adiw r30, 1" "\n\t" \ 00527 "lpm" "\n\t" \ 00528 "mov %D0, r0" "\n\t" \ 00529 : "=r" (__result), "=z" (__addr16) \ 00530 : "1" (__addr16) \ 00531 : "r0" \ 00532 ); \ 00533 __result; \ 00534 })) 00535 00536 #define __LPM_float_enhanced__(addr) \ 00537 (__extension__({ \ 00538 uint16_t __addr16 = (uint16_t)(addr); \ 00539 float __result; \ 00540 __asm__ __volatile__ \ 00541 ( \ 00542 "lpm %A0, Z+" "\n\t" \ 00543 "lpm %B0, Z+" "\n\t" \ 00544 "lpm %C0, Z+" "\n\t" \ 00545 "lpm %D0, Z" "\n\t" \ 00546 : "=r" (__result), "=z" (__addr16) \ 00547 : "1" (__addr16) \ 00548 ); \ 00549 __result; \ 00550 })) 00551 00552 #if defined (__AVR_HAVE_LPMX__) 00553 #define __LPM(addr) __LPM_enhanced__(addr) 00554 #define __LPM_word(addr) __LPM_word_enhanced__(addr) 00555 #define __LPM_dword(addr) __LPM_dword_enhanced__(addr) 00556 #define __LPM_float(addr) __LPM_float_enhanced__(addr) 00557 #else 00558 #define __LPM(addr) __LPM_classic__(addr) 00559 #define __LPM_word(addr) __LPM_word_classic__(addr) 00560 #define __LPM_dword(addr) __LPM_dword_classic__(addr) 00561 #define __LPM_float(addr) __LPM_float_classic__(addr) 00562 #endif 00563 00564 #endif /* !__DOXYGEN__ */ 00565 00566 /** \ingroup avr_pgmspace 00567 \def pgm_read_byte_near(address_short) 00568 Read a byte from the program space with a 16-bit (near) address. 00569 \note The address is a byte address. 00570 The address is in the program space. */ 00571 00572 #define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short)) 00573 00574 /** \ingroup avr_pgmspace 00575 \def pgm_read_word_near(address_short) 00576 Read a word from the program space with a 16-bit (near) address. 00577 \note The address is a byte address. 00578 The address is in the program space. */ 00579 00580 #define pgm_read_word_near(address_short) __LPM_word((uint16_t)(address_short)) 00581 00582 /** \ingroup avr_pgmspace 00583 \def pgm_read_dword_near(address_short) 00584 Read a double word from the program space with a 16-bit (near) address. 00585 \note The address is a byte address. 00586 The address is in the program space. */ 00587 00588 #define pgm_read_dword_near(address_short) \ 00589 __LPM_dword((uint16_t)(address_short)) 00590 00591 /** \ingroup avr_pgmspace 00592 \def pgm_read_float_near(address_short) 00593 Read a float from the program space with a 16-bit (near) address. 00594 \note The address is a byte address. 00595 The address is in the program space. */ 00596 00597 #define pgm_read_float_near(address_short) \ 00598 __LPM_float((uint16_t)(address_short)) 00599 00600 /** \ingroup avr_pgmspace 00601 \def pgm_read_ptr_near(address_short) 00602 Read a pointer from the program space with a 16-bit (near) address. 00603 \note The address is a byte address. 00604 The address is in the program space. */ 00605 00606 #define pgm_read_ptr_near(address_short) \ 00607 (void*)__LPM_word((uint16_t)(address_short)) 00608 00609 #if defined(RAMPZ) || defined(__DOXYGEN__) 00610 00611 /* Only for devices with more than 64K of program memory. 00612 RAMPZ must be defined (see iom103.h, iom128.h). 00613 */ 00614 00615 /* The classic functions are needed for ATmega103. */ 00616 #ifndef __DOXYGEN__ /* These are internal macros, avoid "is 00617 not documented" warnings. */ 00618 #define __ELPM_classic__(addr) \ 00619 (__extension__({ \ 00620 uint32_t __addr32 = (uint32_t)(addr); \ 00621 uint8_t __result; \ 00622 __asm__ __volatile__ \ 00623 ( \ 00624 "out %2, %C1" "\n\t" \ 00625 "mov r31, %B1" "\n\t" \ 00626 "mov r30, %A1" "\n\t" \ 00627 "elpm" "\n\t" \ 00628 "mov %0, r0" "\n\t" \ 00629 : "=r" (__result) \ 00630 : "r" (__addr32), \ 00631 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00632 : "r0", "r30", "r31" \ 00633 ); \ 00634 __result; \ 00635 })) 00636 00637 #define __ELPM_enhanced__(addr) \ 00638 (__extension__({ \ 00639 uint32_t __addr32 = (uint32_t)(addr); \ 00640 uint8_t __result; \ 00641 __asm__ __volatile__ \ 00642 ( \ 00643 "out %2, %C1" "\n\t" \ 00644 "movw r30, %1" "\n\t" \ 00645 "elpm %0, Z+" "\n\t" \ 00646 : "=r" (__result) \ 00647 : "r" (__addr32), \ 00648 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00649 : "r30", "r31" \ 00650 ); \ 00651 __result; \ 00652 })) 00653 00654 #define __ELPM_xmega__(addr) \ 00655 (__extension__({ \ 00656 uint32_t __addr32 = (uint32_t)(addr); \ 00657 uint8_t __result; \ 00658 __asm__ __volatile__ \ 00659 ( \ 00660 "in __tmp_reg__, %2" "\n\t" \ 00661 "out %2, %C1" "\n\t" \ 00662 "movw r30, %1" "\n\t" \ 00663 "elpm %0, Z+" "\n\t" \ 00664 "out %2, __tmp_reg__" \ 00665 : "=r" (__result) \ 00666 : "r" (__addr32), \ 00667 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00668 : "r30", "r31" \ 00669 ); \ 00670 __result; \ 00671 })) 00672 00673 #define __ELPM_word_classic__(addr) \ 00674 (__extension__({ \ 00675 uint32_t __addr32 = (uint32_t)(addr); \ 00676 uint16_t __result; \ 00677 __asm__ __volatile__ \ 00678 ( \ 00679 "out %2, %C1" "\n\t" \ 00680 "mov r31, %B1" "\n\t" \ 00681 "mov r30, %A1" "\n\t" \ 00682 "elpm" "\n\t" \ 00683 "mov %A0, r0" "\n\t" \ 00684 "in r0, %2" "\n\t" \ 00685 "adiw r30, 1" "\n\t" \ 00686 "adc r0, __zero_reg__" "\n\t" \ 00687 "out %2, r0" "\n\t" \ 00688 "elpm" "\n\t" \ 00689 "mov %B0, r0" "\n\t" \ 00690 : "=r" (__result) \ 00691 : "r" (__addr32), \ 00692 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00693 : "r0", "r30", "r31" \ 00694 ); \ 00695 __result; \ 00696 })) 00697 00698 #define __ELPM_word_enhanced__(addr) \ 00699 (__extension__({ \ 00700 uint32_t __addr32 = (uint32_t)(addr); \ 00701 uint16_t __result; \ 00702 __asm__ __volatile__ \ 00703 ( \ 00704 "out %2, %C1" "\n\t" \ 00705 "movw r30, %1" "\n\t" \ 00706 "elpm %A0, Z+" "\n\t" \ 00707 "elpm %B0, Z" "\n\t" \ 00708 : "=r" (__result) \ 00709 : "r" (__addr32), \ 00710 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00711 : "r30", "r31" \ 00712 ); \ 00713 __result; \ 00714 })) 00715 00716 #define __ELPM_word_xmega__(addr) \ 00717 (__extension__({ \ 00718 uint32_t __addr32 = (uint32_t)(addr); \ 00719 uint16_t __result; \ 00720 __asm__ __volatile__ \ 00721 ( \ 00722 "in __tmp_reg__, %2" "\n\t" \ 00723 "out %2, %C1" "\n\t" \ 00724 "movw r30, %1" "\n\t" \ 00725 "elpm %A0, Z+" "\n\t" \ 00726 "elpm %B0, Z" "\n\t" \ 00727 "out %2, __tmp_reg__" \ 00728 : "=r" (__result) \ 00729 : "r" (__addr32), \ 00730 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00731 : "r30", "r31" \ 00732 ); \ 00733 __result; \ 00734 })) 00735 00736 #define __ELPM_dword_classic__(addr) \ 00737 (__extension__({ \ 00738 uint32_t __addr32 = (uint32_t)(addr); \ 00739 uint32_t __result; \ 00740 __asm__ __volatile__ \ 00741 ( \ 00742 "out %2, %C1" "\n\t" \ 00743 "mov r31, %B1" "\n\t" \ 00744 "mov r30, %A1" "\n\t" \ 00745 "elpm" "\n\t" \ 00746 "mov %A0, r0" "\n\t" \ 00747 "in r0, %2" "\n\t" \ 00748 "adiw r30, 1" "\n\t" \ 00749 "adc r0, __zero_reg__" "\n\t" \ 00750 "out %2, r0" "\n\t" \ 00751 "elpm" "\n\t" \ 00752 "mov %B0, r0" "\n\t" \ 00753 "in r0, %2" "\n\t" \ 00754 "adiw r30, 1" "\n\t" \ 00755 "adc r0, __zero_reg__" "\n\t" \ 00756 "out %2, r0" "\n\t" \ 00757 "elpm" "\n\t" \ 00758 "mov %C0, r0" "\n\t" \ 00759 "in r0, %2" "\n\t" \ 00760 "adiw r30, 1" "\n\t" \ 00761 "adc r0, __zero_reg__" "\n\t" \ 00762 "out %2, r0" "\n\t" \ 00763 "elpm" "\n\t" \ 00764 "mov %D0, r0" "\n\t" \ 00765 : "=r" (__result) \ 00766 : "r" (__addr32), \ 00767 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00768 : "r0", "r30", "r31" \ 00769 ); \ 00770 __result; \ 00771 })) 00772 00773 #define __ELPM_dword_enhanced__(addr) \ 00774 (__extension__({ \ 00775 uint32_t __addr32 = (uint32_t)(addr); \ 00776 uint32_t __result; \ 00777 __asm__ __volatile__ \ 00778 ( \ 00779 "out %2, %C1" "\n\t" \ 00780 "movw r30, %1" "\n\t" \ 00781 "elpm %A0, Z+" "\n\t" \ 00782 "elpm %B0, Z+" "\n\t" \ 00783 "elpm %C0, Z+" "\n\t" \ 00784 "elpm %D0, Z" "\n\t" \ 00785 : "=r" (__result) \ 00786 : "r" (__addr32), \ 00787 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00788 : "r30", "r31" \ 00789 ); \ 00790 __result; \ 00791 })) 00792 00793 #define __ELPM_dword_xmega__(addr) \ 00794 (__extension__({ \ 00795 uint32_t __addr32 = (uint32_t)(addr); \ 00796 uint32_t __result; \ 00797 __asm__ __volatile__ \ 00798 ( \ 00799 "in __tmp_reg__, %2" "\n\t" \ 00800 "out %2, %C1" "\n\t" \ 00801 "movw r30, %1" "\n\t" \ 00802 "elpm %A0, Z+" "\n\t" \ 00803 "elpm %B0, Z+" "\n\t" \ 00804 "elpm %C0, Z+" "\n\t" \ 00805 "elpm %D0, Z" "\n\t" \ 00806 "out %2, __tmp_reg__" \ 00807 : "=r" (__result) \ 00808 : "r" (__addr32), \ 00809 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00810 : "r30", "r31" \ 00811 ); \ 00812 __result; \ 00813 })) 00814 00815 #define __ELPM_float_classic__(addr) \ 00816 (__extension__({ \ 00817 uint32_t __addr32 = (uint32_t)(addr); \ 00818 float __result; \ 00819 __asm__ __volatile__ \ 00820 ( \ 00821 "out %2, %C1" "\n\t" \ 00822 "mov r31, %B1" "\n\t" \ 00823 "mov r30, %A1" "\n\t" \ 00824 "elpm" "\n\t" \ 00825 "mov %A0, r0" "\n\t" \ 00826 "in r0, %2" "\n\t" \ 00827 "adiw r30, 1" "\n\t" \ 00828 "adc r0, __zero_reg__" "\n\t" \ 00829 "out %2, r0" "\n\t" \ 00830 "elpm" "\n\t" \ 00831 "mov %B0, r0" "\n\t" \ 00832 "in r0, %2" "\n\t" \ 00833 "adiw r30, 1" "\n\t" \ 00834 "adc r0, __zero_reg__" "\n\t" \ 00835 "out %2, r0" "\n\t" \ 00836 "elpm" "\n\t" \ 00837 "mov %C0, r0" "\n\t" \ 00838 "in r0, %2" "\n\t" \ 00839 "adiw r30, 1" "\n\t" \ 00840 "adc r0, __zero_reg__" "\n\t" \ 00841 "out %2, r0" "\n\t" \ 00842 "elpm" "\n\t" \ 00843 "mov %D0, r0" "\n\t" \ 00844 : "=r" (__result) \ 00845 : "r" (__addr32), \ 00846 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00847 : "r0", "r30", "r31" \ 00848 ); \ 00849 __result; \ 00850 })) 00851 00852 #define __ELPM_float_enhanced__(addr) \ 00853 (__extension__({ \ 00854 uint32_t __addr32 = (uint32_t)(addr); \ 00855 float __result; \ 00856 __asm__ __volatile__ \ 00857 ( \ 00858 "out %2, %C1" "\n\t" \ 00859 "movw r30, %1" "\n\t" \ 00860 "elpm %A0, Z+" "\n\t" \ 00861 "elpm %B0, Z+" "\n\t" \ 00862 "elpm %C0, Z+" "\n\t" \ 00863 "elpm %D0, Z" "\n\t" \ 00864 : "=r" (__result) \ 00865 : "r" (__addr32), \ 00866 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00867 : "r30", "r31" \ 00868 ); \ 00869 __result; \ 00870 })) 00871 00872 #define __ELPM_float_xmega__(addr) \ 00873 (__extension__({ \ 00874 uint32_t __addr32 = (uint32_t)(addr); \ 00875 float __result; \ 00876 __asm__ __volatile__ \ 00877 ( \ 00878 "in __tmp_reg__, %2" "\n\t" \ 00879 "out %2, %C1" "\n\t" \ 00880 "movw r30, %1" "\n\t" \ 00881 "elpm %A0, Z+" "\n\t" \ 00882 "elpm %B0, Z+" "\n\t" \ 00883 "elpm %C0, Z+" "\n\t" \ 00884 "elpm %D0, Z" "\n\t" \ 00885 "out %2, __tmp_reg__" \ 00886 : "=r" (__result) \ 00887 : "r" (__addr32), \ 00888 "I" (_SFR_IO_ADDR(RAMPZ)) \ 00889 : "r30", "r31" \ 00890 ); \ 00891 __result; \ 00892 })) 00893 00894 /* 00895 Check for architectures that implement RAMPD (avrxmega3, avrxmega5, 00896 avrxmega7) as they need to save/restore RAMPZ for ELPM macros so it does 00897 not interfere with data accesses. 00898 */ 00899 #if defined (__AVR_HAVE_RAMPD__) 00900 00901 #define __ELPM(addr) __ELPM_xmega__(addr) 00902 #define __ELPM_word(addr) __ELPM_word_xmega__(addr) 00903 #define __ELPM_dword(addr) __ELPM_dword_xmega__(addr) 00904 #define __ELPM_float(addr) __ELPM_float_xmega__(addr) 00905 00906 #else 00907 00908 #if defined (__AVR_HAVE_LPMX__) 00909 00910 #define __ELPM(addr) __ELPM_enhanced__(addr) 00911 #define __ELPM_word(addr) __ELPM_word_enhanced__(addr) 00912 #define __ELPM_dword(addr) __ELPM_dword_enhanced__(addr) 00913 #define __ELPM_float(addr) __ELPM_float_enhanced__(addr) 00914 00915 #else 00916 00917 #define __ELPM(addr) __ELPM_classic__(addr) 00918 #define __ELPM_word(addr) __ELPM_word_classic__(addr) 00919 #define __ELPM_dword(addr) __ELPM_dword_classic__(addr) 00920 #define __ELPM_float(addr) __ELPM_float_classic__(addr) 00921 00922 #endif /* __AVR_HAVE_LPMX__ */ 00923 00924 #endif /* __AVR_HAVE_RAMPD__ */ 00925 00926 #endif /* !__DOXYGEN__ */ 00927 00928 /** \ingroup avr_pgmspace 00929 \def pgm_read_byte_far(address_long) 00930 Read a byte 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_byte_far(address_long) __ELPM((uint32_t)(address_long)) 00936 00937 /** \ingroup avr_pgmspace 00938 \def pgm_read_word_far(address_long) 00939 Read a word 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_word_far(address_long) __ELPM_word((uint32_t)(address_long)) 00945 00946 /** \ingroup avr_pgmspace 00947 \def pgm_read_dword_far(address_long) 00948 Read a double word from the program space with a 32-bit (far) address. 00949 00950 \note The address is a byte address. 00951 The address is in the program space. */ 00952 00953 #define pgm_read_dword_far(address_long) __ELPM_dword((uint32_t)(address_long)) 00954 00955 /** \ingroup avr_pgmspace 00956 \def pgm_read_float_far(address_long) 00957 Read a float from the program space with a 32-bit (far) address. 00958 00959 \note The address is a byte address. 00960 The address is in the program space. */ 00961 00962 #define pgm_read_float_far(address_long) __ELPM_float((uint32_t)(address_long)) 00963 00964 /** \ingroup avr_pgmspace 00965 \def pgm_read_ptr_far(address_long) 00966 Read a pointer from the program space with a 32-bit (far) address. 00967 00968 \note The address is a byte address. 00969 The address is in the program space. */ 00970 00971 #define pgm_read_ptr_far(address_long) (void*)__ELPM_word((uint32_t)(address_long)) 00972 00973 #endif /* RAMPZ or __DOXYGEN__ */ 00974 00975 /** \ingroup avr_pgmspace 00976 \def pgm_read_byte(address_short) 00977 Read a byte 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_byte(address_short) pgm_read_byte_near(address_short) 00983 00984 /** \ingroup avr_pgmspace 00985 \def pgm_read_word(address_short) 00986 Read a word from the program space with a 16-bit (near) address. 00987 00988 \note The address is a byte address. 00989 The address is in the program space. */ 00990 00991 #define pgm_read_word(address_short) pgm_read_word_near(address_short) 00992 00993 /** \ingroup avr_pgmspace 00994 \def pgm_read_dword(address_short) 00995 Read a double word from the program space with a 16-bit (near) address. 00996 00997 \note The address is a byte address. 00998 The address is in the program space. */ 00999 01000 #define pgm_read_dword(address_short) pgm_read_dword_near(address_short) 01001 01002 /** \ingroup avr_pgmspace 01003 \def pgm_read_float(address_short) 01004 Read a float from the program space with a 16-bit (near) address. 01005 01006 \note The address is a byte address. 01007 The address is in the program space. */ 01008 01009 #define pgm_read_float(address_short) pgm_read_float_near(address_short) 01010 01011 /** \ingroup avr_pgmspace 01012 \def pgm_read_ptr(address_short) 01013 Read a pointer from the program space with a 16-bit (near) address. 01014 01015 \note The address is a byte address. 01016 The address is in the program space. */ 01017 01018 #define pgm_read_ptr(address_short) pgm_read_ptr_near(address_short) 01019 01020 /** \ingroup avr_pgmspace 01021 \def pgm_get_far_address(var) 01022 01023 This macro facilitates the obtention of a 32 bit "far" pointer (only 24 bits 01024 used) to data even passed the 64KB limit for the 16 bit ordinary pointer. It 01025 is similar to the '&' operator, with some limitations. 01026 01027 Comments: 01028 01029 - The overhead is minimal and it's mainly due to the 32 bit size operation. 01030 01031 - 24 bit sizes guarantees the code compatibility for use in future devices. 01032 01033 - hh8() is an undocumented feature but seems to give the third significant byte 01034 of a 32 bit data and accepts symbols, complementing the functionality of hi8() 01035 and lo8(). There is not an equivalent assembler function to get the high 01036 significant byte. 01037 01038 - 'var' has to be resolved at linking time as an existing symbol, i.e, a simple 01039 type variable name, an array name (not an indexed element of the array, if the 01040 index is a constant the compiler does not complain but fails to get the address 01041 if optimization is enabled), a struct name or a struct field name, a function 01042 identifier, a linker defined identifier,... 01043 01044 - The returned value is the identifier's VMA (virtual memory address) determined 01045 by the linker and falls in the corresponding memory region. The AVR Harvard 01046 architecture requires non overlapping VMA areas for the multiple address spaces 01047 in the processor: Flash ROM, RAM, and EEPROM. Typical offset for this are 01048 0x00000000, 0x00800xx0, and 0x00810000 respectively, derived from the linker 01049 script used and linker options. The value returned can be seen then as a 01050 universal pointer. 01051 */ 01052 01053 #define pgm_get_far_address(var) \ 01054 ({ \ 01055 uint_farptr_t tmp; \ 01056 \ 01057 __asm__ __volatile__( \ 01058 \ 01059 "ldi %A0, lo8(%1)" "\n\t" \ 01060 "ldi %B0, hi8(%1)" "\n\t" \ 01061 "ldi %C0, hh8(%1)" "\n\t" \ 01062 "clr %D0" "\n\t" \ 01063 : \ 01064 "=d" (tmp) \ 01065 : \ 01066 "p" (&(var)) \ 01067 ); \ 01068 tmp; \ 01069 }) 01070 01071 01072 01073 /** \ingroup avr_pgmspace 01074 \fn const void * memchr_P(const void *s, int val, size_t len) 01075 \brief Scan flash memory for a character. 01076 01077 The memchr_P() function scans the first \p len bytes of the flash 01078 memory area pointed to by \p s for the character \p val. The first 01079 byte to match \p val (interpreted as an unsigned character) stops 01080 the operation. 01081 01082 \return The memchr_P() function returns a pointer to the matching 01083 byte or \c NULL if the character does not occur in the given memory 01084 area. */ 01085 extern const void * memchr_P(const void *, int __val, size_t __len) __ATTR_CONST__; 01086 01087 /** \ingroup avr_pgmspace 01088 \fn int memcmp_P(const void *s1, const void *s2, size_t len) 01089 \brief Compare memory areas 01090 01091 The memcmp_P() function compares the first \p len bytes of the memory 01092 areas \p s1 and flash \p s2. The comparision is performed using unsigned 01093 char operations. 01094 01095 \returns The memcmp_P() function returns an integer less than, equal 01096 to, or greater than zero if the first \p len bytes of \p s1 is found, 01097 respectively, to be less than, to match, or be greater than the first 01098 \p len bytes of \p s2. */ 01099 extern int memcmp_P(const void *, const void *, size_t) __ATTR_PURE__; 01100 01101 /** \ingroup avr_pgmspace 01102 \fn void *memccpy_P (void *dest, const void *src, int val, size_t len) 01103 01104 This function is similar to memccpy() except that \p src is pointer 01105 to a string in program space. */ 01106 extern void *memccpy_P(void *, const void *, int __val, size_t); 01107 01108 /** \ingroup avr_pgmspace 01109 \fn void *memcpy_P(void *dest, const void *src, size_t n) 01110 01111 The memcpy_P() function is similar to memcpy(), except the src string 01112 resides in program space. 01113 01114 \returns The memcpy_P() function returns a pointer to dest. */ 01115 extern void *memcpy_P(void *, const void *, size_t); 01116 01117 /** \ingroup avr_pgmspace 01118 \fn void *memmem_P(const void *s1, size_t len1, const void *s2, size_t len2) 01119 01120 The memmem_P() function is similar to memmem() except that \p s2 is 01121 pointer to a string in program space. */ 01122 extern void *memmem_P(const void *, size_t, const void *, size_t) __ATTR_PURE__; 01123 01124 /** \ingroup avr_pgmspace 01125 \fn const void +memrchr_P(const void *src, int val, size_t len) 01126 01127 The memrchr_P() function is like the memchr_P() function, except 01128 that it searches backwards from the end of the \p len bytes pointed 01129 to by \p src instead of forwards from the front. (Glibc, GNU extension.) 01130 01131 \return The memrchr_P() function returns a pointer to the matching 01132 byte or \c NULL if the character does not occur in the given memory 01133 area. */ 01134 extern const void * memrchr_P(const void *, int __val, size_t __len) __ATTR_CONST__; 01135 01136 /** \ingroup avr_pgmspace 01137 \fn char *strcat_P(char *dest, const char *src) 01138 01139 The strcat_P() function is similar to strcat() except that the \e src 01140 string must be located in program space (flash). 01141 01142 \returns The strcat() function returns a pointer to the resulting string 01143 \e dest. */ 01144 extern char *strcat_P(char *, const char *); 01145 01146 /** \ingroup avr_pgmspace 01147 \fn const char *strchr_P(const char *s, int val) 01148 \brief Locate character in program space string. 01149 01150 The strchr_P() function locates the first occurrence of \p val 01151 (converted to a char) in the string pointed to by \p s in program 01152 space. The terminating null character is considered to be part of 01153 the string. 01154 01155 The strchr_P() function is similar to strchr() except that \p s is 01156 pointer to a string in program space. 01157 01158 \returns The strchr_P() function returns a pointer to the matched 01159 character or \c NULL if the character is not found. */ 01160 extern const char * strchr_P(const char *, int __val) __ATTR_CONST__; 01161 01162 /** \ingroup avr_pgmspace 01163 \fn const char *strchrnul_P(const char *s, int c) 01164 01165 The strchrnul_P() function is like strchr_P() except that if \p c is 01166 not found in \p s, then it returns a pointer to the null byte at the 01167 end of \p s, rather than \c NULL. (Glibc, GNU extension.) 01168 01169 \return The strchrnul_P() function returns a pointer to the matched 01170 character, or a pointer to the null byte at the end of \p s (i.e., 01171 \c s+strlen(s)) if the character is not found. */ 01172 extern const char * strchrnul_P(const char *, int __val) __ATTR_CONST__; 01173 01174 /** \ingroup avr_pgmspace 01175 \fn int strcmp_P(const char *s1, const char *s2) 01176 01177 The strcmp_P() function is similar to strcmp() except that \p s2 is 01178 pointer to a string in program space. 01179 01180 \returns The strcmp_P() function returns an integer less than, equal 01181 to, or greater than zero if \p s1 is found, respectively, to be less 01182 than, to match, or be greater than \p s2. A consequence of the 01183 ordering used by strcmp_P() is that if \p s1 is an initial substring 01184 of \p s2, then \p s1 is considered to be "less than" \p s2. */ 01185 extern int strcmp_P(const char *, const char *) __ATTR_PURE__; 01186 01187 /** \ingroup avr_pgmspace 01188 \fn char *strcpy_P(char *dest, const char *src) 01189 01190 The strcpy_P() function is similar to strcpy() except that src is a 01191 pointer to a string in program space. 01192 01193 \returns The strcpy_P() function returns a pointer to the destination 01194 string dest. */ 01195 extern char *strcpy_P(char *, const char *); 01196 01197 /** \ingroup avr_pgmspace 01198 \fn int strcasecmp_P(const char *s1, const char *s2) 01199 \brief Compare two strings ignoring case. 01200 01201 The strcasecmp_P() function compares the two strings \p s1 and \p s2, 01202 ignoring the case of the characters. 01203 01204 \param s1 A pointer to a string in the devices SRAM. 01205 \param s2 A pointer to a string in the devices Flash. 01206 01207 \returns The strcasecmp_P() function returns an integer less than, 01208 equal to, or greater than zero if \p s1 is found, respectively, to 01209 be less than, to match, or be greater than \p s2. A consequence of 01210 the ordering used by strcasecmp_P() is that if \p s1 is an initial 01211 substring of \p s2, then \p s1 is considered to be "less than" \p s2. */ 01212 extern int strcasecmp_P(const char *, const char *) __ATTR_PURE__; 01213 01214 /** \ingroup avr_pgmspace 01215 \fn char *strcasestr_P(const char *s1, const char *s2) 01216 01217 This funtion is similar to strcasestr() except that \p s2 is pointer 01218 to a string in program space. */ 01219 extern char *strcasestr_P(const char *, const char *) __ATTR_PURE__; 01220 01221 /** \ingroup avr_pgmspace 01222 \fn size_t strcspn_P(const char *s, const char *reject) 01223 01224 The strcspn_P() function calculates the length of the initial segment 01225 of \p s which consists entirely of characters not in \p reject. This 01226 function is similar to strcspn() except that \p reject is a pointer 01227 to a string in program space. 01228 01229 \return The strcspn_P() function returns the number of characters in 01230 the initial segment of \p s which are not in the string \p reject. 01231 The terminating zero is not considered as a part of string. */ 01232 extern size_t strcspn_P(const char *__s, const char * __reject) __ATTR_PURE__; 01233 01234 /** \ingroup avr_pgmspace 01235 \fn size_t strlcat_P(char *dst, const char *src, size_t siz) 01236 \brief Concatenate two strings. 01237 01238 The strlcat_P() function is similar to strlcat(), except that the \p src 01239 string must be located in program space (flash). 01240 01241 Appends \p src to string \p dst of size \p siz (unlike strncat(), 01242 \p siz is the full size of \p dst, not space left). At most \p siz-1 01243 characters will be copied. Always NULL terminates (unless \p siz <= 01244 \p strlen(dst)). 01245 01246 \returns The strlcat_P() function returns strlen(src) + MIN(siz, 01247 strlen(initial dst)). If retval >= siz, truncation occurred. */ 01248 extern size_t strlcat_P (char *, const char *, size_t ); 01249 01250 /** \ingroup avr_pgmspace 01251 \fn size_t strlcpy_P(char *dst, const char *src, size_t siz) 01252 \brief Copy a string from progmem to RAM. 01253 01254 Copy \p src to string \p dst of size \p siz. At most \p siz-1 01255 characters will be copied. Always NULL terminates (unless \p siz == 0). 01256 The strlcpy_P() function is similar to strlcpy() except that the 01257 \p src is pointer to a string in memory space. 01258 01259 \returns The strlcpy_P() function returns strlen(src). If 01260 retval >= siz, truncation occurred. */ 01261 extern size_t strlcpy_P (char *, const char *, size_t ); 01262 01263 /** \ingroup avr_pgmspace 01264 \fn size_t strnlen_P(const char *src, size_t len) 01265 \brief Determine the length of a fixed-size string. 01266 01267 The strnlen_P() function is similar to strnlen(), except that \c src is a 01268 pointer to a string in program space. 01269 01270 \returns The strnlen_P function returns strlen_P(src), if that is less than 01271 \c len, or \c len if there is no '\\0' character among the first \c len 01272 characters pointed to by \c src. */ 01273 extern size_t strnlen_P(const char *, size_t) __ATTR_CONST__; /* program memory can't change */ 01274 01275 /** \ingroup avr_pgmspace 01276 \fn int strncmp_P(const char *s1, const char *s2, size_t n) 01277 01278 The strncmp_P() function is similar to strcmp_P() except it only compares 01279 the first (at most) n characters of s1 and s2. 01280 01281 \returns The strncmp_P() function returns an integer less than, equal to, 01282 or greater than zero if s1 (or the first n bytes thereof) is found, 01283 respectively, to be less than, to match, or be greater than s2. */ 01284 extern int strncmp_P(const char *, const char *, size_t) __ATTR_PURE__; 01285 01286 /** \ingroup avr_pgmspace 01287 \fn int strncasecmp_P(const char *s1, const char *s2, size_t n) 01288 \brief Compare two strings ignoring case. 01289 01290 The strncasecmp_P() function is similar to strcasecmp_P(), except it 01291 only compares the first \p n characters of \p s1. 01292 01293 \param s1 A pointer to a string in the devices SRAM. 01294 \param s2 A pointer to a string in the devices Flash. 01295 \param n The maximum number of bytes to compare. 01296 01297 \returns The strncasecmp_P() function returns an integer less than, 01298 equal to, or greater than zero if \p s1 (or the first \p n bytes 01299 thereof) is found, respectively, to be less than, to match, or be 01300 greater than \p s2. A consequence of the ordering used by 01301 strncasecmp_P() is that if \p s1 is an initial substring of \p s2, 01302 then \p s1 is considered to be "less than" \p s2. */ 01303 extern int strncasecmp_P(const char *, const char *, size_t) __ATTR_PURE__; 01304 01305 /** \ingroup avr_pgmspace 01306 \fn char *strncat_P(char *dest, const char *src, size_t len) 01307 \brief Concatenate two strings. 01308 01309 The strncat_P() function is similar to strncat(), except that the \e src 01310 string must be located in program space (flash). 01311 01312 \returns The strncat_P() function returns a pointer to the resulting string 01313 dest. */ 01314 extern char *strncat_P(char *, const char *, size_t); 01315 01316 /** \ingroup avr_pgmspace 01317 \fn char *strncpy_P(char *dest, const char *src, size_t n) 01318 01319 The strncpy_P() function is similar to strcpy_P() except that not more 01320 than n bytes of src are copied. Thus, if there is no null byte among the 01321 first n bytes of src, the result will not be null-terminated. 01322 01323 In the case where the length of src is less than that of n, the remainder 01324 of dest will be padded with nulls. 01325 01326 \returns The strncpy_P() function returns a pointer to the destination 01327 string dest. */ 01328 extern char *strncpy_P(char *, const char *, size_t); 01329 01330 /** \ingroup avr_pgmspace 01331 \fn char *strpbrk_P(const char *s, const char *accept) 01332 01333 The strpbrk_P() function locates the first occurrence in the string 01334 \p s of any of the characters in the flash string \p accept. This 01335 function is similar to strpbrk() except that \p accept is a pointer 01336 to a string in program space. 01337 01338 \return The strpbrk_P() function returns a pointer to the character 01339 in \p s that matches one of the characters in \p accept, or \c NULL 01340 if no such character is found. The terminating zero is not considered 01341 as a part of string: if one or both args are empty, the result will 01342 \c NULL. */ 01343 extern char *strpbrk_P(const char *__s, const char * __accept) __ATTR_PURE__; 01344 01345 /** \ingroup avr_pgmspace 01346 \fn const char *strrchr_P(const char *s, int val) 01347 \brief Locate character in string. 01348 01349 The strrchr_P() function returns a pointer to the last occurrence of 01350 the character \p val in the flash string \p s. 01351 01352 \return The strrchr_P() function returns a pointer to the matched 01353 character or \c NULL if the character is not found. */ 01354 extern const char * strrchr_P(const char *, int __val) __ATTR_CONST__; 01355 01356 /** \ingroup avr_pgmspace 01357 \fn char *strsep_P(char **sp, const char *delim) 01358 \brief Parse a string into tokens. 01359 01360 The strsep_P() function locates, in the string referenced by \p *sp, 01361 the first occurrence of any character in the string \p delim (or the 01362 terminating '\\0' character) and replaces it with a '\\0'. The 01363 location of the next character after the delimiter character (or \c 01364 NULL, if the end of the string was reached) is stored in \p *sp. An 01365 ``empty'' field, i.e. one caused by two adjacent delimiter 01366 characters, can be detected by comparing the location referenced by 01367 the pointer returned in \p *sp to '\\0'. This function is similar to 01368 strsep() except that \p delim is a pointer to a string in program 01369 space. 01370 01371 \return The strsep_P() function returns a pointer to the original 01372 value of \p *sp. If \p *sp is initially \c NULL, strsep_P() returns 01373 \c NULL. */ 01374 extern char *strsep_P(char **__sp, const char * __delim); 01375 01376 /** \ingroup avr_pgmspace 01377 \fn size_t strspn_P(const char *s, const char *accept) 01378 01379 The strspn_P() function calculates the length of the initial segment 01380 of \p s which consists entirely of characters in \p accept. This 01381 function is similar to strspn() except that \p accept is a pointer 01382 to a string in program space. 01383 01384 \return The strspn_P() function returns the number of characters in 01385 the initial segment of \p s which consist only of characters from \p 01386 accept. The terminating zero is not considered as a part of string. */ 01387 extern size_t strspn_P(const char *__s, const char * __accept) __ATTR_PURE__; 01388 01389 /** \ingroup avr_pgmspace 01390 \fn char *strstr_P(const char *s1, const char *s2) 01391 \brief Locate a substring. 01392 01393 The strstr_P() function finds the first occurrence of the substring 01394 \p s2 in the string \p s1. The terminating '\\0' characters are not 01395 compared. The strstr_P() function is similar to strstr() except that 01396 \p s2 is pointer to a string in program space. 01397 01398 \returns The strstr_P() function returns a pointer to the beginning 01399 of the substring, or NULL if the substring is not found. If \p s2 01400 points to a string of zero length, the function returns \p s1. */ 01401 extern char *strstr_P(const char *, const char *) __ATTR_PURE__; 01402 01403 /** \ingroup avr_pgmspace 01404 \fn char *strtok_P(char *s, const char * delim) 01405 \brief Parses the string into tokens. 01406 01407 strtok_P() parses the string \p s into tokens. The first call to 01408 strtok_P() should have \p s as its first argument. Subsequent calls 01409 should have the first argument set to NULL. If a token ends with a 01410 delimiter, this delimiting character is overwritten with a '\\0' and a 01411 pointer to the next character is saved for the next call to strtok_P(). 01412 The delimiter string \p delim may be different for each call. 01413 01414 The strtok_P() function is similar to strtok() except that \p delim 01415 is pointer to a string in program space. 01416 01417 \returns The strtok_P() function returns a pointer to the next token or 01418 NULL when no more tokens are found. 01419 01420 \note strtok_P() is NOT reentrant. For a reentrant version of this 01421 function see strtok_rP(). 01422 */ 01423 extern char *strtok_P(char *__s, const char * __delim); 01424 01425 /** \ingroup avr_pgmspace 01426 \fn char *strtok_rP (char *string, const char *delim, char **last) 01427 \brief Parses string into tokens. 01428 01429 The strtok_rP() function parses \p string into tokens. The first call to 01430 strtok_rP() should have string as its first argument. Subsequent calls 01431 should have the first argument set to NULL. If a token ends with a 01432 delimiter, this delimiting character is overwritten with a '\\0' and a 01433 pointer to the next character is saved for the next call to strtok_rP(). 01434 The delimiter string \p delim may be different for each call. \p last is 01435 a user allocated char* pointer. It must be the same while parsing the 01436 same string. strtok_rP() is a reentrant version of strtok_P(). 01437 01438 The strtok_rP() function is similar to strtok_r() except that \p delim 01439 is pointer to a string in program space. 01440 01441 \returns The strtok_rP() function returns a pointer to the next token or 01442 NULL when no more tokens are found. */ 01443 extern char *strtok_rP(char *__s, const char * __delim, char **__last); 01444 01445 /** \ingroup avr_pgmspace 01446 \fn size_t strlen_PF(uint_farptr_t s) 01447 \brief Obtain the length of a string 01448 01449 The strlen_PF() function is similar to strlen(), except that \e s is a 01450 far pointer to a string in program space. 01451 01452 \param s A far pointer to the string in flash 01453 01454 \returns The strlen_PF() function returns the number of characters in 01455 \e s. The contents of RAMPZ SFR are undefined when the function returns. */ 01456 extern size_t strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */ 01457 01458 /** \ingroup avr_pgmspace 01459 \fn size_t strnlen_PF(uint_farptr_t s, size_t len) 01460 \brief Determine the length of a fixed-size string 01461 01462 The strnlen_PF() function is similar to strnlen(), except that \e s is a 01463 far pointer to a string in program space. 01464 01465 \param s A far pointer to the string in Flash 01466 \param len The maximum number of length to return 01467 01468 \returns The strnlen_PF function returns strlen_P(\e s), if that is less 01469 than \e len, or \e len if there is no '\\0' character among the first \e 01470 len characters pointed to by \e s. The contents of RAMPZ SFR are 01471 undefined when the function returns. */ 01472 extern size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */ 01473 01474 /** \ingroup avr_pgmspace 01475 \fn void *memcpy_PF(void *dest, uint_farptr_t src, size_t n) 01476 \brief Copy a memory block from flash to SRAM 01477 01478 The memcpy_PF() function is similar to memcpy(), except the data 01479 is copied from the program space and is addressed using a far pointer. 01480 01481 \param dest A pointer to the destination buffer 01482 \param src A far pointer to the origin of data in flash memory 01483 \param n The number of bytes to be copied 01484 01485 \returns The memcpy_PF() function returns a pointer to \e dst. The contents 01486 of RAMPZ SFR are undefined when the function returns. */ 01487 extern void *memcpy_PF(void *dest, uint_farptr_t src, size_t len); 01488 01489 /** \ingroup avr_pgmspace 01490 \fn char *strcpy_PF(char *dst, uint_farptr_t src) 01491 \brief Duplicate a string 01492 01493 The strcpy_PF() function is similar to strcpy() except that \e src is a far 01494 pointer to a string in program space. 01495 01496 \param dst A pointer to the destination string in SRAM 01497 \param src A far pointer to the source string in Flash 01498 01499 \returns The strcpy_PF() function returns a pointer to the destination 01500 string \e dst. The contents of RAMPZ SFR are undefined when the funcion 01501 returns. */ 01502 extern char *strcpy_PF(char *dest, uint_farptr_t src); 01503 01504 /** \ingroup avr_pgmspace 01505 \fn char *strncpy_PF(char *dst, uint_farptr_t src, size_t n) 01506 \brief Duplicate a string until a limited length 01507 01508 The strncpy_PF() function is similar to strcpy_PF() except that not more 01509 than \e n bytes of \e src are copied. Thus, if there is no null byte among 01510 the first \e n bytes of \e src, the result will not be null-terminated. 01511 01512 In the case where the length of \e src is less than that of \e n, the 01513 remainder of \e dst will be padded with nulls. 01514 01515 \param dst A pointer to the destination string in SRAM 01516 \param src A far pointer to the source string in Flash 01517 \param n The maximum number of bytes to copy 01518 01519 \returns The strncpy_PF() function returns a pointer to the destination 01520 string \e dst. The contents of RAMPZ SFR are undefined when the function 01521 returns. */ 01522 extern char *strncpy_PF(char *dest, uint_farptr_t src, size_t len); 01523 01524 /** \ingroup avr_pgmspace 01525 \fn char *strcat_PF(char *dst, uint_farptr_t src) 01526 \brief Concatenates two strings 01527 01528 The strcat_PF() function is similar to strcat() except that the \e src 01529 string must be located in program space (flash) and is addressed using 01530 a far pointer 01531 01532 \param dst A pointer to the destination string in SRAM 01533 \param src A far pointer to the string to be appended in Flash 01534 01535 \returns The strcat_PF() function returns a pointer to the resulting 01536 string \e dst. The contents of RAMPZ SFR are undefined when the function 01537 returns */ 01538 extern char *strcat_PF(char *dest, uint_farptr_t src); 01539 01540 /** \ingroup avr_pgmspace 01541 \fn size_t strlcat_PF(char *dst, uint_farptr_t src, size_t n) 01542 \brief Concatenate two strings 01543 01544 The strlcat_PF() function is similar to strlcat(), except that the \e src 01545 string must be located in program space (flash) and is addressed using 01546 a far pointer. 01547 01548 Appends src to string dst of size \e n (unlike strncat(), \e n is the 01549 full size of \e dst, not space left). At most \e n-1 characters 01550 will be copied. Always NULL terminates (unless \e n <= strlen(\e dst)). 01551 01552 \param dst A pointer to the destination string in SRAM 01553 \param src A far pointer to the source string in Flash 01554 \param n The total number of bytes allocated to the destination string 01555 01556 \returns The strlcat_PF() function returns strlen(\e src) + MIN(\e n, 01557 strlen(initial \e dst)). If retval >= \e n, truncation occurred. The 01558 contents of RAMPZ SFR are undefined when the funcion returns. */ 01559 extern size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz); 01560 01561 /** \ingroup avr_pgmspace 01562 \fn char *strncat_PF(char *dst, uint_farptr_t src, size_t n) 01563 \brief Concatenate two strings 01564 01565 The strncat_PF() function is similar to strncat(), except that the \e src 01566 string must be located in program space (flash) and is addressed using a 01567 far pointer. 01568 01569 \param dst A pointer to the destination string in SRAM 01570 \param src A far pointer to the source string in Flash 01571 \param n The maximum number of bytes to append 01572 01573 \returns The strncat_PF() function returns a pointer to the resulting 01574 string \e dst. The contents of RAMPZ SFR are undefined when the function 01575 returns. */ 01576 extern char *strncat_PF(char *dest, uint_farptr_t src, size_t len); 01577 01578 /** \ingroup avr_pgmspace 01579 \fn int strcmp_PF(const char *s1, uint_farptr_t s2) 01580 \brief Compares two strings 01581 01582 The strcmp_PF() function is similar to strcmp() except that \e s2 is a far 01583 pointer to a string in program space. 01584 01585 \param s1 A pointer to the first string in SRAM 01586 \param s2 A far pointer to the second string in Flash 01587 01588 \returns The strcmp_PF() function returns an integer less than, equal to, 01589 or greater than zero if \e s1 is found, respectively, to be less than, to 01590 match, or be greater than \e s2. The contents of RAMPZ SFR are undefined 01591 when the function returns. */ 01592 extern int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__; 01593 01594 /** \ingroup avr_pgmspace 01595 \fn int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) 01596 \brief Compare two strings with limited length 01597 01598 The strncmp_PF() function is similar to strcmp_PF() except it only 01599 compares the first (at most) \e n characters of \e s1 and \e s2. 01600 01601 \param s1 A pointer to the first string in SRAM 01602 \param s2 A far pointer to the second string in Flash 01603 \param n The maximum number of bytes to compare 01604 01605 \returns The strncmp_PF() function returns an integer less than, equal 01606 to, or greater than zero if \e s1 (or the first \e n bytes thereof) is found, 01607 respectively, to be less than, to match, or be greater than \e s2. The 01608 contents of RAMPZ SFR are undefined when the function returns. */ 01609 extern int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__; 01610 01611 /** \ingroup avr_pgmspace 01612 \fn int strcasecmp_PF(const char *s1, uint_farptr_t s2) 01613 \brief Compare two strings ignoring case 01614 01615 The strcasecmp_PF() function compares the two strings \e s1 and \e s2, ignoring 01616 the case of the characters. 01617 01618 \param s1 A pointer to the first string in SRAM 01619 \param s2 A far pointer to the second string in Flash 01620 01621 \returns The strcasecmp_PF() function returns an integer less than, equal 01622 to, or greater than zero if \e s1 is found, respectively, to be less than, to 01623 match, or be greater than \e s2. The contents of RAMPZ SFR are undefined 01624 when the function returns. */ 01625 extern int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__; 01626 01627 /** \ingroup avr_pgmspace 01628 \fn int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) 01629 \brief Compare two strings ignoring case 01630 01631 The strncasecmp_PF() function is similar to strcasecmp_PF(), except it 01632 only compares the first \e n characters of \e s1 and the string in flash is 01633 addressed using a far pointer. 01634 01635 \param s1 A pointer to a string in SRAM 01636 \param s2 A far pointer to a string in Flash 01637 \param n The maximum number of bytes to compare 01638 01639 \returns The strncasecmp_PF() function returns an integer less than, equal 01640 to, or greater than zero if \e s1 (or the first \e n bytes thereof) is found, 01641 respectively, to be less than, to match, or be greater than \e s2. The 01642 contents of RAMPZ SFR are undefined when the function returns. */ 01643 extern int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__; 01644 01645 /** \ingroup avr_pgmspace 01646 \fn char *strstr_PF(const char *s1, uint_farptr_t s2) 01647 \brief Locate a substring. 01648 01649 The strstr_PF() function finds the first occurrence of the substring \c s2 01650 in the string \c s1. The terminating '\\0' characters are not 01651 compared. 01652 The strstr_PF() function is similar to strstr() except that \c s2 is a 01653 far pointer to a string in program space. 01654 01655 \returns The strstr_PF() function returns a pointer to the beginning of the 01656 substring, or NULL if the substring is not found. 01657 If \c s2 points to a string of zero length, the function returns \c s1. The 01658 contents of RAMPZ SFR are undefined when the function returns. */ 01659 extern char *strstr_PF(const char *s1, uint_farptr_t s2); 01660 01661 /** \ingroup avr_pgmspace 01662 \fn size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz) 01663 \brief Copy a string from progmem to RAM. 01664 01665 Copy src to string dst of size siz. At most siz-1 characters will be 01666 copied. Always NULL terminates (unless siz == 0). 01667 01668 \returns The strlcpy_PF() function returns strlen(src). If retval >= siz, 01669 truncation occurred. The contents of RAMPZ SFR are undefined when the 01670 function returns. */ 01671 extern size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz); 01672 01673 /** \ingroup avr_pgmspace 01674 \fn int memcmp_PF(const void *s1, uint_farptr_t s2, size_t len) 01675 \brief Compare memory areas 01676 01677 The memcmp_PF() function compares the first \p len bytes of the memory 01678 areas \p s1 and flash \p s2. The comparision is performed using unsigned 01679 char operations. It is an equivalent of memcmp_P() function, except 01680 that it is capable working on all FLASH including the exteded area 01681 above 64kB. 01682 01683 \returns The memcmp_PF() function returns an integer less than, equal 01684 to, or greater than zero if the first \p len bytes of \p s1 is found, 01685 respectively, to be less than, to match, or be greater than the first 01686 \p len bytes of \p s2. */ 01687 extern int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__; 01688 01689 #ifdef __DOXYGEN__ 01690 /** \ingroup avr_pgmspace 01691 \fn size_t strlen_P(const char *src) 01692 01693 The strlen_P() function is similar to strlen(), except that src is a 01694 pointer to a string in program space. 01695 01696 \returns The strlen_P() function returns the number of characters in src. 01697 01698 \note strlen_P() is implemented as an inline function in the avr/pgmspace.h 01699 header file, which will check if the length of the string is a constant 01700 and known at compile time. If it is not known at compile time, the macro 01701 will issue a call to __strlen_P() which will then calculate the length 01702 of the string as normal. 01703 */ 01704 static inline size_t strlen_P(const char * s); 01705 #else 01706 extern size_t __strlen_P(const char *) __ATTR_CONST__; /* internal helper function */ 01707 __attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s); 01708 static __inline__ size_t strlen_P(const char *s) { 01709 return __builtin_constant_p(__builtin_strlen(s)) 01710 ? __builtin_strlen(s) : __strlen_P(s); 01711 } 01712 #endif 01713 01714 #ifdef __cplusplus 01715 } 01716 #endif 01717 01718 #endif /* __PGMSPACE_H_ */