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

pgmspace.h

Go to the documentation of this file.
01	1 Copyright (c) 2002-2007  Marek Michalkiewicz
	022Copyright (c) 2006, Carlos Lamas
033Copyright (c) 2009-2010, Jan Waclawek 044All rights reserved. 055 066Redistribution and use in source and binary forms, with or without 077modification, are permitted provided that the following conditions are met: 088 099* Redistributions of source code must retain the above copyright 1010notice, this list of conditions and the following disclaimer. 1111* Redistributions in binary form must reproduce the above copyright 1212notice, this list of conditions and the following disclaimer in 1313the documentation and/or other materials provided with the 1414distribution. 1515* Neither the name of the copyright holders nor the names of 1616contributors may be used to endorse or promote products derived 1717from this software without specific prior written permission. 1818 1919THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2020AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2121IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2222ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 2323LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2424CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2525SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2626INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2727CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2828ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2929POSSIBILITY OF SUCH DAMAGE. */ 3030 3131/* $Id: pgmspace.h 2503 2016-02-07 22:59:47Z joerg_wunsch $ */ 3232 3333/* 3434pgmspace.h 3535 3636Contributors: 3737Created by Marek Michalkiewicz <marekm@linux.org.pl> 3838Eric B. Weddington <eric@ecentral.com> 3939Wolfgang Haidinger <wh@vmars.tuwien.ac.at> (pgm_read_dword()) 4040Ivanov Anton <anton@arc.com.ru> (pgm_read_float()) 4141*/ 4242 4343/** \file */ 4444/** \defgroup avr_pgmspace <avr/pgmspace.h>: Program Space Utilities 4545\code 4646#include <avr/io.h> 4747#include <avr/pgmspace.h> 4848\endcode 4949 5050The functions in this module provide interfaces for a program to access 5151data stored in program space (flash memory) of the device. In order to 5252use these functions, the target device must support either the \c LPM or 5353\c ELPM instructions. 5454 5555\note These functions are an attempt to provide some compatibility with 5656header files that come with IAR C, to make porting applications between 5757different compilers easier. This is not 100% compatibility though (GCC 5858does not have full support for multiple address spaces yet). 5959 6060\note If you are working with strings which are completely based in ram, 6161use the standard string functions described in \ref avr_string. 6262 6363\note If possible, put your constant tables in the lower 64 KB and use 6464pgm_read_byte_near() or pgm_read_word_near() instead of 6565pgm_read_byte_far() or pgm_read_word_far() since it is more efficient that 6666way, and you can still use the upper 64K for executable code. 6767All functions that are suffixed with a \c _P \e require their 6868arguments to be in the lower 64 KB of the flash ROM, as they do 6969not use ELPM instructions. This is normally not a big concern as 7070the linker setup arranges any program space constants declared 7171using the macros from this header file so they are placed right after 7272the interrupt vectors, and in front of any executable code. However, 7373it can become a problem if there are too many of these constants, or 7474for bootloaders on devices with more than 64 KB of ROM. 7575<em>All these functions will not work in that situation.</em> 7676 7777\note For <b>Xmega</b> devices, make sure the NVM controller 7878command register (\c NVM.CMD or \c NVM_CMD) is set to 0x00 (NOP) 7979before using any of these functions. 8080*/ 8181 8282#ifndef __PGMSPACE_H_ 8383#define __PGMSPACE_H_ 1 8484 8585#ifndef __DOXYGEN__ 8686#define __need_size_t 8787#endif 8888#include <inttypes.h> 8989#include <stddef.h> 9090#include <avr/io.h> 9191 9292#ifndef __DOXYGEN__ 9393#ifndef __ATTR_CONST__ 9494#define __ATTR_CONST__ __attribute__((__const__)) 9595#endif 9696 9797#ifndef __ATTR_PROGMEM__ 9898#define __ATTR_PROGMEM__ __attribute__((__progmem__)) 9999#endif 100100 101101#ifndef __ATTR_PURE__ 102102#define __ATTR_PURE__ __attribute__((__pure__)) 103103#endif 104104#endif /* !__DOXYGEN__ */ 105105 106106/** 107107\ingroup avr_pgmspace 108108\def PROGMEM 109109 110110Attribute to use in order to declare an object being located in 111111flash ROM. 112112*/ 113 113#define PROGMEM __ATTR_PROGMEM__ 114114 115115#ifdef __cplusplus 116116extern "C" { 117117#endif 118118 119119#if defined(__DOXYGEN__) 120120/* 121121* Doxygen doesn't grok the appended attribute syntax of 122122* GCC, and confuses the typedefs with function decls, so 123123* supply a doxygen-friendly view. 124124*/ 125125 126126/** 127127\ingroup avr_pgmspace 128128\typedef prog_void 129129\note DEPRECATED 130130 131131This typedef is now deprecated because the usage of the __progmem__ 132132attribute on a type is not supported in GCC. However, the use of the 133133__progmem__ attribute on a variable declaration is supported, and this is 134134now the recommended usage. 135135 136136The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 137137has been defined before including <avr/pgmspace.h> (either by a 138138\c \#define directive, or by a -D compiler option.) 139139 140140Type of a "void" object located in flash ROM. Does not make much 141141sense by itself, but can be used to declare a "void *" object in 142142flash ROM. 143143*/ 144 144 typedef void PROGMEM prog_void; 145145 146146/** 147147\ingroup avr_pgmspace 148148\typedef prog_char 149149\note DEPRECATED 150150 151151This typedef is now deprecated because the usage of the __progmem__ 152152attribute on a type is not supported in GCC. However, the use of the 153153__progmem__ attribute on a variable declaration is supported, and this is 154154now the recommended usage. 155155 156156The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 157157has been defined before including <avr/pgmspace.h> (either by a 158158\c \#define directive, or by a -D compiler option.) 159159 160160Type of a "char" object located in flash ROM. 161161*/ 162 162 typedef char PROGMEM prog_char; 163163 164164/** 165165\ingroup avr_pgmspace 166166\typedef prog_uchar 167167\note DEPRECATED 168168 169169This typedef is now deprecated because the usage of the __progmem__ 170170attribute on a type is not supported in GCC. However, the use of the 171171__progmem__ attribute on a variable declaration is supported, and this is 172172now the recommended usage. 173173 174174The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 175175has been defined before including <avr/pgmspace.h> (either by a 176176\c \#define directive, or by a -D compiler option.) 177177 178178Type of an "unsigned char" object located in flash ROM. 179179*/ 180 180 typedef unsigned char PROGMEM prog_uchar; 181181 182182/** 183183\ingroup avr_pgmspace 184184\typedef prog_int8_t 185185\note DEPRECATED 186186 187187This typedef is now deprecated because the usage of the __progmem__ 188188attribute on a type is not supported in GCC. However, the use of the 189189__progmem__ attribute on a variable declaration is supported, and this is 190190now the recommended usage. 191191 192192The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 193193has been defined before including <avr/pgmspace.h> (either by a 194194\c \#define directive, or by a -D compiler option.) 195195 196196Type of an "int8_t" object located in flash ROM. 197197*/ 198 198 typedef int8_t PROGMEM prog_int8_t; 199199 200200/** 201201\ingroup avr_pgmspace 202202\typedef prog_uint8_t 203203\note DEPRECATED 204204 205205This typedef is now deprecated because the usage of the __progmem__ 206206attribute on a type is not supported in GCC. However, the use of the 207207__progmem__ attribute on a variable declaration is supported, and this is 208208now the recommended usage. 209209 210210The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 211211has been defined before including <avr/pgmspace.h> (either by a 212212\c \#define directive, or by a -D compiler option.) 213213 214214Type of an "uint8_t" object located in flash ROM. 215215*/ 216 216 typedef uint8_t PROGMEM prog_uint8_t; 217217 218218/** 219219\ingroup avr_pgmspace 220220\typedef prog_int16_t 221221\note DEPRECATED 222222 223223This typedef is now deprecated because the usage of the __progmem__ 224224attribute on a type is not supported in GCC. However, the use of the 225225__progmem__ attribute on a variable declaration is supported, and this is 226226now the recommended usage. 227227 228228The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 229229has been defined before including <avr/pgmspace.h> (either by a 230230\c \#define directive, or by a -D compiler option.) 231231 232232Type of an "int16_t" object located in flash ROM. 233233*/ 234 234 typedef int16_t PROGMEM prog_int16_t; 235235 236236/** 237237\ingroup avr_pgmspace 238238\typedef prog_uint16_t 239239\note DEPRECATED 240240 241241This typedef is now deprecated because the usage of the __progmem__ 242242attribute on a type is not supported in GCC. However, the use of the 243243__progmem__ attribute on a variable declaration is supported, and this is 244244now the recommended usage. 245245 246246The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 247247has been defined before including <avr/pgmspace.h> (either by a 248248\c \#define directive, or by a -D compiler option.) 249249 250250Type of an "uint16_t" object located in flash ROM. 251251*/ 252 252 typedef uint16_t PROGMEM prog_uint16_t; 253253 254254/** 255255\ingroup avr_pgmspace 256256\typedef prog_int32_t 257257\note DEPRECATED 258258 259259This typedef is now deprecated because the usage of the __progmem__ 260260attribute on a type is not supported in GCC. However, the use of the 261261__progmem__ attribute on a variable declaration is supported, and this is 262262now the recommended usage. 263263 264264The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 265265has been defined before including <avr/pgmspace.h> (either by a 266266\c \#define directive, or by a -D compiler option.) 267267 268268Type of an "int32_t" object located in flash ROM. 269269*/ 270 270 typedef int32_t PROGMEM prog_int32_t; 271271 272272/** 273273\ingroup avr_pgmspace 274274\typedef prog_uint32_t 275275\note DEPRECATED 276276 277277This typedef is now deprecated because the usage of the __progmem__ 278278attribute on a type is not supported in GCC. However, the use of the 279279__progmem__ attribute on a variable declaration is supported, and this is 280280now the recommended usage. 281281 282282The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 283283has been defined before including <avr/pgmspace.h> (either by a 284284\c \#define directive, or by a -D compiler option.) 285285 286286Type of an "uint32_t" object located in flash ROM. 287287*/ 288 288 typedef uint32_t PROGMEM prog_uint32_t; 289289 290290/** 291291\ingroup avr_pgmspace 292292\typedef prog_int64_t 293293\note DEPRECATED 294294 295295This typedef is now deprecated because the usage of the __progmem__ 296296attribute on a type is not supported in GCC. However, the use of the 297297__progmem__ attribute on a variable declaration is supported, and this is 298298now the recommended usage. 299299 300300The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 301301has been defined before including <avr/pgmspace.h> (either by a 302302\c \#define directive, or by a -D compiler option.) 303303 304304Type of an "int64_t" object located in flash ROM. 305305 306306\note This type is not available when the compiler 307307option -mint8 is in effect. 308308*/ 309 309 typedef int64_t PROGMEM prog_int64_t; 310310 311311/** 312312\ingroup avr_pgmspace 313313\typedef prog_uint64_t 314314\note DEPRECATED 315315 316316This typedef is now deprecated because the usage of the __progmem__ 317317attribute on a type is not supported in GCC. However, the use of the 318318__progmem__ attribute on a variable declaration is supported, and this is 319319now the recommended usage. 320320 321321The typedef is only visible if the macro __PROG_TYPES_COMPAT__ 322322has been defined before including <avr/pgmspace.h> (either by a 323323\c \#define directive, or by a -D compiler option.) 324324 325325Type of an "uint64_t" object located in flash ROM. 326326 327327\note This type is not available when the compiler 328328option -mint8 is in effect. 329329*/ 330 330 typedef uint64_t PROGMEM prog_uint64_t; 331331 332332/** \ingroup avr_pgmspace 333333\def PGM_P 334334 335335Used to declare a variable that is a pointer to a string in program 336336space. */ 337337 338338#ifndef PGM_P 339 339#define PGM_P const char * 340340#endif 341341 342342/** \ingroup avr_pgmspace 343343\def PGM_VOID_P 344344 345345Used to declare a generic pointer to an object in program space. */ 346346 347347#ifndef PGM_VOID_P 348 348#define PGM_VOID_P const void * 349349#endif 350350 351351#elif defined(__PROG_TYPES_COMPAT__) /* !DOXYGEN */ 352352 353353typedef void prog_void __attribute__((__progmem__,deprecated("prog_void type is deprecated."))); 354354typedef char prog_char __attribute__((__progmem__,deprecated("prog_char type is deprecated."))); 355355typedef unsigned char prog_uchar __attribute__((__progmem__,deprecated("prog_uchar type is deprecated."))); 356356typedef int8_t prog_int8_t __attribute__((__progmem__,deprecated("prog_int8_t type is deprecated."))); 357357typedef uint8_t prog_uint8_t __attribute__((__progmem__,deprecated("prog_uint8_t type is deprecated."))); 358358typedef int16_t prog_int16_t __attribute__((__progmem__,deprecated("prog_int16_t type is deprecated."))); 359359typedef uint16_t prog_uint16_t __attribute__((__progmem__,deprecated("prog_uint16_t type is deprecated."))); 360360typedef int32_t prog_int32_t __attribute__((__progmem__,deprecated("prog_int32_t type is deprecated."))); 361361typedef uint32_t prog_uint32_t __attribute__((__progmem__,deprecated("prog_uint32_t type is deprecated."))); 362362#if !__USING_MINT8 363363typedef int64_t prog_int64_t __attribute__((__progmem__,deprecated("prog_int64_t type is deprecated."))); 364364typedef uint64_t prog_uint64_t __attribute__((__progmem__,deprecated("prog_uint64_t type is deprecated."))); 365365#endif 366366 367367#ifndef PGM_P 368368#define PGM_P const prog_char * 369369#endif 370370 371371#ifndef PGM_VOID_P 372372#define PGM_VOID_P const prog_void * 373373#endif 374374 375375#else /* !defined(__DOXYGEN__), !defined(__PROG_TYPES_COMPAT__) */ 376376 377377#ifndef PGM_P 378378#define PGM_P const char * 379379#endif 380380 381381#ifndef PGM_VOID_P 382382#define PGM_VOID_P const void * 383383#endif 384384#endif /* defined(__DOXYGEN__), defined(__PROG_TYPES_COMPAT__) */ 385385 386386/* Although in C, we can get away with just using __c, it does not work in 387387C++. We need to use &__c[0] to avoid the compiler puking. Dave Hylands 388388explaned it thusly, 389389 390390Let's suppose that we use PSTR("Test"). In this case, the type returned 391391by __c is a prog_char[5] and not a prog_char *. While these are 392392compatible, they aren't the same thing (especially in C++). The type 393393returned by &__c[0] is a prog_char *, which explains why it works 394394fine. */ 395395 396396#if defined(__DOXYGEN__) 397397/* 398398* The #define below is just a dummy that serves documentation 399399* purposes only. 400400*/ 401401/** \ingroup avr_pgmspace 402402\def PSTR(s) 403403 404404Used to declare a static pointer to a string in program space. */ 405 405# define PSTR(s) ((const PROGMEM char *)(s)) 406406#else /* !DOXYGEN */ 407407/* The real thing. */ 408408# define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];})) 409409#endif /* DOXYGEN */ 410410 411411#ifndef __DOXYGEN__ /* Internal macros, not documented. */ 412412#define __LPM_classic__(addr) \ 413413(__extension__({ \ 414414uint16_t __addr16 = (uint16_t)(addr); \ 415415uint8_t __result; \ 416416__asm__ __volatile__ \ 417417( \ 418418"lpm" "\n\t" \ 419419"mov %0, r0" "\n\t" \ 420420: "=r" (__result) \ 421421: "z" (__addr16) \ 422422: "r0" \ 423423); \ 424424__result; \ 425425})) 426426 427427#define __LPM_enhanced__(addr) \ 428428(__extension__({ \ 429429uint16_t __addr16 = (uint16_t)(addr); \ 430430uint8_t __result; \ 431431__asm__ __volatile__ \ 432432( \ 433433"lpm %0, Z" "\n\t" \ 434434: "=r" (__result) \ 435435: "z" (__addr16) \ 436436); \ 437437__result; \ 438438})) 439439 440440#define __LPM_word_classic__(addr) \ 441441(__extension__({ \ 442442uint16_t __addr16 = (uint16_t)(addr); \ 443443uint16_t __result; \ 444444__asm__ __volatile__ \ 445445( \ 446446"lpm" "\n\t" \ 447447"mov %A0, r0" "\n\t" \ 448448"adiw r30, 1" "\n\t" \ 449449"lpm" "\n\t" \ 450450"mov %B0, r0" "\n\t" \ 451451: "=r" (__result), "=z" (__addr16) \ 452452: "1" (__addr16) \ 453453: "r0" \ 454454); \ 455455__result; \ 456456})) 457457 458458#define __LPM_word_enhanced__(addr) \ 459459(__extension__({ \ 460460uint16_t __addr16 = (uint16_t)(addr); \ 461461uint16_t __result; \ 462462__asm__ __volatile__ \ 463463( \ 464464"lpm %A0, Z+" "\n\t" \ 465465"lpm %B0, Z" "\n\t" \ 466466: "=r" (__result), "=z" (__addr16) \ 467467: "1" (__addr16) \ 468468); \ 469469__result; \ 470470})) 471471 472472#define __LPM_dword_classic__(addr) \ 473473(__extension__({ \ 474474uint16_t __addr16 = (uint16_t)(addr); \ 475475uint32_t __result; \ 476476__asm__ __volatile__ \ 477477( \ 478478"lpm" "\n\t" \ 479479"mov %A0, r0" "\n\t" \ 480480"adiw r30, 1" "\n\t" \ 481481"lpm" "\n\t" \ 482482"mov %B0, r0" "\n\t" \ 483483"adiw r30, 1" "\n\t" \ 484484"lpm" "\n\t" \ 485485"mov %C0, r0" "\n\t" \ 486486"adiw r30, 1" "\n\t" \ 487487"lpm" "\n\t" \ 488488"mov %D0, r0" "\n\t" \ 489489: "=r" (__result), "=z" (__addr16) \ 490490: "1" (__addr16) \ 491491: "r0" \ 492492); \ 493493__result; \ 494494})) 495495 496496#define __LPM_dword_enhanced__(addr) \ 497497(__extension__({ \ 498498uint16_t __addr16 = (uint16_t)(addr); \ 499499uint32_t __result; \ 500500__asm__ __volatile__ \ 501501( \ 502502"lpm %A0, Z+" "\n\t" \ 503503"lpm %B0, Z+" "\n\t" \ 504504"lpm %C0, Z+" "\n\t" \ 505505"lpm %D0, Z" "\n\t" \ 506506: "=r" (__result), "=z" (__addr16) \ 507507: "1" (__addr16) \ 508508); \ 509509__result; \ 510510})) 511511 512512#define __LPM_float_classic__(addr) \ 513513(__extension__({ \ 514514uint16_t __addr16 = (uint16_t)(addr); \ 515515float __result; \ 516516__asm__ __volatile__ \ 517517( \ 518518"lpm" "\n\t" \ 519519"mov %A0, r0" "\n\t" \ 520520"adiw r30, 1" "\n\t" \ 521521"lpm" "\n\t" \ 522522"mov %B0, r0" "\n\t" \ 523523"adiw r30, 1" "\n\t" \ 524524"lpm" "\n\t" \ 525525"mov %C0, r0" "\n\t" \ 526526"adiw r30, 1" "\n\t" \ 527527"lpm" "\n\t" \ 528528"mov %D0, r0" "\n\t" \ 529529: "=r" (__result), "=z" (__addr16) \ 530530: "1" (__addr16) \ 531531: "r0" \ 532532); \ 533533__result; \ 534534})) 535535 536536#define __LPM_float_enhanced__(addr) \ 537537(__extension__({ \ 538538uint16_t __addr16 = (uint16_t)(addr); \ 539539float __result; \ 540540__asm__ __volatile__ \ 541541( \ 542542"lpm %A0, Z+" "\n\t" \ 543543"lpm %B0, Z+" "\n\t" \ 544544"lpm %C0, Z+" "\n\t" \ 545545"lpm %D0, Z" "\n\t" \ 546546: "=r" (__result), "=z" (__addr16) \ 547547: "1" (__addr16) \ 548548); \ 549549__result; \ 550550})) 551551 552552#if defined (__AVR_HAVE_LPMX__) 553553#define __LPM(addr) __LPM_enhanced__(addr) 554554#define __LPM_word(addr) __LPM_word_enhanced__(addr) 555555#define __LPM_dword(addr) __LPM_dword_enhanced__(addr) 556556#define __LPM_float(addr) __LPM_float_enhanced__(addr) 557557#else 558558#define __LPM(addr) __LPM_classic__(addr) 559559#define __LPM_word(addr) __LPM_word_classic__(addr) 560560#define __LPM_dword(addr) __LPM_dword_classic__(addr) 561561#define __LPM_float(addr) __LPM_float_classic__(addr) 562562#endif 563563 564564#endif /* !__DOXYGEN__ */ 565565 566566/** \ingroup avr_pgmspace 567567\def pgm_read_byte_near(address_short) 568568Read a byte from the program space with a 16-bit (near) address. 569569\note The address is a byte address. 570570The address is in the program space. */ 571571 572 572#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short)) 573573 574574/** \ingroup avr_pgmspace 575575\def pgm_read_word_near(address_short) 576576Read a word from the program space with a 16-bit (near) address. 577577\note The address is a byte address. 578578The address is in the program space. */ 579579 580 580#define pgm_read_word_near(address_short) __LPM_word((uint16_t)(address_short)) 581581 582582/** \ingroup avr_pgmspace 583583\def pgm_read_dword_near(address_short) 584584Read a double word from the program space with a 16-bit (near) address. 585585\note The address is a byte address. 586586The address is in the program space. */ 587587 588 588#define pgm_read_dword_near(address_short) \ 589589__LPM_dword((uint16_t)(address_short)) 590590 591591/** \ingroup avr_pgmspace 592592\def pgm_read_float_near(address_short) 593593Read a float from the program space with a 16-bit (near) address. 594594\note The address is a byte address. 595595The address is in the program space. */ 596596 597 597#define pgm_read_float_near(address_short) \ 598598__LPM_float((uint16_t)(address_short)) 599599 600600/** \ingroup avr_pgmspace 601601\def pgm_read_ptr_near(address_short) 602602Read a pointer from the program space with a 16-bit (near) address. 603603\note The address is a byte address. 604604The address is in the program space. */ 605605 606 606#define pgm_read_ptr_near(address_short) \ 607607(void*)__LPM_word((uint16_t)(address_short)) 608608 609609#if defined(RAMPZ) || defined(__DOXYGEN__) 610610 611611/* Only for devices with more than 64K of program memory. 612612RAMPZ must be defined (see iom103.h, iom128.h). 613613*/ 614614 615615/* The classic functions are needed for ATmega103. */ 616616#ifndef __DOXYGEN__ /* These are internal macros, avoid "is 617617not documented" warnings. */ 618618#define __ELPM_classic__(addr) \ 619619(__extension__({ \ 620620uint32_t __addr32 = (uint32_t)(addr); \ 621621uint8_t __result; \ 622622__asm__ __volatile__ \ 623623( \ 624624"out %2, %C1" "\n\t" \ 625625"mov r31, %B1" "\n\t" \ 626626"mov r30, %A1" "\n\t" \ 627627"elpm" "\n\t" \ 628628"mov %0, r0" "\n\t" \ 629629: "=r" (__result) \ 630630: "r" (__addr32), \ 631631"I" (_SFR_IO_ADDR(RAMPZ)) \ 632632: "r0", "r30", "r31" \ 633633); \ 634634__result; \ 635635})) 636636 637637#define __ELPM_enhanced__(addr) \ 638638(__extension__({ \ 639639uint32_t __addr32 = (uint32_t)(addr); \ 640640uint8_t __result; \ 641641__asm__ __volatile__ \ 642642( \ 643643"out %2, %C1" "\n\t" \ 644644"movw r30, %1" "\n\t" \ 645645"elpm %0, Z+" "\n\t" \ 646646: "=r" (__result) \ 647647: "r" (__addr32), \ 648648"I" (_SFR_IO_ADDR(RAMPZ)) \ 649649: "r30", "r31" \ 650650); \ 651651__result; \ 652652})) 653653 654654#define __ELPM_xmega__(addr) \ 655655(__extension__({ \ 656656uint32_t __addr32 = (uint32_t)(addr); \ 657657uint8_t __result; \ 658658__asm__ __volatile__ \ 659659( \ 660660"in __tmp_reg__, %2" "\n\t" \ 661661"out %2, %C1" "\n\t" \ 662662"movw r30, %1" "\n\t" \ 663663"elpm %0, Z+" "\n\t" \ 664664"out %2, __tmp_reg__" \ 665665: "=r" (__result) \ 666666: "r" (__addr32), \ 667667"I" (_SFR_IO_ADDR(RAMPZ)) \ 668668: "r30", "r31" \ 669669); \ 670670__result; \ 671671})) 672672 673673#define __ELPM_word_classic__(addr) \ 674674(__extension__({ \ 675675uint32_t __addr32 = (uint32_t)(addr); \ 676676uint16_t __result; \ 677677__asm__ __volatile__ \ 678678( \ 679679"out %2, %C1" "\n\t" \ 680680"mov r31, %B1" "\n\t" \ 681681"mov r30, %A1" "\n\t" \ 682682"elpm" "\n\t" \ 683683"mov %A0, r0" "\n\t" \ 684684"in r0, %2" "\n\t" \ 685685"adiw r30, 1" "\n\t" \ 686686"adc r0, __zero_reg__" "\n\t" \ 687687"out %2, r0" "\n\t" \ 688688"elpm" "\n\t" \ 689689"mov %B0, r0" "\n\t" \ 690690: "=r" (__result) \ 691691: "r" (__addr32), \ 692692"I" (_SFR_IO_ADDR(RAMPZ)) \ 693693: "r0", "r30", "r31" \ 694694); \ 695695__result; \ 696696})) 697697 698698#define __ELPM_word_enhanced__(addr) \ 699699(__extension__({ \ 700700uint32_t __addr32 = (uint32_t)(addr); \ 701701uint16_t __result; \ 702702__asm__ __volatile__ \ 703703( \ 704704"out %2, %C1" "\n\t" \ 705705"movw r30, %1" "\n\t" \ 706706"elpm %A0, Z+" "\n\t" \ 707707"elpm %B0, Z" "\n\t" \ 708708: "=r" (__result) \ 709709: "r" (__addr32), \ 710710"I" (_SFR_IO_ADDR(RAMPZ)) \ 711711: "r30", "r31" \ 712712); \ 713713__result; \ 714714})) 715715 716716#define __ELPM_word_xmega__(addr) \ 717717(__extension__({ \ 718718uint32_t __addr32 = (uint32_t)(addr); \ 719719uint16_t __result; \ 720720__asm__ __volatile__ \ 721721( \ 722722"in __tmp_reg__, %2" "\n\t" \ 723723"out %2, %C1" "\n\t" \ 724724"movw r30, %1" "\n\t" \ 725725"elpm %A0, Z+" "\n\t" \ 726726"elpm %B0, Z" "\n\t" \ 727727"out %2, __tmp_reg__" \ 728728: "=r" (__result) \ 729729: "r" (__addr32), \ 730730"I" (_SFR_IO_ADDR(RAMPZ)) \ 731731: "r30", "r31" \ 732732); \ 733733__result; \ 734734})) 735735 736736#define __ELPM_dword_classic__(addr) \ 737737(__extension__({ \ 738738uint32_t __addr32 = (uint32_t)(addr); \ 739739uint32_t __result; \ 740740__asm__ __volatile__ \ 741741( \ 742742"out %2, %C1" "\n\t" \ 743743"mov r31, %B1" "\n\t" \ 744744"mov r30, %A1" "\n\t" \ 745745"elpm" "\n\t" \ 746746"mov %A0, r0" "\n\t" \ 747747"in r0, %2" "\n\t" \ 748748"adiw r30, 1" "\n\t" \ 749749"adc r0, __zero_reg__" "\n\t" \ 750750"out %2, r0" "\n\t" \ 751751"elpm" "\n\t" \ 752752"mov %B0, r0" "\n\t" \ 753753"in r0, %2" "\n\t" \ 754754"adiw r30, 1" "\n\t" \ 755755"adc r0, __zero_reg__" "\n\t" \ 756756"out %2, r0" "\n\t" \ 757757"elpm" "\n\t" \ 758758"mov %C0, r0" "\n\t" \ 759759"in r0, %2" "\n\t" \ 760760"adiw r30, 1" "\n\t" \ 761761"adc r0, __zero_reg__" "\n\t" \ 762762"out %2, r0" "\n\t" \ 763763"elpm" "\n\t" \ 764764"mov %D0, r0" "\n\t" \ 765765: "=r" (__result) \ 766766: "r" (__addr32), \ 767767"I" (_SFR_IO_ADDR(RAMPZ)) \ 768768: "r0", "r30", "r31" \ 769769); \ 770770__result; \ 771771})) 772772 773773#define __ELPM_dword_enhanced__(addr) \ 774774(__extension__({ \ 775775uint32_t __addr32 = (uint32_t)(addr); \ 776776uint32_t __result; \ 777777__asm__ __volatile__ \ 778778( \ 779779"out %2, %C1" "\n\t" \ 780780"movw r30, %1" "\n\t" \ 781781"elpm %A0, Z+" "\n\t" \ 782782"elpm %B0, Z+" "\n\t" \ 783783"elpm %C0, Z+" "\n\t" \ 784784"elpm %D0, Z" "\n\t" \ 785785: "=r" (__result) \ 786786: "r" (__addr32), \ 787787"I" (_SFR_IO_ADDR(RAMPZ)) \ 788788: "r30", "r31" \ 789789); \ 790790__result; \ 791791})) 792792 793793#define __ELPM_dword_xmega__(addr) \ 794794(__extension__({ \ 795795uint32_t __addr32 = (uint32_t)(addr); \ 796796uint32_t __result; \ 797797__asm__ __volatile__ \ 798798( \ 799799"in __tmp_reg__, %2" "\n\t" \ 800800"out %2, %C1" "\n\t" \ 801801"movw r30, %1" "\n\t" \ 802802"elpm %A0, Z+" "\n\t" \ 803803"elpm %B0, Z+" "\n\t" \ 804804"elpm %C0, Z+" "\n\t" \ 805805"elpm %D0, Z" "\n\t" \ 806806"out %2, __tmp_reg__" \ 807807: "=r" (__result) \ 808808: "r" (__addr32), \ 809809"I" (_SFR_IO_ADDR(RAMPZ)) \ 810810: "r30", "r31" \ 811811); \ 812812__result; \ 813813})) 814814 815815#define __ELPM_float_classic__(addr) \ 816816(__extension__({ \ 817817uint32_t __addr32 = (uint32_t)(addr); \ 818818float __result; \ 819819__asm__ __volatile__ \ 820820( \ 821821"out %2, %C1" "\n\t" \ 822822"mov r31, %B1" "\n\t" \ 823823"mov r30, %A1" "\n\t" \ 824824"elpm" "\n\t" \ 825825"mov %A0, r0" "\n\t" \ 826826"in r0, %2" "\n\t" \ 827827"adiw r30, 1" "\n\t" \ 828828"adc r0, __zero_reg__" "\n\t" \ 829829"out %2, r0" "\n\t" \ 830830"elpm" "\n\t" \ 831831"mov %B0, r0" "\n\t" \ 832832"in r0, %2" "\n\t" \ 833833"adiw r30, 1" "\n\t" \ 834834"adc r0, __zero_reg__" "\n\t" \ 835835"out %2, r0" "\n\t" \ 836836"elpm" "\n\t" \ 837837"mov %C0, r0" "\n\t" \ 838838"in r0, %2" "\n\t" \ 839839"adiw r30, 1" "\n\t" \ 840840"adc r0, __zero_reg__" "\n\t" \ 841841"out %2, r0" "\n\t" \ 842842"elpm" "\n\t" \ 843843"mov %D0, r0" "\n\t" \ 844844: "=r" (__result) \ 845845: "r" (__addr32), \ 846846"I" (_SFR_IO_ADDR(RAMPZ)) \ 847847: "r0", "r30", "r31" \ 848848); \ 849849__result; \ 850850})) 851851 852852#define __ELPM_float_enhanced__(addr) \ 853853(__extension__({ \ 854854uint32_t __addr32 = (uint32_t)(addr); \ 855855float __result; \ 856856__asm__ __volatile__ \ 857857( \ 858858"out %2, %C1" "\n\t" \ 859859"movw r30, %1" "\n\t" \ 860860"elpm %A0, Z+" "\n\t" \ 861861"elpm %B0, Z+" "\n\t" \ 862862"elpm %C0, Z+" "\n\t" \ 863863"elpm %D0, Z" "\n\t" \ 864864: "=r" (__result) \ 865865: "r" (__addr32), \ 866866"I" (_SFR_IO_ADDR(RAMPZ)) \ 867867: "r30", "r31" \ 868868); \ 869869__result; \ 870870})) 871871 872872#define __ELPM_float_xmega__(addr) \ 873873(__extension__({ \ 874874uint32_t __addr32 = (uint32_t)(addr); \ 875875float __result; \ 876876__asm__ __volatile__ \ 877877( \ 878878"in __tmp_reg__, %2" "\n\t" \ 879879"out %2, %C1" "\n\t" \ 880880"movw r30, %1" "\n\t" \ 881881"elpm %A0, Z+" "\n\t" \ 882882"elpm %B0, Z+" "\n\t" \ 883883"elpm %C0, Z+" "\n\t" \ 884884"elpm %D0, Z" "\n\t" \ 885885"out %2, __tmp_reg__" \ 886886: "=r" (__result) \ 887887: "r" (__addr32), \ 888888"I" (_SFR_IO_ADDR(RAMPZ)) \ 889889: "r30", "r31" \ 890890); \ 891891__result; \ 892892})) 893893 894894/* 895895 Check for architectures that implement RAMPD (avrxmega3, avrxmega5, 896896 avrxmega7) as they need to save/restore RAMPZ for ELPM macros so it does 897897 not interfere with data accesses. 898898*/ 899899#if defined (__AVR_HAVE_RAMPD__) 900900 901901#define __ELPM(addr) __ELPM_xmega__(addr) 902902#define __ELPM_word(addr) __ELPM_word_xmega__(addr) 903903#define __ELPM_dword(addr) __ELPM_dword_xmega__(addr) 904904#define __ELPM_float(addr) __ELPM_float_xmega__(addr) 905905 906906#else 907907 908908#if defined (__AVR_HAVE_LPMX__) 909909 910910#define __ELPM(addr) __ELPM_enhanced__(addr) 911911#define __ELPM_word(addr) __ELPM_word_enhanced__(addr) 912912#define __ELPM_dword(addr) __ELPM_dword_enhanced__(addr) 913913#define __ELPM_float(addr) __ELPM_float_enhanced__(addr) 914914 915915#else 916916 917917#define __ELPM(addr) __ELPM_classic__(addr) 918918#define __ELPM_word(addr) __ELPM_word_classic__(addr) 919919#define __ELPM_dword(addr) __ELPM_dword_classic__(addr) 920920#define __ELPM_float(addr) __ELPM_float_classic__(addr) 921921 922922#endif /* __AVR_HAVE_LPMX__ */ 923923 924924#endif /* __AVR_HAVE_RAMPD__ */ 925925 926926#endif /* !__DOXYGEN__ */ 927927 928928/** \ingroup avr_pgmspace 929929\def pgm_read_byte_far(address_long) 930930Read a byte from the program space with a 32-bit (far) address. 931931 932932\note The address is a byte address. 933933The address is in the program space. */ 934934 935 935#define pgm_read_byte_far(address_long) __ELPM((uint32_t)(address_long)) 936936 937937/** \ingroup avr_pgmspace 938938\def pgm_read_word_far(address_long) 939939Read a word from the program space with a 32-bit (far) address. 940940 941941\note The address is a byte address. 942942The address is in the program space. */ 943943 944 944#define pgm_read_word_far(address_long) __ELPM_word((uint32_t)(address_long)) 945945 946946/** \ingroup avr_pgmspace 947947\def pgm_read_dword_far(address_long) 948948Read a double word from the program space with a 32-bit (far) address. 949949 950950\note The address is a byte address. 951951The address is in the program space. */ 952952 953 953#define pgm_read_dword_far(address_long) __ELPM_dword((uint32_t)(address_long)) 954954 955955/** \ingroup avr_pgmspace 956956\def pgm_read_float_far(address_long) 957957Read a float from the program space with a 32-bit (far) address. 958958 959959\note The address is a byte address. 960960The address is in the program space. */ 961961 962 962#define pgm_read_float_far(address_long) __ELPM_float((uint32_t)(address_long)) 963963 964964/** \ingroup avr_pgmspace 965965\def pgm_read_ptr_far(address_long) 966966Read a pointer from the program space with a 32-bit (far) address. 967967 968968\note The address is a byte address. 969969The address is in the program space. */ 970970 971 971#define pgm_read_ptr_far(address_long) (void*)__ELPM_word((uint32_t)(address_long)) 972972 973973#endif /* RAMPZ or __DOXYGEN__ */ 974974 975975/** \ingroup avr_pgmspace 976976\def pgm_read_byte(address_short) 977977Read a byte from the program space with a 16-bit (near) address. 978978 979979\note The address is a byte address. 980980The address is in the program space. */ 981981 982 982#define pgm_read_byte(address_short) pgm_read_byte_near(address_short) 983983 984984/** \ingroup avr_pgmspace 985985\def pgm_read_word(address_short) 986986Read a word from the program space with a 16-bit (near) address. 987987 988988\note The address is a byte address. 989989The address is in the program space. */ 990990 991 991#define pgm_read_word(address_short) pgm_read_word_near(address_short) 992992 993993/** \ingroup avr_pgmspace 994994\def pgm_read_dword(address_short) 995995Read a double word from the program space with a 16-bit (near) address. 996996 997997\note The address is a byte address. 998998The address is in the program space. */ 999999

1000#define pgm_read_dword(address_short) pgm_read_dword_near(address_short)

1009#define pgm_read_float(address_short) pgm_read_float_near(address_short)

1018#define pgm_read_ptr(address_short) pgm_read_ptr_near(address_short)

1053#define pgm_get_far_address(var) \

memchr_P(const void *, int __val, size_t __len) __ATTR_CONST__;

extern int memcmp_P(const void *, const void *, size_t) __ATTR_PURE__;

memccpy_P(void *, const void *, int __val, size_t);

memcpy_P(void *, const void *, size_t);

memmem_P(const void *, size_t, const void *, size_t) __ATTR_PURE__;

void * memrchr_P(const void *, int __val, size_t __len) __ATTR_CONST__;

char *strcat_P(char *, const char *);

char * strchr_P(const char *, int __val) __ATTR_CONST__;

char * strchrnul_P(const char *, int __val) __ATTR_CONST__;

strcmp_P(const char *, const char *) __ATTR_PURE__;

char *strcpy_P(char *, const char *);

strcasecmp_P(const char *, const char *) __ATTR_PURE__;

strcasestr_P(const char *, const char *) __ATTR_PURE__;

strcspn_P(const char *__s, const char * __reject) __ATTR_PURE__;

size_t strlcat_P (char *, const char *, size_t );

strlcpy_P (char *, const char *, size_t );

size_t strnlen_P(const char *, size_t) __ATTR_CONST__; /* program memory can't change */

strncmp_P(const char *, const char *, size_t) __ATTR_PURE__;

strncasecmp_P(const char *, const char *, size_t) __ATTR_PURE__;

strncat_P(char *, const char *, size_t);

char *strncpy_P(char *, const char *, size_t);

strpbrk_P(const char *__s, const char * __accept) __ATTR_PURE__;

strrchr_P(const char *, int __val) __ATTR_CONST__;

char *strsep_P(char **__sp, const char * __delim);

strspn_P(const char *__s, const char * __accept) __ATTR_PURE__;

char *strstr_P(const char *, const char *) __ATTR_PURE__;

char *strtok_P(char *__s, const char * __delim);

char *strtok_rP(char *__s, const char * __delim, char **__last);

strlen_PF(uint_farptr_t src) __ATTR_CONST__; /* program memory can't change */

size_t strnlen_PF(uint_farptr_t src, size_t len) __ATTR_CONST__; /* program memory can't change */

memcpy_PF(void *dest, uint_farptr_t src, size_t len);

strcpy_PF(char *dest, uint_farptr_t src);

char *strncpy_PF(char *dest, uint_farptr_t src, size_t len);

char *strcat_PF(char *dest, uint_farptr_t src);

strlcat_PF(char *dst, uint_farptr_t src, size_t siz);

strncat_PF(char *dest, uint_farptr_t src, size_t len);

int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;

strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;

int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__;

int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__;

char *strstr_PF(const char *s1, uint_farptr_t s2);

size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz);

int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__;

strlen_P(const char * s);

extern size_t __strlen_P(const char *) __ATTR_CONST__; /* internal helper function */

__attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s);

strlen_P(const char *s) {

memcmp_P int memcmp_P(const void *, const void *, size_t) __ATTR_PURE__ Compare memory areas.

prog_uint32_t uint32_t PROGMEM prog_uint32_t

Definition: pgmspace.h:288

strtok_P char * strtok_P(char *__s, const char *__delim) Parses the string into tokens.

int64_t signed long long int int64_t

Definition: stdint.h:110

memmem_P void * memmem_P(const void *, size_t, const void *, size_t) __ATTR_PURE__

strstr_P char * strstr_P(const char *, const char *) __ATTR_PURE__ Locate a substring.

prog_int32_t int32_t PROGMEM prog_int32_t

Definition: pgmspace.h:270

prog_uint64_t uint64_t PROGMEM prog_uint64_t

Definition: pgmspace.h:330

strncpy_P char * strncpy_P(char *, const char *, size_t)

prog_uchar unsigned char PROGMEM prog_uchar

Definition: pgmspace.h:180

prog_void void PROGMEM prog_void

Definition: pgmspace.h:144

strchr_P const char * strchr_P(const char *, int __val) Locate character in program space string.

strlcpy_P size_t strlcpy_P(char *, const char *, size_t) Copy a string from progmem to RAM.

prog_int64_t int64_t PROGMEM prog_int64_t

Definition: pgmspace.h:309

memcpy_PF void * memcpy_PF(void *dest, uint_farptr_t src, size_t len) Copy a memory block from flash to SRAM.

int16_t signed int int16_t

Definition: stdint.h:88

int8_t signed char int8_t

Definition: stdint.h:78

strcasecmp_P int strcasecmp_P(const char *, const char *) __ATTR_PURE__ Compare two strings ignoring case.

io.h

strcspn_P size_t strcspn_P(const char *__s, const char *__reject) __ATTR_PURE__

strcpy_PF char * strcpy_PF(char *dest, uint_farptr_t src) Duplicate a string.

strcat_PF char * strcat_PF(char *dest, uint_farptr_t src) Concatenates two strings.

PROGMEM #define PROGMEM

Definition: pgmspace.h:113

strlcat_PF size_t strlcat_PF(char *dst, uint_farptr_t src, size_t siz) Concatenate two strings.

__attribute__ static __inline void __attribute__((__always_inline__)) __power_all_enable()

Definition: power.h:1148

strncat_PF char * strncat_PF(char *dest, uint_farptr_t src, size_t len) Concatenate two strings.

strncat_P char * strncat_P(char *, const char *, size_t) Concatenate two strings.

int32_t signed long int int32_t

Definition: stdint.h:98

memcpy_P void * memcpy_P(void *, const void *, size_t)

strstr_PF char * strstr_PF(const char *s1, uint_farptr_t s2) Locate a substring.

strcmp_P int strcmp_P(const char *, const char *) __ATTR_PURE__

strlcpy_PF size_t strlcpy_PF(char *dst, uint_farptr_t src, size_t siz) Copy a string from progmem to RAM.

strlen_P static size_t strlen_P(const char *s)

strtok_rP char * strtok_rP(char *__s, const char *__delim, char **__last) Parses string into tokens.

prog_int8_t int8_t PROGMEM prog_int8_t

Definition: pgmspace.h:198

memcmp_PF int memcmp_PF(const void *, uint_farptr_t, size_t) __ATTR_PURE__ Compare memory areas.

strrchr_P const char * strrchr_P(const char *, int __val) Locate character in string.

strcmp_PF int strcmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__ Compares two strings.

uint8_t unsigned char uint8_t

Definition: stdint.h:83

memrchr_P const void * memrchr_P(const void *, int __val, size_t __len)

strpbrk_P char * strpbrk_P(const char *__s, const char *__accept) __ATTR_PURE__

uint_farptr_t uint32_t uint_farptr_t

Definition: inttypes.h:81

strcpy_P char * strcpy_P(char *, const char *)

uint32_t unsigned long int uint32_t

Definition: stdint.h:103

inttypes.h

strncpy_PF char * strncpy_PF(char *dest, uint_farptr_t src, size_t len) Duplicate a string until a limited length.

strncasecmp_P int strncasecmp_P(const char *, const char *, size_t) __ATTR_PURE__ Compare two strings ignoring case.

prog_char char PROGMEM prog_char

Definition: pgmspace.h:162

strspn_P size_t strspn_P(const char *__s, const char *__accept) __ATTR_PURE__

memccpy_P void * memccpy_P(void *, const void *, int __val, size_t)

prog_uint16_t uint16_t PROGMEM prog_uint16_t

Definition: pgmspace.h:252

strchrnul_P const char * strchrnul_P(const char *, int __val)

strnlen_P size_t strnlen_P(const char *, size_t) Determine the length of a fixed-size string.

strncmp_P int strncmp_P(const char *, const char *, size_t) __ATTR_PURE__

strcasestr_P char * strcasestr_P(const char *, const char *) __ATTR_PURE__

strcat_P char * strcat_P(char *, const char *)

uint64_t unsigned long long int uint64_t

Definition: stdint.h:117

memchr_P const void * memchr_P(const void *, int __val, size_t __len) Scan flash memory for a character.

strncmp_PF int strncmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__ Compare two strings with limited length.

strsep_P char * strsep_P(char **__sp, const char *__delim) Parse a string into tokens.

strlen_PF size_t strlen_PF(uint_farptr_t src) Obtain the length of a string.

uint16_t unsigned int uint16_t

Definition: stdint.h:93

prog_uint8_t uint8_t PROGMEM prog_uint8_t

Definition: pgmspace.h:216

strnlen_PF size_t strnlen_PF(uint_farptr_t src, size_t len) Determine the length of a fixed-size string.

strcasecmp_PF int strcasecmp_PF(const char *s1, uint_farptr_t s2) __ATTR_PURE__ Compare two strings ignoring case.

strlcat_P size_t strlcat_P(char *, const char *, size_t) Concatenate two strings.

strncasecmp_PF int strncasecmp_PF(const char *s1, uint_farptr_t s2, size_t n) __ATTR_PURE__ Compare two strings ignoring case.

prog_int16_t int16_t PROGMEM prog_int16_t

Definition: pgmspace.h:234