mirror of
https://github.com/espressif/esp-idf.git
synced 2024-09-20 00:36:01 -04:00
Merge branch 'feature/support_flash_sus_res_c3' into 'master'
spi_flash: Add flash auto-suspend auto-resume mode on esp32c3 Closes IDF-2591 See merge request espressif/esp-idf!11888
This commit is contained in:
commit
7a20ea5f0e
@ -38,6 +38,7 @@
|
||||
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
|
||||
#define CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */
|
||||
#define CMD_WRAP 0x77 /* Set burst with wrap command */
|
||||
#define CMD_RESUME 0x7A /* Resume command to clear flash suspend bit */
|
||||
|
||||
|
||||
/* Provide a Flash API for bootloader_support code,
|
||||
|
@ -193,6 +193,12 @@ static void IRAM_ATTR bootloader_init_flash_configure(void)
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static void bootloader_spi_flash_resume(void)
|
||||
{
|
||||
bootloader_execute_flash_command(CMD_RESUME, 0, 0, 0);
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_flash_configure();
|
||||
@ -204,6 +210,7 @@ static esp_err_t bootloader_init_spi_flash(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloader_spi_flash_resume();
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
|
@ -105,6 +105,147 @@ static inline void spimem_flash_ll_erase_block(spi_mem_dev_t *dev)
|
||||
dev->cmd.flash_be = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspend erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_suspend(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_pes = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume suspended erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_per = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto suspend mode, and esp32c3 doesn't support disable auto-suspend.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_sus Enable/disable Flash Auto-Suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_suspend_init(spi_mem_dev_t *dev, bool auto_sus)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_pes_en = auto_sus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto resume mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_res Enable/Disable Flash Auto-Resume.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool auto_res)
|
||||
{
|
||||
dev->flash_sus_ctrl.pes_per_en = auto_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash suspend command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_cmd Flash suspend command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_pes_command = sus_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash resume command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param res_cmd Flash resume command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_per_command = res_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash read suspend status command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param pesr_cmd Flash read suspend status command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd)
|
||||
{
|
||||
dev->flash_sus_cmd.wait_pesr_command = pesr_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to check SUS/SUS1/SUS2 to ensure the suspend status of flashs.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_check_sus_en 1: enable, 0: disable.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_sus_check_sus_setup(spi_mem_dev_t *dev, bool sus_check_sus_en)
|
||||
{
|
||||
dev->flash_sus_ctrl.sus_timeout_cnt = 5;
|
||||
dev->flash_sus_ctrl.pes_end_en = sus_check_sus_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to check SUS/SUS1/SUS2 to ensure the resume status of flashs.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_check_sus_en 1: enable, 0: disable.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool res_check_sus_en)
|
||||
{
|
||||
dev->flash_sus_ctrl.sus_timeout_cnt = 5;
|
||||
dev->flash_sus_ctrl.per_end_en = res_check_sus_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 8 bit command to read suspend status
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_conf)
|
||||
{
|
||||
dev->flash_sus_ctrl.frd_sus_2b = 0;
|
||||
dev->flash_sus_ctrl.pesr_end_msk = sus_conf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
{
|
||||
dev->flash_waiti_ctrl.waiti_cmd = 0x05;
|
||||
dev->flash_sus_ctrl.flash_per_wait_en = auto_waiti;
|
||||
dev->flash_sus_ctrl.flash_pes_wait_en = auto_waiti;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the suspend status of erase or program operations.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if suspended, otherwise false.
|
||||
*/
|
||||
static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev)
|
||||
{
|
||||
return dev->sus_status.flash_sus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable write protection for the flash chip.
|
||||
*
|
||||
|
@ -105,6 +105,143 @@ static inline void spimem_flash_ll_erase_block(spi_mem_dev_t *dev)
|
||||
dev->cmd.flash_be = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspend erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_suspend(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_pes = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume suspended erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_per = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto suspend mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_sus Enable/disable Flash Auto-Suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_suspend_init(spi_mem_dev_t *dev, bool auto_sus)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_pes_en = auto_sus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto resume mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_res Enable/Disable Flash Auto-Resume.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool auto_res)
|
||||
{
|
||||
dev->misc.auto_per = 0; // Must disable Hardware Auto-Resume (should not be enabled, ESP32-S2 has bugs).
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 8 bit command to read suspend status
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_mask)
|
||||
{
|
||||
abort();// Not supported on esp32s2
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash suspend command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_cmd Flash suspend command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_pes_command = sus_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash resume command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param res_cmd Flash resume command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_per_command = res_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash read suspend status command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param pesr_cmd Flash read suspend status command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd)
|
||||
{
|
||||
abort();// Not supported on esp32s2
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to check SUS/SUS1/SUS2 to ensure the suspend status of flashs.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_check_sus_en 1: enable, 0: disable.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_sus_check_sus_setup(spi_mem_dev_t *dev, bool sus_check_sus_en)
|
||||
{
|
||||
abort();// Not supported on esp32s2
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to check SUS/SUS1/SUS2 to ensure the resume status of flashs.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_check_sus_en 1: enable, 0: disable.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool res_check_sus_en)
|
||||
{
|
||||
abort();// Not supported on esp32s2
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
{
|
||||
dev->flash_waiti_ctrl.waiti_cmd = 0x05; // Set the command to send, to fetch flash status reg value.
|
||||
dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function.
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the suspend status of erase or program operations.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if suspended, otherwise false.
|
||||
*/
|
||||
static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev)
|
||||
{
|
||||
return dev->sus_status.flash_sus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable write protection for the flash chip.
|
||||
*
|
||||
|
@ -105,6 +105,144 @@ static inline void spimem_flash_ll_erase_block(spi_mem_dev_t *dev)
|
||||
dev->cmd.flash_be = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspend erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_suspend(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_pes = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume suspended erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->flash_sus_cmd.flash_per = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_sus Enable/disable Flash Auto-Suspend.
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_suspend_init(spi_mem_dev_t *dev, bool auto_sus)
|
||||
{
|
||||
dev->user.usr_dummy_idle = 1;// MUST SET 1, to avoid missing Resume
|
||||
dev->flash_sus_ctrl.flash_pes_en = auto_sus; // enable Flash Auto-Suspend.
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto resume mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_res Enable/Disable Flash Auto-Resume.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool auto_res)
|
||||
{
|
||||
dev->misc.auto_per = auto_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash suspend command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_cmd Flash suspend command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_t sus_cmd)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_pes_command = sus_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash resume command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param res_cmd Flash resume command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t res_cmd)
|
||||
{
|
||||
dev->flash_sus_ctrl.flash_per_command = res_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the flash read suspend status command, may vary from chips to chips.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param pesr_cmd Flash read suspend status command.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_rd_sus_cmd_setup(spi_mem_dev_t *dev, uint32_t pesr_cmd)
|
||||
{
|
||||
abort(); //Not support on esp32s3
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to check SUS/SUS1/SUS2 to ensure the suspend status of flashs.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_check_sus_en 1: enable, 0: disable.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_sus_check_sus_setup(spi_mem_dev_t *dev, bool sus_check_sus_en)
|
||||
{
|
||||
abort(); //Not support on esp32s3
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to check SUS/SUS1/SUS2 to ensure the resume status of flashs.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param sus_check_sus_en 1: enable, 0: disable.
|
||||
*
|
||||
*/
|
||||
static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool res_check_sus_en)
|
||||
{
|
||||
abort(); //Not support ont esp32s3
|
||||
}
|
||||
|
||||
/**
|
||||
* Set 8 bit command to read suspend status
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_read_sus_status(spi_mem_dev_t *dev, uint32_t sus_mask)
|
||||
{
|
||||
abort();// Not supported on esp32s3
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto wait idle mode
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
*/
|
||||
static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti)
|
||||
{
|
||||
dev->flash_waiti_ctrl.waiti_cmd = 0x05; // Set the command to send, to fetch flash status reg value.
|
||||
dev->flash_waiti_ctrl.waiti_en = auto_waiti; // enable auto wait-idle function.
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the suspend status of erase or program operations.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if suspended, otherwise false.
|
||||
*/
|
||||
static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev)
|
||||
{
|
||||
return dev->sus_status.flash_sus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable write protection for the flash chip.
|
||||
*
|
||||
|
@ -48,18 +48,22 @@ typedef struct {
|
||||
};
|
||||
spi_flash_ll_clock_reg_t clock_conf; ///< Pre-calculated clock configuration value
|
||||
esp_flash_io_mode_t base_io_mode; ///< Default IO mode mask for common commands
|
||||
uint32_t reserved_config[1]; ///< The ROM has reserved some memory for configurations with one set of driver code. (e.g. QPI mode, 64-bit address mode, etc.)
|
||||
uint32_t flags; ///< Flags for configurations with one set of driver code. (e.g. QPI mode, auto-suspend mode, 64-bit address mode, etc.)
|
||||
#define SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND BIT(0) ///< When the auto-suspend is setup in configuration.
|
||||
#define SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME BIT(1) ///< Setup auto-resume feature.
|
||||
spi_flash_sus_cmd_conf sus_cfg; ///< To store suspend command/mask information.
|
||||
} spi_flash_hal_context_t;
|
||||
_Static_assert(sizeof(spi_flash_hal_context_t) == 28, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM");
|
||||
_Static_assert(sizeof(spi_flash_hal_context_t) == 36, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM");
|
||||
|
||||
/// Configuration structure for the SPI driver.
|
||||
typedef struct {
|
||||
spi_host_device_t host_id; ///< SPI peripheral ID.
|
||||
int cs_num; ///< Which cs pin is used, 0-(SOC_SPI_PERIPH_CS_NUM-1).
|
||||
bool iomux; ///< Whether the IOMUX is used, used for timing compensation.
|
||||
int input_delay_ns; ///< Input delay on the MISO pin after the launch clock, used for timing compensation.
|
||||
int input_delay_ns; ///< Input delay on the MISO pin after the launch clock, used for timing compensation.
|
||||
esp_flash_speed_t speed;///< SPI flash clock speed to work at.
|
||||
uint32_t cs_hold; ///< CS hold time config used by the host
|
||||
bool auto_sus_en; ///< Auto suspend feature enable bit 1: enable, 0: disable.
|
||||
} spi_flash_hal_config_t;
|
||||
|
||||
/**
|
||||
@ -160,9 +164,9 @@ esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp);
|
||||
*
|
||||
* @param host The driver context.
|
||||
*
|
||||
* @return ture if idle, otherwise false.
|
||||
* @return 0:busy, 1:idle, 2:suspended.
|
||||
*/
|
||||
bool spi_flash_hal_host_idle(spi_flash_host_inst_t *host);
|
||||
uint32_t spi_flash_hal_check_status(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* @brief Configure the SPI host hardware registers for the specified io mode.
|
||||
@ -226,3 +230,29 @@ bool spi_flash_hal_supports_direct_write(spi_flash_host_inst_t *host, const void
|
||||
* @return True if the buffer can be used to receive data, otherwise false.
|
||||
*/
|
||||
bool spi_flash_hal_supports_direct_read(spi_flash_host_inst_t *host, const void *p);
|
||||
|
||||
/**
|
||||
* @brief Resume flash chip status from suspend.
|
||||
*
|
||||
* @param host The driver context.
|
||||
*
|
||||
*/
|
||||
void spi_flash_hal_resume(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* @brief Set the flash into suspend status manually.
|
||||
*
|
||||
* @param host The driver context.
|
||||
*
|
||||
*/
|
||||
void spi_flash_hal_suspend(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* To setup for reading flash suspend status register
|
||||
*
|
||||
* @param host The driver context.
|
||||
* @param sus_conf Flash chip suspend feature configuration, mainly for command config, may vary from chip to chip.
|
||||
*
|
||||
* @return Always ESP_OK
|
||||
*/
|
||||
esp_err_t spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf);
|
||||
|
@ -75,6 +75,17 @@ typedef enum {
|
||||
SPI_FLASH_READ_MODE_MAX, ///< The fastest io mode supported by the host is ``ESP_FLASH_READ_MODE_MAX-1``.
|
||||
} esp_flash_io_mode_t;
|
||||
|
||||
/// Configuration structure for the flash chip suspend feature.
|
||||
typedef struct {
|
||||
uint32_t sus_mask; ///< SUS/SUS1/SUS2 bit in flash register.
|
||||
struct {
|
||||
uint32_t cmd_rdsr :8; ///< Read flash status register(2) command.
|
||||
uint32_t sus_cmd :8; ///< Flash suspend command.
|
||||
uint32_t res_cmd :8; ///< Flash resume command.
|
||||
uint32_t reserved :8; ///< Reserved, set to 0.
|
||||
};
|
||||
} spi_flash_sus_cmd_conf;
|
||||
|
||||
///Slowest io mode supported by ESP32, currently SlowRd
|
||||
#define SPI_FLASH_READ_MODE_MIN SPI_FLASH_SLOWRD
|
||||
|
||||
@ -159,9 +170,9 @@ struct spi_flash_host_driver_s {
|
||||
*/
|
||||
int (*read_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size);
|
||||
/**
|
||||
* Check whether the host is idle to perform new operations.
|
||||
* Check the host status, 0:busy, 1:idle, 2:suspended.
|
||||
*/
|
||||
bool (*host_idle)(spi_flash_host_inst_t *host);
|
||||
uint32_t (*host_status)(spi_flash_host_inst_t *host);
|
||||
/**
|
||||
* Configure the host to work at different read mode. Responsible to compensate the timing and set IO mode.
|
||||
*/
|
||||
@ -177,6 +188,21 @@ struct spi_flash_host_driver_s {
|
||||
* modified, the cache needs to be flushed. Left NULL if not supported.
|
||||
*/
|
||||
esp_err_t (*flush_cache)(spi_flash_host_inst_t* host, uint32_t addr, uint32_t size);
|
||||
|
||||
/**
|
||||
* Resume flash from suspend manually
|
||||
*/
|
||||
void (*resume)(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* Set flash in suspend status manually
|
||||
*/
|
||||
void (*suspend)(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* Suspend feature setup for setting cmd and status register mask.
|
||||
*/
|
||||
esp_err_t (*sus_setup)(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf);
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -91,6 +91,10 @@ esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_
|
||||
.clock_conf = clock_cfg->clock_reg_val,
|
||||
.cs_hold = cfg->cs_hold,
|
||||
};
|
||||
if (cfg->auto_sus_en) {
|
||||
data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND;
|
||||
data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME;
|
||||
}
|
||||
|
||||
ESP_EARLY_LOGD(TAG, "extra_dummy: %d", data_out->extra_dummy);
|
||||
return ESP_OK;
|
||||
|
@ -50,6 +50,20 @@ esp_err_t spi_flash_hal_device_config(spi_flash_host_inst_t *host)
|
||||
spi_flash_ll_set_clock(dev, &ctx->clock_conf);
|
||||
int cs_hold = ctx->cs_hold;
|
||||
spi_flash_ll_set_hold(dev, cs_hold);
|
||||
#ifndef GPSPI_BUILD
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
if ((ctx->flags & SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND) != 0) {
|
||||
spi_flash_hal_setup_auto_suspend_mode(host);
|
||||
} else {
|
||||
spi_flash_hal_disable_auto_suspend_mode(host);
|
||||
}
|
||||
if ((ctx->flags & SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME) != 0) {
|
||||
spi_flash_hal_setup_auto_resume_mode(host);
|
||||
} else {
|
||||
spi_flash_hal_disable_auto_resume_mode(host);
|
||||
}
|
||||
#endif //SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
#endif //GPSPI_BUILD
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -78,7 +92,7 @@ esp_err_t spi_flash_hal_configure_host_io_mode(
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL
|
||||
#if CONFIG_SPI_FLASH_ROM_IMPL && CONFIG_IDF_TARGET_ESP32S3
|
||||
/*
|
||||
* In S3 ROM, extra bits than 24-bit are used to indicate requirements of M7-M0:
|
||||
* - 24: normal transactions
|
||||
|
@ -36,7 +36,7 @@ bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_inst_t *host, const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool spi_flash_hal_gpspi_host_idle(spi_flash_host_inst_t *host)
|
||||
uint32_t spi_flash_hal_gpspi_check_status(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_dev_t *dev = get_spi_dev(host);
|
||||
return spi_flash_ll_host_idle(dev);
|
||||
|
@ -13,30 +13,33 @@
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "hal/spi_flash_hal.h"
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host);
|
||||
void spi_flash_hal_disable_auto_resume_mode(spi_flash_host_inst_t *host);
|
||||
void spi_flash_hal_disable_auto_suspend_mode(spi_flash_host_inst_t *host);
|
||||
void spi_flash_hal_setup_auto_resume_mode(spi_flash_host_inst_t *host);
|
||||
#endif //SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
#include "spi_flash_hal_common.inc"
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
// HAL for
|
||||
// - MEMSPI
|
||||
// - SPI1~3 on ESP32
|
||||
// - SPI1~3 on ESP32/S2/S3/C3
|
||||
// The common part is in spi_flash_hal_common.inc
|
||||
|
||||
// HAL for
|
||||
// - MEMSPI
|
||||
// - SPI1~3 on ESP32
|
||||
// The common part is in spi_flash_hal_common.inc
|
||||
|
||||
// HAL for
|
||||
// - MEMSPI
|
||||
// - SPI1~3 on ESP32
|
||||
// The common part is in spi_flash_hal_common.inc
|
||||
|
||||
#include "spi_flash_hal_common.inc"
|
||||
|
||||
void spi_flash_hal_erase_chip(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_dev_t *dev = get_spi_dev(host);
|
||||
spi_flash_ll_erase_chip(dev);
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE
|
||||
if((((spi_flash_hal_context_t*)host)->flags & SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND) == 0) {
|
||||
host->driver->poll_cmd_done(host);
|
||||
}
|
||||
#else
|
||||
host->driver->poll_cmd_done(host);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Only support 24bit address
|
||||
@ -46,7 +49,14 @@ void spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_addr
|
||||
spi_flash_ll_set_addr_bitlen(dev, 24);
|
||||
spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT);
|
||||
spi_flash_ll_erase_sector(dev);
|
||||
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE
|
||||
if((((spi_flash_hal_context_t*)host)->flags & SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND) == 0) {
|
||||
host->driver->poll_cmd_done(host);
|
||||
}
|
||||
#else
|
||||
host->driver->poll_cmd_done(host);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Only support 24bit address
|
||||
@ -56,7 +66,13 @@ void spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_addre
|
||||
spi_flash_ll_set_addr_bitlen(dev, 24);
|
||||
spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT);
|
||||
spi_flash_ll_erase_block(dev);
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE
|
||||
if((((spi_flash_hal_context_t*)host)->flags & SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND) == 0) {
|
||||
host->driver->poll_cmd_done(host);
|
||||
}
|
||||
#else
|
||||
host->driver->poll_cmd_done(host);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Only support 24bit address
|
||||
@ -77,22 +93,97 @@ esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool spi_flash_hal_host_idle(spi_flash_host_inst_t *host)
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
uint32_t spi_flash_hal_check_status(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_dev_t *dev = get_spi_dev(host);
|
||||
bool idle = spi_flash_ll_host_idle(dev);
|
||||
|
||||
uint32_t status = spi_flash_ll_host_idle(dev);
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE
|
||||
uint32_t sus_status = spimem_flash_ll_sus_status((spi_mem_dev_t*)dev) << 1;
|
||||
#else
|
||||
uint32_t sus_status = 0;
|
||||
#endif
|
||||
// Not clear if this is necessary, or only necessary if
|
||||
// chip->spi == SPI1. But probably doesn't hurt...
|
||||
if ((void*) dev == spi_flash_ll_get_hw(SPI_HOST)) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
idle &= spi_flash_ll_host_idle(&SPI0);
|
||||
#else
|
||||
idle &= spi_flash_ll_host_idle(&SPIMEM0);
|
||||
status &= spi_flash_ll_host_idle(&SPI0);
|
||||
#endif
|
||||
}
|
||||
|
||||
return idle;
|
||||
//status and sus_status should be mutual exclusion
|
||||
return (status | sus_status);
|
||||
}
|
||||
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
esp_err_t spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf)
|
||||
{
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t *)spi_flash_ll_get_hw(SPI_HOST);
|
||||
spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)host;
|
||||
memcpy(&(ctx->sus_cfg), sus_conf, sizeof(spi_flash_sus_cmd_conf));
|
||||
spimem_flash_ll_set_read_sus_status(dev, sus_conf->sus_mask);
|
||||
spimem_flash_ll_suspend_cmd_setup(dev, sus_conf->sus_cmd);
|
||||
spimem_flash_ll_resume_cmd_setup(dev, sus_conf->res_cmd);
|
||||
spimem_flash_ll_rd_sus_cmd_setup(dev, sus_conf->cmd_rdsr);
|
||||
#endif // SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t*)spi_flash_ll_get_hw(SPI_HOST);
|
||||
spimem_flash_ll_auto_wait_idle_init(dev, true);
|
||||
spimem_flash_ll_auto_suspend_init(dev, true);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_sus_check_sus_setup(dev, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void spi_flash_hal_setup_auto_resume_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t*)spi_flash_ll_get_hw(SPI_HOST);
|
||||
spimem_flash_ll_auto_resume_init(dev, true);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_res_check_sus_setup(dev, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void spi_flash_hal_disable_auto_suspend_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t *)spi_flash_ll_get_hw(SPI_HOST);
|
||||
spimem_flash_ll_auto_wait_idle_init(dev, false);
|
||||
spimem_flash_ll_auto_suspend_init(dev, false);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_sus_check_sus_setup(dev, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void spi_flash_hal_disable_auto_resume_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
spi_mem_dev_t *dev = (spi_mem_dev_t*)spi_flash_ll_get_hw(SPI_HOST);
|
||||
spimem_flash_ll_auto_resume_init(dev, false);
|
||||
#if SOC_SPI_MEM_SUPPORT_CHECK_SUS
|
||||
spimem_flash_ll_res_check_sus_setup(dev, false);
|
||||
#endif
|
||||
}
|
||||
#endif // SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND
|
||||
|
||||
void spi_flash_hal_resume(spi_flash_host_inst_t *host)
|
||||
{
|
||||
#if SOC_SPI_MEM_SUPPORT_SW_SUSPEND
|
||||
spimem_flash_ll_resume((spi_mem_dev_t*)(((spi_flash_hal_context_t *)host)->spi));
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void spi_flash_hal_suspend(spi_flash_host_inst_t *host)
|
||||
{
|
||||
#if SOC_SPI_MEM_SUPPORT_SW_SUSPEND
|
||||
spimem_flash_ll_suspend((spi_mem_dev_t *)(((spi_flash_hal_context_t *)host)->spi));
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
@ -123,6 +123,13 @@
|
||||
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
|
||||
#define SOC_COEX_HW_PTI (1)
|
||||
|
||||
/*-------------------------- SPI MEM CAPS ---------------------------------------*/
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_RESUME (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_IDLE_INTR (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1)
|
||||
/*-------------------------- Power Management CAPS ----------------------------*/
|
||||
#define SOC_PM_SUPPORT_WIFI_WAKEUP (1)
|
||||
|
||||
|
@ -297,6 +297,10 @@
|
||||
/*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/
|
||||
#define SOC_WIFI_HW_TSF (1)
|
||||
|
||||
/*-------------------------- SPI MEM CAPS ---------------------------------------*/
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
|
||||
/*-------------------------- Power Management CAPS ---------------------------*/
|
||||
#define SOC_PM_SUPPORT_EXT_WAKEUP (1)
|
||||
|
||||
|
@ -266,7 +266,7 @@ typedef volatile struct spi_mem_dev_s {
|
||||
};
|
||||
uint32_t val;
|
||||
} fsm;
|
||||
uint32_t data_buf[18]; /*data buffer*/
|
||||
uint32_t data_buf[16]; /*data buffer*/
|
||||
union {
|
||||
struct {
|
||||
uint32_t waiti_en: 1; /*auto-waiting flash idle operation when program flash or erase flash. 1: enable 0: disable.*/
|
||||
@ -699,6 +699,7 @@ typedef volatile struct spi_mem_dev_s {
|
||||
uint32_t val;
|
||||
} date;
|
||||
} spi_mem_dev_t;
|
||||
_Static_assert(sizeof(spi_mem_dev_t) == 0x400, "invalid spi_mem_dev_t size");
|
||||
extern spi_mem_dev_t SPIMEM0;
|
||||
extern spi_mem_dev_t SPIMEM1;
|
||||
#ifdef __cplusplus
|
||||
|
@ -167,5 +167,11 @@
|
||||
/*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/
|
||||
#define SOC_WIFI_HW_TSF (1)
|
||||
|
||||
|
||||
/*-------------------------- SPI MEM CAPS ---------------------------------------*/
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_AUTO_RESUME (1)
|
||||
#define SOC_SPI_MEM_SUPPORT_SW_SUSPEND (1)
|
||||
/*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
|
||||
#define SOC_COEX_HW_PTI (1)
|
||||
|
@ -85,6 +85,7 @@ else()
|
||||
"spi_flash_chip_mxic.c"
|
||||
"spi_flash_chip_gd.c"
|
||||
"spi_flash_chip_winbond.c"
|
||||
"spi_flash_chip_boya.c"
|
||||
"memspi_host_driver.c")
|
||||
|
||||
list(APPEND cache_srcs
|
||||
|
@ -137,12 +137,23 @@ menu "SPI Flash driver"
|
||||
then it will yield CPUs after finishing a current command.
|
||||
|
||||
config SPI_FLASH_ERASE_YIELD_TICKS
|
||||
int "CPU release time (tick)"
|
||||
int "CPU release time (tick) for an erase operation"
|
||||
depends on SPI_FLASH_YIELD_DURING_ERASE
|
||||
default 1
|
||||
help
|
||||
Defines how many ticks will be before returning to continue a erasing.
|
||||
|
||||
config SPI_FLASH_AUTO_SUSPEND
|
||||
bool "Auto suspend long erase/write operations"
|
||||
default n
|
||||
depends on IDF_TARGET_ESP32C3 && !SPI_FLASH_USE_LEGACY_IMPL && !SPI_FLASH_ROM_IMPL
|
||||
help
|
||||
This is made default n, because this needs bootloader support.
|
||||
This feature needs special bootloader support.
|
||||
If you want to OTA to a image with this feature
|
||||
(e.g. turn on this config option for OTA image), please make
|
||||
sure the bootloader has the support for it. (above IDF v4.3)
|
||||
|
||||
config SPI_FLASH_WRITE_CHUNK_SIZE
|
||||
int "Flash write chunk size"
|
||||
default 8192
|
||||
@ -208,6 +219,15 @@ menu "SPI Flash driver"
|
||||
given by ``chip_drv`` member of the chip struct. This adds support for variant
|
||||
chips, however will extend detecting time.
|
||||
|
||||
config SPI_FLASH_SUPPORT_BOYA_CHIP
|
||||
bool "BOYA"
|
||||
depends on !IDF_TARGET_ESP32
|
||||
default y
|
||||
help
|
||||
Enable this to support auto detection of BOYA chips if chip vendor not directly
|
||||
given by ``chip_drv`` member of the chip struct. This adds support for variant
|
||||
chips, however will extend detecting time.
|
||||
|
||||
endmenu #auto detect flash chips
|
||||
|
||||
endmenu
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
static const char TAG[] = "spi_flash";
|
||||
|
||||
@ -832,6 +833,12 @@ IRAM_ATTR esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe)
|
||||
}
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
//init suspend mode cmd, uses internal.
|
||||
esp_err_t esp_flash_suspend_cmd_init(esp_flash_t* chip)
|
||||
{
|
||||
return chip->chip_drv->sus_setup(chip);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
|
||||
esp_err_t esp_flash_app_disable_protect(bool disable)
|
||||
{
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "esp_heap_caps.h"
|
||||
#include "hal/spi_types.h"
|
||||
#include "driver/spi_common_internal.h"
|
||||
#include "hal/spi_flash_hal.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -89,6 +90,7 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/efuse.h"
|
||||
#if !CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
|
||||
.host_id = SPI_HOST,\
|
||||
.speed = DEFAULT_FLASH_SPEED, \
|
||||
@ -96,6 +98,16 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
|
||||
.iomux = true, \
|
||||
.input_delay_ns = 0,\
|
||||
}
|
||||
#else
|
||||
#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
|
||||
.host_id = SPI_HOST,\
|
||||
.speed = DEFAULT_FLASH_SPEED, \
|
||||
.cs_num = 0, \
|
||||
.iomux = true, \
|
||||
.input_delay_ns = 0,\
|
||||
.auto_sus_en = true,\
|
||||
}
|
||||
#endif //!CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
#endif
|
||||
|
||||
|
||||
@ -239,6 +251,7 @@ static DRAM_ATTR esp_flash_t default_chip = {
|
||||
.os_func = &esp_flash_noos_functions,
|
||||
};
|
||||
|
||||
extern esp_err_t esp_flash_suspend_cmd_init(esp_flash_t* chip);
|
||||
esp_err_t esp_flash_init_default_chip(void)
|
||||
{
|
||||
const esp_rom_spiflash_chip_t *legacy_chip = &g_rom_flashchip;
|
||||
@ -272,6 +285,12 @@ esp_err_t esp_flash_init_default_chip(void)
|
||||
default_chip.size = legacy_chip->chip_size;
|
||||
|
||||
esp_flash_default_chip = &default_chip;
|
||||
#ifdef CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
err = esp_flash_suspend_cmd_init(&default_chip);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,13 @@
|
||||
.write_data_slicer = memspi_host_write_data_slicer, \
|
||||
.read = spi_flash_hal_read, \
|
||||
.read_data_slicer = memspi_host_read_data_slicer, \
|
||||
.host_idle = spi_flash_hal_host_idle, \
|
||||
.host_status = spi_flash_hal_check_status, \
|
||||
.configure_host_io_mode = spi_flash_hal_configure_host_io_mode, \
|
||||
.poll_cmd_done = spi_flash_hal_poll_cmd_done, \
|
||||
.flush_cache = memspi_host_flush_cache, \
|
||||
.resume = spi_flash_hal_resume, \
|
||||
.suspend = spi_flash_hal_suspend,\
|
||||
.sus_setup = spi_flash_hal_setup_read_suspend,\
|
||||
}
|
||||
|
||||
/// configuration for the memspi host
|
||||
|
21
components/spi_flash/include/spi_flash_chip_boya.h
Normal file
21
components/spi_flash/include/spi_flash_chip_boya.h
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_flash.h"
|
||||
#include "spi_flash_chip_driver.h"
|
||||
|
||||
extern const spi_flash_chip_t esp_flash_chip_boya;
|
@ -186,6 +186,8 @@ struct spi_flash_chip_t {
|
||||
/** Yield to other tasks. Called during erase operations. */
|
||||
esp_err_t (*yield)(esp_flash_t *chip, uint32_t wip);
|
||||
|
||||
/** Setup flash suspend configuration. */
|
||||
esp_err_t (*sus_setup)(esp_flash_t *chip);
|
||||
};
|
||||
|
||||
/* Pointer to an array of pointers to all known drivers for flash chips. This array is used
|
||||
|
@ -255,24 +255,6 @@ extern const spi_flash_chip_t esp_flash_chip_generic;
|
||||
* Utilities
|
||||
*******************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Wait for the SPI host hardware state machine to be idle.
|
||||
*
|
||||
* This isn't a flash chip_drv operation, but it's called by
|
||||
* spi_flash_chip_generic_wait_idle() and may be useful when implementing
|
||||
* alternative drivers.
|
||||
*
|
||||
* timeout_us will be decremented if the function needs to wait until the host hardware is idle.
|
||||
*
|
||||
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_TIMEOUT if not idle before timeout
|
||||
* - or other error passed from the ``set_write_protect`` or ``common_command`` function of host driver
|
||||
*/
|
||||
esp_err_t spi_flash_generic_wait_host_idle(esp_flash_t *chip, uint32_t *timeout_us);
|
||||
|
||||
/// Function pointer type for reading status register with QE bit.
|
||||
typedef esp_err_t (*esp_flash_rdsr_func_t)(esp_flash_t* chip, uint32_t* out_sr);
|
||||
|
||||
@ -394,5 +376,13 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, bool add
|
||||
*/
|
||||
esp_err_t spi_flash_chip_generic_yield(esp_flash_t* chip, uint32_t wip);
|
||||
|
||||
/**
|
||||
* @brief Setup for flash suspend command configuration.
|
||||
*
|
||||
* @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted.
|
||||
* @return ESP_OK
|
||||
*/
|
||||
esp_err_t spi_flash_chip_generic_suspend_cmd_conf(esp_flash_t *chip);
|
||||
|
||||
/// Default timeout configuration used by most chips
|
||||
const flash_chip_op_timeout_t spi_flash_chip_generic_timeout;
|
||||
|
@ -8,3 +8,6 @@ entries:
|
||||
spi_flash_chip_gd (noflash)
|
||||
spi_flash_chip_winbond (noflash)
|
||||
memspi_host_driver (noflash)
|
||||
|
||||
if IDF_TARGET_ESP32 = n:
|
||||
spi_flash_chip_boya (noflash)
|
||||
|
@ -37,7 +37,7 @@ esp_err_t spi_flash_hal_gpspi_configure_host_io_mode(
|
||||
esp_flash_io_mode_t io_mode);
|
||||
extern esp_err_t spi_flash_hal_gpspi_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans);
|
||||
extern esp_err_t spi_flash_hal_gpspi_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len);
|
||||
extern bool spi_flash_hal_gpspi_host_idle(spi_flash_host_inst_t *host);
|
||||
extern uint32_t spi_flash_hal_gpspi_check_status(spi_flash_host_inst_t *host);
|
||||
extern bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_inst_t *host, const void *p);
|
||||
extern bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_inst_t *host, const void *p);
|
||||
|
||||
@ -57,10 +57,12 @@ static const spi_flash_host_driver_t esp_flash_gpspi_host = {
|
||||
.write_data_slicer = memspi_host_write_data_slicer,
|
||||
.read = spi_flash_hal_gpspi_read,
|
||||
.read_data_slicer = memspi_host_read_data_slicer,
|
||||
.host_idle = spi_flash_hal_gpspi_host_idle,
|
||||
.host_status = spi_flash_hal_gpspi_check_status,
|
||||
.configure_host_io_mode = spi_flash_hal_gpspi_configure_host_io_mode,
|
||||
.poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done,
|
||||
.flush_cache = NULL,
|
||||
.resume = spi_flash_hal_resume,
|
||||
.suspend = spi_flash_hal_suspend,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -26,6 +26,8 @@
|
||||
#define CMD_WRDI 0x04
|
||||
#define CMD_RDSR 0x05
|
||||
#define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
|
||||
#define CMD_RDSCUR 0x2B /* on specific(MXIC) board, read security register */
|
||||
#define CMD_RDFR 0x48 /* on specific(ISSI) board, read function register */
|
||||
|
||||
#define CMD_FASTRD_QIO 0xEB
|
||||
#define CMD_FASTRD_QIO_4B 0xEC
|
||||
@ -47,6 +49,8 @@
|
||||
#define CMD_LARGE_BLOCK_ERASE_4B 0xDC /* 64KB block erase command */
|
||||
#define CMD_PROGRAM_PAGE 0x02
|
||||
#define CMD_PROGRAM_PAGE_4B 0x12
|
||||
#define CMD_SUSPEND 0x75
|
||||
#define CMD_RESUME 0x7A
|
||||
|
||||
#define CMD_RST_EN 0x66
|
||||
#define CMD_RST_DEV 0x99
|
||||
|
@ -121,9 +121,9 @@ struct spi_flash_host_driver_s {
|
||||
*/
|
||||
int (*read_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size);
|
||||
/**
|
||||
* Check whether the host is idle to perform new operations.
|
||||
* Check the host status, 0:busy, 1:idle, 2:suspended.
|
||||
*/
|
||||
bool (*host_idle)(spi_flash_host_inst_t *host);
|
||||
uint32_t (*host_status)(spi_flash_host_inst_t *host);
|
||||
/**
|
||||
* Configure the host to work at different read mode. Responsible to compensate the timing and set IO mode.
|
||||
*/
|
||||
@ -139,6 +139,21 @@ struct spi_flash_host_driver_s {
|
||||
* modified, the cache needs to be flushed. Left NULL if not supported.
|
||||
*/
|
||||
esp_err_t (*flush_cache)(spi_flash_host_inst_t* host, uint32_t addr, uint32_t size);
|
||||
|
||||
/**
|
||||
* Resume flash from suspend manually
|
||||
*/
|
||||
void (*resume)(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* Set flash in suspend status manually
|
||||
*/
|
||||
void (*suspend)(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* Suspend feature setup for setting cmd and status register mask.
|
||||
*/
|
||||
esp_err_t (*sus_setup)(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf);
|
||||
};
|
||||
///Slowest io mode supported by ESP32, currently SlowRd
|
||||
#define SPI_FLASH_READ_MODE_MIN SPI_FLASH_SLOWRD
|
||||
|
80
components/spi_flash/spi_flash_chip_boya.c
Normal file
80
components/spi_flash/spi_flash_chip_boya.c
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "spi_flash_chip_generic.h"
|
||||
#include "spi_flash_chip_gd.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
/* Driver for BOYA flash chip */
|
||||
esp_err_t spi_flash_chip_gd_suspend_cmd_conf(esp_flash_t *chip);
|
||||
|
||||
// Use the same implementation as GD chips
|
||||
#define spi_flash_chip_boya_suspend_cmd_conf spi_flash_chip_gd_suspend_cmd_conf
|
||||
|
||||
esp_err_t spi_flash_chip_boya_probe(esp_flash_t *chip, uint32_t flash_id)
|
||||
{
|
||||
/* Check manufacturer and product IDs match our desired masks */
|
||||
const uint8_t MFG_ID = 0x68;
|
||||
if (flash_id >> 16 != MFG_ID) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
const uint16_t FLASH_ID_MASK = 0xFF00;
|
||||
const uint16_t FLASH_ID_VALUE = 0x4000;
|
||||
if ((flash_id & FLASH_ID_MASK) != FLASH_ID_VALUE) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static const char chip_name[] = "boya";
|
||||
|
||||
// The BOYA chip can use the functions for generic chips except from set read mode and probe,
|
||||
// So we only replace these two functions.
|
||||
const spi_flash_chip_t esp_flash_chip_boya = {
|
||||
.name = chip_name,
|
||||
.timeout = &spi_flash_chip_generic_timeout,
|
||||
.probe = spi_flash_chip_boya_probe,
|
||||
.reset = spi_flash_chip_generic_reset,
|
||||
.detect_size = spi_flash_chip_generic_detect_size,
|
||||
.erase_chip = spi_flash_chip_generic_erase_chip,
|
||||
.erase_sector = spi_flash_chip_generic_erase_sector,
|
||||
.erase_block = spi_flash_chip_generic_erase_block,
|
||||
.sector_size = 4 * 1024,
|
||||
.block_erase_size = 64 * 1024,
|
||||
|
||||
.get_chip_write_protect = spi_flash_chip_generic_get_write_protect,
|
||||
.set_chip_write_protect = spi_flash_chip_generic_set_write_protect,
|
||||
|
||||
.num_protectable_regions = 0,
|
||||
.protectable_regions = NULL,
|
||||
.get_protected_regions = NULL,
|
||||
.set_protected_regions = NULL,
|
||||
|
||||
.read = spi_flash_chip_generic_read,
|
||||
.write = spi_flash_chip_generic_write,
|
||||
.program_page = spi_flash_chip_generic_page_program,
|
||||
.page_size = 256,
|
||||
.write_encrypted = spi_flash_chip_generic_write_encrypted,
|
||||
|
||||
.wait_idle = spi_flash_chip_generic_wait_idle,
|
||||
.set_io_mode = spi_flash_chip_generic_set_io_mode,
|
||||
.get_io_mode = spi_flash_chip_generic_get_io_mode,
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
.sus_setup = spi_flash_chip_boya_suspend_cmd_conf,
|
||||
};
|
@ -19,6 +19,7 @@
|
||||
#include "spi_flash_chip_mxic.h"
|
||||
#include "spi_flash_chip_gd.h"
|
||||
#include "spi_flash_chip_winbond.h"
|
||||
#include "spi_flash_chip_boya.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/*
|
||||
@ -42,6 +43,9 @@ static const spi_flash_chip_t *default_registered_chips[] = {
|
||||
#endif
|
||||
#ifdef CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP
|
||||
&esp_flash_chip_winbond,
|
||||
#endif
|
||||
#ifdef CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP
|
||||
&esp_flash_chip_boya,
|
||||
#endif
|
||||
// Default chip drivers that will accept all chip ID.
|
||||
// FM, Winbond and XMC chips are supposed to be supported by this chip driver.
|
||||
|
@ -75,6 +75,18 @@ esp_err_t spi_flash_chip_gd_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t*
|
||||
}
|
||||
#endif //CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
esp_err_t spi_flash_chip_gd_suspend_cmd_conf(esp_flash_t *chip)
|
||||
{
|
||||
spi_flash_sus_cmd_conf sus_conf = {
|
||||
.sus_mask = 0x84,
|
||||
.cmd_rdsr = CMD_RDSR2,
|
||||
.sus_cmd = CMD_SUSPEND,
|
||||
.res_cmd = CMD_RESUME,
|
||||
};
|
||||
|
||||
return chip->host->driver->sus_setup(chip->host, &sus_conf);
|
||||
}
|
||||
|
||||
static const char chip_name[] = "gd";
|
||||
|
||||
// The issi chip can use the functions for generic chips except from set read mode and probe,
|
||||
@ -111,4 +123,5 @@ const spi_flash_chip_t esp_flash_chip_gd = {
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
.sus_setup = spi_flash_chip_gd_suspend_cmd_conf,
|
||||
};
|
||||
|
@ -301,22 +301,6 @@ esp_err_t spi_flash_chip_generic_get_write_protect(esp_flash_t *chip, bool *out_
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_generic_wait_host_idle(esp_flash_t *chip, uint32_t *timeout_us)
|
||||
{
|
||||
while (!chip->host->driver->host_idle(chip->host) && *timeout_us > 0) {
|
||||
#if HOST_DELAY_INTERVAL_US > 0
|
||||
if (*timeout_us > 1) {
|
||||
int delay = MIN(HOST_DELAY_INTERVAL_US, *timeout_us);
|
||||
chip->os_func->delay_us(chip->os_func_data, delay);
|
||||
*timeout_us -= delay;
|
||||
} else {
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_chip_generic_read_reg(esp_flash_t* chip, spi_flash_register_t reg_id, uint32_t* out_reg)
|
||||
{
|
||||
return chip->host->driver->read_status(chip->host, (uint8_t*)out_reg);
|
||||
@ -357,14 +341,19 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u
|
||||
uint8_t status = 0;
|
||||
const int interval = CHIP_WAIT_IDLE_INTERVAL_US;
|
||||
while (timeout_us > 0) {
|
||||
while (!chip->host->driver->host_status(chip->host) && timeout_us > 0) {
|
||||
|
||||
esp_err_t err = spi_flash_generic_wait_host_idle(chip, & timeout_us);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
#if HOST_DELAY_INTERVAL_US > 0
|
||||
if (timeout_us > 1) {
|
||||
int delay = MIN(HOST_DELAY_INTERVAL_US, timeout_us);
|
||||
chip->os_func->delay_us(chip->os_func_data, delay);
|
||||
timeout_us -= delay;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t read;
|
||||
err = chip->chip_drv->read_reg(chip, SPI_FLASH_REG_STATUS, &read);
|
||||
esp_err_t err = chip->chip_drv->read_reg(chip, SPI_FLASH_REG_STATUS, &read);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
@ -511,6 +500,7 @@ const spi_flash_chip_t esp_flash_chip_generic = {
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
.sus_setup = spi_flash_chip_generic_suspend_cmd_conf,
|
||||
};
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_IMPL
|
||||
@ -652,3 +642,15 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t
|
||||
}
|
||||
|
||||
#endif // !CONFIG_SPI_FLASH_ROM_IMPL
|
||||
|
||||
esp_err_t spi_flash_chip_generic_suspend_cmd_conf(esp_flash_t *chip)
|
||||
{
|
||||
spi_flash_sus_cmd_conf sus_conf = {
|
||||
.sus_mask = 0x80,
|
||||
.cmd_rdsr = CMD_RDSR2,
|
||||
.sus_cmd = CMD_SUSPEND,
|
||||
.res_cmd = CMD_RESUME,
|
||||
};
|
||||
|
||||
return chip->host->driver->sus_setup(chip->host, &sus_conf);
|
||||
}
|
||||
|
@ -58,6 +58,17 @@ esp_err_t spi_flash_chip_issi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_chip_issi_suspend_cmd_conf(esp_flash_t *chip)
|
||||
{
|
||||
spi_flash_sus_cmd_conf sus_conf = {
|
||||
.sus_mask = 0x06,
|
||||
.cmd_rdsr = CMD_RDFR,
|
||||
.sus_cmd = CMD_SUSPEND,
|
||||
.res_cmd = CMD_RESUME,
|
||||
};
|
||||
|
||||
return chip->host->driver->sus_setup(chip->host, &sus_conf);
|
||||
}
|
||||
|
||||
static const char chip_name[] = "issi";
|
||||
|
||||
@ -95,4 +106,5 @@ const spi_flash_chip_t esp_flash_chip_issi = {
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
.sus_setup = spi_flash_chip_issi_suspend_cmd_conf,
|
||||
};
|
||||
|
@ -39,6 +39,18 @@ esp_err_t spi_flash_chip_issi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t
|
||||
|
||||
static const char chip_name[] = "mxic";
|
||||
|
||||
esp_err_t spi_flash_chip_mxic_suspend_cmd_conf(esp_flash_t *chip)
|
||||
{
|
||||
spi_flash_sus_cmd_conf sus_conf = {
|
||||
.sus_mask = 0x06,
|
||||
.cmd_rdsr = CMD_RDSCUR,
|
||||
.sus_cmd = CMD_SUSPEND,
|
||||
.res_cmd = CMD_RESUME,
|
||||
};
|
||||
|
||||
return chip->host->driver->sus_setup(chip->host, &sus_conf);
|
||||
}
|
||||
|
||||
// The mxic chip can use the functions for generic chips except from set read mode and probe,
|
||||
// So we only replace these two functions.
|
||||
const spi_flash_chip_t esp_flash_chip_mxic = {
|
||||
@ -73,4 +85,5 @@ const spi_flash_chip_t esp_flash_chip_mxic = {
|
||||
|
||||
.read_reg = spi_flash_chip_mxic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
.sus_setup = spi_flash_chip_mxic_suspend_cmd_conf,
|
||||
};
|
||||
|
@ -176,6 +176,7 @@ const spi_flash_chip_t esp_flash_chip_winbond = {
|
||||
|
||||
.read_reg = spi_flash_chip_generic_read_reg,
|
||||
.yield = spi_flash_chip_generic_yield,
|
||||
.sus_setup = spi_flash_chip_generic_suspend_cmd_conf,
|
||||
};
|
||||
|
||||
|
||||
|
@ -67,12 +67,16 @@ static inline IRAM_ATTR bool on_spi1_check_yield(spi1_app_func_arg_t* ctx);
|
||||
|
||||
IRAM_ATTR static void cache_enable(void* arg)
|
||||
{
|
||||
#ifndef CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
g_flash_guard_default_ops.end();
|
||||
#endif
|
||||
}
|
||||
|
||||
IRAM_ATTR static void cache_disable(void* arg)
|
||||
{
|
||||
#ifndef CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
g_flash_guard_default_ops.start();
|
||||
#endif
|
||||
}
|
||||
|
||||
static IRAM_ATTR esp_err_t spi_start(void *arg)
|
||||
|
@ -24,6 +24,14 @@
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/cache.h"
|
||||
#endif
|
||||
|
||||
#define FUNC_SPI 1
|
||||
|
||||
static uint8_t sector_buf[4096];
|
||||
@ -606,6 +614,51 @@ void test_erase_large_region(const esp_partition_t *part)
|
||||
FLASH_TEST_CASE("SPI flash erase large region", test_erase_large_region);
|
||||
FLASH_TEST_CASE_3("SPI flash erase large region", test_erase_large_region);
|
||||
|
||||
#if CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
void esp_test_for_suspend(void)
|
||||
{
|
||||
/*clear content in cache*/
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3
|
||||
Cache_Invalidate_DCache_All();
|
||||
#endif
|
||||
Cache_Invalidate_ICache_All();
|
||||
ESP_LOGI(TAG, "suspend test begins:");
|
||||
printf("run into test suspend function\n");
|
||||
printf("print something when flash is erasing:\n");
|
||||
printf("aaaaa bbbbb zzzzz fffff qqqqq ccccc\n");
|
||||
}
|
||||
|
||||
void task_erase_large_region(void *arg)
|
||||
{
|
||||
esp_partition_t *part = (esp_partition_t *)arg;
|
||||
test_erase_large_region(part);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void task_request_suspend(void *arg)
|
||||
{
|
||||
vTaskDelay(2);
|
||||
ESP_LOGI(TAG, "flash go into suspend");
|
||||
esp_test_for_suspend();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void task_delay(void *arg)
|
||||
{
|
||||
esp_rom_delay_us(2000000);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void test_flash_suspend_resume(const esp_partition_t* part)
|
||||
{
|
||||
xTaskCreatePinnedToCore(task_request_suspend, "suspend", 2048, (void *)"test_for_suspend", UNITY_FREERTOS_PRIORITY + 3, NULL, 0);
|
||||
xTaskCreatePinnedToCore(task_erase_large_region, "test", 2048, (void *)part, UNITY_FREERTOS_PRIORITY + 2, NULL, 0);
|
||||
xTaskCreatePinnedToCore(task_delay, "task_delay", 1024, (void *)"task_delay", UNITY_FREERTOS_PRIORITY + 1, NULL, 0);
|
||||
}
|
||||
|
||||
FLASH_TEST_CASE("SPI flash suspend and resume test", test_flash_suspend_resume);
|
||||
#endif //CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
|
||||
static void test_write_protection(const esp_partition_t* part)
|
||||
{
|
||||
esp_flash_t* chip = part->flash_chip;
|
||||
|
@ -42,6 +42,7 @@ components/spi_flash/include/spi_flash_chip_issi.h
|
||||
components/spi_flash/include/spi_flash_chip_mxic.h
|
||||
components/spi_flash/include/spi_flash_chip_gd.h
|
||||
components/spi_flash/include/spi_flash_chip_winbond.h
|
||||
components/spi_flash/include/spi_flash_chip_boya.h
|
||||
components/spi_flash/include/memspi_host_driver.h
|
||||
components/spi_flash/include/spi_flash_chip_driver.h
|
||||
components/spi_flash/include/spi_flash_chip_generic.h
|
||||
|
Loading…
Reference in New Issue
Block a user