mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
spi_flash: Add auto suspend mode on esp32c3
This commit is contained in:
parent
1f37a5f162
commit
9905da46e0
@ -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
|
||||
|
@ -117,51 +117,6 @@ static inline void spi_flash_ll_erase_block(spi_dev_t *dev)
|
||||
dev->cmd.flash_be = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suspend erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_flash_ll_suspend(spi_dev_t *dev)
|
||||
{
|
||||
dev->cmd.flash_pes = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resume suspended erase/program operation.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_flash_ll_resume(spi_dev_t *dev)
|
||||
{
|
||||
dev->cmd.flash_per = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto wait idle mode. (work only for ESP32-S2)
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_sus Enable/disable Flash Auto-Suspend.
|
||||
*/
|
||||
#define spi_flash_ll_auto_wait_idle_init(...) ()
|
||||
|
||||
/**
|
||||
* Initialize auto wait idle mode (work only for ESP32-S2)
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param auto_waiti Enable/disable auto wait-idle function
|
||||
*/
|
||||
#define spi_flash_ll_auto_suspend_init(...) ()
|
||||
|
||||
/**
|
||||
* Return the suspend status of erase or program operations. (work only for ESP32-S2)
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if suspended, otherwise false.
|
||||
*/
|
||||
#define spi_flash_ll_sus_status(...) ({false;})
|
||||
|
||||
/**
|
||||
* Enable/disable write protection for the flash chip.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -83,8 +83,6 @@ typedef union {
|
||||
#define spi_flash_ll_erase_chip(dev) spimem_flash_ll_erase_chip((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_erase_sector(dev) spimem_flash_ll_erase_sector((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_erase_block(dev) spimem_flash_ll_erase_block((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_suspend(dev) spimem_flash_ll_suspend((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_resume(dev) spimem_flash_ll_resume((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_set_write_protect(dev, wp) spimem_flash_ll_set_write_protect((spi_mem_dev_t*)dev, wp)
|
||||
#define spi_flash_ll_get_buffer_data(dev, buffer, read_len) spimem_flash_ll_get_buffer_data((spi_mem_dev_t*)dev, buffer, read_len)
|
||||
#define spi_flash_ll_set_buffer_data(dev, buffer, len) spimem_flash_ll_set_buffer_data((spi_mem_dev_t*)dev, buffer, len)
|
||||
@ -105,9 +103,6 @@ typedef union {
|
||||
#define spi_flash_ll_set_dummy(dev, dummy) spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
|
||||
#define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev)
|
||||
#define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n)
|
||||
#define spi_flash_ll_auto_wait_idle_init(dev, auto_waiti) spimem_flash_ll_auto_wait_idle_init((spi_mem_dev_t*)dev, auto_waiti)
|
||||
#define spi_flash_ll_auto_suspend_init(dev, auto_sus) spimem_flash_ll_auto_suspend_init((spi_mem_dev_t*)dev, auto_sus)
|
||||
#define spi_flash_ll_sus_status(dev) spimem_flash_ll_sus_status((spi_mem_dev_t*)dev)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -122,24 +122,100 @@ static inline void spimem_flash_ll_suspend(spi_mem_dev_t *dev)
|
||||
*/
|
||||
static inline void spimem_flash_ll_resume(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->misc.auto_per = 0; // Must disable Hardware Auto-Resume (should not be enabled, ESP32-S2 has bugs).
|
||||
dev->flash_sus_cmd.flash_per = 1;
|
||||
while (dev->flash_sus_cmd.flash_per) { };
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize auto wait idle mode
|
||||
* 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_command = 0x75; // Set auto suspend command, usually 0x75
|
||||
dev->flash_sus_ctrl.flash_per_command = 0x7A; // Set auto resume command, usually 0x7A
|
||||
// SET_PERI_REG_MASK(SPI_MEM_FLASH_SUS_CMD_REG(1), SPI_MEM_PES_PER_EN_M); // Only on S3 chip
|
||||
// SET_PERI_REG_MASK(SPI_MEM_FLASH_SUS_CMD_REG(1), SPI_MEM_PESR_IDLE_EN_M); // MUST SET 1, to avoid missing Resume (Only on S3 chip)
|
||||
dev->flash_sus_ctrl.flash_pes_en = auto_sus; // enable Flash Auto-Suspend.
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,7 +237,7 @@ static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool
|
||||
*
|
||||
* @return true if suspended, otherwise false.
|
||||
*/
|
||||
static inline bool spimem_flash_ll_sus_status(const spi_mem_dev_t *dev)
|
||||
static inline bool spimem_flash_ll_sus_status(spi_mem_dev_t *dev)
|
||||
{
|
||||
return dev->sus_status.flash_sus;
|
||||
}
|
||||
|
@ -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_host_idle(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* @brief Configure the SPI host hardware registers for the specified io mode.
|
||||
@ -205,13 +209,6 @@ esp_err_t spi_flash_hal_configure_host_io_mode(spi_flash_host_inst_t *host, uint
|
||||
*/
|
||||
void spi_flash_hal_poll_cmd_done(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* Setup a auto-suspend mode.
|
||||
*
|
||||
* @param host The driver context.
|
||||
*/
|
||||
void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* Check whether the given buffer can be used as the write buffer directly. If 'chip' is connected to the main SPI bus, we can only write directly from
|
||||
* regions that are accessible ith cache disabled. *
|
||||
@ -233,3 +230,37 @@ 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 Check the suspend status and resume a suspended operation.
|
||||
*
|
||||
* @param host The driver context.
|
||||
*
|
||||
*/
|
||||
bool spi_flash_hal_check_suspend(spi_flash_host_inst_t *host);
|
||||
|
||||
/**
|
||||
* @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,10 +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);
|
||||
|
||||
/**
|
||||
* Check the necessity of suspending erase/program operations.
|
||||
* Resume flash from suspend manually
|
||||
*/
|
||||
void (*check_suspend)(spi_flash_host_inst_t *host);
|
||||
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
|
||||
|
@ -71,17 +71,6 @@ static inline int get_dummy_n(bool gpio_is_used, int input_delay_ns, int eff_clk
|
||||
return apb_period_n / apbclk_n;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
|
||||
void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host)
|
||||
{
|
||||
mspi_auto_suspend_stub_install();
|
||||
spi_flash_ll_auto_wait_idle_init(spi_flash_ll_get_hw(SPI_HOST), true);
|
||||
spi_flash_ll_auto_suspend_init(spi_flash_ll_get_hw(SPI_HOST), true);
|
||||
}
|
||||
|
||||
#endif // CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
|
||||
esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_hal_config_t *cfg)
|
||||
{
|
||||
if (!esp_ptr_internal(data_out) && cfg->host_id == SPI1_HOST) {
|
||||
@ -102,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_host_idle(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,104 @@ 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)
|
||||
uint32_t spi_flash_hal_host_idle(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);
|
||||
uint32_t sus_status = spi_flash_hal_check_suspend(host) << 1;
|
||||
// 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);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
status &= spi_flash_ll_host_idle(&SPIMEM0);
|
||||
#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
|
||||
|
||||
bool spi_flash_hal_check_suspend(spi_flash_host_inst_t *host)
|
||||
{
|
||||
#if SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE
|
||||
if (spimem_flash_ll_sus_status((spi_mem_dev_t*)(((spi_flash_hal_context_t *)host)->spi))) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -125,6 +125,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)
|
||||
|
||||
|
@ -296,6 +296,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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -124,7 +124,6 @@ menu "SPI Flash driver"
|
||||
config SPI_FLASH_YIELD_DURING_ERASE
|
||||
bool "Enables yield operation during flash erase"
|
||||
default y
|
||||
depends on SPI_FLASH_USE_LEGACY_IMPL
|
||||
help
|
||||
This allows to yield the CPUs between erase commands.
|
||||
Prevents starvation of other tasks.
|
||||
@ -144,6 +143,17 @@ menu "SPI Flash driver"
|
||||
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
|
||||
|
@ -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";
|
||||
|
||||
@ -173,9 +174,6 @@ bool esp_flash_chip_driver_initialized(const esp_flash_t *chip)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
spi_flash_ll_auto_suspend_init(spi_flash_ll_get_hw(SPI_HOST), val);
|
||||
#endif
|
||||
esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip)
|
||||
{
|
||||
// Chip init flow
|
||||
@ -835,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)
|
||||
{
|
||||
|
@ -90,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, \
|
||||
@ -97,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
|
||||
|
||||
|
||||
@ -240,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;
|
||||
@ -256,10 +268,6 @@ esp_err_t esp_flash_init_default_chip(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPI_FLASH_AUTO_SUSPEND
|
||||
spi_flash_hal_setup_auto_suspend_mode(default_chip.host);
|
||||
#endif
|
||||
|
||||
// ROM TODO: account for non-standard default pins in efuse
|
||||
// ROM TODO: to account for chips which are slow to power on, maybe keep probing in a loop here
|
||||
err = esp_flash_init(&default_chip);
|
||||
@ -277,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,11 +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_host_idle, \
|
||||
.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, \
|
||||
.check_suspend = memspi_host_cb_check_suspend, \
|
||||
.resume = spi_flash_hal_resume, \
|
||||
.suspend = spi_flash_hal_suspend,\
|
||||
.sus_setup = spi_flash_hal_setup_read_suspend,\
|
||||
}
|
||||
|
||||
/// configuration for the memspi host
|
||||
@ -178,10 +180,3 @@ int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address,
|
||||
*/
|
||||
int memspi_host_write_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size);
|
||||
|
||||
/**
|
||||
* @brief Check the suspend status and resume a suspended operation.
|
||||
*
|
||||
* @param host The driver context.
|
||||
*
|
||||
*/
|
||||
void memspi_host_cb_check_suspend(spi_flash_host_inst_t *host);
|
||||
|
@ -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;
|
||||
|
@ -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_host_idle(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,11 +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_host_idle,
|
||||
.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,
|
||||
.check_suspend = memspi_host_cb_check_suspend,
|
||||
.resume = spi_flash_hal_resume,
|
||||
.suspend = spi_flash_hal_suspend,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -47,8 +47,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_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
|
||||
|
@ -111,4 +111,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_generic_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 = 0x84,
|
||||
.cmd_rdsr = CMD_RDSR2,
|
||||
.sus_cmd = CMD_SUSPEND,
|
||||
.res_cmd = CMD_RESUME,
|
||||
};
|
||||
|
||||
return chip->host->driver->sus_setup(chip->host, &sus_conf);
|
||||
}
|
||||
|
@ -140,6 +140,18 @@ esp_err_t spi_flash_chip_winbond_erase_block(esp_flash_t *chip, uint32_t start_a
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t spi_flash_chip_winbond_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);
|
||||
}
|
||||
|
||||
static const char chip_name[] = "winbond";
|
||||
|
||||
// The issi chip can use the functions for generic chips except from set read mode and probe,
|
||||
@ -176,6 +188,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,
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user