4 * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
5 * This file is part of DevLib - See README.devlib for information.
8 * \brief Support for reading program memory on Harvard architectures.
10 * Support is currently provided for AVR microcontrollers only.
12 * These macros allow building code twice, with and without
13 * pgm support (e.g.: strcpy() and strcpy_P()).
15 * Set the _PROGMEM predefine to compile in conditional
16 * program-memory support.
19 * \note This module contains code ripped out from avr-libc,
20 * which is distributed under a 3-clause BSD license.
25 #include <cfg/cpu_detect.h>
26 #include <cfg/compiler.h> /* For intXX_t */
27 #include <cfg/cpu.h> /* For CPU_HARVARD */
31 #ifdef __AVR_ENHANCED__
32 #define pgm_read_char(addr) \
34 uint16_t __addr16 = (uint16_t)(addr); \
44 #define pgm_read_uint16_t(addr) \
46 uint16_t __addr16 = (uint16_t)(addr); \
50 "lpm %A0, Z+" "\n\t" \
52 : "=r" (__result), "=z" (__addr16) \
59 #else /* !__AVR_ENHANCED__ */
61 #define pgm_read_char(addr) \
63 uint16_t __addr16 = (uint16_t)(addr); \
75 #define pgm_read_uint16_t(addr) \
77 uint16_t __addr16 = (uint16_t)(addr); \
82 "mov %A0, r0" "\n\t" \
83 "adiw r30, 1" "\n\t" \
85 "mov %B0, r0" "\n\t" \
86 : "=r" (__result), "=z" (__addr16) \
93 #endif /* !__AVR_ENHANCED__ */
96 #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr))
98 #error Missing support for CPU word size != 16bit
102 #define PROGMEM __attribute__((__progmem__))
105 #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; })
108 #define PFUNC(x) x ## _P
112 #error Missing CPU support
116 #define PSTR /* nothing */
124 #define PROGMEM /* nothing */
128 * \name Types for variables stored in program memory (harvard processors).
131 typedef PROGMEM char pgm_char;
132 typedef PROGMEM int8_t pgm_int8_t;
133 typedef PROGMEM uint8_t pgm_uint8_t;
134 typedef PROGMEM int16_t pgm_int16_t;
135 typedef PROGMEM uint16_t pgm_uint16_t;
136 typedef PROGMEM int32_t pgm_int32_t;
137 typedef PROGMEM uint32_t pgm_uint32_t;
141 * \name PGM support macros.
143 * These macros enable dual compilation of code for both program
146 * Such a function may be defined like this:
149 * void PGM_FUNC(lcd_puts)(PGM_ATTR const char *str)
152 * while ((c = PGM_READ_CHAR(str++))
157 * The above code can be compiled twice: once with the _PROGMEM preprocessor
158 * symbol defined, and once without. The two object modules can then be
159 * linked in the same application for use by client code:
162 * lcd_puts("Hello, world!");
163 * lcd_puts_P(PSTR("Hello, world!"));
165 * // To be used when invoking inside other PGM_FUNC functions:
166 * PGM_FUNC(lcd_puts)(some_string);
172 #define PGM_READ_CHAR(s) pgm_read_char(s)
173 #define PGM_FUNC(x) PFUNC(x)
174 #define PGM_STR(x) PSTR(x)
175 #define PGM_ATTR PROGMEM
177 #define PGM_READ_CHAR(s) (*(s))
178 #define PGM_FUNC(x) x
180 #define PGM_ATTR /* nothing */
185 #endif /* MWARE_PGM_H */