Skip to content

Commit 960d7ae

Browse files
committed
Merge branch 'bugfix/xmc_overerase' into 'master'
feat(bootloader): add xmc spi_flash startup flow to improve reliability See merge request sdk/ESP8266_RTOS_SDK!1661
2 parents ea598f1 + 8381971 commit 960d7ae

File tree

5 files changed

+192
-11
lines changed

5 files changed

+192
-11
lines changed

components/bootloader/Kconfig.projbuild

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,15 @@ config BOOTLOADER_STORE_OFFSET
174174
bootloader of the SDK's bootloader, you can set the option to store SDK's bootloader
175175
to other space in the flash instead of "0x0".
176176

177+
config BOOTLOADER_FLASH_XMC_SUPPORT
178+
bool "Enable the support for flash chips of XMC (READ HELP FIRST)"
179+
default y
180+
help
181+
Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.
182+
XMC chips will be forbidden to be used, when this option is disabled.
183+
184+
DON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.
185+
177186
endmenu # Bootloader
178187

179188

components/bootloader/subproject/main/esp8266.bootloader.rom.ld

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ PROVIDE ( gpio_input_get = 0x40004cf0 );
88

99
PROVIDE ( xthal_get_ccount = 0x4000dd38 );
1010
PROVIDE ( uart_div_modify = 0x400039d8 );
11-
PROVIDE ( ets_io_vprintf = 0x40001f00 );
11+
PROVIDE ( ets_io_vprintf = 0x40001f00 );
12+
PROVIDE ( ets_rom_delay_us = 0x40002ecc );

components/bootloader_support/include_priv/bootloader_flash.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222

2323
#define FLASH_SECTOR_SIZE 0x1000
2424

25+
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
26+
#define CMD_RDJEDECID 0x9F /* Read the JEDEC ID of the flash */
27+
28+
#define XMC_VENDOR_ID 0x20
29+
2530
/* Provide a Flash API for bootloader_support code,
2631
that can be used from bootloader or app code.
2732
@@ -100,4 +105,20 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
100105
*/
101106
esp_err_t bootloader_flash_erase_sector(size_t sector);
102107

108+
/**
109+
* @brief Read the SFDP of the flash
110+
*
111+
* @param sfdp_addr Address of the parameter to read
112+
* @param miso_byte_num Bytes to read
113+
* @return The read SFDP, little endian, 4 bytes at most
114+
*/
115+
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num);
116+
117+
/**
118+
* @brief Startup flow recommended by XMC. Call at startup before any erase/write operation.
119+
*
120+
* @return ESP_OK When startup successfully, otherwise ESP_FAIL (indiciating you should reboot before erase/write).
121+
*/
122+
esp_err_t bootloader_flash_xmc_startup(void);
123+
103124
#endif

components/bootloader_support/src/bootloader_flash.c

Lines changed: 153 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,13 @@ esp_err_t bootloader_flash_erase_sector(size_t sector)
263263

264264
#include "esp_err.h"
265265
#include "esp_log.h"
266+
#include "esp8266/rom_functions.h"
266267

267268
#ifndef BOOTLOADER_BUILD
268269
#include "esp_spi_flash.h"
270+
#else
271+
#include "bootloader_flash.h"
272+
#include "priv/esp_spi_flash_raw.h"
269273
#endif
270274

271275
#ifdef CONFIG_SOC_FULL_ICACHE
@@ -274,18 +278,11 @@ esp_err_t bootloader_flash_erase_sector(size_t sector)
274278
#define SOC_CACHE_SIZE 0 // 16KB
275279
#endif
276280

277-
extern void Cache_Read_Disable();
278-
extern void Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v);
279-
280-
static const char *TAG = "bootloader_flash";
281+
#define XMC_SUPPORT CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT
281282

282-
typedef enum { SPI_FLASH_RESULT_OK = 0,
283-
SPI_FLASH_RESULT_ERR = 1,
284-
SPI_FLASH_RESULT_TIMEOUT = 2 } SpiFlashOpResult;
283+
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
285284

286-
SpiFlashOpResult SPIRead(uint32_t addr, void *dst, uint32_t size);
287-
SpiFlashOpResult SPIWrite(uint32_t addr, const uint8_t *src, uint32_t size);
288-
SpiFlashOpResult SPIEraseSector(uint32_t sector_num);
285+
static const char *TAG = "bootloader_flash";
289286

290287
static bool mapped;
291288

@@ -406,4 +403,150 @@ esp_err_t bootloader_flash_erase_sector(size_t sector)
406403
return ESP_OK;
407404
}
408405

406+
#ifdef BOOTLOADER_BUILD
407+
uint32_t bootloader_read_flash_id(void)
408+
{
409+
uint32_t id = spi_flash_get_id_raw(&g_rom_flashchip);
410+
id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00);
411+
return id;
412+
}
413+
414+
#if XMC_SUPPORT
415+
static bool is_xmc_chip_strict(uint32_t rdid)
416+
{
417+
uint32_t vendor_id = BYTESHIFT(rdid, 2);
418+
uint32_t mfid = BYTESHIFT(rdid, 1);
419+
uint32_t cpid = BYTESHIFT(rdid, 0);
420+
421+
if (vendor_id != XMC_VENDOR_ID) {
422+
return false;
423+
}
424+
425+
bool matched = false;
426+
if (mfid == 0x40) {
427+
if (cpid >= 0x13 && cpid <= 0x20) {
428+
matched = true;
429+
}
430+
} else if (mfid == 0x41) {
431+
if (cpid >= 0x17 && cpid <= 0x20) {
432+
matched = true;
433+
}
434+
} else if (mfid == 0x50) {
435+
if (cpid >= 0x15 && cpid <= 0x16) {
436+
matched = true;
437+
}
438+
}
439+
return matched;
440+
}
441+
442+
bool bootloader_execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
443+
{
444+
bool ret;
445+
spi_cmd_t cmd;
446+
447+
cmd.cmd = command;
448+
cmd.cmd_len = 1;
449+
cmd.addr = NULL;
450+
cmd.addr_len = 0;
451+
cmd.dummy_bits = 0;
452+
cmd.data = NULL;
453+
cmd.data_len = 0;
454+
455+
ret = spi_user_cmd_raw(&g_rom_flashchip, SPI_TX, &cmd);
456+
if (!ret) {
457+
ESP_LOGE(TAG, "failed to write cmd=%02x", command);
458+
}
459+
460+
return ret;
461+
}
462+
463+
uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num)
464+
{
465+
bool ret;
466+
spi_cmd_t cmd;
467+
uint32_t data = 0;
468+
uint32_t addr = sfdp_addr << 8;
469+
470+
cmd.cmd = CMD_RDSFDP;
471+
cmd.cmd_len = 1;
472+
cmd.addr = &addr;
473+
cmd.addr_len = 3;
474+
cmd.dummy_bits = 8;
475+
cmd.data = &data;
476+
cmd.data_len = miso_byte_num;
477+
478+
ret = spi_user_cmd_raw(&g_rom_flashchip, SPI_RX, &cmd);
479+
if (!ret) {
480+
ESP_LOGE(TAG, "failed to read sfdp");
481+
}
482+
483+
return data;
484+
}
485+
486+
esp_err_t bootloader_flash_xmc_startup(void)
487+
{
488+
extern void ets_rom_delay_us(uint16_t us);
489+
490+
uint32_t id = bootloader_read_flash_id();
491+
492+
// If the RDID value is a valid XMC one, may skip the flow
493+
const bool fast_check = true;
494+
if (fast_check && is_xmc_chip_strict(id)) {
495+
ESP_LOGD(TAG, "XMC chip detected by RDID (%08X), skip.", id);
496+
return ESP_OK;
497+
}
498+
499+
// Check the Manufacturer ID in SFDP registers (JEDEC standard). If not XMC chip, no need to run the flow
500+
const int sfdp_mfid_addr = 0x10;
501+
uint8_t mf_id = (bootloader_flash_read_sfdp(sfdp_mfid_addr, 1) & 0xff);
502+
if (mf_id != XMC_VENDOR_ID) {
503+
ESP_LOGD(TAG, "non-XMC chip detected by SFDP Read (%02X), skip.", mf_id);
504+
return ESP_OK;
505+
}
506+
507+
ESP_LOGI(TAG, "XM25QHxxC startup flow");
508+
// Enter DPD
509+
bootloader_execute_flash_command(0xB9, 0, 0, 0);
510+
// Enter UDPD
511+
bootloader_execute_flash_command(0x79, 0, 0, 0);
512+
// Exit UDPD
513+
bootloader_execute_flash_command(0xFF, 0, 0, 0);
514+
// Delay tXUDPD
515+
ets_rom_delay_us(2000);
516+
// Release Power-down
517+
bootloader_execute_flash_command(0xAB, 0, 0, 0);
518+
ets_rom_delay_us(20);
519+
// Read flash ID and check again
520+
id = bootloader_read_flash_id();
521+
if (!is_xmc_chip_strict(id)) {
522+
ESP_LOGE(TAG, "XMC flash startup fail");
523+
return ESP_FAIL;
524+
}
525+
526+
return ESP_OK;
527+
}
528+
#else
529+
static bool is_xmc_chip(uint32_t rdid)
530+
{
531+
uint32_t vendor_id = (rdid >> 16) &0xff;
532+
533+
return vendor_id == XMC_VENDOR_ID;
534+
}
535+
536+
esp_err_t bootloader_flash_xmc_startup(void)
537+
{
538+
uint32_t id = bootloader_read_flash_id();
539+
540+
if (is_xmc_chip(id)) {
541+
ESP_LOGE(TAG, "XMC chip detected(%08X) while support disable.", id);
542+
return ESP_FAIL;
543+
} else {
544+
ESP_LOGI(TAG, "flash chip is %08X", id);
545+
}
546+
547+
return ESP_OK;
548+
}
549+
#endif
550+
#endif
551+
409552
#endif

components/bootloader_support/src/bootloader_init.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,8 @@ esp_err_t bootloader_init()
642642

643643
static esp_err_t bootloader_main()
644644
{
645+
esp_err_t ret;
646+
645647
#ifdef CONFIG_BOOTLOADER_DISABLE_JTAG_IO
646648
/* Set GPIO 12-15 to be normal GPIO */
647649
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12);
@@ -655,6 +657,11 @@ static esp_err_t bootloader_main()
655657

656658
uart_console_configure();
657659

660+
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
661+
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
662+
return ESP_FAIL;
663+
}
664+
658665
esp_image_header_t fhdr;
659666
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) {
660667
ESP_LOGE(TAG, "failed to load bootloader header!");

0 commit comments

Comments
 (0)