Skip to content

Commit cbdae58

Browse files
Import PSTR and pgm_read_float fixes
Fixes #3 Also removes register keyword which is going away in later C++ versions from the macro. It was always a hint, and the C compiler was free to ignore it anyway. GCC should still be smart enough to use registers when possible.
1 parent 42f6e16 commit cbdae58

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

newlib/libc/sys/xtensa/sys/pgmspace.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ extern "C" {
3434
// PSTR() macro modified to start on a 32-bit boundary. This adds on average
3535
// 1.5 bytes/string, but in return memcpy_P and strcpy_P will work 4~8x faster
3636
#ifndef PSTR
37-
#define PSTR(s) (__extension__({static const char __c[] __attribute__((__aligned__(4))) PROGMEM = (s); &__c[0];}))
37+
// Adapted from AVR-specific code at https://forum.arduino.cc/index.php?topic=194603.0
38+
// Uses C attribute section instead of ASM block to allow for C language string concatenation ("x" "y" === "xy")
39+
#define PSTR(s) (__extension__({static const char __c[] __attribute__((__aligned__(4))) __attribute__((section( "\".irom0.pstr." __FILE__ "." __STRINGIZE(__LINE__) "." __STRINGIZE(__COUNTER__) "\", \"aSM\", @progbits, 1 #"))) = (s); &__c[0];}))
3840
#endif
3941

4042
// Flash memory must be read using 32 bit aligned addresses else a processor
@@ -66,18 +68,26 @@ extern "C" {
6668
:"a15");
6769

6870
static inline uint8_t pgm_read_byte_inlined(const void* addr) {
69-
register uint32_t res;
71+
uint32_t res;
7072
pgm_read_with_offset(addr, res);
7173
return (uint8_t) res; /* This masks the lower byte from the returned word */
7274
}
7375

7476
/* Although this says "word", it's actually 16 bit, i.e. half word on Xtensa */
7577
static inline uint16_t pgm_read_word_inlined(const void* addr) {
76-
register uint32_t res;
78+
uint32_t res;
7779
pgm_read_with_offset(addr, res);
7880
return (uint16_t) res; /* This masks the lower half-word from the returned word */
7981
}
8082

83+
/* Can't legally cast bits of uint32_t to a float w/o conversion or std::memcpy, which is inefficient. */
84+
/* The ASM block doesn't care the type, so just pass in what C thinks is a float and return in custom fcn. */
85+
static inline float pgm_read_float_unaligned(const void *addr) {
86+
float res;
87+
pgm_read_with_offset(addr, res);
88+
return res;
89+
}
90+
8191
#define pgm_read_byte(addr) pgm_read_byte_inlined(addr)
8292
#define pgm_read_word_aligned(addr) pgm_read_word_inlined(addr)
8393
#ifdef __cplusplus
@@ -96,7 +106,6 @@ static inline uint32_t pgm_read_dword_unaligned(const void *addr) {
96106
return res;
97107
}
98108

99-
#define pgm_read_float_unaligned(addr) ((float)pgm_read_dword_unaligned(addr))
100109
#define pgm_read_ptr_unaligned(addr) ((void*)pgm_read_dword_unaligned(addr))
101110
#define pgm_read_word_unaligned(addr) ((uint16_t)(pgm_read_dword_unaligned(addr) & 0xffff))
102111

0 commit comments

Comments
 (0)