From 8f3a2b1d0a5a6a76eb14d5ae5e99dc9e3f092f83 Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Sun, 11 Dec 2022 18:33:40 -0800 Subject: [PATCH 1/8] 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. --- cores/esp8266/core_esp8266_main.cpp | 107 +++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 0b0c4ddc75..dbfe7b1bc2 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -39,6 +39,7 @@ extern "C" { #include #include #include "core_esp8266_vm.h" +#include "flash_hal.h" #define LOOP_TASK_PRIORITY 1 #define LOOP_QUEUE_SIZE 1 @@ -406,6 +407,7 @@ uint32_t __flashindex; #if (NONOSDK >= (0x30000)) +#if 0 extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) { uint32_t rf_cal = 0; @@ -457,22 +459,121 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) extern uint32_t user_rf_cal_sector_set(void); user_rf_cal_sector_set(); - const partition_item_t at_partition_table[] = + static partition_item_t at_partition_table[] = { { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, }; +#ifdef DEV_DEBUG_PRINT + extern void set_pll(void); + set_pll(); // fix printing at 115200 bps + ets_uart_printf("\n\nConfig info referenced for system partition table registration:\n"); + ets_uart_printf(" %-17s 0x%08X\n", "PHY_DATA", phy_data); + ets_uart_printf(" %-17s 0x%08X\n", "RF_CAL", rf_cal); + ets_uart_printf(" %-17s 0x%08X\n", "EEPROM Address", EEPROM_start - 0x40200000u); + ets_uart_printf(" %-17s 0x%08X\n", "SYSTEM_PARAMETER", system_parameter); + ets_uart_printf(" %-17s 0x%08X %u\n", "chip_size", flashchip->chip_size, flashchip->chip_size); + ets_uart_printf(" %-17s 0x%08X\n", "EEPROM_start", EEPROM_start); + ets_uart_printf(" %-17s 0x%08X\n", "FS_start", FS_start); + ets_uart_printf(" %-17s 0x%08X\n", "FS_end", FS_end); + ets_uart_printf(" %-17s 0x%08X\n", "FS_page", FS_page); + ets_uart_printf(" %-17s 0x%08X\n", "FS_block", FS_block); + if (!system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) + { + ets_uart_printf("\nSystem partition table registration failed!\n"); + panic(); + } +#else system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()); +#endif } +#else +extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) +{ + // For SDKs 3.0.0 and later, place phy_data readonly overlay on top of the + // EEPROM address. For older SDKs without a system partition, RF_CAL and + // PHY_DATA shared the same flash segment. + uint32_t phy_data = EEPROM_start - 0x40200000u; + uint32_t rf_cal = phy_data + 0x1000; + uint32_t system_parameter = rf_cal + 0x1000; + + // Examples show partition table in global address space + static partition_item_t at_partition_table[] = + { + { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, + { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, + { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, + }; + + // For SDKs v3.0.0 and later, the functions `uint32 + // user_rf_cal_sector_set(void)` and `void user_rf_pre_init(void)` are not + // called by the SDK. We need these called to start and stop spoofing logic + // for flash read of PHY Init data. + extern uint32_t user_rf_cal_sector_set(void); + user_rf_cal_sector_set(); // Start spoofing logic + +#ifdef DEV_DEBUG_PRINT + extern void set_pll(void); + set_pll(); // fix printing for 115200 bps + ets_uart_printf("\n\nConfig info referenced for system partition table registration:\n"); + ets_uart_printf(" %-18s 0x%08X\n", "PHY_DATA", phy_data); + ets_uart_printf(" %-18s 0x%08X\n", "RF_CAL", rf_cal); + ets_uart_printf(" %-18s 0x%08X\n", "SYSTEM_PARAMETER", system_parameter); + ets_uart_printf(" %-18s 0x%08X %u\n", "ota_1_sz", user_bin_sz, user_bin_sz); + ets_uart_printf(" %-18s 0x%08X %u\n", "chip_size", flashchip->chip_size, flashchip->chip_size); + ets_uart_printf(" %-18s 0x%08X\n", "EEPROM_start", EEPROM_start); + ets_uart_printf(" %-18s 0x%08X\n", "FS_start", FS_start); + ets_uart_printf(" %-18s 0x%08X\n", "FS_end", FS_end); + ets_uart_printf(" %-18s 0x%08X\n", "FS_page", FS_page); + ets_uart_printf(" %-18s 0x%08X\n", "FS_block", FS_block); + uint32_t configured_chip_size = system_parameter + 4096 * 3; + if (flashchip->chip_size != configured_chip_size) + { + ets_uart_printf("\nMissmatch between actual(%u) vs configured(%u) flash size\n", flashchip->chip_size, configured_chip_size); + panic(); + } + if (!system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) + { + ets_uart_printf("\nSystem partition table registration failed!\n"); + panic(); + } + +#else +//+ restore conditional for final or remove - to be discussed +#if 1 // defined(FLASH_MAP_SUPPORT) && defined(DEBUG_ESP_CORE) + uint32_t configured_chip_size = system_parameter + 4096 * 3; + // flashchip->chip_size is updated by the SDK. The size is based on the + // value patched into the .bin header by esptool. + // system_get_flash_size_map() returns that patched value. + if (flashchip->chip_size != configured_chip_size) + { + // For this message and postmortem to be readable, the console speed may + // need to be 74880 bps. + ets_uart_printf("\nMissmatch between actual(%u) vs configured(%u) flash size\n", flashchip->chip_size, configured_chip_size); + // Full stop to avoid possible stored flash data corruption. This + // missmatch does not occur with flash size selection "Mapping defined by + // Hardware and Sketch". + panic(); + } +#endif + + system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()); + // No test for failure !!! + // How to handle failure ??? + // It appears the PLL calibration for CPU clock has not run. + // Postmortem will be unreadable. +#endif +} +#endif #endif extern "C" void user_init(void) { #if (NONOSDK >= (0x30000)) extern void user_rf_pre_init(); - user_rf_pre_init(); + user_rf_pre_init(); // Stop spoofing logic #endif struct rst_info *rtc_info_ptr = system_get_rst_info(); @@ -496,7 +597,7 @@ extern "C" void user_init(void) { install_vm_exception_handler(); #endif -#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) +#if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1))) install_non32xfer_exception_handler(); #endif From 0bcbec760b2aa30ac2bbc1966ec60ce4192f0c71 Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:25:09 -0800 Subject: [PATCH 2/8] Cleanup and improve comments --- cores/esp8266/core_esp8266_main.cpp | 166 ++++++++-------------------- 1 file changed, 46 insertions(+), 120 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index dbfe7b1bc2..cad78b6cb2 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -407,105 +407,30 @@ uint32_t __flashindex; #if (NONOSDK >= (0x30000)) -#if 0 -extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) -{ - uint32_t rf_cal = 0; - uint32_t phy_data = 0; - uint32_t system_parameter = 0; - - switch (system_get_flash_size_map()) - { - case FLASH_SIZE_2M: - rf_cal = 0x3b000; - phy_data = 0x3c000; - system_parameter = 0x3d000; - break; - case FLASH_SIZE_4M_MAP_256_256: - rf_cal = 0x7b000; - phy_data = 0x7c000; - system_parameter = 0x7d000; - break; - case FLASH_SIZE_8M_MAP_512_512: - rf_cal = 0xfb000; - phy_data = 0xfc000; - system_parameter = 0xfd000; - break; - case FLASH_SIZE_16M_MAP_512_512: - case FLASH_SIZE_16M_MAP_1024_1024: - rf_cal = 0x1fb000; - phy_data = 0x1fc000; - system_parameter = 0x1fd000; - break; - case FLASH_SIZE_32M_MAP_512_512: - case FLASH_SIZE_32M_MAP_1024_1024: - case FLASH_SIZE_32M_MAP_2048_2048: - rf_cal = 0x3fb000; - phy_data = 0x3fc000; - system_parameter = 0x3fd000; - break; - case FLASH_SIZE_64M_MAP_1024_1024: - rf_cal = 0x7fb000; - phy_data = 0x7fc000; - system_parameter = 0x7fd000; - break; - case FLASH_SIZE_128M_MAP_1024_1024: - rf_cal = 0xffb000; - phy_data = 0xffc000; - system_parameter = 0xffd000; - break; - } - - extern uint32_t user_rf_cal_sector_set(void); - user_rf_cal_sector_set(); - - static partition_item_t at_partition_table[] = - { - { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, - { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, - { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, - }; -#ifdef DEV_DEBUG_PRINT - extern void set_pll(void); - set_pll(); // fix printing at 115200 bps - ets_uart_printf("\n\nConfig info referenced for system partition table registration:\n"); - ets_uart_printf(" %-17s 0x%08X\n", "PHY_DATA", phy_data); - ets_uart_printf(" %-17s 0x%08X\n", "RF_CAL", rf_cal); - ets_uart_printf(" %-17s 0x%08X\n", "EEPROM Address", EEPROM_start - 0x40200000u); - ets_uart_printf(" %-17s 0x%08X\n", "SYSTEM_PARAMETER", system_parameter); - ets_uart_printf(" %-17s 0x%08X %u\n", "chip_size", flashchip->chip_size, flashchip->chip_size); - ets_uart_printf(" %-17s 0x%08X\n", "EEPROM_start", EEPROM_start); - ets_uart_printf(" %-17s 0x%08X\n", "FS_start", FS_start); - ets_uart_printf(" %-17s 0x%08X\n", "FS_end", FS_end); - ets_uart_printf(" %-17s 0x%08X\n", "FS_page", FS_page); - ets_uart_printf(" %-17s 0x%08X\n", "FS_block", FS_block); - if (!system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) - { - ets_uart_printf("\nSystem partition table registration failed!\n"); - panic(); - } -#else - system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()); -#endif -} - -#else extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) { // For SDKs 3.0.0 and later, place phy_data readonly overlay on top of the // EEPROM address. For older SDKs without a system partition, RF_CAL and // PHY_DATA shared the same flash segment. + // + // For the Arduino ESP8266 core, the sectors for "EEPROM +0x1000", "RF_CAL + // +0x1000", and "SYSTEM_PARAMETERs +0x3000" are positioned in the last five + // sectors of flash memory. PHY_INIT_DATA is special. It is a one time read + // of 128 bytes of data that is provided by a one time spoofed flash read. uint32_t phy_data = EEPROM_start - 0x40200000u; uint32_t rf_cal = phy_data + 0x1000; uint32_t system_parameter = rf_cal + 0x1000; - // Examples show partition table in global address space + // All the examples I find, show the partition table in the global address space. static partition_item_t at_partition_table[] = { { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, }; + // SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report + // on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see + // anything we can do about this. Other than maybe turning off os_print. // For SDKs v3.0.0 and later, the functions `uint32 // user_rf_cal_sector_set(void)` and `void user_rf_pre_init(void)` are not @@ -515,34 +440,20 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) user_rf_cal_sector_set(); // Start spoofing logic #ifdef DEV_DEBUG_PRINT + // Deeper debugging maybe delete this block later extern void set_pll(void); set_pll(); // fix printing for 115200 bps - ets_uart_printf("\n\nConfig info referenced for system partition table registration:\n"); - ets_uart_printf(" %-18s 0x%08X\n", "PHY_DATA", phy_data); - ets_uart_printf(" %-18s 0x%08X\n", "RF_CAL", rf_cal); - ets_uart_printf(" %-18s 0x%08X\n", "SYSTEM_PARAMETER", system_parameter); - ets_uart_printf(" %-18s 0x%08X %u\n", "ota_1_sz", user_bin_sz, user_bin_sz); - ets_uart_printf(" %-18s 0x%08X %u\n", "chip_size", flashchip->chip_size, flashchip->chip_size); - ets_uart_printf(" %-18s 0x%08X\n", "EEPROM_start", EEPROM_start); - ets_uart_printf(" %-18s 0x%08X\n", "FS_start", FS_start); - ets_uart_printf(" %-18s 0x%08X\n", "FS_end", FS_end); - ets_uart_printf(" %-18s 0x%08X\n", "FS_page", FS_page); - ets_uart_printf(" %-18s 0x%08X\n", "FS_block", FS_block); - uint32_t configured_chip_size = system_parameter + 4096 * 3; - if (flashchip->chip_size != configured_chip_size) - { - ets_uart_printf("\nMissmatch between actual(%u) vs configured(%u) flash size\n", flashchip->chip_size, configured_chip_size); - panic(); - } - if (!system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) - { - ets_uart_printf("\nSystem partition table registration failed!\n"); - panic(); - } - -#else -//+ restore conditional for final or remove - to be discussed -#if 1 // defined(FLASH_MAP_SUPPORT) && defined(DEBUG_ESP_CORE) + ets_uart_printf(PSTR("\n\nConfig info referenced for system partition table registration:\n")); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("PHY_DATA"), phy_data); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("RF_CAL"), rf_cal); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter); + ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("chip_size"), flashchip->chip_size, flashchip->chip_size); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_start"), FS_start); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_end"), FS_end); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_page"), FS_page); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_block"), FS_block); +#if !defined(FLASH_MAP_SUPPORT) uint32_t configured_chip_size = system_parameter + 4096 * 3; // flashchip->chip_size is updated by the SDK. The size is based on the // value patched into the .bin header by esptool. @@ -551,23 +462,38 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) { // For this message and postmortem to be readable, the console speed may // need to be 74880 bps. - ets_uart_printf("\nMissmatch between actual(%u) vs configured(%u) flash size\n", flashchip->chip_size, configured_chip_size); + ets_uart_printf(PSTR("\nMissmatch between actual(%u) vs configured(%u) flash size\n"), flashchip->chip_size, configured_chip_size); // Full stop to avoid possible stored flash data corruption. This // missmatch does not occur with flash size selection "Mapping defined by // Hardware and Sketch". - panic(); + abort(); } #endif - - system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()); - // No test for failure !!! - // How to handle failure ??? - // It appears the PLL calibration for CPU clock has not run. - // Postmortem will be unreadable. #endif + if (!system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) + { + // We will land here anytime the build flash size value set by the Arduino + // IDE Tools menu mismatches the firmware image value detected and updated + // on the fly by esptool. + // + // The SDKs PLL CPU clock calibration hasn't run. For this message and + // postmortem to be readable, the console speed may need to be 74880 bps. + // + // Because SDK v3.0.x always has a non-32-bit wide exception handler + // installed, we can use PROGMEM strings with Boot ROM print functions. + ets_uart_printf(PSTR("\nSystem partition table registration failed!\n")); + + //C What is the best action on failure? + //C * The above printf maybe redundant. `system_partition_table_regist` + //C appears to print specific failure messages. most of the time. + //C * Things will not get better by rebooting. + //C * Most likely the error message was not readable - mismatched console speed + //C * Expressif example do a `while(true){};` on fail. HWDT appears to be + //C off and the device freezes. + abort(); + } } -#endif -#endif +#endif // #if (NONOSDK >= (0x30000)) extern "C" void user_init(void) { From 61e4665b0c15ab2c9329e30f41b1ece20501aa0f Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Mon, 12 Dec 2022 11:56:53 -0800 Subject: [PATCH 3/8] 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. --- cores/esp8266/core_esp8266_main.cpp | 115 ++++++++++++++++------------ cores/esp8266/mmu_iram.cpp | 66 ++++++++-------- cores/esp8266/mmu_iram.h | 16 +++- 3 files changed, 117 insertions(+), 80 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index cad78b6cb2..34bd19a42c 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -407,6 +407,7 @@ uint32_t __flashindex; #if (NONOSDK >= (0x30000)) +extern "C" uint8_t uart_rx_one_char_block(); extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) { // For SDKs 3.0.0 and later, place phy_data readonly overlay on top of the @@ -418,8 +419,8 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) // sectors of flash memory. PHY_INIT_DATA is special. It is a one time read // of 128 bytes of data that is provided by a one time spoofed flash read. uint32_t phy_data = EEPROM_start - 0x40200000u; - uint32_t rf_cal = phy_data + 0x1000; - uint32_t system_parameter = rf_cal + 0x1000; + uint32_t rf_cal = phy_data + 0x1000u; + uint32_t system_parameter = rf_cal + 0x1000u; // All the examples I find, show the partition table in the global address space. static partition_item_t at_partition_table[] = @@ -439,58 +440,78 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) extern uint32_t user_rf_cal_sector_set(void); user_rf_cal_sector_set(); // Start spoofing logic -#ifdef DEV_DEBUG_PRINT - // Deeper debugging maybe delete this block later - extern void set_pll(void); - set_pll(); // fix printing for 115200 bps - ets_uart_printf(PSTR("\n\nConfig info referenced for system partition table registration:\n")); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("PHY_DATA"), phy_data); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("RF_CAL"), rf_cal); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter); - ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("chip_size"), flashchip->chip_size, flashchip->chip_size); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_start"), FS_start); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_end"), FS_end); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_page"), FS_page); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_block"), FS_block); -#if !defined(FLASH_MAP_SUPPORT) + // -DALLOW_SMALL_FLASH_SIZE=1 + // Allows for small flash-size builds targeted for multiple devices, + // commonly IoT, of varying flash sizes. + const char *chip_sz_str = NULL; +#if !defined(FLASH_MAP_SUPPORT) & defined(DEBUG_ESP_PORT) & !defined(ALLOW_SMALL_FLASH_SIZE) + // Note, system_partition_table_regist would only catch when the build flash + // size value set by the Arduino IDE Tools menu is larger than firmware + // image value detected and updated on the fly by esptool. uint32_t configured_chip_size = system_parameter + 4096 * 3; // flashchip->chip_size is updated by the SDK. The size is based on the // value patched into the .bin header by esptool. // system_get_flash_size_map() returns that patched value. - if (flashchip->chip_size != configured_chip_size) - { - // For this message and postmortem to be readable, the console speed may - // need to be 74880 bps. - ets_uart_printf(PSTR("\nMissmatch between actual(%u) vs configured(%u) flash size\n"), flashchip->chip_size, configured_chip_size); - // Full stop to avoid possible stored flash data corruption. This - // missmatch does not occur with flash size selection "Mapping defined by - // Hardware and Sketch". - abort(); + if (flashchip->chip_size != configured_chip_size) { + // Full stop to avoid possible stored flash data corruption. This + // mismatch will not occur with flash size selection "Mapping defined by + // Hardware and Sketch". + chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n\n"); } #endif + + if (chip_sz_str || !system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) { + // user_pre_init() is called very early in the SDK startup. When called, + // the PLL CPU clock calibration hasn't not run. Since we are failing, the + // calibration will never complete. And the process will repeat over and + // over. The effective data rate will always be 74880 bps. If we had a + // successful boot, the effective data rate would be 115200 on a restart + // or HWDT. This hack relies on the CPU clock calibration never having + // completed. + + // After flashing, the Arduino Serial Monitor needs a moment to reconnect. + // This also allows time for the FIFO to clear and the host serial port time + // to clear any framing errors. + ets_delay_us(200u * 1000u); // For an uncalibrated CPU Clock, this is close enough. + + #if !defined(F_CRYSTAL) + #define F_CRYSTAL 26000000 + #endif + // For print messages to be readable, the UART clock rate is based on the + // precalibration rate. + if (F_CRYSTAL != 40000000) { + uart_div_modify(0, F_CRYSTAL * 2 / 115200); + ets_delay_us(150); + } + ets_uart_printf("\n\n"); + do { + // Because SDK v3.0.x always has a non-32-bit wide exception handler + // installed, we can use PROGMEM strings with Boot ROM print functions. +#ifdef DEBUG_ESP_CORE + ets_uart_printf(PSTR("Config info referenced for system partition table registration:\n")); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("PHY_DATA"), phy_data); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("RF_CAL"), rf_cal); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter); + ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("chip_size"), flashchip->chip_size, flashchip->chip_size); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_start"), FS_start); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_end"), FS_end); + ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_page"), FS_page); + ets_uart_printf(PSTR(" %-18s 0x%08X\n\n"), PSTR("FS_block"), FS_block); #endif - if (!system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) - { - // We will land here anytime the build flash size value set by the Arduino - // IDE Tools menu mismatches the firmware image value detected and updated - // on the fly by esptool. - // - // The SDKs PLL CPU clock calibration hasn't run. For this message and - // postmortem to be readable, the console speed may need to be 74880 bps. - // - // Because SDK v3.0.x always has a non-32-bit wide exception handler - // installed, we can use PROGMEM strings with Boot ROM print functions. - ets_uart_printf(PSTR("\nSystem partition table registration failed!\n")); - - //C What is the best action on failure? - //C * The above printf maybe redundant. `system_partition_table_regist` - //C appears to print specific failure messages. most of the time. - //C * Things will not get better by rebooting. - //C * Most likely the error message was not readable - mismatched console speed - //C * Expressif example do a `while(true){};` on fail. HWDT appears to be - //C off and the device freezes. - abort(); + if (chip_sz_str) { + ets_uart_printf(chip_sz_str); + } else { +#if defined(DEBUG_ESP_CORE) | defined(DEBUG_ESP_PORT) + // Now that the UART speed is corrected and messages will + // display, run system_partition_table_regist again. + system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()); +#endif + ets_uart_printf(PSTR("System partition table registration failed!\n\n")); + } + uart_rx_one_char_block(); // Someone said hello - repeat message + } while(true); + } } #endif // #if (NONOSDK >= (0x30000)) diff --git a/cores/esp8266/mmu_iram.cpp b/cores/esp8266/mmu_iram.cpp index c54e9994c8..0193241890 100644 --- a/cores/esp8266/mmu_iram.cpp +++ b/cores/esp8266/mmu_iram.cpp @@ -122,43 +122,15 @@ void IRAM_ATTR Cache_Read_Disable(void) { } #endif -/* - * Early adjustment for CPU crystal frequency, so debug printing will work. - * This should not be left enabled all the time in Cashe_Read..., I am concerned - * that there may be unknown interference with the NONOS SDK startup. - * - * Inspired by: - * https://github.com/pvvx/esp8266web/blob/2e25559bc489487747205db2ef171d48326b32d4/app/sdklib/system/app_main.c#L581-L591 - */ -extern "C" uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add); -extern "C" void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); - -extern "C" void IRAM_ATTR set_pll(void) -{ -#if !defined(F_CRYSTAL) -#define F_CRYSTAL 26000000 -#endif - if (F_CRYSTAL != 40000000) { - // At Boot ROM(-BIOS) start, it assumes a 40MHz crystal. - // If it is not, we assume a 26MHz crystal. - // There is no support for 24MHz crustal at this time. - if(rom_i2c_readReg(103,4,1) != 136) { // 8: 40MHz, 136: 26MHz - // Assume 26MHz crystal - // soc_param0: 0: 40MHz, 1: 26MHz, 2: 24MHz - // set 80MHz PLL CPU - rom_i2c_writeReg(103,4,1,136); - rom_i2c_writeReg(103,4,2,145); - } - } -} - //C This was used to probe at different stages of boot the state of the PLL //C register. I think we can get rid of this one. +extern "C" uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add); +extern "C" void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); extern "C" void IRAM_ATTR dbg_set_pll(void) { char r103_4_1 = rom_i2c_readReg(103,4,1); char r103_4_2 = rom_i2c_readReg(103,4,2); - set_pll(); + mmu_set_pll(); ets_uart_printf("\nrom_i2c_readReg(103,4,1) == %u\n", r103_4_1); ets_uart_printf( "rom_i2c_readReg(103,4,2) == %u\n", r103_4_2); } @@ -196,6 +168,38 @@ extern void Cache_Read_Disable(void); extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v); #endif // #if (MMU_ICACHE_SIZE == 0x4000) +/* + * Early adjustment for CPU crystal frequency will allow early debug printing to + * be readable before the SDK initialization is complete. + * This should not be left enabled all the time in Cashe_Read..., I am concerned + * that there may be unknown interference with the NONOS SDK startup. + * It does low-level calls that could clash with the SDKs startup. + * + * Inspired by: + * https://github.com/pvvx/esp8266web/blob/2e25559bc489487747205db2ef171d48326b32d4/app/sdklib/system/app_main.c#L581-L591 + */ +extern "C" uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add); +extern "C" void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data); + +extern "C" void IRAM_ATTR mmu_set_pll(void) +{ +#if !defined(F_CRYSTAL) +#define F_CRYSTAL 26000000 +#endif + if (F_CRYSTAL != 40000000) { + // At Boot ROM(-BIOS) start, it assumes a 40MHz crystal. + // If it is not, we assume a 26MHz crystal. + // There is no support for 24MHz crustal at this time. + if(rom_i2c_readReg(103,4,1) != 136) { // 8: 40MHz, 136: 26MHz + // Assume 26MHz crystal + // soc_param0: 0: 40MHz, 1: 26MHz, 2: 24MHz + // set 80MHz PLL CPU + rom_i2c_writeReg(103,4,1,136); + rom_i2c_writeReg(103,4,2,145); + } + } +} + /* * This wrapper is for running code early from IROM (flash) before the SDK * starts. Since the NONOS SDK will do a full and proper flash device init for diff --git a/cores/esp8266/mmu_iram.h b/cores/esp8266/mmu_iram.h index bb4a33898b..e80c5ec348 100644 --- a/cores/esp8266/mmu_iram.h +++ b/cores/esp8266/mmu_iram.h @@ -46,6 +46,19 @@ extern "C" { */ #endif +#if defined(DEV_DEBUG_PRINT) || defined(DEBUG_ESP_MMU) || defined(DEBUG_ESP_CORE) || defined(DEBUG_ESP_PORT) +/* + * Early adjustment for CPU crystal frequency will allow early debug printing to + * be readable before the SDK initialization is complete. + * + * It is unknown if there are any side effects with SDK startup, but a + * possibility. Out of an abundance of caution, limit the use of mmu_set_pll for + * handling printing in failure cases that finish with a reboot. Or for other + * rare debug contexts. + */ +extern void mmu_set_pll(void); +#endif + /* * DEV_DEBUG_PRINT: * Debug printing macros for printing before before, during, and after @@ -63,11 +76,10 @@ extern "C" { #define DBG_MMU_FLUSH(a) while((USS(a) >> USTXC) & 0xff) {} #if defined(DEV_DEBUG_PRINT) -extern void set_pll(void); extern void dbg_set_pll(void); #define DBG_MMU_PRINTF(fmt, ...) \ -set_pll(); \ +mmu_set_pll(); \ uart_buff_switch(0); \ ets_uart_printf(fmt, ##__VA_ARGS__); \ DBG_MMU_FLUSH(0) From 23a491df8758e0d575c31bd9f1d8cad522665bca Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Tue, 13 Dec 2022 19:36:42 -0800 Subject: [PATCH 4/8] Now supports FLASH_MAP_SUPPORT with SDKs v3.0 RF_CAL and system_parameter always occupy the last 5 sectors of flash memory. --- cores/esp8266/core_esp8266_main.cpp | 97 ++++++++++++++++++++++------- cores/esp8266/flash_hal.h | 10 +-- 2 files changed, 80 insertions(+), 27 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 34bd19a42c..71b3bc24a1 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -401,33 +401,60 @@ extern "C" void __disableWiFiAtBootTime (void) #if FLASH_MAP_SUPPORT #include "flash_hal.h" -extern "C" void flashinit (void); +extern "C" bool flashinit (void); +#if (NONOSDK >= (0x30000)) +uint32_t __flashindex __attribute__((section(".noinit"))); +#else uint32_t __flashindex; #endif +#endif #if (NONOSDK >= (0x30000)) extern "C" uint8_t uart_rx_one_char_block(); extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) { + const char *flash_map_str = NULL; +#if FLASH_MAP_SUPPORT + __flashindex = 0; + if (!flashinit()) { + flash_map_str = PSTR("flashinit failed\n"); + } +#endif + // For SDKs 3.0.0 and later, place phy_data readonly overlay on top of the // EEPROM address. For older SDKs without a system partition, RF_CAL and // PHY_DATA shared the same flash segment. // - // For the Arduino ESP8266 core, the sectors for "EEPROM +0x1000", "RF_CAL - // +0x1000", and "SYSTEM_PARAMETERs +0x3000" are positioned in the last five - // sectors of flash memory. PHY_INIT_DATA is special. It is a one time read - // of 128 bytes of data that is provided by a one time spoofed flash read. + // For the Arduino ESP8266 core, the sectors for "EEPROM = size - 0x5000", + // "RF_CAL = size - 0x4000", and "SYSTEM_PARAMETER = size - 0x3000" are + // positioned in the last five sectors of flash memory. PHY_INIT_DATA is + // special. It is a one time read of 128 bytes of data that is provided by a + // one time spoofed flash read. +#if FLASH_MAP_SUPPORT + uint32_t flash_size = __flashdesc[__flashindex].flash_size_kb * 1024u; +#else + // flashchip->chip_size is updated by the SDK. The size is based on the + // value patched into the .bin header by esptool. + // system_get_flash_size_map() returns that patched value. + uint32_t flash_size = flashchip->chip_size; +#endif + // Always put RF_CAL and system_parameter in the last 4 sectors of flash chip. + uint32_t rf_cal = flash_size - 0x4000u; + uint32_t system_parameter = flash_size - 0x3000u; + + // system_partition_table_regist will not allow partitions to overlap. + // EEPROM_start is a good choice for phy_data overlay. The SDK does not need + // to know about it. So we can omit it from the table not used until after + // user_init() begins. So it should be safe from conflicts. uint32_t phy_data = EEPROM_start - 0x40200000u; - uint32_t rf_cal = phy_data + 0x1000u; - uint32_t system_parameter = rf_cal + 0x1000u; // All the examples I find, show the partition table in the global address space. static partition_item_t at_partition_table[] = { - { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, - { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, - { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, + { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, // type 5 + { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, // type 4 + { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, // type 6 }; // SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report // on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see @@ -444,14 +471,12 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) // Allows for small flash-size builds targeted for multiple devices, // commonly IoT, of varying flash sizes. const char *chip_sz_str = NULL; + + [[maybe_unused]] uint32_t configured_chip_size = phy_data + 4096 * 5; #if !defined(FLASH_MAP_SUPPORT) & defined(DEBUG_ESP_PORT) & !defined(ALLOW_SMALL_FLASH_SIZE) - // Note, system_partition_table_regist would only catch when the build flash + // Note, system_partition_table_regist will only catch when the build flash // size value set by the Arduino IDE Tools menu is larger than firmware // image value detected and updated on the fly by esptool. - uint32_t configured_chip_size = system_parameter + 4096 * 3; - // flashchip->chip_size is updated by the SDK. The size is based on the - // value patched into the .bin header by esptool. - // system_get_flash_size_map() returns that patched value. if (flashchip->chip_size != configured_chip_size) { // Full stop to avoid possible stored flash data corruption. This // mismatch will not occur with flash size selection "Mapping defined by @@ -460,14 +485,25 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) } #endif - if (chip_sz_str || !system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) { +#if FLASH_MAP_SUPPORT & defined(DEBUG_ESP_PORT) + // This should never fail everything traces back to the results of spi_flash_get_id() + if (flash_size != flashchip->chip_size) { + chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n\n"); + } +#endif + + if (flash_map_str || chip_sz_str || !system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) { // user_pre_init() is called very early in the SDK startup. When called, // the PLL CPU clock calibration hasn't not run. Since we are failing, the // calibration will never complete. And the process will repeat over and // over. The effective data rate will always be 74880 bps. If we had a // successful boot, the effective data rate would be 115200 on a restart // or HWDT. This hack relies on the CPU clock calibration never having - // completed. + // completed. This assumes we are starting from a hard reset. + + // A possible exception would be a soft reset after flashing. In which + // case the message will not be readable until after a hard reset or + // power cycle. // After flashing, the Arduino Serial Monitor needs a moment to reconnect. // This also allows time for the FIFO to clear and the host serial port time @@ -493,25 +529,40 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("RF_CAL"), rf_cal); ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter); ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("chip_size"), flashchip->chip_size, flashchip->chip_size); +#if FLASH_MAP_SUPPORT + ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("flash_size"), flash_size, flash_size); +#else + ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("config_flash_size"), configured_chip_size, configured_chip_size); +#endif ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start); ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_start"), FS_start); ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_end"), FS_end); ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_page"), FS_page); ets_uart_printf(PSTR(" %-18s 0x%08X\n\n"), PSTR("FS_block"), FS_block); #endif + +#if FLASH_MAP_SUPPORT + if (flash_map_str) { + ets_uart_printf(flash_map_str); + } else +#endif +#if !defined(FLASH_MAP_SUPPORT) & defined(DEBUG_ESP_PORT) & !defined(ALLOW_SMALL_FLASH_SIZE) if (chip_sz_str) { ets_uart_printf(chip_sz_str); - } else { + } else +#endif + { #if defined(DEBUG_ESP_CORE) | defined(DEBUG_ESP_PORT) // Now that the UART speed is corrected and messages will - // display, run system_partition_table_regist again. + // display, run system_partition_table_regist again to repeat + // the error messages. system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()); #endif ets_uart_printf(PSTR("System partition table registration failed!\n\n")); } + uart_rx_one_char_block(); // Someone said hello - repeat message } while(true); - } } #endif // #if (NONOSDK >= (0x30000)) @@ -551,8 +602,10 @@ extern "C" void user_init(void) { #if defined(MMU_IRAM_HEAP) umm_init_iram(); #endif -#if FLASH_MAP_SUPPORT - flashinit(); +#if FLASH_MAP_SUPPORT & (NONOSDK < 0x30000) + if (!flashinit()) { + panic(); + } #endif preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable. __disableWiFiAtBootTime(); // default weak function disables WiFi diff --git a/cores/esp8266/flash_hal.h b/cores/esp8266/flash_hal.h index effca0f965..51500d8b11 100644 --- a/cores/esp8266/flash_hal.h +++ b/cores/esp8266/flash_hal.h @@ -33,21 +33,21 @@ extern "C" { #include extern uint32_t spi_flash_get_id (void); // -extern void flashinit(void); +extern bool flashinit(void); extern uint32_t __flashindex; extern const flash_map_s __flashdesc[]; #define FLASH_MAP_SETUP_CONFIG(conf) FLASH_MAP_SETUP_CONFIG_ATTR(,conf) #define FLASH_MAP_SETUP_CONFIG_ATTR(attr, conf...) \ const flash_map_s __flashdesc[] PROGMEM = conf; \ - void flashinit (void) attr; \ - void flashinit (void) \ + bool flashinit (void) attr; \ + bool flashinit (void) \ { \ uint32_t flash_chip_size_kb = 1 << (((spi_flash_get_id() >> 16) & 0xff) - 10); \ for (__flashindex = 0; __flashindex < sizeof(__flashdesc) / sizeof(__flashdesc[0]); __flashindex++) \ if (__flashdesc[__flashindex].flash_size_kb == flash_chip_size_kb) \ - return; \ - panic(); /* configuration not found */ \ + return true; \ + return false; /* configuration not found */ \ } #define EEPROM_start (__flashdesc[__flashindex].eeprom_start) From b4b7be06590de5bd40243ea34a37bce9a2bcaa70 Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:32:08 -0800 Subject: [PATCH 5/8] cleanup and refactoring comment cleanup --- cores/esp8266/core_esp8266_main.cpp | 266 ++++++++++++++++------------ cores/esp8266/core_esp8266_phy.cpp | 18 ++ 2 files changed, 173 insertions(+), 111 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 71b3bc24a1..7510b6888e 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -410,89 +410,112 @@ uint32_t __flashindex; #endif #if (NONOSDK >= (0x30000)) - +#undef ETS_PRINTF +#define ETS_PRINTF(...) ets_uart_printf(__VA_ARGS__) extern "C" uint8_t uart_rx_one_char_block(); + extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) { const char *flash_map_str = NULL; -#if FLASH_MAP_SUPPORT - __flashindex = 0; - if (!flashinit()) { - flash_map_str = PSTR("flashinit failed\n"); - } -#endif - - // For SDKs 3.0.0 and later, place phy_data readonly overlay on top of the - // EEPROM address. For older SDKs without a system partition, RF_CAL and - // PHY_DATA shared the same flash segment. - // - // For the Arduino ESP8266 core, the sectors for "EEPROM = size - 0x5000", - // "RF_CAL = size - 0x4000", and "SYSTEM_PARAMETER = size - 0x3000" are - // positioned in the last five sectors of flash memory. PHY_INIT_DATA is - // special. It is a one time read of 128 bytes of data that is provided by a - // one time spoofed flash read. -#if FLASH_MAP_SUPPORT - uint32_t flash_size = __flashdesc[__flashindex].flash_size_kb * 1024u; -#else - // flashchip->chip_size is updated by the SDK. The size is based on the - // value patched into the .bin header by esptool. - // system_get_flash_size_map() returns that patched value. - uint32_t flash_size = flashchip->chip_size; -#endif - // Always put RF_CAL and system_parameter in the last 4 sectors of flash chip. - uint32_t rf_cal = flash_size - 0x4000u; - uint32_t system_parameter = flash_size - 0x3000u; - - // system_partition_table_regist will not allow partitions to overlap. - // EEPROM_start is a good choice for phy_data overlay. The SDK does not need - // to know about it. So we can omit it from the table not used until after - // user_init() begins. So it should be safe from conflicts. - uint32_t phy_data = EEPROM_start - 0x40200000u; - - // All the examples I find, show the partition table in the global address space. - static partition_item_t at_partition_table[] = - { - { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, // type 5 - { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, // type 4 - { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, // type 6 - }; - // SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report - // on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see - // anything we can do about this. Other than maybe turning off os_print. - - // For SDKs v3.0.0 and later, the functions `uint32 - // user_rf_cal_sector_set(void)` and `void user_rf_pre_init(void)` are not - // called by the SDK. We need these called to start and stop spoofing logic - // for flash read of PHY Init data. - extern uint32_t user_rf_cal_sector_set(void); - user_rf_cal_sector_set(); // Start spoofing logic - - // -DALLOW_SMALL_FLASH_SIZE=1 - // Allows for small flash-size builds targeted for multiple devices, - // commonly IoT, of varying flash sizes. const char *chip_sz_str = NULL; + const char *table_regist_str = NULL; + [[maybe_unused]] uint32_t ld_config_chip_size = 0; + uint32_t flash_size = 0; + uint32_t phy_data = 0; + uint32_t rf_cal = 0; + uint32_t system_parameter = 0; + [[maybe_unused]] partition_item_t *_at_partition_table = NULL; + size_t _at_partition_table_sz = 0; + + do { + #if FLASH_MAP_SUPPORT + if (!flashinit()) { + flash_map_str = PSTR("flashinit: flash size missing from FLASH_MAP table\n"); + continue; + } + #endif - [[maybe_unused]] uint32_t configured_chip_size = phy_data + 4096 * 5; -#if !defined(FLASH_MAP_SUPPORT) & defined(DEBUG_ESP_PORT) & !defined(ALLOW_SMALL_FLASH_SIZE) - // Note, system_partition_table_regist will only catch when the build flash - // size value set by the Arduino IDE Tools menu is larger than firmware - // image value detected and updated on the fly by esptool. - if (flashchip->chip_size != configured_chip_size) { - // Full stop to avoid possible stored flash data corruption. This - // mismatch will not occur with flash size selection "Mapping defined by - // Hardware and Sketch". - chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n\n"); - } -#endif + // For SDKs 3.0.0 and later, place phy_data readonly overlay on top of + // the EEPROM address. For older SDKs without a system partition, RF_CAL + // and PHY_DATA shared the same flash segment. + // + // For the Arduino ESP8266 core, the sectors for "EEPROM = size - + // 0x5000", "RF_CAL = size - 0x4000", and "SYSTEM_PARAMETER = size - + // 0x3000" are positioned in the last five sectors of flash memory. + // PHY_INIT_DATA is special. It is a one time read of 128 bytes of data + // that is provided by a spoofed flash read. + #if FLASH_MAP_SUPPORT + flash_size = __flashdesc[__flashindex].flash_size_kb * 1024u; + #else + // flashchip->chip_size is updated by the SDK. The size is based on the + // value patched into the .bin header by esptool. + // system_get_flash_size_map() returns that patched value. + flash_size = flashchip->chip_size; + #endif -#if FLASH_MAP_SUPPORT & defined(DEBUG_ESP_PORT) - // This should never fail everything traces back to the results of spi_flash_get_id() - if (flash_size != flashchip->chip_size) { - chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n\n"); - } -#endif + // For all configurations, place RF_CAL and system_parameter in the + // last 4 sectors of the flash chip. + rf_cal = flash_size - 0x4000u; + system_parameter = flash_size - 0x3000u; + + // The system_partition_table_regist will not allow partitions to + // overlap. EEPROM_start is a good choice for phy_data overlay. The SDK + // does not need to know about EEPROM_start. So we can omit it from the + // table. The real EEPROM access is after user_init() begins long after + // the PHY_DATA read. So it should be safe from conflicts. + phy_data = EEPROM_start - 0x40200000u; + + // For SDKs 3.0 builds, "sdk3_begin_phy_data_spoof and + // user_rf_cal_sector_set" starts and stops the spoofing logic in + // `core_esp8266_phy.cpp`. + extern void sdk3_begin_phy_data_spoof(); + sdk3_begin_phy_data_spoof(); + + ld_config_chip_size = phy_data + 4096 * 5; + + // -DALLOW_SMALL_FLASH_SIZE=1 + // Allows for small flash-size builds targeted for multiple devices, + // commonly IoT, of varying flash sizes. + #if !defined(FLASH_MAP_SUPPORT) & !defined(ALLOW_SMALL_FLASH_SIZE) + // Note, system_partition_table_regist will only catch when the build + // flash size value set by the Arduino IDE Tools menu is larger than + // the firmware image value detected and updated on the fly by esptool. + if (flashchip->chip_size != ld_config_chip_size) { + // Stop to avoid possible stored flash data corruption. This + // mismatch will not occur with flash size selection "Mapping + // defined by Hardware and Sketch". + chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n"); + continue; + } + #endif - if (flash_map_str || chip_sz_str || !system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map())) { + #if FLASH_MAP_SUPPORT & defined(DEBUG_ESP_PORT) + // I don't think this will ever fail. Everything traces back to the results of spi_flash_get_id() + if (flash_size != flashchip->chip_size) { + chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n"); + continue; + } + #endif + + // All the examples I find, show the partition table in the global address space. + static partition_item_t at_partition_table[] = + { + { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, // type 5 + { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, // type 4 + { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, // type 6 + }; + _at_partition_table = at_partition_table; + _at_partition_table_sz = sizeof(at_partition_table) / sizeof(at_partition_table[0]); + // SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report + // on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see + // anything we can do about this. Other than maybe turning off os_print. + if (!system_partition_table_regist(at_partition_table, _at_partition_table_sz, system_get_flash_size_map())) { + table_regist_str = PSTR("System partition table registration failed!\n"); + continue; + } + } while(false); + + if (chip_sz_str || flash_map_str || table_regist_str) { // user_pre_init() is called very early in the SDK startup. When called, // the PLL CPU clock calibration hasn't not run. Since we are failing, the // calibration will never complete. And the process will repeat over and @@ -505,9 +528,9 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) // case the message will not be readable until after a hard reset or // power cycle. - // After flashing, the Arduino Serial Monitor needs a moment to reconnect. - // This also allows time for the FIFO to clear and the host serial port time - // to clear any framing errors. + // After flashing, the Arduino Serial Monitor needs a moment to + // reconnect. This also allows time for the FIFO to clear and the host + // serial port to clear any framing errors. ets_delay_us(200u * 1000u); // For an uncalibrated CPU Clock, this is close enough. #if !defined(F_CRYSTAL) @@ -519,48 +542,69 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) uart_div_modify(0, F_CRYSTAL * 2 / 115200); ets_delay_us(150); } - ets_uart_printf("\n\n"); do { + ETS_PRINTF("\n\n"); // Because SDK v3.0.x always has a non-32-bit wide exception handler // installed, we can use PROGMEM strings with Boot ROM print functions. -#ifdef DEBUG_ESP_CORE - ets_uart_printf(PSTR("Config info referenced for system partition table registration:\n")); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("PHY_DATA"), phy_data); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("RF_CAL"), rf_cal); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter); - ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("chip_size"), flashchip->chip_size, flashchip->chip_size); -#if FLASH_MAP_SUPPORT - ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("flash_size"), flash_size, flash_size); +#if defined(DEBUG_ESP_CORE) | defined(DEBUG_ESP_PORT) // DEBUG_ESP_CORE => verbose + #if FLASH_MAP_SUPPORT + if (flash_map_str) { + ETS_PRINTF(flash_map_str); + #if defined(DEBUG_ESP_CORE) + size_t num = __flashindex; // On failure __flashindex is the size of __flashdesc[]; :/ + ETS_PRINTF(PSTR("Table of __flashdesc[%u].flash_size_kb entries converted to bytes:\n"), num); + for (size_t i = 0; i < num; i++) { + uint32_t size = __flashdesc[i].flash_size_kb << 10; + ETS_PRINTF(PSTR(" [%02u] 0x%08X %8u\n"), i, size, size); + } + ETS_PRINTF(PSTR("Reference info:\n")); + uint32_t flash_chip_size = 1 << ((spi_flash_get_id() >> 16) & 0xff); + ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("fn(spi_flash_get_id())"), flash_chip_size, flash_chip_size); + ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("bin_chip_size"), flashchip->chip_size, flashchip->chip_size); + #endif + } else + #endif + if (chip_sz_str) { + ETS_PRINTF(chip_sz_str); + } else + if (table_regist_str) { + ETS_PRINTF(table_regist_str); + // (printing now works) repeat ...regist error messages + system_partition_table_regist(_at_partition_table, _at_partition_table_sz, system_get_flash_size_map()); + } + if (chip_sz_str || table_regist_str) { + ETS_PRINTF(PSTR("Reference info:\n")); + #if FLASH_MAP_SUPPORT + ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("fn(...ex].flash_size_kb)"), flash_size, flash_size); + uint32_t flash_chip_size = 1 << ((spi_flash_get_id() >> 16) & 0xff); + ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("fn(spi_flash_get_id())"), flash_chip_size, flash_chip_size); + ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("bin_chip_size"), flashchip->chip_size, flashchip->chip_size); + #else + ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("config_flash_size"), ld_config_chip_size, ld_config_chip_size); + ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("bin_chip_size"), flashchip->chip_size, flashchip->chip_size); + #endif + #if defined(DEBUG_ESP_CORE) + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("PHY_DATA"), phy_data); + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("RF_CAL"), rf_cal); + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("SYSTEM_PARAMETER"), system_parameter); + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start); + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_start"), FS_start); + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_end"), FS_end); + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_page"), FS_page); + ETS_PRINTF(PSTR(" %-24s 0x%08X\n"), PSTR("FS_block"), FS_block); + #endif + } #else - ets_uart_printf(PSTR(" %-18s 0x%08X %u\n"), PSTR("config_flash_size"), configured_chip_size, configured_chip_size); -#endif - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("EEPROM_start"), EEPROM_start); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_start"), FS_start); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_end"), FS_end); - ets_uart_printf(PSTR(" %-18s 0x%08X\n"), PSTR("FS_page"), FS_page); - ets_uart_printf(PSTR(" %-18s 0x%08X\n\n"), PSTR("FS_block"), FS_block); -#endif - -#if FLASH_MAP_SUPPORT if (flash_map_str) { - ets_uart_printf(flash_map_str); + ETS_PRINTF(flash_map_str); } else -#endif -#if !defined(FLASH_MAP_SUPPORT) & defined(DEBUG_ESP_PORT) & !defined(ALLOW_SMALL_FLASH_SIZE) if (chip_sz_str) { - ets_uart_printf(chip_sz_str); + ETS_PRINTF(chip_sz_str); } else -#endif - { -#if defined(DEBUG_ESP_CORE) | defined(DEBUG_ESP_PORT) - // Now that the UART speed is corrected and messages will - // display, run system_partition_table_regist again to repeat - // the error messages. - system_partition_table_regist(at_partition_table, sizeof(at_partition_table) / sizeof(at_partition_table[0]), system_get_flash_size_map()); -#endif - ets_uart_printf(PSTR("System partition table registration failed!\n\n")); + if (table_regist_str) { + ETS_PRINTF(table_regist_str); } - +#endif uart_rx_one_char_block(); // Someone said hello - repeat message } while(true); } diff --git a/cores/esp8266/core_esp8266_phy.cpp b/cores/esp8266/core_esp8266_phy.cpp index f06a698bf7..4a32b44810 100644 --- a/cores/esp8266/core_esp8266_phy.cpp +++ b/cores/esp8266/core_esp8266_phy.cpp @@ -303,6 +303,17 @@ extern int __real_spi_flash_read(uint32_t addr, uint32_t* dst, size_t size); extern int IRAM_ATTR __wrap_spi_flash_read(uint32_t addr, uint32_t* dst, size_t size); extern int __get_adc_mode(); +/* + Verified that the wide filtering of all 128 byte flash reads during + spoof_init_data continues to be safe for SDK 3.0.5 + From start call to user_pre_init() to stop call with user_rf_pre_init(). + + flash read count during spoof_init_data 4 + flash read 0x00000 8 // system_get_flash_size_map() + flash read 0x00000 4 // system_partition_table_regist() + flash read 0xFB000 128 // PHY_DATA (EEPROM address space) + flash read 0xFC000 628 // RC_CAL + */ extern int IRAM_ATTR __wrap_spi_flash_read(uint32_t addr, uint32_t* dst, size_t size) { if (!spoof_init_data || size != 128) { @@ -332,11 +343,18 @@ extern void __run_user_rf_pre_init(void) return; // default do noting } +#if (NONOSDK >= (0x30000)) +void sdk3_begin_phy_data_spoof(void) +{ + spoof_init_data = true; +} +#else uint32_t user_rf_cal_sector_set(void) { spoof_init_data = true; return flashchip->chip_size/SPI_FLASH_SEC_SIZE - 4; } +#endif void user_rf_pre_init() { From d42bbdb25137a32a48309421f454e60a4bc9d37b Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Thu, 15 Dec 2022 09:28:33 -0800 Subject: [PATCH 6/8] Add more build issolation when including flash_hal.h --- cores/esp8266/core_esp8266_main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 7510b6888e..d87c220ec7 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -39,7 +39,6 @@ extern "C" { #include #include #include "core_esp8266_vm.h" -#include "flash_hal.h" #define LOOP_TASK_PRIORITY 1 #define LOOP_QUEUE_SIZE 1 @@ -414,6 +413,10 @@ uint32_t __flashindex; #define ETS_PRINTF(...) ets_uart_printf(__VA_ARGS__) extern "C" uint8_t uart_rx_one_char_block(); +#if ! FLASH_MAP_SUPPORT +#include "flash_hal.h" +#endif + extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) { const char *flash_map_str = NULL; @@ -487,6 +490,11 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n"); continue; } + #elif defined(ALLOW_SMALL_FLASH_SIZE) && !defined(FLASH_MAP_SUPPORT) + // Note, while EEPROM is confined to a smaller flash size, we are still + // placing RF_CAL and SYSTEM_PARAMETER at the end of flash. To prevent + // this, esptool or its equal needs to not update the flash size in the + // .bin image. #endif #if FLASH_MAP_SUPPORT & defined(DEBUG_ESP_PORT) From 0cd76504b16dcdde4c61227b645346abe8b90254 Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Thu, 15 Dec 2022 11:38:16 -0800 Subject: [PATCH 7/8] Improve details for autoconfig fail. --- cores/esp8266/core_esp8266_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index d87c220ec7..417de99984 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -565,11 +565,11 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) uint32_t size = __flashdesc[i].flash_size_kb << 10; ETS_PRINTF(PSTR(" [%02u] 0x%08X %8u\n"), i, size, size); } + #endif ETS_PRINTF(PSTR("Reference info:\n")); uint32_t flash_chip_size = 1 << ((spi_flash_get_id() >> 16) & 0xff); ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("fn(spi_flash_get_id())"), flash_chip_size, flash_chip_size); ETS_PRINTF(PSTR(" %-24s 0x%08X %8u\n"), PSTR("bin_chip_size"), flashchip->chip_size, flashchip->chip_size); - #endif } else #endif if (chip_sz_str) { From c3e22f070be1fbf5a695673c56d0d464519afe2f Mon Sep 17 00:00:00 2001 From: M Hightower <27247790+mhightower83@users.noreply.github.com> Date: Sat, 17 Dec 2022 08:42:18 -0800 Subject: [PATCH 8/8] requested changes --- cores/esp8266/core_esp8266_main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cores/esp8266/core_esp8266_main.cpp b/cores/esp8266/core_esp8266_main.cpp index 417de99984..a143b1cd5e 100644 --- a/cores/esp8266/core_esp8266_main.cpp +++ b/cores/esp8266/core_esp8266_main.cpp @@ -427,7 +427,7 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) uint32_t phy_data = 0; uint32_t rf_cal = 0; uint32_t system_parameter = 0; - [[maybe_unused]] partition_item_t *_at_partition_table = NULL; + [[maybe_unused]] const partition_item_t *_at_partition_table = NULL; size_t _at_partition_table_sz = 0; do { @@ -479,7 +479,7 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) // -DALLOW_SMALL_FLASH_SIZE=1 // Allows for small flash-size builds targeted for multiple devices, // commonly IoT, of varying flash sizes. - #if !defined(FLASH_MAP_SUPPORT) & !defined(ALLOW_SMALL_FLASH_SIZE) + #if !defined(FLASH_MAP_SUPPORT) && !defined(ALLOW_SMALL_FLASH_SIZE) // Note, system_partition_table_regist will only catch when the build // flash size value set by the Arduino IDE Tools menu is larger than // the firmware image value detected and updated on the fly by esptool. @@ -497,7 +497,7 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) // .bin image. #endif - #if FLASH_MAP_SUPPORT & defined(DEBUG_ESP_PORT) + #if FLASH_MAP_SUPPORT && defined(DEBUG_ESP_PORT) // I don't think this will ever fail. Everything traces back to the results of spi_flash_get_id() if (flash_size != flashchip->chip_size) { chip_sz_str = PSTR("Flash size mismatch, check that the build setting matches the device.\n"); @@ -506,14 +506,14 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) #endif // All the examples I find, show the partition table in the global address space. - static partition_item_t at_partition_table[] = + static const partition_item_t at_partition_table[] = { { SYSTEM_PARTITION_PHY_DATA, phy_data, 0x1000 }, // type 5 { SYSTEM_PARTITION_RF_CAL, rf_cal, 0x1000 }, // type 4 { SYSTEM_PARTITION_SYSTEM_PARAMETER, system_parameter, 0x3000 }, // type 6 }; _at_partition_table = at_partition_table; - _at_partition_table_sz = sizeof(at_partition_table) / sizeof(at_partition_table[0]); + _at_partition_table_sz = std::size(at_partition_table); // SDK 3.0's `system_partition_table_regist` is FOTA-centric. It will report // on BOOT, OTA1, and OTA2 being missing. We are Non-FOTA. I don't see // anything we can do about this. Other than maybe turning off os_print. @@ -554,7 +554,7 @@ extern "C" void ICACHE_FLASH_ATTR user_pre_init(void) ETS_PRINTF("\n\n"); // Because SDK v3.0.x always has a non-32-bit wide exception handler // installed, we can use PROGMEM strings with Boot ROM print functions. -#if defined(DEBUG_ESP_CORE) | defined(DEBUG_ESP_PORT) // DEBUG_ESP_CORE => verbose +#if defined(DEBUG_ESP_CORE) || defined(DEBUG_ESP_PORT) // DEBUG_ESP_CORE => verbose #if FLASH_MAP_SUPPORT if (flash_map_str) { ETS_PRINTF(flash_map_str); @@ -654,7 +654,7 @@ extern "C" void user_init(void) { #if defined(MMU_IRAM_HEAP) umm_init_iram(); #endif -#if FLASH_MAP_SUPPORT & (NONOSDK < 0x30000) +#if FLASH_MAP_SUPPORT && (NONOSDK < 0x30000) if (!flashinit()) { panic(); } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy