mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-30 18:57:19 +02:00
Merge branch 'feature/add_official_support_for_gd_v4.0' into 'release/v4.0'
spi_flash: move the unlock patch to bootloader and add support for GD (backport v4.0) See merge request espressif/esp-idf!14913
This commit is contained in:
@ -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,14 @@ void bootloader_enable_qio_mode(void);
|
|||||||
*/
|
*/
|
||||||
uint32_t bootloader_read_flash_id();
|
uint32_t bootloader_read_flash_id();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unlock Flash write protect.
|
||||||
|
* Please do not call this function in SDK.
|
||||||
|
*
|
||||||
|
* @note This can be overridden because it's attribute weak.
|
||||||
|
*/
|
||||||
|
esp_err_t bootloader_flash_unlock(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read the SFDP of the flash
|
* @brief Read the SFDP of the flash
|
||||||
*
|
*
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||||
#include <esp_flash_encrypt.h>
|
#include <esp_flash_encrypt.h>
|
||||||
|
#include "flash_qio_mode.h"
|
||||||
|
|
||||||
#ifndef BOOTLOADER_BUILD
|
#ifndef BOOTLOADER_BUILD
|
||||||
/* Normal app version maps to esp_spi_flash.h operations...
|
/* Normal app version maps to esp_spi_flash.h operations...
|
||||||
@ -249,7 +250,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
|||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = spi_to_esp_err(esp_rom_spiflash_unlock());
|
err = bootloader_flash_unlock();
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ static esp_err_t bootloader_main()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
esp_rom_spiflash_unlock();
|
bootloader_flash_unlock();
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
|
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
|
||||||
bootloader_random_enable();
|
bootloader_random_enable();
|
||||||
|
@ -41,7 +41,16 @@
|
|||||||
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
|
#define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */
|
||||||
|
|
||||||
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
|
#define BYTESHIFT(VAR, IDX) (((VAR) >> ((IDX) * 8)) & 0xFF)
|
||||||
|
#define ISSI_ID 0x9D
|
||||||
|
#define GD_Q_ID_HIGH 0xC8
|
||||||
|
#define GD_Q_ID_MID 0x40
|
||||||
|
#define GD_Q_ID_LOW 0x16
|
||||||
|
|
||||||
|
#define ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
|
||||||
|
#define ESP_BOOTLOADER_SPIFLASH_QE_16B BIT9 // QE position when you write 16 bits at one time.
|
||||||
|
#define ESP_BOOTLOADER_SPIFLASH_QE_8B BIT1 // QE position when you write 8 bits(for SR2) at one time.
|
||||||
|
#define ESP_BOOTLOADER_SPIFLASH_WRITE_8B (8)
|
||||||
|
#define ESP_BOOTLOADER_SPIFLASH_WRITE_16B (16)
|
||||||
|
|
||||||
static DRAM_ATTR char TAG[] = "qio_mode";
|
static DRAM_ATTR char TAG[] = "qio_mode";
|
||||||
|
|
||||||
@ -467,3 +476,77 @@ esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
|
|||||||
|
|
||||||
#endif //XMC_SUPPORT
|
#endif //XMC_SUPPORT
|
||||||
|
|
||||||
|
static inline IRAM_ATTR bool is_issi_chip(const esp_rom_spiflash_chip_t* chip)
|
||||||
|
{
|
||||||
|
return BYTESHIFT(chip->device_id, 2) == ISSI_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For GD25Q32, GD25Q64, GD25Q127C, GD25Q128, which use single command to read/write different SR.
|
||||||
|
static inline IRAM_ATTR bool is_gd_q_chip(const esp_rom_spiflash_chip_t* chip)
|
||||||
|
{
|
||||||
|
return BYTESHIFT(chip->device_id, 2) == GD_Q_ID_HIGH && BYTESHIFT(chip->device_id, 1) == GD_Q_ID_MID && BYTESHIFT(chip->device_id, 0) >= GD_Q_ID_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void)
|
||||||
|
{
|
||||||
|
uint16_t status = 0; // status for SR1 or SR1+SR2 if writing SR with 01H + 2Bytes.
|
||||||
|
uint16_t new_status = 0;
|
||||||
|
uint8_t status_sr2 = 0; // status_sr2 for SR2.
|
||||||
|
uint8_t new_status_sr2 = 0;
|
||||||
|
uint8_t write_sr_bit = 0;
|
||||||
|
esp_err_t err = ESP_OK;
|
||||||
|
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
if (is_issi_chip(&g_rom_flashchip)) {
|
||||||
|
write_sr_bit = ESP_BOOTLOADER_SPIFLASH_WRITE_8B;
|
||||||
|
// ISSI chips have different QE position
|
||||||
|
|
||||||
|
status = execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||||
|
|
||||||
|
/* Clear all bits in the mask.
|
||||||
|
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||||
|
*/
|
||||||
|
new_status = status & (~ESP_BOOTLOADER_SPIFLASH_BP_MASK_ISSI);
|
||||||
|
// Skip if nothing needs to be cleared. Otherwise will waste time waiting for the flash to clear nothing.
|
||||||
|
} else if (is_gd_q_chip(&g_rom_flashchip)) {
|
||||||
|
/* The GD chips behaviour is to clear all bits in SR1 and clear bits in SR2 except QE bit.
|
||||||
|
Use 01H to write SR1 and 31H to write SR2.
|
||||||
|
*/
|
||||||
|
write_sr_bit = ESP_BOOTLOADER_SPIFLASH_WRITE_8B;
|
||||||
|
|
||||||
|
status = execute_flash_command(CMD_RDSR, 0, 0, 8);
|
||||||
|
new_status = 0;
|
||||||
|
|
||||||
|
status_sr2 = execute_flash_command(CMD_RDSR2, 0, 0, 8);
|
||||||
|
new_status_sr2 = status_sr2 & ESP_BOOTLOADER_SPIFLASH_QE_8B;
|
||||||
|
} else {
|
||||||
|
/* For common behaviour, like XMC chips, Use 01H+2Bytes to write both SR1 and SR2*/
|
||||||
|
write_sr_bit = ESP_BOOTLOADER_SPIFLASH_WRITE_16B;
|
||||||
|
status = execute_flash_command(CMD_RDSR, 0, 0, 8) | (execute_flash_command(CMD_RDSR2, 0, 0, 8) << 8);
|
||||||
|
|
||||||
|
/* Clear all bits except QE, if it is set.
|
||||||
|
(This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
|
||||||
|
*/
|
||||||
|
new_status = status & ESP_BOOTLOADER_SPIFLASH_QE_16B;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != new_status) {
|
||||||
|
/* if the status in SR not equal to the ideal status, the status need to be updated */
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
execute_flash_command(CMD_WRSR, new_status, write_sr_bit, 0);
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_sr2 != new_status_sr2) {
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
execute_flash_command(CMD_WREN, 0, 0, 0);
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
execute_flash_command(CMD_WRSR2, new_status_sr2, write_sr_bit, 0);
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
}
|
||||||
|
execute_flash_command(CMD_WRDI, 0, 0, 0);
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
@ -88,6 +88,7 @@ static void do_global_ctors(void);
|
|||||||
static void main_task(void* args);
|
static void main_task(void* args);
|
||||||
extern void app_main(void);
|
extern void app_main(void);
|
||||||
extern esp_err_t esp_pthread_init(void);
|
extern esp_err_t esp_pthread_init(void);
|
||||||
|
extern esp_err_t bootloader_flash_unlock(void);
|
||||||
|
|
||||||
extern int _bss_start;
|
extern int _bss_start;
|
||||||
extern int _bss_end;
|
extern int _bss_end;
|
||||||
@ -466,6 +467,7 @@ void start_cpu0_default(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bootloader_flash_update_id();
|
bootloader_flash_update_id();
|
||||||
|
bootloader_flash_unlock();
|
||||||
#if !CONFIG_SPIRAM_BOOT_INIT
|
#if !CONFIG_SPIRAM_BOOT_INIT
|
||||||
// If psram is uninitialized, we need to improve some flash configuration.
|
// If psram is uninitialized, we need to improve some flash configuration.
|
||||||
bootloader_flash_clock_config(&fhdr);
|
bootloader_flash_clock_config(&fhdr);
|
||||||
|
Reference in New Issue
Block a user