Sistema l'errore da me commesso in fase di conversione...
[bertos.git] / mware / pgm.h
1 /**
2  * \file
3  * <!--
4  * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
5  * This file is part of DevLib - See README.devlib for information.
6  * -->
7  *
8  * \brief Support for reading program memory on Harvard architectures.
9  *
10  * Support is currently provided for AVR microcontrollers only.
11  *
12  * These macros allow building code twice, with and without
13  * pgm support (e.g.: strcpy() and strcpy_P()).
14  *
15  * Set the _PROGMEM predefine to compile in conditional
16  * program-memory support.
17  *
18  *
19  * \note This module contains code ripped out from avr-libc,
20  *       which is distributed under a 3-clause BSD license.
21  */
22 #ifndef MWARE_PGM_H
23 #define MWARE_PGM_H
24
25 #include <cfg/cpu_detect.h>
26 #include <cfg/compiler.h> /* For intXX_t */
27 #include <cfg/cpu.h> /* For CPU_HARVARD */
28
29 #if CPU_AVR
30
31         #ifdef __AVR_ENHANCED__
32                 #define pgm_read_char(addr) \
33                 ({ \
34                         uint16_t __addr16 = (uint16_t)(addr); \
35                         uint8_t __result; \
36                         __asm__ \
37                         ( \
38                                 "lpm %0, Z" "\n\t" \
39                                 : "=r" (__result) \
40                                 : "z" (__addr16) \
41                         ); \
42                         __result; \
43                 })
44                 #define pgm_read_uint16_t(addr) \
45                 ({ \
46                         uint16_t __addr16 = (uint16_t)(addr); \
47                         uint16_t __result; \
48                         __asm__ \
49                         ( \
50                                 "lpm %A0, Z+"   "\n\t" \
51                                 "lpm %B0, Z"    "\n\t" \
52                                 : "=r" (__result), "=z" (__addr16) \
53                                 : "1" (__addr16) \
54                         ); \
55                         __result; \
56                 })
57
58
59         #else /* !__AVR_ENHANCED__ */
60
61                 #define pgm_read_char(addr) \
62                 ({ \
63                         uint16_t __addr16 = (uint16_t)(addr); \
64                         uint8_t __result; \
65                         __asm__ \
66                         ( \
67                                 "lpm" "\n\t" \
68                                 "mov %0, r0" "\n\t" \
69                                 : "=r" (__result) \
70                                 : "z" (__addr16) \
71                                 : "r0" \
72                         ); \
73                         __result; \
74                 })
75                 #define pgm_read_uint16_t(addr) \
76                 ({ \
77                         uint16_t __addr16 = (uint16_t)(addr); \
78                         uint16_t __result; \
79                         __asm__ \
80                         ( \
81                                 "lpm"           "\n\t" \
82                                 "mov %A0, r0"   "\n\t" \
83                                 "adiw r30, 1"   "\n\t" \
84                                 "lpm"           "\n\t" \
85                                 "mov %B0, r0"   "\n\t" \
86                                 : "=r" (__result), "=z" (__addr16) \
87                                 : "1" (__addr16) \
88                                 : "r0" \
89                         ); \
90                         __result; \
91                 })
92
93         #endif /* !__AVR_ENHANCED__ */
94
95         #if SIZEOF_INT == 2
96                 #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr))
97         #else
98                 #error Missing support for CPU word size != 16bit
99         #endif
100
101         #ifndef PROGMEM
102         #define PROGMEM  __attribute__((__progmem__))
103         #endif
104         #ifndef PSTR
105         #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; })
106         #endif
107         #ifndef PFUNC
108         #define PFUNC(x)      x ## _P
109         #endif
110
111 #elif CPU_HARVARD
112         #error Missing CPU support
113 #endif
114
115 #ifndef PSTR
116 #define PSTR            /* nothing */
117 #endif
118
119 #ifndef PFUNC
120 #define PFUNC(x) x
121 #endif
122
123 #ifndef PROGMEM
124 #define PROGMEM         /* nothing */
125 #endif
126
127 /**
128  * \name Types for variables stored in program memory (harvard processors).
129  * \{
130  */
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;
138 /*\}*/
139
140 /**
141  * \name PGM support macros.
142  *
143  * These macros enable dual compilation of code for both program
144  * and data memory.
145  *
146  * Such a function may be defined like this:
147  *
148  * \code
149  *      void PGM_FUNC(lcd_puts)(PGM_ATTR const char *str)
150  *      {
151  *              char c;
152  *              while ((c = PGM_READ_CHAR(str++))
153  *                      lcd_putchar(c);
154  *      }
155  * \endcode
156  *
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:
160  *
161  * \code
162  *      lcd_puts("Hello, world!");
163  *      lcd_puts_P(PSTR("Hello, world!"));
164  *
165  *      // To be used when invoking inside other PGM_FUNC functions:
166  *      PGM_FUNC(lcd_puts)(some_string);
167  * \endcode
168  *
169  * \{
170  */
171 #ifdef _PROGMEM
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
176 #else
177         #define PGM_READ_CHAR(s) (*(s))
178         #define PGM_FUNC(x)      x
179         #define PGM_STR(x)       x
180         #define PGM_ATTR         /* nothing */
181 #endif
182 /* \} */
183
184
185 #endif /* MWARE_PGM_H */