Arch/Esp8266/Components/libc/include/sys/pgmspace.h
Go to the documentation of this file.
1 /****
2  * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3  * Created 2015 by Skurydin Alexey
4  * http://github.com/SmingHub/Sming
5  * All files of the Sming Core are provided under the LGPL v3 license.
6  *
7  * pgmspace.h - Support for reading flash memory (for old GCC versions)
8  *
9  ****/
10 
11 #pragma once
12 
13 #include <sys/features.h>
14 #include "../c_types.h"
15 #include "../esp_attr.h"
16 
29 #define PROGMEM STORE_ATTR ICACHE_RODATA_ATTR
30 
37 #define PROGMEM_PSTR \
38  STORE_ATTR \
39  __attribute__((section("\".irom0.pstr." __FILE__ \
40  "." MACROQUOTE(__LINE__) "." MACROQUOTE(__COUNTER__) "\", \"aSM\", @progbits, 1 #")))
41 
48 #define PSTR(str) \
49  (__extension__({ \
50  static const char __pstr__[] PROGMEM_PSTR = str; \
51  &__pstr__[0]; \
52  }))
53 
56 #ifdef __NEWLIB__
57 
58 #include_next <sys/pgmspace.h>
59 
60 #else
61 
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65 
75 #define PGM_P const char*
76 
80 #define PRIPSTR "%s"
81 
87 typedef void prog_void;
88 typedef char prog_char;
89 typedef unsigned char prog_uchar;
90 typedef int8_t prog_int8_t;
91 typedef uint8_t prog_uint8_t;
92 typedef int16_t prog_int16_t;
94 typedef int32_t prog_int32_t;
95 typedef uint32_t prog_uint32_t;
98 // flash memory must be read using 32 bit aligned addresses else a processor exception will be triggered
99 // order within the 32 bit values are
100 // --------------
101 // b3, b2, b1, b0
102 // w1, w0
103 
104 #define pgm_read_with_offset(addr, res) \
105  __asm__("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */ \
106  "sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */ \
107  "l32i.n %1, %1, 0x0\n" /* Load word from aligned address */ \
108  "ssa8l %0\n" /* Prepare to shift by offset (in bits) */ \
109  "src %0, %1, %1\n" /* Shift right; now the requested byte is the first one */ \
110  : "=r"(res), "=r"(addr) \
111  : "1"(addr) \
112  :);
113 
114 static inline uint8_t pgm_read_byte_inlined(const void* addr)
115 {
116  uint32_t res;
117  pgm_read_with_offset(addr, res);
118  return (uint8_t)res; /* This masks the lower byte from the returned word */
119 }
120 
121 /* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */
122 static inline uint16_t pgm_read_word_inlined(const void* addr)
123 {
124  uint32_t res;
125  pgm_read_with_offset(addr, res);
126  return (uint16_t)res; /* This masks the lower half-word from the returned word */
127 }
128 
134 // Make sure, that libraries checking existence of this macro are not failing
135 #define pgm_read_byte(addr) pgm_read_byte_inlined(addr)
136 #define pgm_read_word(addr) pgm_read_word_inlined(addr)
137 
138 // No translation necessary (provided address is aligned)
139 #define pgm_read_dword(addr) (*(const unsigned long*)(addr))
140 #define pgm_read_float(addr) (*(const float*)(addr))
141 
149 void* memcpy_P(void* dest, const void* src_P, size_t length);
150 int memcmp_P(const void* a1, const void* b1, size_t len);
151 size_t strlen_P(const char* src_P);
152 char* strcpy_P(char* dest, const char* src_P);
153 char* strncpy_P(char* dest, const char* src_P, size_t size);
154 int strcmp_P(const char* str1, const char* str2_P);
155 int strncmp_P(const char* str1, const char* str2_P, const size_t size);
156 int strcasecmp_P(const char* str1, const char* str2_P);
157 char* strcat_P(char* dest, const char* src_P);
158 char* strstr_P(char* haystack, const char* needle_P);
159 
160 #define sprintf_P(s, f_P, ...) \
161  (__extension__({ \
162  int len_P = strlen_P(f_P); \
163  int __result = 0; \
164  char* __localF = (char*)malloc(len_P + 1); \
165  if(__localF) { \
166  strcpy_P(__localF, f_P); \
167  __localF[len_P] = '\0'; \
168  } \
169  __result = m_snprintf(s, len_P, __localF, ##__VA_ARGS__); \
170  free(__localF); \
171  __result; \
172  }))
173 
180 #define pgm_read_byte_near(addr) pgm_read_byte(addr)
181 #define pgm_read_word_near(addr) pgm_read_word(addr)
182 #define pgm_read_dword_near(addr) pgm_read_dword(addr)
183 #define pgm_read_float_near(addr) pgm_read_float(addr)
184 #define pgm_read_byte_far(addr) pgm_read_byte(addr)
185 #define pgm_read_word_far(addr) pgm_read_word(addr)
186 #define pgm_read_dword_far(addr) pgm_read_dword(addr)
187 #define pgm_read_float_far(addr) pgm_read_float(addr)
188 
192 #ifdef __cplusplus
193 }
194 #endif
195 
196 #endif // __NEWLIB__
int memcmp_P(const void *a1, const void *b1, size_t len)
char * strcpy_P(char *dest, const char *src_P)
size_t strlen_P(const char *src_P)
int32_t prog_int32_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:94
uint16_t prog_uint16_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:93
int8_t prog_int8_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:90
char * strstr_P(char *haystack, const char *needle_P)
char prog_char
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:88
char * strcat_P(char *dest, const char *src_P)
#define pgm_read_with_offset(addr, res)
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:104
uint8_t prog_uint8_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:91
int16_t prog_int16_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:92
void * memcpy_P(void *dest, const void *src_P, size_t length)
unsigned char prog_uchar
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:89
static uint16_t pgm_read_word_inlined(const void *addr)
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:122
char * strncpy_P(char *dest, const char *src_P, size_t size)
int strncmp_P(const char *str1, const char *str2_P, const size_t size)
uint32_t prog_uint32_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:95
int strcasecmp_P(const char *str1, const char *str2_P)
int strcmp_P(const char *str1, const char *str2_P)
static uint8_t pgm_read_byte_inlined(const void *addr)
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:114
void prog_void
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:87