From 5c8daf89fd3038b2bde0ce85f0d12fb1a8e61c88 Mon Sep 17 00:00:00 2001 From: Mike Nix Date: Tue, 19 May 2020 20:08:48 +0800 Subject: [PATCH 1/3] Remove unnecessary XMC support from eboot eboot is always run with the flash access speed set to 20MHz, so there is no need for special treatment of XMC chips. --- bootloaders/eboot/eboot.c | 61 ------------------------------------ bootloaders/eboot/eboot.elf | Bin 34780 -> 34912 bytes 2 files changed, 61 deletions(-) diff --git a/bootloaders/eboot/eboot.c b/bootloaders/eboot/eboot.c index edbd92aa54..a213147aa2 100644 --- a/bootloaders/eboot/eboot.c +++ b/bootloaders/eboot/eboot.c @@ -12,7 +12,6 @@ #include #include "flash.h" #include "eboot_command.h" -#include "spi_vendors.h" #include extern unsigned char _gzip_dict; @@ -190,29 +189,6 @@ int copy_raw(const uint32_t src_addr, return 0; } -//#define XMC_SUPPORT -#ifdef XMC_SUPPORT -// Define a few SPI0 registers we need access to -#define ESP8266_REG(addr) *((volatile uint32_t *)(0x60000000+(addr))) -#define SPI0CMD ESP8266_REG(0x200) -#define SPI0CLK ESP8266_REG(0x218) -#define SPI0C ESP8266_REG(0x208) -#define SPI0W0 ESP8266_REG(0x240) - -#define SPICMDRDID (1 << 28) - -/* spi_flash_get_id() - Returns the flash chip ID - same as the SDK function. - We need our own version as the SDK isn't available here. - */ -uint32_t __attribute__((noinline)) spi_flash_get_id() { - SPI0W0=0; - SPI0CMD=SPICMDRDID; - while (SPI0CMD) {} - return SPI0W0; -} -#endif // XMC_SUPPORT - int main() { int res = 9; @@ -235,47 +211,10 @@ int main() if (cmd.action == ACTION_COPY_RAW) { ets_putc('c'); ets_putc('p'); ets_putc(':'); -#ifdef XMC_SUPPORT - // save the flash access speed registers - uint32_t spi0clk = SPI0CLK; - uint32_t spi0c = SPI0C; - - uint32_t vendor = spi_flash_get_id() & 0x000000ff; - if (vendor == SPI_FLASH_VENDOR_XMC) { - uint32_t flashinfo=0; - if (SPIRead(0, &flashinfo, 4)) { - // failed to read the configured flash speed. - // Do not change anything, - } else { - // select an appropriate flash speed - // Register values are those used by ROM - switch ((flashinfo >> 24) & 0x0f) { - case 0x0: // 40MHz, slow to 20 - case 0x1: // 26MHz, slow to 20 - SPI0CLK = 0x00003043; - SPI0C = 0x00EAA313; - break; - case 0x2: // 20MHz, no change - break; - case 0xf: // 80MHz, slow to 26 - SPI0CLK = 0x00002002; - SPI0C = 0x00EAA202; - break; - default: - break; - } - } - } -#endif // XMC_SUPPORT ets_wdt_disable(); res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2]); ets_wdt_enable(); -#ifdef XMC_SUPPORT - // restore the saved flash access speed registers - SPI0CLK = spi0clk; - SPI0C = spi0c; -#endif ets_putc('0'+res); ets_putc('\n'); if (res == 0) { cmd.action = ACTION_LOAD_APP; diff --git a/bootloaders/eboot/eboot.elf b/bootloaders/eboot/eboot.elf index f9a641c2f37fa922c86ed25b7a6ec080d810b940..fa4b6ecffd03c23e0daeae5780b813e17051a7c0 100755 GIT binary patch delta 2669 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 LIU~P+T3P%JIkGs? From 5ad1c0a291928d8f82646f011b3288a23bed9cd9 Mon Sep 17 00:00:00 2001 From: Mike Nix Date: Tue, 19 May 2020 20:17:27 +0800 Subject: [PATCH 2/3] After eboot copies the new firmware into place, verify the copy. If the data written to flash is as expected, the line cmp:0 will be displayed after the usual @cp:0 from eboot. --- bootloaders/eboot/eboot.c | 37 +++++++++++++++++++++++++++++------- bootloaders/eboot/eboot.elf | Bin 34912 -> 35800 bytes 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/bootloaders/eboot/eboot.c b/bootloaders/eboot/eboot.c index a213147aa2..be67b0b6fe 100644 --- a/bootloaders/eboot/eboot.c +++ b/bootloaders/eboot/eboot.c @@ -114,10 +114,12 @@ int uzlib_flash_read_cb(struct uzlib_uncomp *m) } unsigned char gzip_dict[32768]; +uint8_t buffer2[FLASH_SECTOR_SIZE]; // no room for this on the stack int copy_raw(const uint32_t src_addr, const uint32_t dst_addr, - const uint32_t size) + const uint32_t size, + const bool verify) { // require regions to be aligned if ((src_addr & 0xfff) != 0 || @@ -157,8 +159,10 @@ int copy_raw(const uint32_t src_addr, gzip = true; } while (left > 0) { - if (SPIEraseSector(daddr/buffer_size)) { - return 2; + if (!verify) { + if (SPIEraseSector(daddr/buffer_size)) { + return 2; + } } if (!gzip) { if (SPIRead(saddr, buffer, buffer_size)) { @@ -178,8 +182,17 @@ int copy_raw(const uint32_t src_addr, buffer[i] = 0xff; } } - if (SPIWrite(daddr, buffer, buffer_size)) { - return 4; + if (verify) { + if (SPIRead(daddr, buffer2, buffer_size)) { + return 4; + } + if (memcmp(buffer, buffer2, buffer_size)) { + return 9; + } + } else { + if (SPIWrite(daddr, buffer, buffer_size)) { + return 4; + } } saddr += buffer_size; daddr += buffer_size; @@ -212,9 +225,19 @@ int main() ets_putc('c'); ets_putc('p'); ets_putc(':'); ets_wdt_disable(); - res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2]); + res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2], false); ets_wdt_enable(); - + + ets_putc('0'+res); ets_putc('\n'); + + // Verify the copy + ets_putc('c'); ets_putc('m'); ets_putc('p'); ets_putc(':'); + if (res == 0) { + ets_wdt_disable(); + res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2], true); + ets_wdt_enable(); + } + ets_putc('0'+res); ets_putc('\n'); if (res == 0) { cmd.action = ACTION_LOAD_APP; diff --git a/bootloaders/eboot/eboot.elf b/bootloaders/eboot/eboot.elf index fa4b6ecffd03c23e0daeae5780b813e17051a7c0..60329d847e6307f2211d8c762ff1a6f68c4da0d7 100755 GIT binary patch literal 35800 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 Date: Thu, 21 May 2020 07:58:57 +0800 Subject: [PATCH 3/3] Disable interrupts during the precached part of _SPICommand() For some reason this was an issue during the reboot after an OTA update. --- cores/esp8266/core_esp8266_spi_utils.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cores/esp8266/core_esp8266_spi_utils.cpp b/cores/esp8266/core_esp8266_spi_utils.cpp index 110b139688..ccf800e7d9 100644 --- a/cores/esp8266/core_esp8266_spi_utils.cpp +++ b/cores/esp8266/core_esp8266_spi_utils.cpp @@ -52,7 +52,7 @@ static SpiOpResult PRECACHE_ATTR _SPICommand(volatile uint32_t spiIfNum, uint32_t spic,uint32_t spiu,uint32_t spiu1,uint32_t spiu2, uint32_t *data,uint32_t writeWords,uint32_t readWords) -{ +{ if (spiIfNum>1) return SPI_RESULT_ERR; @@ -69,8 +69,11 @@ _SPICommand(volatile uint32_t spiIfNum, volatile SpiFlashChip *fchip=flashchip; volatile uint32_t spicmdusr=SPICMDUSR; + uint32_t saved_ps=0; + if (!spiIfNum) { - // Only need to precache when using SPI0 + // Only need to disable interrupts and precache when using SPI0 + saved_ps = xt_rsil(15); PRECACHE_START(); Wait_SPI_Idlep((SpiFlashChip *)fchip); } @@ -116,6 +119,9 @@ _SPICommand(volatile uint32_t spiIfNum, SPIREG(SPI0C) = oldSPI0C; PRECACHE_END(); + if (!spiIfNum) { + xt_wsr_ps(saved_ps); + } return (timeout>0 ? SPI_RESULT_OK : SPI_RESULT_TIMEOUT); }