Skip to content

Commit

Permalink
Add READ_FLASH_UINT8, allowing ESP8266 to read&exec strings stored in…
Browse files Browse the repository at this point in the history
… Flash with E.memoryArea
  • Loading branch information
gfwilliams committed Jan 26, 2016
1 parent 391ae89 commit cadc44c
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 24 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Expand Up @@ -26,6 +26,7 @@
Only garbage collect on idle if we're low on memory (fix #767)
Improve malloc behaviour for crypto lib (try and free all command history is first alloc fails)
Improve HTTPS error messages
Add READ_FLASH_UINT8, allowing ESP8266 to read&exec strings stored in Flash with E.memoryArea

1v84 : Fix device initialisation flags not working when the device number is above 32 (fix #751, #748)
- this fixes broken SPI when not on standard pins
Expand Down
2 changes: 1 addition & 1 deletion src/jslex.c
Expand Up @@ -26,7 +26,7 @@ JslCharPos jslCharPosClone(JslCharPos *pos) {

/// Return the next character (do not move to the next character)
static ALWAYS_INLINE char jslNextCh(JsLex *lex) {
return (char)(lex->it.ptr ? lex->it.ptr[lex->it.charIdx] : 0);
return (char)(lex->it.ptr ? READ_FLASH_UINT8(&lex->it.ptr[lex->it.charIdx]) : 0);
}

/// Move on to the next character
Expand Down
41 changes: 22 additions & 19 deletions src/jsutils.h
Expand Up @@ -56,46 +56,49 @@ extern int isfinite ( double );

#if defined(ESP8266)

// Place constant strings into flash when we can in order to save RAM space. Strings in flash
// must be accessed with word reads on aligned boundaries, so we'll have to copy them before
// regular use.
/** Place constant strings into flash when we can in order to save RAM space. Strings in flash
must be accessed with word reads on aligned boundaries, so we'll have to copy them before
regular use. */
#define FLASH_STR(name, x) static char name[] __attribute__((section(".irom.literal"))) __attribute__((aligned(4))) = x

// Get the length of a string in flash
/// Get the length of a string in flash
size_t flash_strlen(const char *str);

// Copy a string from flash to RAM
/// Copy a string from flash to RAM
char *flash_strncpy(char *dest, const char *source, size_t cap);

/** Read a uint8_t from this pointer, which could be in RAM or Flash.
On ESP8266 you have to read flash in 32 bit chunks, so force a 32 bit read
and extract just the 8 bits we want */
#define READ_FLASH_UINT8(ptr) ({ uint32_t __p = (uint32_t)(char*)(ptr); volatile uint32_t __d = *(uint32_t*)(__p & (uint32_t)~3); ((uint8_t*)&__d)[__p & 3]; })

#else

/** Read a uint8_t from this pointer, which could be in RAM or Flash.
On ARM this is just a standard read, it's different on ESP8266 */
#define READ_FLASH_UINT8(ptr) (*(uint8_t*)(ptr))

#endif


#if defined(ESP8266)
// For the esp8266 we need to add CALLED_FROM_INTERRUPT to all functions that may execute at
// interrupt time so they get loaded into static RAM instead of flash. We define
// it as a no-op for everyone else. This is identical the ICACHE_RAM_ATTR used elsewhere.
/** For the esp8266 we need to add CALLED_FROM_INTERRUPT to all functions that may execute at
interrupt time so they get loaded into static RAM instead of flash. We define
it as a no-op for everyone else. This is identical the ICACHE_RAM_ATTR used elsewhere. */
#define CALLED_FROM_INTERRUPT __attribute__((section(".iram1.text")))
#else
#define CALLED_FROM_INTERRUPT
#endif



#if !defined(__USB_TYPE_H) && !defined(CPLUSPLUS) && !defined(__cplusplus) // it is defined in this file too!
#undef FALSE
#undef TRUE
//typedef enum {FALSE = 0, TRUE = !FALSE} bool;
#define FALSE 0
#define TRUE 1
#define FALSE (0)
#define TRUE (1)
//typedef unsigned char bool;
//#define TRUE (1)
//#define FALSE (0)
#endif

// Not needed because including stdbool.h instead.
/*#ifndef Arduino_h
#define true (1)
#define false (0)
#endif*/

#define DBL_MIN 2.2250738585072014e-308
#define DBL_MAX 1.7976931348623157e+308
Expand Down
4 changes: 2 additions & 2 deletions src/jsvariterator.h
Expand Up @@ -56,13 +56,13 @@ static ALWAYS_INLINE JsvStringIterator jsvStringIteratorClone(JsvStringIterator
/// Gets the current character (or 0)
static ALWAYS_INLINE char jsvStringIteratorGetChar(JsvStringIterator *it) {
if (!it->ptr) return 0;
return it->ptr[it->charIdx];
return READ_FLASH_UINT8(&it->ptr[it->charIdx]);
}

/// Gets the current (>=0) character (or -1)
static ALWAYS_INLINE int jsvStringIteratorGetCharOrMinusOne(JsvStringIterator *it) {
if (!it->ptr) return -1;
return (int)(unsigned char)it->ptr[it->charIdx];
return (int)(unsigned char)READ_FLASH_UINT8(&it->ptr[it->charIdx]);
}

/// Do we have a character, or are we at the end?
Expand Down
6 changes: 4 additions & 2 deletions src/jswrap_io.c
Expand Up @@ -88,8 +88,10 @@ Write 32 bits of memory at the given location - VERY DANGEROUS!
*/

uint32_t _jswrap_io_peek(JsVarInt addr, int wordSize) {
if (wordSize==1) return (uint32_t)*(unsigned char*)(size_t)addr;
if (wordSize==2) return (uint32_t)*(unsigned short*)(size_t)addr;
if (wordSize==1) return READ_FLASH_UINT8((char*)(size_t)addr);
if (wordSize==2) {
return READ_FLASH_UINT8((char*)(size_t)addr) | (uint32_t)(READ_FLASH_UINT8((char*)(size_t)(addr+1)) << 8);
}
if (wordSize==4) return (uint32_t)*(unsigned int*)(size_t)addr;
return 0;
}
Expand Down

0 comments on commit cadc44c

Please sign in to comment.