mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 04:59:55 +00:00 
			
		
		
		
	spi_flash: Add auto suspend mode on esp32c3
This commit is contained in:
		| @@ -38,6 +38,7 @@ | |||||||
| #define CMD_RDSR2      0x35 /* Not all SPI flash uses this command */ | #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_OTPEN      0x3A /* Enable OTP mode, not all SPI flash uses this command */ | ||||||
| #define CMD_WRAP       0x77 /* Set burst with wrap 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, | /* 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(); |     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) | static esp_err_t bootloader_init_spi_flash(void) | ||||||
| { | { | ||||||
|     bootloader_init_flash_configure(); |     bootloader_init_flash_configure(); | ||||||
| @@ -204,6 +210,7 @@ static esp_err_t bootloader_init_spi_flash(void) | |||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |     bootloader_spi_flash_resume(); | ||||||
|     esp_rom_spiflash_unlock(); |     esp_rom_spiflash_unlock(); | ||||||
|  |  | ||||||
| #if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT | #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; |     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. |  * 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; |     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. |  * 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_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_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_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_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_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) | #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(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_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_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 | #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) | 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; |     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 dev Beginning address of the peripheral registers. | ||||||
|  * @param auto_sus Enable/disable Flash Auto-Suspend. |  * @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) | 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_pes_en = auto_sus; | ||||||
|     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. |  * 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. |  * @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; |     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; |     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. |  * 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 |     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 |     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; | } 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. | /// Configuration structure for the SPI driver. | ||||||
| typedef struct { | typedef struct { | ||||||
|     spi_host_device_t host_id;            ///< SPI peripheral ID. |     spi_host_device_t host_id;            ///< SPI peripheral ID. | ||||||
|     int cs_num;             ///< Which cs pin is used, 0-(SOC_SPI_PERIPH_CS_NUM-1). |     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. |     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. |     esp_flash_speed_t speed;///< SPI flash clock speed to work at. | ||||||
|     uint32_t cs_hold;       ///< CS hold time config used by the host |     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; | } 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. |  * @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. |  * @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); | 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 |  * 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. * |  * 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. |  * @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); | 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``. |     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; | } 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 | ///Slowest io mode supported by ESP32, currently SlowRd | ||||||
| #define SPI_FLASH_READ_MODE_MIN SPI_FLASH_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); |     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. |      * 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. |      * 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); |     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 | #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; |     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) | 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) { |     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, |         .clock_conf = clock_cfg->clock_reg_val, | ||||||
|         .cs_hold = cfg->cs_hold, |         .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); |     ESP_EARLY_LOGD(TAG, "extra_dummy: %d", data_out->extra_dummy); | ||||||
|     return ESP_OK; |     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); |     spi_flash_ll_set_clock(dev, &ctx->clock_conf); | ||||||
|     int cs_hold = ctx->cs_hold; |     int cs_hold = ctx->cs_hold; | ||||||
|     spi_flash_ll_set_hold(dev, 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; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -78,7 +92,7 @@ esp_err_t spi_flash_hal_configure_host_io_mode( | |||||||
|         return ESP_ERR_NOT_SUPPORTED; |         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: |      * In S3 ROM, extra bits than 24-bit are used to indicate requirements of M7-M0: | ||||||
|      * - 24: normal transactions |      * - 24: normal transactions | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_inst_t *host, const | |||||||
|     return true; |     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); |     spi_dev_t *dev = get_spi_dev(host); | ||||||
|     return spi_flash_ll_host_idle(dev); |     return spi_flash_ll_host_idle(dev); | ||||||
|   | |||||||
| @@ -13,30 +13,33 @@ | |||||||
| // limitations under the License. | // limitations under the License. | ||||||
| #include "sdkconfig.h" | #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 | #ifndef CONFIG_SPI_FLASH_ROM_IMPL | ||||||
|  |  | ||||||
| // HAL for | // HAL for | ||||||
| //  - MEMSPI | //  - MEMSPI | ||||||
| //  - SPI1~3 on ESP32 | //  - SPI1~3 on ESP32/S2/S3/C3 | ||||||
| // The common part is in spi_flash_hal_common.inc | // 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) | void spi_flash_hal_erase_chip(spi_flash_host_inst_t *host) | ||||||
| { | { | ||||||
|     spi_dev_t *dev = get_spi_dev(host); |     spi_dev_t *dev = get_spi_dev(host); | ||||||
|     spi_flash_ll_erase_chip(dev); |     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); |     host->driver->poll_cmd_done(host); | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| // Only support 24bit address | // 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_addr_bitlen(dev, 24); | ||||||
|     spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT); |     spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT); | ||||||
|     spi_flash_ll_erase_sector(dev); |     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); |     host->driver->poll_cmd_done(host); | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| // Only support 24bit address | // 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_addr_bitlen(dev, 24); | ||||||
|     spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT); |     spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT); | ||||||
|     spi_flash_ll_erase_block(dev); |     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); |     host->driver->poll_cmd_done(host); | ||||||
|  | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
| // Only support 24bit address | // 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; |     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); |     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 |     // Not clear if this is necessary, or only necessary if | ||||||
|     // chip->spi == SPI1. But probably doesn't hurt... |     // chip->spi == SPI1. But probably doesn't hurt... | ||||||
|     if ((void*) dev == spi_flash_ll_get_hw(SPI_HOST)) { |     if ((void*) dev == spi_flash_ll_get_hw(SPI_HOST)) { | ||||||
| #if CONFIG_IDF_TARGET_ESP32 | #if CONFIG_IDF_TARGET_ESP32 | ||||||
|         idle &= spi_flash_ll_host_idle(&SPI0); |         status &= spi_flash_ll_host_idle(&SPI0); | ||||||
| #else | #elif CONFIG_IDF_TARGET_ESP32S2 | ||||||
|         idle &= spi_flash_ll_host_idle(&SPIMEM0); |         status &= spi_flash_ll_host_idle(&SPIMEM0); | ||||||
| #endif | #endif | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return idle; |     //status and sus_status should be mutual exclusion | ||||||
|  |     return (status | sus_status); | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif // !CONFIG_SPI_FLASH_ROM_IMPL | #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 -------------------------------*/ | /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ | ||||||
| #define SOC_COEX_HW_PTI                 (1) | #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 ----------------------------*/ | /*-------------------------- Power Management CAPS ----------------------------*/ | ||||||
| #define SOC_PM_SUPPORT_WIFI_WAKEUP      (1) | #define SOC_PM_SUPPORT_WIFI_WAKEUP      (1) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -296,6 +296,10 @@ | |||||||
| /*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/ | /*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/ | ||||||
| #define SOC_WIFI_HW_TSF                 (1) | #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 ---------------------------*/ | /*-------------------------- Power Management CAPS ---------------------------*/ | ||||||
| #define SOC_PM_SUPPORT_EXT_WAKEUP       (1) | #define SOC_PM_SUPPORT_EXT_WAKEUP       (1) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -699,6 +699,7 @@ typedef volatile struct spi_mem_dev_s { | |||||||
|         uint32_t val; |         uint32_t val; | ||||||
|     } date; |     } date; | ||||||
| } spi_mem_dev_t; | } 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 SPIMEM0; | ||||||
| extern spi_mem_dev_t SPIMEM1; | extern spi_mem_dev_t SPIMEM1; | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|   | |||||||
| @@ -167,5 +167,11 @@ | |||||||
| /*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/ | /*-------------------------- WI-FI HARDWARE TSF CAPS -------------------------------*/ | ||||||
| #define SOC_WIFI_HW_TSF                 (1) | #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 -------------------------------*/ | /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ | ||||||
| #define SOC_COEX_HW_PTI                 (1) | #define SOC_COEX_HW_PTI                 (1) | ||||||
|   | |||||||
| @@ -124,7 +124,6 @@ menu "SPI Flash driver" | |||||||
|     config SPI_FLASH_YIELD_DURING_ERASE |     config SPI_FLASH_YIELD_DURING_ERASE | ||||||
|         bool "Enables yield operation during flash erase" |         bool "Enables yield operation during flash erase" | ||||||
|         default y |         default y | ||||||
|         depends on SPI_FLASH_USE_LEGACY_IMPL |  | ||||||
|         help |         help | ||||||
|             This allows to yield the CPUs between erase commands. |             This allows to yield the CPUs between erase commands. | ||||||
|             Prevents starvation of other tasks. |             Prevents starvation of other tasks. | ||||||
| @@ -144,6 +143,17 @@ menu "SPI Flash driver" | |||||||
|         help |         help | ||||||
|             Defines how many ticks will be before returning to continue a erasing. |             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 |     config SPI_FLASH_WRITE_CHUNK_SIZE | ||||||
|         int "Flash write chunk size" |         int "Flash write chunk size" | ||||||
|         default 8192 |         default 8192 | ||||||
|   | |||||||
| @@ -22,6 +22,7 @@ | |||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
| #include "sdkconfig.h" | #include "sdkconfig.h" | ||||||
| #include "esp_flash_internal.h" | #include "esp_flash_internal.h" | ||||||
|  | #include "spi_flash_defs.h" | ||||||
|  |  | ||||||
| static const char TAG[] = "spi_flash"; | static const char TAG[] = "spi_flash"; | ||||||
|  |  | ||||||
| @@ -173,9 +174,6 @@ bool esp_flash_chip_driver_initialized(const esp_flash_t *chip) | |||||||
|     return true; |     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) | esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip) | ||||||
| { | { | ||||||
|     // Chip init flow |     // 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 | #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 | #ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL | ||||||
| esp_err_t esp_flash_app_disable_protect(bool disable) | 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 | #elif CONFIG_IDF_TARGET_ESP32C3 | ||||||
| #include "esp32c3/rom/efuse.h" | #include "esp32c3/rom/efuse.h" | ||||||
|  | #if !CONFIG_SPI_FLASH_AUTO_SUSPEND | ||||||
| #define ESP_FLASH_HOST_CONFIG_DEFAULT()  (memspi_host_config_t){ \ | #define ESP_FLASH_HOST_CONFIG_DEFAULT()  (memspi_host_config_t){ \ | ||||||
|     .host_id = SPI_HOST,\ |     .host_id = SPI_HOST,\ | ||||||
|     .speed = DEFAULT_FLASH_SPEED, \ |     .speed = DEFAULT_FLASH_SPEED, \ | ||||||
| @@ -97,6 +98,16 @@ __attribute__((unused)) static const char TAG[] = "spi_flash"; | |||||||
|     .iomux = true, \ |     .iomux = true, \ | ||||||
|     .input_delay_ns = 0,\ |     .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 | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -240,6 +251,7 @@ static DRAM_ATTR esp_flash_t default_chip = { | |||||||
|     .os_func = &esp_flash_noos_functions, |     .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) | esp_err_t esp_flash_init_default_chip(void) | ||||||
| { | { | ||||||
|     const esp_rom_spiflash_chip_t *legacy_chip = &g_rom_flashchip; |     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; |         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: 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 |     // 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); |     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; |     default_chip.size = legacy_chip->chip_size; | ||||||
|  |  | ||||||
|     esp_flash_default_chip = &default_chip; |     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; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,11 +31,13 @@ | |||||||
|         .write_data_slicer = memspi_host_write_data_slicer, \ |         .write_data_slicer = memspi_host_write_data_slicer, \ | ||||||
|         .read = spi_flash_hal_read, \ |         .read = spi_flash_hal_read, \ | ||||||
|         .read_data_slicer = memspi_host_read_data_slicer, \ |         .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, \ |         .configure_host_io_mode = spi_flash_hal_configure_host_io_mode, \ | ||||||
|         .poll_cmd_done = spi_flash_hal_poll_cmd_done, \ |         .poll_cmd_done = spi_flash_hal_poll_cmd_done, \ | ||||||
|         .flush_cache = memspi_host_flush_cache, \ |         .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 | /// 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); | 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. */ |     /** Yield to other tasks. Called during erase operations. */ | ||||||
|     esp_err_t (*yield)(esp_flash_t *chip, uint32_t wip); |     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 | /* 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 |  *  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. | /// 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); | 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); | 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 | /// Default timeout configuration used by most chips | ||||||
| const flash_chip_op_timeout_t spi_flash_chip_generic_timeout; | 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); |     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_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 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_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); | 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, |         .write_data_slicer = memspi_host_write_data_slicer, | ||||||
|         .read = spi_flash_hal_gpspi_read, |         .read = spi_flash_hal_gpspi_read, | ||||||
|         .read_data_slicer = memspi_host_read_data_slicer, |         .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, |         .configure_host_io_mode = spi_flash_hal_gpspi_configure_host_io_mode, | ||||||
|         .poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done, |         .poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done, | ||||||
|         .flush_cache = NULL, |         .flush_cache = NULL, | ||||||
|         .check_suspend = memspi_host_cb_check_suspend, |         .resume = spi_flash_hal_resume, | ||||||
|  |         .suspend = spi_flash_hal_suspend, | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,8 +47,8 @@ | |||||||
| #define CMD_LARGE_BLOCK_ERASE_4B 0xDC /* 64KB block erase command */ | #define CMD_LARGE_BLOCK_ERASE_4B 0xDC /* 64KB block erase command */ | ||||||
| #define CMD_PROGRAM_PAGE        0x02 | #define CMD_PROGRAM_PAGE        0x02 | ||||||
| #define CMD_PROGRAM_PAGE_4B     0x12 | #define CMD_PROGRAM_PAGE_4B     0x12 | ||||||
| #define CMD_SUSPEND     0x75 | #define CMD_SUSPEND             0x75 | ||||||
| #define CMD_RESUME      0x7A | #define CMD_RESUME              0x7A | ||||||
|  |  | ||||||
| #define CMD_RST_EN      0x66 | #define CMD_RST_EN      0x66 | ||||||
| #define CMD_RST_DEV     0x99 | #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); |     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. |      * 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. |      * 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); |     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 | ///Slowest io mode supported by ESP32, currently SlowRd | ||||||
| #define SPI_FLASH_READ_MODE_MIN SPI_FLASH_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, |     .read_reg = spi_flash_chip_generic_read_reg, | ||||||
|     .yield = spi_flash_chip_generic_yield, |     .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; |     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) | 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); |     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; |     uint8_t status = 0; | ||||||
|     const int interval = CHIP_WAIT_IDLE_INTERVAL_US; |     const int interval = CHIP_WAIT_IDLE_INTERVAL_US; | ||||||
|     while (timeout_us > 0) { |     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 HOST_DELAY_INTERVAL_US > 0 | ||||||
|         if (err != ESP_OK) { |             if (timeout_us > 1) { | ||||||
|             return err; |                 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; |         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) { |         if (err != ESP_OK) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -511,6 +500,7 @@ const spi_flash_chip_t esp_flash_chip_generic = { | |||||||
|  |  | ||||||
|     .read_reg = spi_flash_chip_generic_read_reg, |     .read_reg = spi_flash_chip_generic_read_reg, | ||||||
|     .yield = spi_flash_chip_generic_yield, |     .yield = spi_flash_chip_generic_yield, | ||||||
|  |     .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #ifndef CONFIG_SPI_FLASH_ROM_IMPL | #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 | #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; |     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"; | static const char chip_name[] = "winbond"; | ||||||
|  |  | ||||||
| // The issi chip can use the functions for generic chips except from set read mode and probe, | // 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, |     .read_reg = spi_flash_chip_generic_read_reg, | ||||||
|     .yield = spi_flash_chip_generic_yield, |     .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_rom_sys.h" | ||||||
| #include "esp_timer.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 | #define FUNC_SPI    1 | ||||||
|  |  | ||||||
| static uint8_t sector_buf[4096]; | 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("SPI flash erase large region", test_erase_large_region); | ||||||
| FLASH_TEST_CASE_3("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) | static void test_write_protection(const esp_partition_t* part) | ||||||
| { | { | ||||||
|     esp_flash_t* chip = part->flash_chip; |     esp_flash_t* chip = part->flash_chip; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Cao Sen Miao
					Cao Sen Miao