Skip to content

Commit

Permalink
Xmc flash 2 (#7317)
Browse files Browse the repository at this point in the history
* 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.

* 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.

* Disable interrupts during the precached part of _SPICommand()

For some reason this was an issue during the reboot after an OTA update.
  • Loading branch information
ChocolateFrogsNuts authored May 27, 2020
1 parent 0deb874 commit 51daecc
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 70 deletions.
98 changes: 30 additions & 68 deletions bootloaders/eboot/eboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <string.h>
#include "flash.h"
#include "eboot_command.h"
#include "spi_vendors.h"
#include <uzlib.h>

extern unsigned char _gzip_dict;
Expand Down Expand Up @@ -115,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 ||
Expand Down Expand Up @@ -158,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)) {
Expand All @@ -179,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;
Expand All @@ -190,29 +202,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;
Expand All @@ -235,47 +224,20 @@ 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]);
res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2], false);
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');

// 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;
Expand Down
Binary file modified bootloaders/eboot/eboot.elf
Binary file not shown.
10 changes: 8 additions & 2 deletions cores/esp8266/core_esp8266_spi_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit 51daecc

Please sign in to comment.