Skip to content

Commit f60defc

Browse files
authored
flash-size agnostic builds (#6690)
* flash: mapping definition by sketch at runtime depending on flash chip size and user configuration
1 parent 3027aca commit f60defc

22 files changed

+554
-544
lines changed

boards.txt

+206-435
Large diffs are not rendered by default.

cores/esp8266/Arduino.h

+3
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ void attachInterrupt(uint8_t pin, void (*)(void), int mode);
186186
void detachInterrupt(uint8_t pin);
187187
void attachInterruptArg(uint8_t pin, void (*)(void*), void* arg, int mode);
188188

189+
#if FLASH_MAP_SUPPORT
190+
#include "flash_hal.h"
191+
#endif
189192
void preinit(void);
190193
void setup(void);
191194
void loop(void);

cores/esp8266/Esp.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include "MD5Builder.h"
2727
#include "umm_malloc/umm_malloc.h"
2828
#include "cont.h"
29-
29+
#include "flash_hal.h"
3030
#include "coredecls.h"
3131
#include "umm_malloc/umm_malloc.h"
3232
#include <pgmspace.h>
@@ -291,13 +291,17 @@ uint32_t EspClass::getFlashChipRealSize(void)
291291

292292
uint32_t EspClass::getFlashChipSize(void)
293293
{
294+
#if FLASH_MAP_SUPPORT
295+
return getFlashChipRealSize();
296+
#else
294297
uint32_t data;
295298
uint8_t * bytes = (uint8_t *) &data;
296299
// read first 4 byte (magic byte + flash config)
297300
if(spi_flash_read(0x0000, &data, 4) == SPI_FLASH_RESULT_OK) {
298301
return magicFlashChipSize((bytes[3] & 0xf0) >> 4);
299302
}
300303
return 0;
304+
#endif
301305
}
302306

303307
uint32_t EspClass::getFlashChipSpeed(void)
@@ -323,6 +327,7 @@ FlashMode_t EspClass::getFlashChipMode(void)
323327
return mode;
324328
}
325329

330+
#if !FLASH_MAP_SUPPORT
326331
uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
327332
switch(byte & 0x0F) {
328333
case 0x0: // 4 Mbit (512KB)
@@ -343,6 +348,7 @@ uint32_t EspClass::magicFlashChipSize(uint8_t byte) {
343348
return 0;
344349
}
345350
}
351+
#endif
346352

347353
uint32_t EspClass::magicFlashChipSpeed(uint8_t byte) {
348354
switch(byte & 0x0F) {
@@ -612,14 +618,12 @@ uint32_t EspClass::getSketchSize() {
612618
return result;
613619
}
614620

615-
extern "C" uint32_t _FS_start;
616-
617621
uint32_t EspClass::getFreeSketchSpace() {
618622

619623
uint32_t usedSize = getSketchSize();
620624
// round one sector up
621625
uint32_t freeSpaceStart = (usedSize + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
622-
uint32_t freeSpaceEnd = (uint32_t)&_FS_start - 0x40200000;
626+
uint32_t freeSpaceEnd = (uint32_t)FS_start - 0x40200000;
623627

624628
#ifdef DEBUG_SERIAL
625629
DEBUG_SERIAL.printf("usedSize=%u freeSpaceStart=%u freeSpaceEnd=%u\r\n", usedSize, freeSpaceStart, freeSpaceEnd);

cores/esp8266/FlashMap.h

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
2+
// - do not edit - autogenerated by boards.txt.py
3+
4+
#ifndef __FLASH_MAP_H
5+
#define __FLASH_MAP_H
6+
7+
#include <stdint.h>
8+
#include <stddef.h>
9+
10+
typedef struct
11+
{
12+
uint32_t eeprom_start;
13+
uint32_t fs_start;
14+
uint32_t fs_end;
15+
uint32_t fs_block_size;
16+
uint32_t fs_page_size;
17+
uint32_t flash_size_kb;
18+
} flash_map_s;
19+
20+
/*
21+
Following definitions map the above structure, one per line.
22+
FLASH_MAP_* is a user choice in sketch:
23+
`FLASH_MAP_SETUP_CONFIG(FLASH_MAP_OTA_FS)`
24+
Configuration is made at boot with detected flash chip size (last argument 512..16384)
25+
Other values are defined from `tools/boards.txt.py`.
26+
*/
27+
28+
#define FLASH_MAP_OTA_FS \
29+
{ \
30+
{ .eeprom_start = 0x402fb000, .fs_start = 0x402eb000, .fs_end = 0x402fb000, .fs_block_size = 0x1000, .fs_page_size = 0x100, .flash_size_kb = 1024 }, \
31+
{ .eeprom_start = 0x403fb000, .fs_start = 0x403c0000, .fs_end = 0x403fb000, .fs_block_size = 0x1000, .fs_page_size = 0x100, .flash_size_kb = 2048 }, \
32+
{ .eeprom_start = 0x405fb000, .fs_start = 0x40400000, .fs_end = 0x405fa000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 4096 }, \
33+
{ .eeprom_start = 0x409fb000, .fs_start = 0x40400000, .fs_end = 0x409fa000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 8192 }, \
34+
{ .eeprom_start = 0x411fb000, .fs_start = 0x40400000, .fs_end = 0x411fa000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 16384 }, \
35+
{ .eeprom_start = 0x4027b000, .fs_start = 0x40273000, .fs_end = 0x4027b000, .fs_block_size = 0x1000, .fs_page_size = 0x100, .flash_size_kb = 512 }, \
36+
}
37+
38+
#define FLASH_MAP_MAX_FS \
39+
{ \
40+
{ .eeprom_start = 0x402fb000, .fs_start = 0x4027b000, .fs_end = 0x402fb000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 1024 }, \
41+
{ .eeprom_start = 0x403fb000, .fs_start = 0x40300000, .fs_end = 0x403fa000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 2048 }, \
42+
{ .eeprom_start = 0x405fb000, .fs_start = 0x40300000, .fs_end = 0x405fa000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 4096 }, \
43+
{ .eeprom_start = 0x409fb000, .fs_start = 0x40300000, .fs_end = 0x409fa000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 8192 }, \
44+
{ .eeprom_start = 0x411fb000, .fs_start = 0x40300000, .fs_end = 0x411fa000, .fs_block_size = 0x2000, .fs_page_size = 0x100, .flash_size_kb = 16384 }, \
45+
{ .eeprom_start = 0x4027b000, .fs_start = 0x4025b000, .fs_end = 0x4027b000, .fs_block_size = 0x1000, .fs_page_size = 0x100, .flash_size_kb = 512 }, \
46+
}
47+
48+
#define FLASH_MAP_NO_FS \
49+
{ \
50+
{ .eeprom_start = 0x402fb000, .fs_start = 0x402fb000, .fs_end = 0x402fb000, .fs_block_size = 0x0, .fs_page_size = 0x0, .flash_size_kb = 1024 }, \
51+
{ .eeprom_start = 0x403fb000, .fs_start = 0x403fb000, .fs_end = 0x403fb000, .fs_block_size = 0x0, .fs_page_size = 0x0, .flash_size_kb = 2048 }, \
52+
{ .eeprom_start = 0x405fb000, .fs_start = 0x405fb000, .fs_end = 0x405fb000, .fs_block_size = 0x0, .fs_page_size = 0x0, .flash_size_kb = 4096 }, \
53+
{ .eeprom_start = 0x409fb000, .fs_start = 0x409fb000, .fs_end = 0x409fb000, .fs_block_size = 0x0, .fs_page_size = 0x0, .flash_size_kb = 8192 }, \
54+
{ .eeprom_start = 0x411fb000, .fs_start = 0x411fb000, .fs_end = 0x411fb000, .fs_block_size = 0x0, .fs_page_size = 0x0, .flash_size_kb = 16384 }, \
55+
{ .eeprom_start = 0x4027b000, .fs_start = 0x4027b000, .fs_end = 0x4027b000, .fs_block_size = 0x0, .fs_page_size = 0x0, .flash_size_kb = 512 }, \
56+
}
57+
58+
#endif // __FLASH_MAP_H
59+

cores/esp8266/Updater.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ extern "C" {
2424
#include "user_interface.h"
2525
}
2626

27-
extern "C" uint32_t _FS_start;
28-
extern "C" uint32_t _FS_end;
27+
#include <flash_hal.h> // not "flash_hal.h": can use hijacked MOCK version
2928

3029
UpdaterClass::UpdaterClass()
3130
{
@@ -118,7 +117,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
118117

119118
if (command == U_FLASH) {
120119
//address of the end of the space available for sketch and update
121-
uintptr_t updateEndAddress = (uintptr_t)&_FS_start - 0x40200000;
120+
uintptr_t updateEndAddress = FS_start - 0x40200000;
122121

123122
updateStartAddress = (updateEndAddress > roundedSize)? (updateEndAddress - roundedSize) : 0;
124123

@@ -135,14 +134,14 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
135134
}
136135
}
137136
else if (command == U_FS) {
138-
if((uintptr_t)&_FS_start + roundedSize > (uintptr_t)&_FS_end) {
137+
if(FS_start + roundedSize > FS_end) {
139138
_setError(UPDATE_ERROR_SPACE);
140139
return false;
141140
}
142141

143142
#ifdef ATOMIC_FS_UPDATE
144143
//address of the end of the space available for update
145-
uintptr_t updateEndAddress = (uintptr_t)&_FS_start - 0x40200000;
144+
uintptr_t updateEndAddress = FS_start - 0x40200000;
146145

147146
updateStartAddress = (updateEndAddress > roundedSize)? (updateEndAddress - roundedSize) : 0;
148147

@@ -151,7 +150,7 @@ bool UpdaterClass::begin(size_t size, int command, int ledPin, uint8_t ledOn) {
151150
return false;
152151
}
153152
#else
154-
updateStartAddress = (uintptr_t)&_FS_start - 0x40200000;
153+
updateStartAddress = FS_start - 0x40200000;
155154
#endif
156155
}
157156
else {
@@ -314,7 +313,7 @@ bool UpdaterClass::end(bool evenIfRemaining){
314313
eboot_command ebcmd;
315314
ebcmd.action = ACTION_COPY_RAW;
316315
ebcmd.args[0] = _startAddress;
317-
ebcmd.args[1] = (uintptr_t)&_FS_start - 0x40200000;
316+
ebcmd.args[1] = FS_start - 0x40200000;
318317
ebcmd.args[2] = _size;
319318
eboot_command_write(&ebcmd);
320319
#endif
@@ -460,6 +459,9 @@ bool UpdaterClass::_verifyEnd() {
460459
return false;
461460
}
462461

462+
// it makes no sense to check flash size in auto flash mode
463+
// (sketch size would have to be set in bin header, instead of flash size)
464+
#if !FLASH_MAP_SUPPORT
463465
uint32_t bin_flash_size = ESP.magicFlashChipSize((buf[3] & 0xf0) >> 4);
464466

465467
// check if new bin fits to SPI flash
@@ -468,6 +470,7 @@ bool UpdaterClass::_verifyEnd() {
468470
_setError(UPDATE_ERROR_NEW_FLASH_CONFIG);
469471
return false;
470472
}
473+
#endif
471474

472475
return true;
473476
} else if(_command == U_FS) {

cores/esp8266/core_esp8266_main.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,12 @@ extern "C" void __disableWiFiAtBootTime (void)
393393
wifi_fpm_do_sleep(0xFFFFFFF);
394394
}
395395

396+
#if FLASH_MAP_SUPPORT
397+
#include "flash_hal.h"
398+
extern "C" void flashinit (void);
399+
uint32_t __flashindex;
400+
#endif
401+
396402
extern "C" void user_init(void) {
397403
struct rst_info *rtc_info_ptr = system_get_rst_info();
398404
memcpy((void *) &resetInfo, (void *) rtc_info_ptr, sizeof(resetInfo));
@@ -421,6 +427,9 @@ extern "C" void user_init(void) {
421427

422428
#if defined(MMU_IRAM_HEAP)
423429
umm_init_iram();
430+
#endif
431+
#if FLASH_MAP_SUPPORT
432+
flashinit();
424433
#endif
425434
preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
426435
__disableWiFiAtBootTime(); // default weak function disables WiFi

cores/esp8266/flash_hal.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,13 @@ int32_t flash_hal_erase(uint32_t addr, uint32_t size) {
6868
}
6969
return FLASH_HAL_OK;
7070
}
71+
72+
#if FLASH_MAP_SUPPORT
73+
74+
// default weak configuration:
75+
FLASH_MAP_SETUP_CONFIG_ATTR(__attribute__((weak)), FLASH_MAP_OTA_FS)
76+
77+
// can be overridden by user with:
78+
//FLASH_MAP_SETUP_CONFIG(FLASH_MAP_some_configuration)
79+
80+
#endif

cores/esp8266/flash_hal.h

+54-10
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,58 @@
2424
License along with this library; if not, write to the Free Software
2525
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2626
*/
27-
#ifdef ARDUINO
28-
extern "C" uint32_t _FS_start;
29-
extern "C" uint32_t _FS_end;
30-
extern "C" uint32_t _FS_page;
31-
extern "C" uint32_t _FS_block;
32-
33-
#define FS_PHYS_ADDR ((uint32_t) (&_FS_start) - 0x40200000)
34-
#define FS_PHYS_SIZE ((uint32_t) (&_FS_end) - (uint32_t) (&_FS_start))
35-
#define FS_PHYS_PAGE ((uint32_t) &_FS_page)
36-
#define FS_PHYS_BLOCK ((uint32_t) &_FS_block)
27+
28+
#ifdef __cplusplus
29+
extern "C" {
3730
#endif
3831

32+
#if FLASH_MAP_SUPPORT
33+
#include <FlashMap.h>
34+
35+
extern uint32_t spi_flash_get_id (void); // <user_interface.h>
36+
extern void flashinit(void);
37+
extern uint32_t __flashindex;
38+
extern const flash_map_s __flashdesc[];
39+
40+
#define FLASH_MAP_SETUP_CONFIG(conf) FLASH_MAP_SETUP_CONFIG_ATTR(,conf)
41+
#define FLASH_MAP_SETUP_CONFIG_ATTR(attr, conf...) \
42+
const flash_map_s __flashdesc[] PROGMEM = conf; \
43+
void flashinit (void) attr; \
44+
void flashinit (void) \
45+
{ \
46+
uint32_t flash_chip_size_kb = 1 << (((spi_flash_get_id() >> 16) & 0xff) - 10); \
47+
for (__flashindex = 0; __flashindex < sizeof(__flashdesc) / sizeof(__flashdesc[0]); __flashindex++) \
48+
if (__flashdesc[__flashindex].flash_size_kb == flash_chip_size_kb) \
49+
return; \
50+
panic(); /* configuration not found */ \
51+
}
52+
53+
#define EEPROM_start (__flashdesc[__flashindex].eeprom_start)
54+
#define FS_start (__flashdesc[__flashindex].fs_start)
55+
#define FS_end (__flashdesc[__flashindex].fs_end)
56+
#define FS_block (__flashdesc[__flashindex].fs_block_size)
57+
#define FS_page (__flashdesc[__flashindex].fs_page_size)
58+
59+
#else // !FLASH_MAP_SUPPORT
60+
61+
extern uint32_t _FS_start;
62+
extern uint32_t _FS_end;
63+
extern uint32_t _FS_page;
64+
extern uint32_t _FS_block;
65+
extern uint32_t _EEPROM_start;
66+
#define EEPROM_start ((uint32_t)&_EEPROM_start)
67+
#define FS_start ((uint32_t)&_FS_start)
68+
#define FS_end ((uint32_t)&_FS_end)
69+
#define FS_page ((uint32_t)&_FS_page)
70+
#define FS_block ((uint32_t)&_FS_block)
71+
72+
#endif // FLASH_MAP_SUPPORT
73+
74+
#define FS_PHYS_ADDR ((uint32_t)FS_start - 0x40200000)
75+
#define FS_PHYS_SIZE ((uint32_t)(FS_end - FS_start))
76+
#define FS_PHYS_PAGE ((uint32_t)FS_page)
77+
#define FS_PHYS_BLOCK ((uint32_t)FS_block)
78+
3979
// Return values of the following functions
4080
#define FLASH_HAL_OK (0)
4181
#define FLASH_HAL_READ_ERROR (-1)
@@ -46,4 +86,8 @@ extern int32_t flash_hal_write(uint32_t addr, uint32_t size, const uint8_t *src)
4686
extern int32_t flash_hal_erase(uint32_t addr, uint32_t size);
4787
extern int32_t flash_hal_read(uint32_t addr, uint32_t size, uint8_t *dst);
4888

89+
#ifdef __cplusplus
90+
} // extern "C"
91+
#endif
92+
4993
#endif // !defined(flash_hal_h)

doc/faq/readme.rst

+5
Original file line numberDiff line numberDiff line change
@@ -186,3 +186,8 @@ indeed off at boot and is powered on only when starting to be used with the
186186
regular API.
187187

188188
Read more at `former WiFi persistent mode <../esp8266wifi/generic-class.rst#persistent>`__.
189+
190+
How to resolve "undefined reference to ``flashinit`'" error ?
191+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
192+
193+
Please read `flash layout <../filesystem.rst>`__ documentation entry.

0 commit comments

Comments
 (0)