From f5ad07fe5e7f150a5f90c3e66764de3e44c0eb4b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 22 Nov 2020 17:35:04 +0100 Subject: [PATCH] Fix ESP32 flashwrites --- tasmota/support_esp32.ino | 112 +++++++++++++++++++++++++++++++++- tasmota/xdrv_01_webserver.ino | 23 +++---- 2 files changed, 123 insertions(+), 12 deletions(-) diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index c587c2ca0..f4a89a8e9 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -75,6 +75,17 @@ void ESP_Restart(void) { ESP.reset(); } +uint32_t FlashWriteStartSector(void) { + return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side +} + +uint32_t FlashWriteMaxSector(void) { + return (((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SIZE) - 2; +} + +uint8_t* FlashDirectAccess(void) { + return (uint8_t*)(0x40200000 + (FlashWriteStartSector() * SPI_FLASH_SEC_SIZE)); +} #endif /*********************************************************************************************\ @@ -190,6 +201,76 @@ void NvsInfo(void) { nvs_stats.used_entries, nvs_stats.free_entries, nvs_stats.total_entries, nvs_stats.namespace_count); } +// +// Flash memory mapping +// + +#include "Esp.h" +#include "rom/spi_flash.h" +#include "esp_spi_flash.h" +#include +#include +#include +#include +extern "C" { +#include "esp_ota_ops.h" +#include "esp_image_format.h" +} + +uint32_t EspFlashBaseAddress(void) { + const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr); + if (!partition) { return 0; } + + return partition->address; // For tasmota 0x00010000 or 0x00200000 +} + +uint32_t EspFlashBaseEndAddress(void) { + const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr); + if (!partition) { return 0; } + + return partition->address + partition->size; // For tasmota 0x00200000 or 0x003F0000 +} + +uint8_t* EspFlashMmap(uint32_t address) { + static spi_flash_mmap_handle_t handle = 0; + + if (handle) { + spi_flash_munmap(handle); + handle = 0; + } + + const uint8_t* data; + int32_t err = spi_flash_mmap(address, 5 * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMAP_DATA, (const void **)&data, &handle); + +/* + AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: Spi_flash_map %d"), err); + + spi_flash_mmap_dump(); +*/ + return (uint8_t*)data; +} + +/* +int32_t EspPartitionMmap(uint32_t action) { + static spi_flash_mmap_handle_t handle; + + int32_t err = 0; + if (1 == action) { + const esp_partition_t *partition = esp_ota_get_running_partition(); +// const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr); + if (!partition) { return 0; } + err = esp_partition_mmap(partition, 0, 4 * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMAP_DATA, (const void **)&TasmotaGlobal_mmap_data, &handle); + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: Partition start 0x%08X, Partition end 0x%08X, Mmap data 0x%08X"), partition->address, partition->size, TasmotaGlobal_mmap_data); + + } else { + spi_flash_munmap(handle); + handle = 0; + } + return err; +} + +*/ // // Crash stuff // @@ -262,7 +343,7 @@ String ESP32GetResetReason(uint32_t cpu_no) { case RTCWDT_CPU_RESET : return F("RTC Watch dog Reset CPU"); // 13 case EXT_CPU_RESET : return F("or APP CPU, reseted by PRO CPU"); // 14 case RTCWDT_BROWN_OUT_RESET : return F("Reset when the vdd voltage is not stable"); // 15 - case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); // 16 + case RTCWDT_RTC_RESET : return F("RTC Watch dog reset digital core and rtc module"); // 16 } return F("No meaning"); // 0 and undefined } @@ -313,4 +394,33 @@ void ESP_Restart(void) { ESP.restart(); } +uint32_t FlashWriteStartSector(void) { + // Needs to be on SPI_FLASH_MMU_PAGE_SIZE (= 0x10000) alignment for mmap usage + uint32_t aligned_address = ((EspFlashBaseAddress() + (2 * SPI_FLASH_MMU_PAGE_SIZE)) / SPI_FLASH_MMU_PAGE_SIZE) * SPI_FLASH_MMU_PAGE_SIZE; + return aligned_address / SPI_FLASH_SEC_SIZE; +} + +uint32_t FlashWriteMaxSector(void) { + // Needs to be on SPI_FLASH_MMU_PAGE_SIZE (= 0x10000) alignment for mmap usage + uint32_t aligned_end_address = (EspFlashBaseEndAddress() / SPI_FLASH_MMU_PAGE_SIZE) * SPI_FLASH_MMU_PAGE_SIZE; + return aligned_end_address / SPI_FLASH_SEC_SIZE; +} + +uint8_t* FlashDirectAccess(void) { + uint32_t address = FlashWriteStartSector() * SPI_FLASH_SEC_SIZE; + uint8_t* data = EspFlashMmap(address); + +/* + AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: Flash start address 0x%08X, Mmap address 0x%08X"), address, data); + + uint8_t buf[32]; + memcpy(buf, data, sizeof(buf)); + AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&buf, 32); + + memcpy(buf, data, sizeof(buf)); + AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t*)&buf + , 32); +*/ + + return data; +} #endif // ESP32 diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 1a45bbbfa..bf08d61e3 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2575,14 +2575,10 @@ struct { bool ready; } BUpload; -uint32_t BUploadStartSector(void) { - return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side -} - void BUploadInit(uint32_t file_type) { Web.upload_file_type = file_type; BUpload.spi_hex_size = 0; - BUpload.spi_sector_counter = BUploadStartSector(); + BUpload.spi_sector_counter = FlashWriteStartSector(); BUpload.spi_sector_cursor = 0; BUpload.active = true; BUpload.ready = false; @@ -2590,15 +2586,19 @@ void BUploadInit(uint32_t file_type) { uint32_t BUploadWriteBuffer(uint8_t *buf, size_t size) { if (0 == BUpload.spi_sector_cursor) { // Starting a new sector write so we need to erase it first - ESP.flashEraseSector(BUpload.spi_sector_counter); + if (!ESP.flashEraseSector(BUpload.spi_sector_counter)) { + return 7; // Upload aborted - flash failed + } } BUpload.spi_sector_cursor++; - ESP.flashWrite((BUpload.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((BUpload.spi_sector_cursor -1) * 2048), (uint32_t*)buf, size); + if (!ESP.flashWrite((BUpload.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((BUpload.spi_sector_cursor -1) * 2048), (uint32_t*)buf, size)) { + return 7; // Upload aborted - flash failed + } BUpload.spi_hex_size += size; if (2 == BUpload.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase BUpload.spi_sector_cursor = 0; BUpload.spi_sector_counter++; - if (BUpload.spi_sector_counter > (SPIFFS_END -2)) { + if (BUpload.spi_sector_counter > FlashWriteMaxSector()) { return 9; // File too large - Not enough free space } } @@ -2660,7 +2660,7 @@ void HandleUploadDone(void) if ((UPL_EFR32 == Web.upload_file_type) && !Web.upload_error && BUpload.ready) { BUpload.ready = false; // Make sure not to follow thru again // GUI xmodem - ZigbeeUploadStep1Done(BUploadStartSector(), BUpload.spi_hex_size); + ZigbeeUploadStep1Done(FlashWriteStartSector(), BUpload.spi_hex_size); HandleZigbeeXfer(); return; } @@ -2886,7 +2886,8 @@ void HandleUploadLoop(void) AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPLOAD "Transfer %u bytes"), upload.totalSize); - uint8_t* data = (uint8_t*)(0x40200000 + (BUploadStartSector() * SPI_FLASH_SEC_SIZE)); +// uint8_t* data = (uint8_t*)(0x40200000 + (FlashWriteStartSector() * SPI_FLASH_SEC_SIZE)); + uint8_t* data = FlashDirectAccess(); // uint32_t* values = (uint32_t*)(data); // Only 4-byte access allowed // AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "Head 0x%08X"), values[0]); @@ -2899,7 +2900,7 @@ void HandleUploadLoop(void) #endif // USE_RF_FLASH #ifdef USE_TASMOTA_CLIENT if (UPL_TASMOTACLIENT == Web.upload_file_type) { - error = TasmotaClient_Flash(BUploadStartSector() * SPI_FLASH_SEC_SIZE, BUpload.spi_hex_size); + error = TasmotaClient_Flash(FlashWriteStartSector() * SPI_FLASH_SEC_SIZE, BUpload.spi_hex_size); } #endif // USE_TASMOTA_CLIENT #ifdef SHELLY_FW_UPGRADE