pgm.h

Go to the documentation of this file.
00001 
00047 #ifndef MWARE_PGM_H
00048 #define MWARE_PGM_H
00049 
00050 #include <cfg/compiler.h> /* For intXX_t */
00051 #include <cpu/detect.h>
00052 #include <cpu/attr.h>     /* For CPU_HARVARD */
00053 #include <cpu/types.h>    /* For SIZEOF_INT */
00054 
00055 #if CPU_AVR
00056 
00057     #ifdef __AVR_ENHANCED__
00058         #define pgm_read_char(addr) \
00059         ({ \
00060             uint16_t __addr16 = (uint16_t)(addr); \
00061             uint8_t __result; \
00062             __asm__ \
00063             ( \
00064                 "lpm %0, Z" "\n\t" \
00065                 : "=r" (__result) \
00066                 : "z" (__addr16) \
00067             ); \
00068             __result; \
00069         })
00070         #define pgm_read_uint16_t(addr) \
00071         ({ \
00072             uint16_t __addr16 = (uint16_t)(addr); \
00073             uint16_t __result; \
00074             __asm__ \
00075             ( \
00076                 "lpm %A0, Z+"   "\n\t" \
00077                 "lpm %B0, Z"    "\n\t" \
00078                 : "=r" (__result), "=z" (__addr16) \
00079                 : "1" (__addr16) \
00080             ); \
00081             __result; \
00082         })
00083 
00084 
00085     #else /* !__AVR_ENHANCED__ */
00086 
00087         #define pgm_read_char(addr) \
00088         ({ \
00089             uint16_t __addr16 = (uint16_t)(addr); \
00090             uint8_t __result; \
00091             __asm__ \
00092             ( \
00093                 "lpm" "\n\t" \
00094                 "mov %0, r0" "\n\t" \
00095                 : "=r" (__result) \
00096                 : "z" (__addr16) \
00097                 : "r0" \
00098             ); \
00099             __result; \
00100         })
00101         #define pgm_read_uint16_t(addr) \
00102         ({ \
00103             uint16_t __addr16 = (uint16_t)(addr); \
00104             uint16_t __result; \
00105             __asm__ \
00106             ( \
00107                 "lpm"           "\n\t" \
00108                 "mov %A0, r0"   "\n\t" \
00109                 "adiw r30, 1"   "\n\t" \
00110                 "lpm"           "\n\t" \
00111                 "mov %B0, r0"   "\n\t" \
00112                 : "=r" (__result), "=z" (__addr16) \
00113                 : "1" (__addr16) \
00114                 : "r0" \
00115             ); \
00116             __result; \
00117         })
00118 
00119     #endif /* !__AVR_ENHANCED__ */
00120 
00121     #if SIZEOF_INT == 2
00122         #define pgm_read_int(addr) ((int)pgm_read_uint16_t(addr))
00123     #else
00124         #error Missing support for CPU word size != 16bit
00125     #endif
00126 
00127     #ifndef PROGMEM
00128     #define PROGMEM  __attribute__((__progmem__))
00129     #endif
00130     #ifndef PSTR
00131     #define PSTR(s) ({ static const char __c[] PROGMEM = (s); &__c[0]; })
00132     #endif
00133     #ifndef PFUNC
00134     #define PFUNC(x)      x ## _P
00135     #endif
00136 
00137 #elif CPU_HARVARD
00138     #error Missing CPU support
00139 #endif
00140 
00141 #ifndef PSTR
00142 #define PSTR            /* nothing */
00143 #endif
00144 
00145 #ifndef PFUNC
00146 #define PFUNC(x) x
00147 #endif
00148 
00149 #ifndef PROGMEM
00150 #define PROGMEM         /* nothing */
00151 #endif
00152 
00157 typedef PROGMEM char pgm_char;
00158 typedef PROGMEM int8_t pgm_int8_t;
00159 typedef PROGMEM uint8_t pgm_uint8_t;
00160 typedef PROGMEM int16_t pgm_int16_t;
00161 typedef PROGMEM uint16_t pgm_uint16_t;
00162 typedef PROGMEM int32_t pgm_int32_t;
00163 typedef PROGMEM uint32_t pgm_uint32_t;
00164 /*\}*/
00165 
00197 #ifdef _PROGMEM
00198     #define PGM_READ_CHAR(s) pgm_read_char(s)
00199     #define PGM_FUNC(x)      PFUNC(x)
00200     #define PGM_STR(x)       PSTR(x)
00201     #define PGM_ATTR         PROGMEM
00202 #else
00203     #define PGM_READ_CHAR(s) (*(s))
00204     #define PGM_FUNC(x)      x
00205     #define PGM_STR(x)       x
00206     #define PGM_ATTR         /* nothing */
00207 #endif
00208 /* \} */
00209 
00210 
00211 #endif /* MWARE_PGM_H */