mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/xmc_overerase_xiaomi_v4.0' into customer/maintain_v4.0_xiaomi_tsf_issue
See merge request espressif/esp-idf!13892
This commit is contained in:
commit
b7c8288056
@ -219,6 +219,22 @@ menu "Bootloader config"
|
|||||||
It allow to test anti-rollback implemention without permanent write eFuse bits.
|
It allow to test anti-rollback implemention without permanent write eFuse bits.
|
||||||
In partition table should be exist this partition `emul_efuse, data, 5, , 0x2000`.
|
In partition table should be exist this partition `emul_efuse, data, 5, , 0x2000`.
|
||||||
|
|
||||||
|
choice BOOTLOADER_FLASH_XMC_OVERERASE_PATCH
|
||||||
|
bool "Patch strategy for XMC over-erase issue"
|
||||||
|
default BOOTLOADER_FLASH_XMC_OVERERASE_PATCH_DEFAULT
|
||||||
|
help
|
||||||
|
Specify the patch strategy for XMC chips. The over-erase issue may exist on
|
||||||
|
XM25QH16C, XM25QH32C and XM25QH128C.
|
||||||
|
|
||||||
|
config BOOTLOADER_FLASH_XMC_OVERERASE_PATCH_ALL
|
||||||
|
bool "Run the patch for all XMC chips. This can completely avoid over-erase issue. But may cost some time."
|
||||||
|
config BOOTLOADER_FLASH_XMC_OVERERASE_PATCH_DEFAULT
|
||||||
|
bool "Run the patch on XMC chips when there are clues indicating the flash is running incorrectly."
|
||||||
|
config BOOTLOADER_FLASH_XMC_OVERERASE_PATCH_BYPASS
|
||||||
|
bool "Not using the patch"
|
||||||
|
|
||||||
|
endchoice # BOOTLOADER_FLASH_XMC_OVERERASE_PATCH
|
||||||
|
|
||||||
endmenu # Bootloader
|
endmenu # Bootloader
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
/** @brief Enable Quad I/O mode in bootloader (if configured)
|
/** @brief Enable Quad I/O mode in bootloader (if configured)
|
||||||
*
|
*
|
||||||
* Queries attached SPI flash ID and sends correct SPI flash
|
* Queries attached SPI flash ID and sends correct SPI flash
|
||||||
@ -32,6 +34,8 @@ void bootloader_enable_qio_mode(void);
|
|||||||
*/
|
*/
|
||||||
uint32_t bootloader_read_flash_id();
|
uint32_t bootloader_read_flash_id();
|
||||||
|
|
||||||
|
esp_err_t bootloader_xmc_flash_overerase_fix();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -120,8 +120,16 @@ esp_err_t bootloader_init()
|
|||||||
static esp_err_t bootloader_main()
|
static esp_err_t bootloader_main()
|
||||||
{
|
{
|
||||||
bootloader_common_vddsdio_configure();
|
bootloader_common_vddsdio_configure();
|
||||||
|
|
||||||
/* Read and keep flash ID, for further use. */
|
/* Read and keep flash ID, for further use. */
|
||||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||||
|
#if CONFIG_BOOTLOADER_FLASH_XMC_OVERERASE_PATCH_ALL || CONFIG_BOOTLOADER_FLASH_XMC_OVERERASE_PATCH_DEFAULT
|
||||||
|
if (bootloader_xmc_flash_overerase_fix() != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "failed to fix XMC flash overerase, reboot!");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
esp_image_header_t fhdr;
|
esp_image_header_t fhdr;
|
||||||
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "failed to load bootloader header!");
|
ESP_LOGE(TAG, "failed to load bootloader header!");
|
||||||
|
@ -306,3 +306,111 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
|||||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||||
return SPIFLASH.data_buf[0];
|
return SPIFLASH.data_buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cmd(0x5A) + 24bit address + 8 cycles dummy
|
||||||
|
static uint32_t bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigned int miso_byte_num)
|
||||||
|
{
|
||||||
|
assert(miso_byte_num <= 4);
|
||||||
|
uint8_t command = 0x5A;
|
||||||
|
uint8_t miso_len = miso_byte_num * 8;
|
||||||
|
uint8_t mosi_len = 0;
|
||||||
|
uint32_t mosi_data = 0;
|
||||||
|
|
||||||
|
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||||
|
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||||
|
SPIFLASH.user.usr_dummy = 1;
|
||||||
|
SPIFLASH.user1.usr_dummy_cyclelen = 7 + g_rom_spiflash_dummy_len_plus[1];
|
||||||
|
SPIFLASH.user.usr_addr = 1;
|
||||||
|
SPIFLASH.addr = (sfdp_addr<<8);
|
||||||
|
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||||
|
SPIFLASH.user.usr_command = 1;
|
||||||
|
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||||
|
|
||||||
|
SPIFLASH.user2.usr_command_value = command;
|
||||||
|
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||||
|
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||||
|
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||||
|
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||||
|
SPIFLASH.data_buf[0] = mosi_data;
|
||||||
|
|
||||||
|
SPIFLASH.cmd.usr = 1;
|
||||||
|
while(SPIFLASH.cmd.usr != 0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||||
|
uint32_t ret = SPIFLASH.data_buf[0];
|
||||||
|
if (miso_len < 32) {
|
||||||
|
//set unused bits to 0
|
||||||
|
ret &= ~(UINT32_MAX << miso_len);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define XMC_VENDOR_ID 0x20
|
||||||
|
|
||||||
|
//use strict model checking for over-erase issue
|
||||||
|
static bool is_xmc_chip_strict(uint32_t rdid)
|
||||||
|
{
|
||||||
|
uint32_t vendor_id = (rdid >> 16) & 0xFF;
|
||||||
|
uint32_t mfid = (rdid >> 8) & 0xFF;
|
||||||
|
uint32_t cpid = rdid & 0xFF;
|
||||||
|
|
||||||
|
if (vendor_id != XMC_VENDOR_ID) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool matched = false;
|
||||||
|
if (mfid == 0x40) {
|
||||||
|
if (cpid >= 0x13 && cpid <= 0x20) {
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
} else if (mfid == 0x41) {
|
||||||
|
if (cpid >= 0x17 && cpid <= 0x20) {
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
} else if (mfid == 0x50) {
|
||||||
|
if (cpid >= 0x15 && cpid <= 0x16) {
|
||||||
|
matched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t bootloader_xmc_flash_overerase_fix()
|
||||||
|
{
|
||||||
|
#if CONFIG_BOOTLOADER_FLASH_XMC_OVERERASE_PATCH_DEFAULT
|
||||||
|
//correct RDID value means the issue doesn't occur
|
||||||
|
if (is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check vendor ID in SFDP registers. If not XMC chip, no need to run the patch
|
||||||
|
uint8_t mf_id = (bootloader_flash_read_sfdp(0x10, 1) & 0xff);
|
||||||
|
if (mf_id != XMC_VENDOR_ID) {
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "XM25QHxxC flash overerase fix");
|
||||||
|
// Enter DPD
|
||||||
|
execute_flash_command(0xB9, 0, 0, 0);
|
||||||
|
// Enter UDPD
|
||||||
|
execute_flash_command(0x79, 0, 0, 0);
|
||||||
|
// Exit UDPD
|
||||||
|
execute_flash_command(0xFF, 0, 0, 0);
|
||||||
|
// Delay tXUDPD
|
||||||
|
ets_delay_us(2000);
|
||||||
|
// Release Power-down
|
||||||
|
execute_flash_command(0xAB, 0, 0, 0);
|
||||||
|
ets_delay_us(20);
|
||||||
|
// Read flash ID and check
|
||||||
|
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||||
|
if (!is_xmc_chip_strict(g_rom_flashchip.device_id)) {
|
||||||
|
// fail
|
||||||
|
ESP_LOGE(TAG, "XM25QH32C flash overerase fix fail");
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user