diff --git a/tasmota/_changelog.ino b/tasmota/_changelog.ino index 137bcf1d3..f7c53a1f9 100644 --- a/tasmota/_changelog.ino +++ b/tasmota/_changelog.ino @@ -8,6 +8,7 @@ * Add support for I2C sensor TLS2591 Light Intensity sensor (#6873) * Change Kept only NEC/RC5/RC6/HASH IR protocols in standard Tasmota, all other protocols require Tasmota-IR, saving 4K * Add command SetOption76 0/1 to enable incrementing bootcount when deepsleep is enabled (#6930) + * Change Reset erase end address from as seen by SDK (getFlashChipSize) to full flash size (getFlashChipRealSize) * * 7.0.0.3 20191103 * Add command I2cDriver for I2C driver runtime control using document I2CDEVICES.md diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 3c664bd34..753e8602b 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -536,27 +536,31 @@ void SettingsLoad(void) void SettingsErase(uint8_t type) { /* + For Arduino core and SDK: Erase only works from flash start address to SDK recognized flash end address (flashchip->chip_size = ESP.getFlashChipSize). Addresses above SDK recognized size (up to ESP.getFlashChipRealSize) are not accessable. + For Esptool: The only way to erase whole flash is esptool which uses direct SPI writes to flash. + The default erase function is EspTool (EsptoolEraseSector) + 0 = Erase from program end until end of flash as seen by SDK 1 = Erase 16k SDK parameter area near end of flash as seen by SDK (0x0xFCxxx - 0x0xFFFFF) solving possible wifi errors - 2 = Erase Tasmota settings (0x0xF4xxx - 0x0xFBFFF) + 2 = Erase Tasmota settings (0x0xF3xxx - 0x0xFBFFF) */ #ifndef FIRMWARE_MINIMAL // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDK: Flash size 0x%08X"), flashchip->chip_size); uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; -// uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; - uint32_t _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; + uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; +// uint32_t _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; if (1 == type) { // source Esp.cpp and core_esp8266_phy.cpp _sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; } else if (2 == type) { - _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota parameter area (0x0F4xxx - 0x0FBFFF) + _sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota parameter area (0x0F3xxx - 0x0FBFFF) _sectorEnd = SETTINGS_LOCATION +1; } @@ -565,16 +569,22 @@ void SettingsErase(uint8_t type) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart); for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) { - bool result = ESP.flashEraseSector(_sector); + +// bool result = ESP.flashEraseSector(_sector); // Arduino core - erases flash as seen by SDK +// bool result = !SPIEraseSector(_sector); // SDK - erases flash as seen by SDK + bool result = EsptoolEraseSector(_sector); // Esptool - erases flash completely + if (_serialoutput) { Serial.print(F(D_LOG_APPLICATION D_ERASED_SECTOR " ")); Serial.print(_sector); if (result) { Serial.println(F(" " D_OK)); } else { - Serial.println(F(" " D_ERROR)); // + Serial.println(F(" " D_ERROR)); } delay(10); + } else { + yield(); } OsWatchLoop(); } diff --git a/tasmota/support_esptool.ino b/tasmota/support_esptool.ino new file mode 100644 index 000000000..45e5245bf --- /dev/null +++ b/tasmota/support_esptool.ino @@ -0,0 +1,91 @@ +/* + support_esptool.ino - esptool support for Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#define USE_ESPTOOL +#ifdef USE_ESPTOOL +/*********************************************************************************************\ + * EspTool Erase function based on Version 2.8 + * + * Source: https://github.com/espressif/esptool/blob/master/flasher_stub +\*********************************************************************************************/ + +// *** flasher_stub/include/soc_support.h +#define READ_REG(REG) (*((volatile uint32_t *)(REG))) +#define WRITE_REG(REG, VAL) *((volatile uint32_t *)(REG)) = (VAL) +#define REG_SET_MASK(reg, mask) WRITE_REG((reg), (READ_REG(reg)|(mask))) + +#define SPI_BASE_REG 0x60000200 // SPI peripheral 0 + +#define SPI_CMD_REG (SPI_BASE_REG + 0x00) +#define SPI_FLASH_RDSR (1<<27) +#define SPI_FLASH_SE (1<<24) +#define SPI_FLASH_BE (1<<23) +#define SPI_FLASH_WREN (1<<30) + +#define SPI_ADDR_REG (SPI_BASE_REG + 0x04) +#define SPI_CTRL_REG (SPI_BASE_REG + 0x08) +#define SPI_RD_STATUS_REG (SPI_BASE_REG + 0x10) +#define SPI_W0_REG (SPI_BASE_REG + 0x40) +#define SPI_EXT2_REG (SPI_BASE_REG + 0xF8) + +#define SPI_ST 0x7 // Done state value + +// *** flasher_stub/stub_write_flash.c +static const uint32_t STATUS_WIP_BIT = (1 << 0); // SPI status bits + +// Wait for the SPI state machine to be ready, ie no command in progress in the internal host. +inline static void spi_wait_ready(void) +{ + // Wait for SPI state machine ready + while((READ_REG(SPI_EXT2_REG) & SPI_ST)) { } +} + +// Returns true if the spiflash is ready for its next write operation. +// Doesn't block, except for the SPI state machine to finish any previous SPI host operation. +static bool spiflash_is_ready(void) +{ + spi_wait_ready(); + WRITE_REG(SPI_RD_STATUS_REG, 0); + WRITE_REG(SPI_CMD_REG, SPI_FLASH_RDSR); // Issue read status command + while(READ_REG(SPI_CMD_REG) != 0) { } + uint32_t status_value = READ_REG(SPI_RD_STATUS_REG); + return (status_value & STATUS_WIP_BIT) == 0; +} + +static void spi_write_enable(void) +{ + while(!spiflash_is_ready()) { } + WRITE_REG(SPI_CMD_REG, SPI_FLASH_WREN); + while(READ_REG(SPI_CMD_REG) != 0) { } +} + +bool EsptoolEraseSector(uint32_t sector) +{ + spi_write_enable(); + spi_wait_ready(); + + WRITE_REG(SPI_ADDR_REG, (sector * SPI_FLASH_SEC_SIZE) & 0xffffff); + WRITE_REG(SPI_CMD_REG, SPI_FLASH_SE); // Sector erase, 4KB + while(READ_REG(SPI_CMD_REG) != 0) { } + while(!spiflash_is_ready()) { } + + return true; +} + +#endif // USE_ESPTOOL