Skip to content

Commit

Permalink
Change Reset erase
Browse files Browse the repository at this point in the history
Change Reset erase end address from as seen by SDK (getFlashChipSize) to full flash size (getFlashChipRealSize)
  • Loading branch information
arendst committed Nov 15, 2019
1 parent f64264d commit 822b719
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 6 deletions.
1 change: 1 addition & 0 deletions tasmota/_changelog.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 16 additions & 6 deletions tasmota/settings.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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();
}
Expand Down
91 changes: 91 additions & 0 deletions tasmota/support_esptool.ino
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

#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

0 comments on commit 822b719

Please sign in to comment.