diff --git a/components/hal/esp32c2/include/hal/spimem_flash_ll.h b/components/hal/esp32c2/include/hal/spimem_flash_ll.h index de92fc45cc..e5b9f2acf6 100644 --- a/components/hal/esp32c2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c2/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,7 +18,7 @@ #include // For MIN/MAX #include #include - +#include "hal/misc.h" #include "soc/spi_periph.h" #include "hal/spi_types.h" #include "hal/spi_flash_types.h" @@ -144,7 +144,7 @@ static inline void spimem_flash_ll_auto_resume_init(spi_mem_dev_t *dev, bool aut */ 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; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_pes_command, sus_cmd); } /** @@ -156,7 +156,7 @@ static inline void spimem_flash_ll_suspend_cmd_setup(spi_mem_dev_t *dev, uint32_ */ 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; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, flash_per_command, res_cmd); } /** @@ -168,7 +168,7 @@ static inline void spimem_flash_ll_resume_cmd_setup(spi_mem_dev_t *dev, uint32_t */ 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; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_cmd, wait_pesr_command, pesr_cmd); } /** @@ -205,7 +205,7 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool 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; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_sus_ctrl, pesr_end_msk, sus_conf); } /** @@ -236,13 +236,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_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; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); + dev->flash_sus_ctrl.flash_per_wait_en = per_waiti; + dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti; } /** @@ -398,7 +399,7 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev, bool pe_ops) */ static inline bool spimem_flash_ll_host_idle(const spi_mem_dev_t *dev) { - return dev->fsm.spi0_mst_st == 0; + return dev->cmd.mst_st == 0; } /** @@ -515,11 +516,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** diff --git a/components/hal/esp32c3/include/hal/spimem_flash_ll.h b/components/hal/esp32c3/include/hal/spimem_flash_ll.h index 873142de39..127abdf4e5 100644 --- a/components/hal/esp32c3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c3/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -238,13 +238,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { HAL_FORCE_MODIFY_U32_REG_FIELD(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; + dev->flash_sus_ctrl.flash_per_wait_en = per_waiti; + dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti; } /** @@ -400,7 +401,7 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev, bool pe_ops) */ static inline bool spimem_flash_ll_host_idle(const spi_mem_dev_t *dev) { - return dev->fsm.spi0_mst_st == 0; + return dev->cmd.mst_st == 0; } /** @@ -517,11 +518,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** diff --git a/components/hal/esp32c5/include/hal/spimem_flash_ll.h b/components/hal/esp32c5/include/hal/spimem_flash_ll.h index 531d559265..2efea74ba4 100644 --- a/components/hal/esp32c5/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c5/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -242,13 +242,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { HAL_FORCE_MODIFY_U32_REG_FIELD(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; + dev->flash_sus_ctrl.flash_per_wait_en = per_waiti; + dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti; } /** @@ -521,11 +522,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** diff --git a/components/hal/esp32c6/include/hal/spimem_flash_ll.h b/components/hal/esp32c6/include/hal/spimem_flash_ll.h index dae851b685..20b54c18f6 100644 --- a/components/hal/esp32c6/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c6/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -239,13 +239,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { HAL_FORCE_MODIFY_U32_REG_FIELD(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; + dev->flash_sus_ctrl.flash_per_wait_en = per_waiti; + dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti; } /** @@ -518,11 +519,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** @@ -557,7 +555,7 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr) { dev->cache_fctrl.usr_addr_4byte = 0; - dev->rd_status.wb_mode = extra_addr; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr); } /** diff --git a/components/hal/esp32c61/include/hal/spimem_flash_ll.h b/components/hal/esp32c61/include/hal/spimem_flash_ll.h index d60bc1d978..94f0de7784 100644 --- a/components/hal/esp32c61/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32c61/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -242,13 +242,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { HAL_FORCE_MODIFY_U32_REG_FIELD(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; + dev->flash_sus_ctrl.flash_per_wait_en = per_waiti; + dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti; } /** @@ -521,11 +522,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** @@ -560,7 +558,7 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr) { dev->cache_fctrl.usr_addr_4byte = 0; - dev->rd_status.wb_mode = extra_addr; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr); } /** diff --git a/components/hal/esp32h2/include/hal/spimem_flash_ll.h b/components/hal/esp32h2/include/hal/spimem_flash_ll.h index 95cee518a8..92749a2106 100644 --- a/components/hal/esp32h2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32h2/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -240,13 +240,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { HAL_FORCE_MODIFY_U32_REG_FIELD(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; + dev->flash_sus_ctrl.flash_per_wait_en = per_waiti; + dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti; } /** @@ -539,11 +540,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** @@ -578,7 +576,7 @@ static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_extra_address(spi_mem_dev_t *dev, uint32_t extra_addr) { dev->cache_fctrl.usr_addr_4byte = 0; - dev->rd_status.wb_mode = extra_addr; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr); } /** diff --git a/components/hal/esp32p4/include/hal/spimem_flash_ll.h b/components/hal/esp32p4/include/hal/spimem_flash_ll.h index 2fc156aaa2..d4b043ff40 100644 --- a/components/hal/esp32p4/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32p4/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -244,13 +244,14 @@ static inline void spimem_flash_set_cs_hold_delay(spi_mem_dev_t *dev, uint32_t c * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { HAL_FORCE_MODIFY_U32_REG_FIELD(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; + dev->flash_sus_ctrl.flash_per_wait_en = per_waiti; + dev->flash_sus_ctrl.flash_pes_wait_en = pes_waiti; } /** @@ -527,11 +528,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** diff --git a/components/hal/esp32s2/include/hal/spimem_flash_ll.h b/components/hal/esp32s2/include/hal/spimem_flash_ll.h index 3b5611146a..35411eb591 100644 --- a/components/hal/esp32s2/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s2/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -209,12 +209,13 @@ static inline void spimem_flash_ll_res_check_sus_setup(spi_mem_dev_t *dev, bool * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { - HAL_FORCE_MODIFY_U32_REG_FIELD(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. + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); + dev->flash_waiti_ctrl.waiti_en = (per_waiti | pes_waiti); // enable auto wait-idle function. } /** @@ -457,11 +458,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** diff --git a/components/hal/esp32s3/include/hal/spimem_flash_ll.h b/components/hal/esp32s3/include/hal/spimem_flash_ll.h index 9b07256b4d..716ca1c6c0 100644 --- a/components/hal/esp32s3/include/hal/spimem_flash_ll.h +++ b/components/hal/esp32s3/include/hal/spimem_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -253,7 +253,7 @@ static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *de { uint32_t tsus_unit = 0; if (dev->sus_status.flash_pes_dly_256 == 1) { - tsus_unit = 128; + tsus_unit = 256; } else { tsus_unit = 4; } @@ -264,14 +264,15 @@ static inline uint32_t spimem_flash_ll_get_tsus_unit_in_cycles(spi_mem_dev_t *de * Initialize auto wait idle mode * * @param dev Beginning address of the peripheral registers. - * @param auto_waiti Enable/disable auto wait-idle function + * @param per_waiti Enable wait-idle with time delay function after resume. + * @param pes_waiti Enable wait-idle with time delay function after suspend. */ -static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool auto_waiti) +static inline void spimem_flash_ll_auto_wait_idle_init(spi_mem_dev_t *dev, bool per_waiti, bool pes_waiti) { - HAL_FORCE_MODIFY_U32_REG_FIELD(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. - dev->flash_sus_cmd.flash_per_wait_en = 1; - dev->flash_sus_cmd.flash_pes_wait_en = 1; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->flash_waiti_ctrl, waiti_cmd, 0x05); + dev->flash_waiti_ctrl.waiti_en = (per_waiti | pes_waiti); // enable auto wait-idle function. + dev->flash_sus_cmd.flash_per_wait_en = per_waiti; + dev->flash_sus_cmd.flash_pes_wait_en = pes_waiti; } /** @@ -403,7 +404,8 @@ static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev, bool pe_ops) */ static inline bool spimem_flash_ll_host_idle(const spi_mem_dev_t *dev) { - return dev->fsm.st == 0; + // s3 has no cmd.mst_st, can use cmd.val instead + return dev->cmd.val == 0; } /** @@ -534,11 +536,8 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; - typeof(dev->user2) user2 = { - .usr_command_value = command, - .usr_command_bitlen = (bitlen - 1), - }; - dev->user2.val = user2.val; + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_value, command); + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user2, usr_command_bitlen, (bitlen - 1)); } /** diff --git a/components/hal/include/hal/spi_flash_hal.h b/components/hal/include/hal/spi_flash_hal.h index 593bb5b1a1..b50ac7726b 100644 --- a/components/hal/include/hal/spi_flash_hal.h +++ b/components/hal/include/hal/spi_flash_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,10 @@ extern "C" { #define SPI_FLASH_HAL_MAX_WRITE_BYTES 64 #define SPI_FLASH_HAL_MAX_READ_BYTES 64 +/* spi flash state */ +#define SPI_FLASH_HAL_STATUS_BUSY BIT0 +#define SPI_FLASH_HAL_STATUS_SUSPEND BIT1 + /** * Generic driver context structure for all chips using the SPI peripheral. * Include this into the HEAD of the driver data for other driver @@ -53,6 +57,7 @@ typedef struct { #define SPI_FLASH_HOST_CONTEXT_SLICER_FLAG_DTR BIT(0) ///< Slice data according to DTR mode, the address and length must be even (A0=0). int freq_mhz; /// Flash clock frequency. uint8_t tsus_val; ///< Tsus value of suspend (us) + bool auto_waiti_pes; ///< True for auto-wait idle after suspend command. False for using time delay. } spi_flash_hal_context_t; ESP_STATIC_ASSERT(sizeof(spi_flash_hal_context_t) == 48, "size of spi_flash_hal_context_t incorrect. Please check data compatibility with the ROM"); @@ -82,11 +87,12 @@ typedef struct { int cs_num; ///< Which cs pin is used, 0-(SOC_SPI_PERIPH_CS_NUM-1). bool auto_sus_en; ///< Auto suspend feature enable bit 1: enable, 0: disable. bool octal_mode_en; ///< Octal spi flash mode enable bit 1: enable, 0: disable. - bool using_timing_tuning; ///< System exist SPI0/1 timing tuning, using value from system directely if set to 1. + bool using_timing_tuning; ///< System exist SPI0/1 timing tuning, using value from system directly if set to 1. esp_flash_io_mode_t default_io_mode; ///< Default flash io mode. int freq_mhz; ///< SPI flash clock speed (MHZ). int clock_src_freq; ///< SPI flash clock source (MHZ). - uint8_t tsus_val; ///< Tsus value of suspend (us) + uint8_t tsus_val; ///< Tsus value of suspend (us). + bool auto_waiti_pes; ///< True for auto-wait idle after suspend command. False for using time delay. } spi_flash_hal_config_t; /** diff --git a/components/hal/spi_flash_hal.c b/components/hal/spi_flash_hal.c index 75414367ef..b57c43c836 100644 --- a/components/hal/spi_flash_hal.c +++ b/components/hal/spi_flash_hal.c @@ -126,8 +126,13 @@ esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_ data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_SUSPEND; data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME; data_out->tsus_val = cfg->tsus_val; + data_out->auto_waiti_pes = cfg->auto_waiti_pes; } +#if CONFIG_SPI_FLASH_SOFTWARE_RESUME + data_out->flags &= ~SPI_FLASH_HOST_CONTEXT_FLAG_AUTO_RESUME; +#endif + #if SOC_SPI_MEM_SUPPORT_OPI_MODE if (cfg->octal_mode_en) { data_out->flags |= SPI_FLASH_HOST_CONTEXT_FLAG_OCTAL_MODE; diff --git a/components/hal/spi_flash_hal_iram.c b/components/hal/spi_flash_hal_iram.c index e73ead6ad9..faf55a6adb 100644 --- a/components/hal/spi_flash_hal_iram.c +++ b/components/hal/spi_flash_hal_iram.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -145,7 +145,8 @@ 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(SPI1_HOST); spi_flash_hal_context_t* ctx = (spi_flash_hal_context_t*)host; - spimem_flash_ll_auto_wait_idle_init(dev, true); + bool pes_waiti_delay = ctx->auto_waiti_pes ? false : true; + spimem_flash_ll_auto_wait_idle_init(dev, true, pes_waiti_delay); if (ctx->freq_mhz == 120) { spimem_flash_ll_set_wait_idle_dummy_phase(dev, ctx->extra_dummy); } @@ -159,6 +160,7 @@ void spi_flash_hal_setup_auto_suspend_mode(spi_flash_host_inst_t *host) spimem_flash_ll_sus_set_spi0_lock_trans(dev, SPIMEM_FLASH_LL_SPI0_MAX_LOCK_VAL_MSPI_TICKS); #if SOC_SPI_MEM_SUPPORT_CHECK_SUS spimem_flash_ll_sus_check_sus_setup(dev, true); + spimem_flash_ll_res_check_sus_setup(dev, true); #endif } @@ -166,18 +168,16 @@ 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(SPI1_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(SPI1_HOST); - spimem_flash_ll_auto_wait_idle_init(dev, false); + spimem_flash_ll_auto_wait_idle_init(dev, false, 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); + spimem_flash_ll_res_check_sus_setup(dev, false); #endif } @@ -185,9 +185,6 @@ 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(SPI1_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 @@ -195,6 +192,7 @@ 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)); + host->driver->poll_cmd_done(host); #else abort(); #endif @@ -204,6 +202,7 @@ 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)); + host->driver->poll_cmd_done(host); #else abort(); #endif diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 4cc4964a94..5a9a4e8d84 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -127,6 +127,40 @@ menu "Main Flash configuration" For new users, DO NOT enable this config. + config SPI_FLASH_SOFTWARE_RESUME + bool "Resume flash program/erase form suspend state by software control" + default n + depends on SPI_FLASH_AUTO_SUSPEND && FREERTOS_UNICORE && IDF_EXPERIMENTAL_FEATURES + help + Enable this config will disable auto-resume from hardware. Thus the software will resume the chip + after any higher priority task/interrupt which suspend the chip. The benefit is that the suspend-resume + will not disturb the higher priority task and interrupt. + + This currently is only valid on single core chip. + + config SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND + bool "Disable task scheduler when suspend is enabled when SPI1 operation is ongoing" + default n + # Only valid on single core because no protection is supported on multi core + depends on SPI_FLASH_AUTO_SUSPEND && FREERTOS_UNICORE + help + Disable freertos task scheduler when CONFIG_SPI_FLASH_AUTO_SUSPEND is enabled. + Thus only interrupt can trigger a suspend. When SPI_FLASH_AUTO_SUSPEND is enabled, + default behavior is not disable the task scheduler, so both interrupt and high priority + task can suspend the erase/program operation. When this option is enabled, task + scheduler is disabled, only interrupt can suspend erase/program operation. + + config SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS + bool "Check flash status automatically after flash suspend" + default n + depends on SPI_FLASH_AUTO_SUSPEND + help + Majority flash supports to use flash register to judge if flash suspend status is + done or not. So enable this config, the behavior would use flash register WIP bit to judge + whether suspend is valid instead of waiting for a specific long time, which can save a + lot of time and benefit for performance improvement. + + endmenu endmenu diff --git a/components/spi_flash/esp_flash_api.c b/components/spi_flash/esp_flash_api.c index aafaa32233..a4cb822718 100644 --- a/components/spi_flash/esp_flash_api.c +++ b/components/spi_flash/esp_flash_api.c @@ -21,6 +21,7 @@ #include "esp_rom_spiflash.h" #include "esp_private/esp_clk.h" #include "esp_spi_flash_counters.h" +#include "esp_check.h" #if CONFIG_IDF_TARGET_ESP32S2 #include "esp_crypto_lock.h" // for locking flash encryption peripheral @@ -1269,7 +1270,7 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres that share a key (as derived from flash address). On ESP32-S2 and later, the temporary buffer need to be - seperated into 16-bytes, 32-bytes, 64-bytes(if supported). + separated into 16-bytes, 32-bytes, 64-bytes(if supported). So, on ESP32-S2 and later, here has a totally different data prepare implementation. diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 389565166e..e66980279f 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -387,6 +387,10 @@ esp_err_t esp_flash_init_default_chip(void) cfg.tsus_val = TSUS_VAL_SUSPEND; #endif // CONFIG_SPI_FLASH_AUTO_SUSPEND + #if CONFIG_SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS + cfg.auto_waiti_pes = true; + #endif + //the host is already initialized, only do init for the data and load it to the host esp_err_t err = memspi_host_init_pointers(&esp_flash_default_host, &cfg); if (err != ESP_OK) { diff --git a/components/spi_flash/include/esp_flash.h b/components/spi_flash/include/esp_flash.h index f9b6d11f3a..062e1c598f 100644 --- a/components/spi_flash/include/esp_flash.h +++ b/components/spi_flash/include/esp_flash.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -204,7 +204,7 @@ esp_err_t esp_flash_erase_chip(esp_flash_t *chip); * @param start Address to start erasing flash. Must be sector aligned. * @param len Length of region to erase. Must also be sector aligned. * - * Sector size is specifyed in chip->drv->sector_size field (typically 4096 bytes.) ESP_ERR_INVALID_ARG will be + * Sector size is specified in chip->drv->sector_size field (typically 4096 bytes.) ESP_ERR_INVALID_ARG will be * returned if the start & length are not a multiple of this size. * * Erase is performed using block (multi-sector) erases where possible (block size is specified in diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index 4cb4ed5ced..71c32ed198 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -376,6 +376,7 @@ 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; + bool suspend_state = false; while (timeout_us > 0) { while (!chip->host->driver->host_status(chip->host) && timeout_us > 0) { @@ -388,6 +389,15 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u #endif } +#if CONFIG_SPI_FLASH_SOFTWARE_RESUME + suspend_state = ((chip->host->driver->host_status(chip->host) & SPI_FLASH_HAL_STATUS_SUSPEND) != 0) ? true : false; + + if (suspend_state) { + // Oh! find you are in suspend state + chip->host->driver->resume(chip->host); + } +#endif + uint32_t read; esp_err_t err = chip->chip_drv->read_reg(chip, SPI_FLASH_REG_STATUS, &read); if (err != ESP_OK) { @@ -395,7 +405,7 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u } status = read; - if ((status & SR_WIP) == 0) { // Verify write in progress is complete + if ((status & SR_WIP) == 0 && (suspend_state == false)) { // Verify write in progress is complete if (chip->busy == 1) { chip->busy = 0; if ((status & SR_WREN) != 0) { // The previous command is not accepted, leaving the WEL still set. diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index 1cae387281..700a230950 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/components/spi_flash/spi_flash_os_func_app.c @@ -121,6 +121,20 @@ static IRAM_ATTR esp_err_t spi1_start(void *arg) //directly disable the cache and interrupts when lock is not used cache_disable(NULL); #endif + +#if CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND + // Disable scheduler + if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) { +#ifdef CONFIG_FREERTOS_SMP + //Note: Scheduler suspension behavior changed in FreeRTOS SMP + vTaskPreemptionDisable(NULL); +#else + // Disable scheduler on the current CPU + vTaskSuspendAll(); +#endif // CONFIG_FREERTOS_SMP + } +#endif // CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND + on_spi_acquired((app_func_arg_t*)arg); return ret; } @@ -139,6 +153,18 @@ static IRAM_ATTR esp_err_t spi1_end(void *arg) #else cache_enable(NULL); #endif + +#if CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND + if (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING) { +#ifdef CONFIG_FREERTOS_SMP + //Note: Scheduler suspension behavior changed in FreeRTOS SMP + vTaskPreemptionEnable(NULL); +#else + xTaskResumeAll(); +#endif // CONFIG_FREERTOS_SMP + } +#endif // CONFIG_SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND + on_spi_released((app_func_arg_t*)arg); return ret; }