Skip to content

Commit 1dccc03

Browse files
mhightower83hasenradball
authored andcommitted
Resolve flash address issues with SDK v3.0.0 (esp8266#8755)
* Reslove flash address issues with SDK v3.0.0 Fix EEPROM vs RF_CAL flash address conflict. The EEPROM address and RF_CAL address were the same. Add support for Flash size: "Mapping defined by Hardware and Sketch" Change at_partition_table static from dynamic to static. * Cleanup and improve comments * Improve flash size and partition error reporting/indication Changed set_pll() to mmu_set_pll() and made available for debug builds and other settings where required. Provide more checks and feedback in the debug builds and trim code for production. * Now supports FLASH_MAP_SUPPORT with SDKs v3.0 RF_CAL and system_parameter always occupy the last 5 sectors of flash memory. * cleanup and refactoring comment cleanup * Add more build issolation when including flash_hal.h * Improve details for autoconfig fail. * requested changes
1 parent ea11c88 commit 1dccc03

File tree

5 files changed

+284
-97
lines changed

5 files changed

+284
-97
lines changed

cores/esp8266/core_esp8266_main.cpp

+212-59
Original file line numberDiff line numberDiff line change
@@ -400,79 +400,230 @@ extern "C" void __disableWiFiAtBootTime (void)
400400

401401
#if FLASH_MAP_SUPPORT
402402
#include "flash_hal.h"
403-
extern "C" void flashinit (void);
403+
extern "C" bool flashinit (void);
404+
#if (NONOSDK >= (0x30000))
405+
uint32_t __flashindex __attribute__((section(".noinit")));
406+
#else
404407
uint32_t __flashindex;
405408
#endif
409+
#endif
406410

407411
#if (NONOSDK >= (0x30000))
412+
#undef ETS_PRINTF
413+
#define ETS_PRINTF(...) ets_uart_printf(__VA_ARGS__)
414+
extern "C" uint8_t uart_rx_one_char_block();
415+
416+
#if ! FLASH_MAP_SUPPORT
417+
#include "flash_hal.h"
418+
#endif
408419

409420
extern "C" void ICACHE_FLASH_ATTR user_pre_init(void)
410421
{
411-
uint32_t rf_cal = 0;
422+
const char *flash_map_str = NULL;
423+
const char *chip_sz_str = NULL;
424+
const char *table_regist_str = NULL;
425+
[[maybe_unused]] uint32_t ld_config_chip_size = 0;
426+
uint32_t flash_size = 0;
412427
uint32_t phy_data = 0;
428+
uint32_t rf_cal = 0;
413429
uint32_t system_parameter = 0;
414-
415-
switch (system_get_flash_size_map())
416-
{
417-
case FLASH_SIZE_2M:
418-
rf_cal = 0x3b000;
419-
phy_data = 0x3c000;
420-
system_parameter = 0x3d000;
421-
break;
422-
case FLASH_SIZE_4M_MAP_256_256:
423-
rf_cal = 0x7b000;
424-
phy_data = 0x7c000;
425-
system_parameter = 0x7d000;
426-
break;
427-
case FLASH_SIZE_8M_MAP_512_512:
428-
rf_cal = 0xfb000;
429-
phy_data = 0xfc000;
430-
system_parameter = 0xfd000;
431-
break;
432-
case FLASH_SIZE_16M_MAP_512_512:
433-
case FLASH_SIZE_16M_MAP_1024_1024:
434-
rf_cal = 0x1fb000;
435-
phy_data = 0x1fc000;
436-
system_parameter = 0x1fd000;
437-
break;
438-
case FLASH_SIZE_32M_MAP_512_512:
439-
case FLASH_SIZE_32M_MAP_1024_1024:
440-
case FLASH_SIZE_32M_MAP_2048_2048:
441-
rf_cal = 0x3fb000;
442-
phy_data = 0x3fc000;
443-
system_parameter = 0x3fd000;
444-
break;
445-
case FLASH_SIZE_64M_MAP_1024_1024:
446-
rf_cal = 0x7fb000;
447-
phy_data = 0x7fc000;
448-
system_parameter = 0x7fd000;
449-
break;
450-
case FLASH_SIZE_128M_MAP_1024_1024:
451-
rf_cal = 0xffb000;
452-
phy_data = 0xffc000;
453-
system_parameter = 0xffd000;
454-
break;
430+
[[maybe_unused]] const partition_item_t *_at_partition_table = NULL;
431+
size_t _at_partition_table_sz = 0;
432+
433+
do {
434+
#if FLASH_MAP_SUPPORT
435+
if (!flashinit()) {
436+
flash_map_str = PSTR("flashinit: flash size missing from FLASH_MAP table\n");
437+
continue;
438+
}
439+
#endif
440+
441+
// For SDKs 3.0.0 and later, place phy_data readonly overlay on top of
442+
// the EEPROM address. For older SDKs without a system partition, RF_CAL
443+
// and PHY_DATA shared the same flash segment.
444+
//
445+
// For the Arduino ESP8266 core, the sectors for "EEPROM = size -
446+
// 0x5000", "RF_CAL = size - 0x4000", and "SYSTEM_PARAMETER = size -
447+
// 0x3000" are positioned in the last five sectors of flash memory.
448+
// PHY_INIT_DATA is special. It is a one time read of 128 bytes of data
449+
// that is provided by a spoofed flash read.
450+
#if FLASH_MAP_SUPPORT
451+
flash_size = __flashdesc[__flashindex].flash_size_kb * 1024u;
452+
#else
453+
// flashchip->chip_size is updated by the SDK. The size is based on the
454+
// value patched into the .bin header by esptool.
455+
// system_get_flash_size_map() returns that patched value.
456+
flash_size = flashchip->chip_size;
457+
#endif
458+
459+
// For all configurations, place RF_CAL and system_parameter in the
460+
// last 4 sectors of the flash chip.
461+
rf_cal = flash_size - 0x4000u;
462+
system_parameter = flash_size - 0x3000u;
463+
464+
// The system_partition_table_regist will not allow partitions to
465+
// overlap. EEPROM_start is a good choice for phy_data overlay. The SDK
466+
// does not need to know about EEPROM_start. So we can omit it from the
467+
// table. The real EEPROM access is after user_init() begins long after
468+
// the PHY_DATA read. So it should be safe from conflicts.
469+
phy_data = EEPROM_start - 0x40200000u;
470+
471+
// For SDKs 3.0 builds, "sdk3_begin_phy_data_spoof and
472+
// user_rf_cal_sector_set" starts and stops the spoofing logic in
473+
// `core_esp8266_phy.cpp`.
474+
extern void sdk3_begin_phy_data_spoof();
475+
sdk3_begin_phy_data_spoof();
476+
477+
ld_config_chip_size = phy_data + 4096 * 5;
478+
479+
// -DALLOW_SMALL_FLASH_SIZE=1
480+
// Allows for small flash-size builds targeted for multiple devices,
481+
// commonly IoT, of varying flash sizes.
482+
#if !defined(FLASH_MAP_SUPPORT) && !defined(ALLOW_SMALL_FLASH_SIZE)
483+
// Note, system_partition_table_regist will only catch when the build
484+
// flash size value set by the Arduino IDE Tools menu is larger than
485+
// the firmware image value detected and updated on the fly by esptool.
486+
if (flashchip->chip_size != ld_config_chip_size) {
487+
// Stop to avoid possible stored flash data corruption. This
488+
// mismatch will not occur with flash size selection "Mapping
489+
// defined by Hardware and Sketch".
490+
chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n");
491+
continue;
492+
}
493+
#elif defined(ALLOW_SMALL_FLASH_SIZE) && !defined(FLASH_MAP_SUPPORT)
494+
// Note, while EEPROM is confined to a smaller flash size, we are still
495+
// placing RF_CAL and SYSTEM_PARAMETER at the end of flash. To prevent
496+
// this, esptool or its equal needs to not update the flash size in the
497+
// .bin image.
498+
#endif
499+
500+
#if FLASH_MAP_SUPPORT && defined(DEBUG_ESP_PORT)
501+
// I don't think this will ever fail. Everything traces back to the results of spi_flash_get_id()
502+
if (flash_size != flashchip->chip_size) {
503+
chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n");
504+
continue;
505+
}
506+
#endif
507+
508+
// All the examples I find, show the partition table in the global address space.
509+
static const partition_item_t at_partition_table[] =
510+
{
511+
{ SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, // type 5
512+
{ SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, // type 4
513+
{ SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, // type 6
514+
};
515+
_at_partition_table = at_partition_table;
516+
_at_partition_table_sz = std::size(at_partition_table);
517+
// SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report
518+
// on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see
519+
// anything we can do about this. Other than maybe turning off os_print.
520+
if (!system_partition_table_regist(at_partition_table, _at_partition_table_sz, system_get_flash_size_map())) {
521+
table_regist_str = PSTR("System partition table registration failed!\n");
522+
continue;
523+
}
524+
} while(false);
525+
526+
if (chip_sz_str || flash_map_str || table_regist_str) {
527+
// user_pre_init() is called very early in the SDK startup. When called,
528+
// the PLL CPU clock calibration hasn't not run. Since we are failing, the
529+
// calibration will never complete. And the process will repeat over and
530+
// over. The effective data rate will always be 74880 bps. If we had a
531+
// successful boot, the effective data rate would be 115200 on a restart
532+
// or HWDT. This hack relies on the CPU clock calibration never having
533+
// completed. This assumes we are starting from a hard reset.
534+
535+
// A possible exception would be a soft reset after flashing. In which
536+
// case the message will not be readable until after a hard reset or
537+
// power cycle.
538+
539+
// After flashing, the Arduino Serial Monitor needs a moment to
540+
// reconnect. This also allows time for the FIFO to clear and the host
541+
// serial port to clear any framing errors.
542+
ets_delay_us(200u * 1000u); // For an uncalibrated CPU Clock, this is close enough.
543+
544+
#if !defined(F_CRYSTAL)
545+
#define F_CRYSTAL 26000000
546+
#endif
547+
// For print messages to be readable, the UART clock rate is based on the
548+
// precalibration rate.
549+
if (F_CRYSTAL != 40000000) {
550+
uart_div_modify(0, F_CRYSTAL * 2 / 115200);
551+
ets_delay_us(150);
552+
}
553+
do {
554+
ETS_PRINTF("\n\n");
555+
// Because SDK v3.0.x always has a non-32-bit wide exception handler
556+
// installed, we can use PROGMEM strings with Boot ROM print functions.
557+
#if defined(DEBUG_ESP_CORE) || defined(DEBUG_ESP_PORT) // DEBUG_ESP_CORE => verbose
558+
#if FLASH_MAP_SUPPORT
559+
if (flash_map_str) {
560+
ETS_PRINTF(flash_map_str);
561+
#if defined(DEBUG_ESP_CORE)
562+
size_t num = __flashindex; // On failure __flashindex is the size of __flashdesc[]; :/
563+
ETS_PRINTF(PSTR("Table of __flashdesc[%u].flash_size_kb entries converted to bytes:\n"), num);
564+
for (size_t i = 0; i < num; i++) {
565+
uint32_t size = __flashdesc[i].flash_size_kb << 10;
566+
ETS_PRINTF(PSTR(" [%02u] 0x%08X %8u\n"), i, size, size);
567+
}
568+
#endif
569+
ETS_PRINTF(PSTR("Reference info:\n"));
570+
uint32_t flash_chip_size = 1 << ((spi_flash_get_id() >> 16) & 0xff);
571+
ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("fn(spi_flash_get_id())"), flash_chip_size, flash_chip_size);
572+
ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("bin_chip_size"), flashchip->chip_size, flashchip->chip_size);
573+
} else
574+
#endif
575+
if (chip_sz_str) {
576+
ETS_PRINTF(chip_sz_str);
577+
} else
578+
if (table_regist_str) {
579+
ETS_PRINTF(table_regist_str);
580+
// (printing now works) repeat ...regist error messages
581+
system_partition_table_regist(_at_partition_table, _at_partition_table_sz, system_get_flash_size_map());
582+
}
583+
if (chip_sz_str || table_regist_str) {
584+
ETS_PRINTF(PSTR("Reference info:\n"));
585+
#if FLASH_MAP_SUPPORT
586+
ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("fn(...ex].flash_size_kb)"), flash_size, flash_size);
587+
uint32_t flash_chip_size = 1 << ((spi_flash_get_id() >> 16) & 0xff);
588+
ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("fn(spi_flash_get_id())"), flash_chip_size, flash_chip_size);
589+
ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("bin_chip_size"), flashchip->chip_size, flashchip->chip_size);
590+
#else
591+
ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("config_flash_size"), ld_config_chip_size, ld_config_chip_size);
592+
ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("bin_chip_size"), flashchip->chip_size, flashchip->chip_size);
593+
#endif
594+
#if defined(DEBUG_ESP_CORE)
595+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("PHY_DATA"), phy_data);
596+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("RF_CAL"), rf_cal);
597+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter);
598+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start);
599+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_start"), FS_start);
600+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_end"), FS_end);
601+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_page"), FS_page);
602+
ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_block"), FS_block);
603+
#endif
604+
}
605+
#else
606+
if (flash_map_str) {
607+
ETS_PRINTF(flash_map_str);
608+
} else
609+
if (chip_sz_str) {
610+
ETS_PRINTF(chip_sz_str);
611+
} else
612+
if (table_regist_str) {
613+
ETS_PRINTF(table_regist_str);
614+
}
615+
#endif
616+
uart_rx_one_char_block(); // Someone said hello - repeat message
617+
} while(true);
455618
}
456-
457-
extern uint32_t user_rf_cal_sector_set(void);
458-
user_rf_cal_sector_set();
459-
460-
const partition_item_t at_partition_table[] =
461-
{
462-
{ SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 },
463-
{ SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 },
464-
{ SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 },
465-
};
466-
system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map());
467619
}
468-
469-
#endif
620+
#endif // #if (NONOSDK >= (0x30000))
470621

471622
extern "C" void user_init(void) {
472623

473624
#if (NONOSDK >= (0x30000))
474625
extern void user_rf_pre_init();
475-
user_rf_pre_init();
626+
user_rf_pre_init(); // Stop spoofing logic
476627
#endif
477628

478629
struct rst_info *rtc_info_ptr = system_get_rst_info();
@@ -503,8 +654,10 @@ extern "C" void user_init(void) {
503654
#if defined(MMU_IRAM_HEAP)
504655
umm_init_iram();
505656
#endif
506-
#if FLASH_MAP_SUPPORT
507-
flashinit();
657+
#if FLASH_MAP_SUPPORT && (NONOSDK < 0x30000)
658+
if (!flashinit()) {
659+
panic();
660+
}
508661
#endif
509662
preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
510663
__disableWiFiAtBootTime(); // default weak function disables WiFi

cores/esp8266/core_esp8266_phy.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,17 @@ extern int __real_spi_flash_read(uint32_t addr, uint32_t* dst, size_t size);
303303
extern int IRAM_ATTR __wrap_spi_flash_read(uint32_t addr, uint32_t* dst, size_t size);
304304
extern int __get_adc_mode();
305305

306+
/*
307+
Verified that the wide filtering of all 128 byte flash reads during
308+
spoof_init_data continues to be safe for SDK 3.0.5
309+
From start call to user_pre_init() to stop call with user_rf_pre_init().
310+
311+
flash read count during spoof_init_data 4
312+
flash read 0x00000 8 // system_get_flash_size_map()
313+
flash read 0x00000 4 // system_partition_table_regist()
314+
flash read 0xFB000 128 // PHY_DATA (EEPROM address space)
315+
flash read 0xFC000 628 // RC_CAL
316+
*/
306317
extern int IRAM_ATTR __wrap_spi_flash_read(uint32_t addr, uint32_t* dst, size_t size)
307318
{
308319
if (!spoof_init_data || size != 128) {
@@ -332,11 +343,18 @@ extern void __run_user_rf_pre_init(void)
332343
return; // default do noting
333344
}
334345

346+
#if (NONOSDK >= (0x30000))
347+
void sdk3_begin_phy_data_spoof(void)
348+
{
349+
spoof_init_data = true;
350+
}
351+
#else
335352
uint32_t user_rf_cal_sector_set(void)
336353
{
337354
spoof_init_data = true;
338355
return flashchip->chip_size/SPI_FLASH_SEC_SIZE - 4;
339356
}
357+
#endif
340358

341359
void user_rf_pre_init()
342360
{

cores/esp8266/flash_hal.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,21 @@ extern "C" {
3333
#include <FlashMap.h>
3434

3535
extern uint32_t spi_flash_get_id (void); // <user_interface.h>
36-
extern void flashinit(void);
36+
extern bool flashinit(void);
3737
extern uint32_t __flashindex;
3838
extern const flash_map_s __flashdesc[];
3939

4040
#define FLASH_MAP_SETUP_CONFIG(conf) FLASH_MAP_SETUP_CONFIG_ATTR(,conf)
4141
#define FLASH_MAP_SETUP_CONFIG_ATTR(attr, conf...) \
4242
const flash_map_s __flashdesc[] PROGMEM = conf; \
43-
void flashinit (void) attr; \
44-
void flashinit (void) \
43+
bool flashinit (void) attr; \
44+
bool flashinit (void) \
4545
{ \
4646
uint32_t flash_chip_size_kb = 1 << (((spi_flash_get_id() >> 16) & 0xff) - 10); \
4747
for (__flashindex = 0; __flashindex < sizeof(__flashdesc) / sizeof(__flashdesc[0]); __flashindex++) \
4848
if (__flashdesc[__flashindex].flash_size_kb == flash_chip_size_kb) \
49-
return; \
50-
panic(); /* configuration not found */ \
49+
return true; \
50+
return false; /* configuration not found */ \
5151
}
5252

5353
#define EEPROM_start (__flashdesc[__flashindex].eeprom_start)

0 commit comments

Comments
 (0)