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 
31 #define PROGMEM STORE_ATTR ICACHE_RODATA_ATTR
32 
39 #define PROGMEM_PSTR \
40  STORE_ATTR \
41  __attribute__((section("\".irom0.pstr." __FILE__ \
42  "." MACROQUOTE(__LINE__) "." MACROQUOTE(__COUNTER__) "\", \"aSM\", @progbits, 1 #")))
43 
50 #define PSTR(str) \
51  (__extension__({ \
52  static const char __pstr__[] PROGMEM_PSTR = str; \
53  &__pstr__[0]; \
54  }))
55 
58 #ifdef __NEWLIB__
59 
60 #include_next <sys/pgmspace.h>
61 
62 #else
63 
64 #ifdef __cplusplus
65 extern "C" {
66 #endif
67 
77 #define PGM_P const char*
78 
82 #define PRIPSTR "%s"
83 
89 typedef void prog_void;
90 typedef char prog_char;
91 typedef unsigned char prog_uchar;
92 typedef int8_t prog_int8_t;
93 typedef uint8_t prog_uint8_t;
94 typedef int16_t prog_int16_t;
96 typedef int32_t prog_int32_t;
97 typedef uint32_t prog_uint32_t;
100 // flash memory must be read using 32 bit aligned addresses else a processor exception will be triggered
101 // order within the 32 bit values are
102 // --------------
103 // b3, b2, b1, b0
104 // w1, w0
105 
106 #define pgm_read_with_offset(addr, res) \
107  __asm__("extui %0, %1, 0, 2\n" /* Extract offset within word (in bytes) */ \
108  "sub %1, %1, %0\n" /* Subtract offset from addr, yielding an aligned address */ \
109  "l32i.n %1, %1, 0x0\n" /* Load word from aligned address */ \
110  "ssa8l %0\n" /* Prepare to shift by offset (in bits) */ \
111  "src %0, %1, %1\n" /* Shift right; now the requested byte is the first one */ \
112  : "=r"(res), "=r"(addr) \
113  : "1"(addr) \
114  :);
115 
116 static inline uint8_t pgm_read_byte_inlined(const void* addr)
117 {
118  uint32_t res;
119  pgm_read_with_offset(addr, res);
120  return (uint8_t)res; /* This masks the lower byte from the returned word */
121 }
122 
123 /* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */
124 static inline uint16_t pgm_read_word_inlined(const void* addr)
125 {
126  uint32_t res;
127  pgm_read_with_offset(addr, res);
128  return (uint16_t)res; /* This masks the lower half-word from the returned word */
129 }
130 
136 // Make sure, that libraries checking existence of this macro are not failing
137 #define pgm_read_byte(addr) pgm_read_byte_inlined(addr)
138 #define pgm_read_word(addr) pgm_read_word_inlined(addr)
139 
140 // No translation necessary (provided address is aligned)
141 #define pgm_read_dword(addr) (*(const unsigned long*)(addr))
142 #define pgm_read_float(addr) (*(const float*)(addr))
143 
151 void* memcpy_P(void* dest, const void* src_P, size_t length);
152 int memcmp_P(const void* a1, const void* b1, size_t len);
153 size_t strlen_P(const char* src_P);
154 char* strcpy_P(char* dest, const char* src_P);
155 char* strncpy_P(char* dest, const char* src_P, size_t size);
156 int strcmp_P(const char* str1, const char* str2_P);
157 int strncmp_P(const char* str1, const char* str2_P, const size_t size);
158 int strcasecmp_P(const char* str1, const char* str2_P);
159 char* strcat_P(char* dest, const char* src_P);
160 char* strstr_P(char* haystack, const char* needle_P);
161 
162 #define sprintf_P(s, f_P, ...) \
163  (__extension__({ \
164  int len_P = strlen_P(f_P); \
165  int __result = 0; \
166  char* __localF = (char*)malloc(len_P + 1); \
167  if(__localF) { \
168  strcpy_P(__localF, f_P); \
169  __localF[len_P] = '\0'; \
170  } \
171  __result = m_snprintf(s, len_P, __localF, ##__VA_ARGS__); \
172  free(__localF); \
173  __result; \
174  }))
175 
182 #define pgm_read_byte_near(addr) pgm_read_byte(addr)
183 #define pgm_read_word_near(addr) pgm_read_word(addr)
184 #define pgm_read_dword_near(addr) pgm_read_dword(addr)
185 #define pgm_read_float_near(addr) pgm_read_float(addr)
186 #define pgm_read_byte_far(addr) pgm_read_byte(addr)
187 #define pgm_read_word_far(addr) pgm_read_word(addr)
188 #define pgm_read_dword_far(addr) pgm_read_dword(addr)
189 #define pgm_read_float_far(addr) pgm_read_float(addr)
190 
194 #ifdef __cplusplus
195 }
196 #endif
197 
198 #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:96
uint16_t prog_uint16_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:95
int8_t prog_int8_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:92
char * strstr_P(char *haystack, const char *needle_P)
char prog_char
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:90
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:106
uint8_t prog_uint8_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:93
int16_t prog_int16_t
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:94
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:91
static uint16_t pgm_read_word_inlined(const void *addr)
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:124
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:97
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:116
void prog_void
Definition: Arch/Esp8266/Components/libc/include/sys/pgmspace.h:89