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 
22 #define FLASH_MEMORY_START_ADDR 0x40200000
23 
27 #define isFlashPtr(ptr) ((uint32_t)ptr >= FLASH_MEMORY_START_ADDR)
28 
36 #define PROGMEM STORE_ATTR ICACHE_RODATA_ATTR
37 
44 #define PROGMEM_PSTR \
45  STORE_ATTR \
46  __attribute__((section("\".irom0.pstr." __FILE__ \
47  "." MACROQUOTE(__LINE__) "." MACROQUOTE(__COUNTER__) "\", \"aSM\", @progbits, 1 #")))
48 
55 #define PSTR(str) \
56  (__extension__({ \
57  static const char __pstr__[] PROGMEM_PSTR = str; \
58  &__pstr__[0]; \
59  }))
60 
63 #ifdef __NEWLIB__
64 
65 #include_next <sys/pgmspace.h>
66 
67 #else
68 
69 #ifdef __cplusplus
70 extern "C" {
71 #endif
72 
82 #define PGM_P const char*
83 
87 #define PRIPSTR "%s"
88 
94 typedef void prog_void;
95 typedef char prog_char;
96 typedef unsigned char prog_uchar;
97 typedef int8_t prog_int8_t;
98 typedef uint8_t prog_uint8_t;
99 typedef int16_t prog_int16_t;
100 typedef uint16_t prog_uint16_t;
101 typedef int32_t prog_int32_t;
102 typedef uint32_t prog_uint32_t;
105 // flash memory must be read using 32 bit aligned addresses else a processor exception will be triggered
106 // order within the 32 bit values are
107 // --------------
108 // b3, b2, b1, b0
109 // w1, w0
110 
111 #define pgm_read_with_offset(addr, res) \
112  __asm__("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */ \
113  "sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */ \
114  "l32i.n %1, %1, 0x0\n" /* Load word from aligned address */ \
115  "ssa8l %0\n" /* Prepare to shift by offset (in bits) */ \
116  "src %0, %1, %1\n" /* Shift right; now the requested byte is the first one */ \
117  : "=r"(res), "=r"(addr) \
118  : "1"(addr) \
119  :);
120 
121 static inline uint8_t pgm_read_byte_inlined(const void* addr)
122 {
123  uint32_t res;
124  pgm_read_with_offset(addr, res);
125  return (uint8_t)res; /* This masks the lower byte from the returned word */
126 }
127 
128 /* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */
129 static inline uint16_t pgm_read_word_inlined(const void* addr)
130 {
131  uint32_t res;
132  pgm_read_with_offset(addr, res);
133  return (uint16_t)res; /* This masks the lower half-word from the returned word */
134 }
135 
141 // Make sure, that libraries checking existence of this macro are not failing
142 #define pgm_read_byte(addr) pgm_read_byte_inlined(addr)
143 #define pgm_read_word(addr) pgm_read_word_inlined(addr)
144 
145 // No translation necessary (provided address is aligned)
146 #define pgm_read_dword(addr) (*(const unsigned long*)(addr))
147 #define pgm_read_float(addr) (*(const float*)(addr))
148 
156 void* memcpy_P(void* dest, PGM_VOID_P src_P, size_t length);
157 int memcmp_P(const void* buf1, PGM_VOID_P buf2_P, size_t len);
158 size_t strlen_P(PGM_VOID_P src_P);
159 char* strcpy_P(char* dest, PGM_P src_P);
160 char* strncpy_P(char* dest, PGM_P src_P, size_t size);
161 int strcmp_P(const char* str1, PGM_P str2_P);
162 int strncmp_P(const char* str1, PGM_P str2_P, const size_t size);
163 int strcasecmp_P(const char* str1, PGM_P str2_P);
164 char* strcat_P(char* dest, PGM_P src_P);
165 char* strstr_P(char* haystack, PGM_P needle_P);
166 
167 #define sprintf_P(s, f_P, ...) \
168  (__extension__({ \
169  int len_P = strlen_P(f_P); \
170  int __result = 0; \
171  char* __localF = (char*)malloc(len_P + 1); \
172  if(__localF) { \
173  strcpy_P(__localF, f_P); \
174  __localF[len_P] = '\0'; \
175  } \
176  __result = m_snprintf(s, len_P, __localF, ##__VA_ARGS__); \
177  free(__localF); \
178  __result; \
179  }))
180 
187 #define pgm_read_byte_near(addr) pgm_read_byte(addr)
188 #define pgm_read_word_near(addr) pgm_read_word(addr)
189 #define pgm_read_dword_near(addr) pgm_read_dword(addr)
190 #define pgm_read_float_near(addr) pgm_read_float(addr)
191 #define pgm_read_byte_far(addr) pgm_read_byte(addr)
192 #define pgm_read_word_far(addr) pgm_read_word(addr)
193 #define pgm_read_dword_far(addr) pgm_read_dword(addr)
194 #define pgm_read_float_far(addr) pgm_read_float(addr)
199 #ifdef __cplusplus
200 }
201 #endif
202 
203 #endif // __NEWLIB__
#define PGM_VOID_P
Definition: Arch/Esp32/Components/libc/src/include/sys/pgmspace.h:31
uint16_t prog_uint16_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:100
uint32_t prog_uint32_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:102
char * strcat_P(char *dest, PGM_P src_P)
uint8_t prog_uint8_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:98
void prog_void
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:94
size_t strlen_P(PGM_VOID_P src_P)
#define pgm_read_with_offset(addr, res)
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:111
unsigned char prog_uchar
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:96
static uint8_t pgm_read_byte_inlined(const void *addr)
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:121
int memcmp_P(const void *buf1, PGM_VOID_P buf2_P, size_t len)
int16_t prog_int16_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:99
char prog_char
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:95
int32_t prog_int32_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:101
char * strstr_P(char *haystack, PGM_P needle_P)
char * strncpy_P(char *dest, PGM_P src_P, size_t size)
int strncmp_P(const char *str1, PGM_P str2_P, const size_t size)
int strcmp_P(const char *str1, PGM_P str2_P)
static uint16_t pgm_read_word_inlined(const void *addr)
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:129
int8_t prog_int8_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:97
void * memcpy_P(void *dest, PGM_VOID_P src_P, size_t length)
int strcasecmp_P(const char *str1, PGM_P str2_P)
char * strcpy_P(char *dest, PGM_P src_P)
#define PGM_P
Identifies a char pointer as living in flash memory Use to clarify code.
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:82