You can chat about native SDK questions and issues here.

User avatar
By MartinC
#73614 An example of how to access bytes stored in Flash. There's a few posts out there on how to do this, but not too many complete examples.

My twist on the accessor function is to cache the previously-read 32bits of flash data in a STATIC, so as to avoid repeated reads when accessing consecutive bytes of e.g. strings.

A slight 'gotcha' to be aware of is that since GCC3.0, the compiler won't let you mix const and non-const symbols in the same linker section. This means, for example, that if you define an array of strings it has to be declared as type 'const char * const strArray[]' (const pointer to const data) otherwise you'll get a section conflict error.

Code: Select all#include <stdint.h>
#include <ets_sys.h>
#include <osapi.h>
#include <user_interface.h>


//--------------------
// user data in flash
//--------------------
const uint8_t myString[] __attribute__((section(".irom.text"))) = "The quick brown fox jumps over the lazy dog";
// NB: you CAN use section(".irom.text") if you are also using -DUSE_OPTIMIZED_PRINTF
//     but if you do so, you MUST ensure that ALL elements of your data are declared const.


//------------
// prototypes
//------------
uint8_t readByte(uint8_t *);
void initDoneCB(void);


//-----------
// functions
//-----------

// access byte stored in flash
//
uint8_t ICACHE_FLASH_ATTR readByte(uint8_t *pByte) {
    static uint8_t *prevPtr = NULL;
    static uint32_t longVal = 0;
    uint8_t offset;
   
    offset = (uint8_t)(*((uint8_t *)&pByte) & 0x3);     // get lowest 2 bits
    *((uint8_t *)&pByte) &= (uint8_t)(~ 0x3);           // align address (clear lowest 2 bits)
   
    if (pByte != prevPtr) {                             // optimise consecutive reads by caching
        prevPtr = pByte;
        longVal = *((uint32_t *)pByte);                 // read aligned 32bit value
    }
   
    return *((uint8_t *)(&longVal) + offset);           // extract required byte
}


// entry point
//
void ICACHE_FLASH_ATTR user_init() {
    system_init_done_cb(&initDoneCB);
}


// called when initialisation is complete
//
void ICACHE_FLASH_ATTR initDoneCB(void) {
    uint8_t *pByte;
    uint8_t byte;
   
    os_printf("\n");

    pByte = myString;                                   // use accessor function to print string characters
    do {
        byte = readByte(pByte);
        pByte += 1;
        if (byte != 0) {
            os_printf("%c", byte);
        }
    } while (byte != 0);
   
    os_printf("\nDone\n");
}