From c9f52c7ca76d8a045f154a7d615718a0ff71651a Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Thu, 16 Apr 2026 16:02:03 +0800 Subject: [PATCH] feat(spi_flash): Add exclusive support for ESP32H4 Add 32bit addr support for esp32s31 as well --- .../bootloader_flash/src/bootloader_flash.c | 12 - .../src/bootloader_flash_config_esp32.c | 2 +- .../src/bootloader_flash_config_esp32c2.c | 2 +- .../src/bootloader_flash_config_esp32c3.c | 2 +- .../src/bootloader_flash_config_esp32c5.c | 2 +- .../src/bootloader_flash_config_esp32c6.c | 2 +- .../src/bootloader_flash_config_esp32c61.c | 2 +- .../src/bootloader_flash_config_esp32h2.c | 2 +- .../src/bootloader_flash_config_esp32h21.c | 6 +- .../src/bootloader_flash_config_esp32h4.c | 13 +- .../src/bootloader_flash_config_esp32p4.c | 2 +- .../src/bootloader_flash_config_esp32s2.c | 2 +- .../src/bootloader_flash_config_esp32s3.c | 2 +- .../esp32h2/include/hal/gpspi_flash_ll.h | 2 +- .../esp32h21/include/hal/spimem_flash_ll.h | 4 +- .../esp32h4/include/hal/gpspi_flash_ll.h | 330 ++++++++++-------- .../esp32h4/include/hal/psram_ctrlr_ll.h | 2 +- .../esp32h4/include/hal/spi_flash_ll.h | 5 +- .../esp32h4/include/hal/spimem_flash_ll.h | 41 ++- .../esp32s31/include/hal/spi_flash_ll.h | 2 +- .../esp32h4/include/esp32h4/rom/cache.h | 2 +- .../esp32h4/include/esp32h4/rom/opi_flash.h | 319 +++++++++++++++++ .../esp32h4/include/esp32h4/rom/spi_flash.h | 120 +------ components/esp_rom/include/esp_rom_spiflash.h | 45 ++- components/esp_rom/patches/esp_rom_spiflash.c | 19 +- .../port/soc/esp32h4/system_internal.c | 2 +- components/hal/esp32h4/include/hal/cache_ll.h | 4 +- .../esp32h4/include/soc/Kconfig.soc_caps.in | 8 + components/soc/esp32h4/include/soc/soc_caps.h | 2 + .../soc/esp32h4/register/soc/spi1_mem_reg.h | 26 +- .../esp_flash/main/test_esp_flash_def.h | 1 - .../esp_flash/main/test_esp_flash_drv.c | 2 +- .../test_apps/esp_flash/main/test_spi_flash.c | 2 +- .../flash_suspend/main/test_flash_suspend.c | 10 +- examples/storage/fatfs/ext_flash/README.md | 4 +- 35 files changed, 647 insertions(+), 356 deletions(-) create mode 100644 components/esp_rom/esp32h4/include/esp32h4/rom/opi_flash.h diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index e179fe9fc6c..b9af5588f04 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -123,18 +123,6 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) #include "hal/mmu_ll.h" #include "hal/cache_hal.h" #include "hal/cache_ll.h" - -#if CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/opi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32P4 -#include "esp32p4/rom/opi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32C5 -#include "esp32c5/rom/opi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32C61 -#include "esp32c61/rom/opi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32S31 -#include "esp32s31/rom/opi_flash.h" -#endif #include "esp_flash_chips/spi_flash_defs.h" #if ESP_TEE_BUILD diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c index 10350bdc115..35adbdf5df0 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32.c @@ -281,7 +281,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) } // Set flash chip size esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); - // TODO: set mode + // TODO: IDF-15747 set mode // TODO: set frequency } diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c index 553aed51fdf..309d608a7b7 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c2.c @@ -141,7 +141,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c index 107da83e9ac..06a70ba2c6c 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c3.c @@ -152,7 +152,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c index 1d1ce7e2094..ec604b44585 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c5.c @@ -132,7 +132,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c index 51b31956895..37dd92f217f 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c6.c @@ -115,7 +115,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c index bc2efd29e9f..7cc94ec24ab 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32c61.c @@ -128,7 +128,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c index 0955677a62d..55b3c5d9f78 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h2.c @@ -123,7 +123,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h21.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h21.c index 264e78d1501..91c737c0694 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h21.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h21.c @@ -123,7 +123,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) @@ -137,10 +137,10 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr) const char *str; switch (bootloader_hdr->spi_speed) { case ESP_IMAGE_SPI_SPEED_DIV_2: - str = ESP_LOG_ATTR_STR("24MHz"); + str = ESP_LOG_ATTR_STR("32MHz"); break; case ESP_IMAGE_SPI_SPEED_DIV_1: - str = ESP_LOG_ATTR_STR("48MHz"); + str = ESP_LOG_ATTR_STR("64MHz"); break; default: str = ESP_LOG_ATTR_STR("16MHz"); diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h4.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h4.c index f6e29c0498a..485b75cfef8 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h4.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32h4.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -130,7 +130,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: [ESP32H4] IDF-12290 set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) @@ -144,16 +144,13 @@ static void print_flash_info(const esp_image_header_t *bootloader_hdr) const char *str; switch (bootloader_hdr->spi_speed) { case ESP_IMAGE_SPI_SPEED_DIV_2: - str = ESP_LOG_ATTR_STR("24MHz"); - break; - case ESP_IMAGE_SPI_SPEED_DIV_4: - str = ESP_LOG_ATTR_STR("12MHz"); + str = ESP_LOG_ATTR_STR("32MHz"); break; case ESP_IMAGE_SPI_SPEED_DIV_1: - str = ESP_LOG_ATTR_STR("48MHz"); + str = ESP_LOG_ATTR_STR("64MHz"); break; default: - str = ESP_LOG_ATTR_STR("12MHz"); + str = ESP_LOG_ATTR_STR("16MHz"); break; } ESP_EARLY_LOGI(TAG, "SPI Speed : %s", str); diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c index 0eb51fd271a..7adc3199ae6 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32p4.c @@ -124,7 +124,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) size = 2; } // Set flash chip size - esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode + esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: IDF-15747 set mode } static void print_flash_info(const esp_image_header_t *bootloader_hdr) diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c index 61d8a5f59c2..046f42d37a7 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s2.c @@ -156,7 +156,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) } // Set flash chip size esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); - // TODO: set mode + // TODO: IDF-15747 set mode // TODO: set frequency } diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c index 3c321ff5857..47a86f8c896 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash_config_esp32s3.c @@ -168,7 +168,7 @@ static void update_flash_config(const esp_image_header_t *bootloader_hdr) // Set flash chip size esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); - // TODO: set mode + // TODO: IDF-15747 set mode // TODO: set frequency } diff --git a/components/esp_hal_mspi/esp32h2/include/hal/gpspi_flash_ll.h b/components/esp_hal_mspi/esp32h2/include/hal/gpspi_flash_ll.h index 136b12aebf6..f485c44ee1b 100644 --- a/components/esp_hal_mspi/esp32h2/include/hal/gpspi_flash_ll.h +++ b/components/esp_hal_mspi/esp32h2/include/hal/gpspi_flash_ll.h @@ -31,7 +31,7 @@ extern "C" { #define gpspi_flash_ll_hw_get_id(dev) ( ((dev) == (void*)&GPSPI2) ? SPI2_HOST : -1 ) typedef typeof(GPSPI2.clock.val) gpspi_flash_ll_clock_reg_t; -#define GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (80) +#define GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (32) /*------------------------------------------------------------------------------ * Control diff --git a/components/esp_hal_mspi/esp32h21/include/hal/spimem_flash_ll.h b/components/esp_hal_mspi/esp32h21/include/hal/spimem_flash_ll.h index 45f380a0477..6af49547db8 100644 --- a/components/esp_hal_mspi/esp32h21/include/hal/spimem_flash_ll.h +++ b/components/esp_hal_mspi/esp32h21/include/hal/spimem_flash_ll.h @@ -671,10 +671,10 @@ static inline uint8_t spimem_flash_ll_get_source_freq_mhz(void) uint8_t clock_val = 0; switch (PCR.mspi_conf.mspi_clk_sel) { case 0: - clock_val = 48; + clock_val = 32; break; case 1: - clock_val = 8; + clock_val = 20; break; case 2: clock_val = 64; diff --git a/components/esp_hal_mspi/esp32h4/include/hal/gpspi_flash_ll.h b/components/esp_hal_mspi/esp32h4/include/hal/gpspi_flash_ll.h index 0d73bf7a040..8649a5a4872 100644 --- a/components/esp_hal_mspi/esp32h4/include/hal/gpspi_flash_ll.h +++ b/components/esp_hal_mspi/esp32h4/include/hal/gpspi_flash_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,8 +23,6 @@ #include #include "hal/misc.h" -//TODO: [ESP32H4] IDF-12389 inherited from verification branch, need check - #ifdef __cplusplus extern "C" { #endif @@ -33,7 +31,9 @@ extern "C" { #define gpspi_flash_ll_hw_get_id(dev) ( ((dev) == (void*)&GPSPI2) ? SPI2_HOST : -1 ) typedef typeof(GPSPI2.clock.val) gpspi_flash_ll_clock_reg_t; -#define GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (80) +#define GPSPI_FLASH_LL_PERIPHERAL_FREQUENCY_MHZ (32) +#define GPSPI_FLASH_LL_SUPPORT_CLK_SRC_PRE_DIV (1) +#define GPSPI_FLASH_LL_PERIPH_CLK_DIV_MAX ((SPI_CLKCNT_N + 1) * (SPI_CLKDIV_PRE + 1)) //peripheral internal maxmum clock divider /*------------------------------------------------------------------------------ * Control @@ -45,18 +45,17 @@ typedef typeof(GPSPI2.clock.val) gpspi_flash_ll_clock_reg_t; */ static inline void gpspi_flash_ll_reset(spi_dev_t *dev) { - // dev->user.val = 0; - // dev->ctrl.val = 0; + dev->user.val = 0; + dev->ctrl.val = 0; - // dev->clk_gate.clk_en = 1; - // dev->clk_gate.mst_clk_active = 1; - // dev->clk_gate.mst_clk_sel = 1; + dev->clk_gate.clk_en = 1; + dev->clk_gate.mst_clk_active = 1; + dev->clk_gate.mst_clk_sel = 1; - // dev->dma_conf.val = 0; - // dev->dma_conf.slv_tx_seg_trans_clr_en = 1; - // dev->dma_conf.slv_rx_seg_trans_clr_en = 1; - // dev->dma_conf.dma_slv_seg_trans_en = 0; - abort(); + dev->dma_conf.val = 0; + dev->dma_conf.slv_tx_seg_trans_clr_en = 1; + dev->dma_conf.slv_rx_seg_trans_clr_en = 1; + dev->dma_conf.dma_slv_seg_trans_en = 0; } /** @@ -68,8 +67,7 @@ static inline void gpspi_flash_ll_reset(spi_dev_t *dev) */ static inline bool gpspi_flash_ll_cmd_is_done(const spi_dev_t *dev) { - // return (dev->cmd.usr == 0); - abort(); + return (dev->cmd.usr == 0); } /** @@ -81,21 +79,20 @@ static inline bool gpspi_flash_ll_cmd_is_done(const spi_dev_t *dev) */ static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, uint32_t read_len) { - // if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) { - // // If everything is word-aligned, do a faster memcpy - // memcpy(buffer, (void *)dev->data_buf, read_len); - // } else { - // // Otherwise, slow(er) path copies word by word - // int copy_len = read_len; - // for (int i = 0; i < (read_len + 3) / 4; i++) { - // int word_len = MIN(sizeof(uint32_t), copy_len); - // uint32_t word = dev->data_buf[i].buf; - // memcpy(buffer, &word, word_len); - // buffer = (void *)((intptr_t)buffer + word_len); - // copy_len -= word_len; - // } - // } - abort(); + if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) { + // If everything is word-aligned, do a faster memcpy + memcpy(buffer, (void *)dev->data_buf, read_len); + } else { + // Otherwise, slow(er) path copies word by word + int copy_len = read_len; + for (int i = 0; i < (read_len + 3) / 4; i++) { + int word_len = MIN(sizeof(uint32_t), copy_len); + uint32_t word = dev->data_buf[i].buf; + memcpy(buffer, &word, word_len); + buffer = (void *)((intptr_t)buffer + word_len); + copy_len -= word_len; + } + } } /** @@ -106,8 +103,7 @@ static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, */ static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word) { - // dev->data_buf[0].buf = word; - abort(); + dev->data_buf[0].buf = word; } /** @@ -119,17 +115,16 @@ static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word) */ static inline void gpspi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *buffer, uint32_t length) { - // // Load data registers, word at a time - // int num_words = (length + 3) / 4; - // for (int i = 0; i < num_words; i++) { - // uint32_t word = 0; - // uint32_t word_len = MIN(length, sizeof(word)); - // memcpy(&word, buffer, word_len); - // dev->data_buf[i].buf = word; - // length -= word_len; - // buffer = (void *)((intptr_t)buffer + word_len); - // } - abort(); + // Load data registers, word at a time + int num_words = (length + 3) / 4; + for (int i = 0; i < num_words; i++) { + uint32_t word = 0; + uint32_t word_len = MIN(length, sizeof(word)); + memcpy(&word, buffer, word_len); + dev->data_buf[i].buf = word; + length -= word_len; + buffer = (void *)((intptr_t)buffer + word_len); + } } /** @@ -141,10 +136,9 @@ static inline void gpspi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *bu */ static inline void gpspi_flash_ll_user_start(spi_dev_t *dev, bool pe_ops) { - // dev->cmd.update = 1; - // while (dev->cmd.update); - // dev->cmd.usr = 1; - abort(); + dev->cmd.update = 1; + while (dev->cmd.update); + dev->cmd.usr = 1; } /** @@ -164,8 +158,7 @@ static inline void gpspi_flash_ll_set_pe_bit(spi_dev_t *dev) */ static inline void gpspi_flash_ll_set_hold_pol(spi_dev_t *dev, uint32_t pol_val) { - // dev->ctrl.hold_pol = pol_val; - abort(); + dev->ctrl.hold_pol = pol_val; } /** @@ -177,8 +170,7 @@ static inline void gpspi_flash_ll_set_hold_pol(spi_dev_t *dev, uint32_t pol_val) */ static inline bool gpspi_flash_ll_host_idle(const spi_dev_t *dev) { - // return dev->cmd.usr == 0; - abort(); + return dev->cmd.usr == 0; } /** @@ -188,14 +180,13 @@ static inline bool gpspi_flash_ll_host_idle(const spi_dev_t *dev) */ static inline void gpspi_flash_ll_read_phase(spi_dev_t *dev) { - // typeof (dev->user) user = { - // .usr_mosi = 0, - // .usr_miso = 1, - // .usr_addr = 1, - // .usr_command = 1, - // }; - // dev->user.val = user.val; - abort(); + typeof(dev->user) user = { + .usr_mosi = 0, + .usr_miso = 1, + .usr_addr = 1, + .usr_command = 1, + }; + dev->user.val = user.val; } /*------------------------------------------------------------------------------ * Configs @@ -208,9 +199,8 @@ static inline void gpspi_flash_ll_read_phase(spi_dev_t *dev) */ static inline void gpspi_flash_ll_set_cs_pin(spi_dev_t *dev, int pin) { - // dev->misc.cs0_dis = (pin == 0) ? 0 : 1; - // dev->misc.cs1_dis = (pin == 1) ? 0 : 1; - abort(); + dev->misc.cs0_dis = (pin == 0) ? 0 : 1; + dev->misc.cs1_dis = (pin == 1) ? 0 : 1; } /** @@ -221,44 +211,43 @@ static inline void gpspi_flash_ll_set_cs_pin(spi_dev_t *dev, int pin) */ static inline void gpspi_flash_ll_set_read_mode(spi_dev_t *dev, esp_flash_io_mode_t read_mode) { - // typeof (dev->ctrl) ctrl; - // ctrl.val = dev->ctrl.val; - // typeof (dev->user) user; - // user.val = dev->user.val; + typeof(dev->ctrl) ctrl; + ctrl.val = dev->ctrl.val; + typeof(dev->user) user; + user.val = dev->user.val; - // ctrl.val &= ~(SPI_FCMD_QUAD_M | SPI_FADDR_QUAD_M | SPI_FREAD_QUAD_M | SPI_FCMD_DUAL_M | SPI_FADDR_DUAL_M | SPI_FREAD_DUAL_M); - // user.val &= ~(SPI_FWRITE_QUAD_M | SPI_FWRITE_DUAL_M); + ctrl.val &= ~(SPI_FCMD_QUAD_M | SPI_FADDR_QUAD_M | SPI_FREAD_QUAD_M | SPI_FCMD_DUAL_M | SPI_FADDR_DUAL_M | SPI_FREAD_DUAL_M); + user.val &= ~(SPI_FWRITE_QUAD_M | SPI_FWRITE_DUAL_M); - // switch (read_mode) { - // case SPI_FLASH_FASTRD: - // //the default option - // case SPI_FLASH_SLOWRD: - // break; - // case SPI_FLASH_QIO: - // ctrl.fread_quad = 1; - // ctrl.faddr_quad = 1; - // user.fwrite_quad = 1; - // break; - // case SPI_FLASH_QOUT: - // ctrl.fread_quad = 1; - // user.fwrite_quad = 1; - // break; - // case SPI_FLASH_DIO: - // ctrl.fread_dual = 1; - // ctrl.faddr_dual = 1; - // user.fwrite_dual = 1; - // break; - // case SPI_FLASH_DOUT: - // ctrl.fread_dual = 1; - // user.fwrite_dual = 1; - // break; - // default: - // abort(); - // } + switch (read_mode) { + case SPI_FLASH_FASTRD: + //the default option + case SPI_FLASH_SLOWRD: + break; + case SPI_FLASH_QIO: + ctrl.fread_quad = 1; + ctrl.faddr_quad = 1; + user.fwrite_quad = 1; + break; + case SPI_FLASH_QOUT: + ctrl.fread_quad = 1; + user.fwrite_quad = 1; + break; + case SPI_FLASH_DIO: + ctrl.fread_dual = 1; + ctrl.faddr_dual = 1; + user.fwrite_dual = 1; + break; + case SPI_FLASH_DOUT: + ctrl.fread_dual = 1; + user.fwrite_dual = 1; + break; + default: + abort(); + } - // dev->ctrl.val = ctrl.val; - // dev->user.val = user.val; - abort(); + dev->ctrl.val = ctrl.val; + dev->user.val = user.val; } /** @@ -269,8 +258,7 @@ static inline void gpspi_flash_ll_set_read_mode(spi_dev_t *dev, esp_flash_io_mod */ static inline void gpspi_flash_ll_set_clock(spi_dev_t *dev, gpspi_flash_ll_clock_reg_t *clock_val) { - // dev->clock.val = *clock_val; - abort(); + dev->clock.val = *clock_val; } /** @@ -281,11 +269,10 @@ static inline void gpspi_flash_ll_set_clock(spi_dev_t *dev, gpspi_flash_ll_clock */ static inline void gpspi_flash_ll_set_miso_bitlen(spi_dev_t *dev, uint32_t bitlen) { - // dev->user.usr_miso = bitlen > 0; - // if (bitlen) { - // dev->ms_dlen.ms_data_bitlen = bitlen - 1; - // } - abort(); + dev->user.usr_miso = bitlen > 0; + if (bitlen) { + dev->ms_dlen.ms_data_bitlen = bitlen - 1; + } } /** @@ -297,11 +284,10 @@ static inline void gpspi_flash_ll_set_miso_bitlen(spi_dev_t *dev, uint32_t bitle */ static inline void gpspi_flash_ll_set_mosi_bitlen(spi_dev_t *dev, uint32_t bitlen) { - // dev->user.usr_mosi = bitlen > 0; - // if (bitlen) { - // dev->ms_dlen.ms_data_bitlen = bitlen - 1; - // } - abort(); + dev->user.usr_mosi = bitlen > 0; + if (bitlen) { + dev->ms_dlen.ms_data_bitlen = bitlen - 1; + } } /** @@ -313,13 +299,12 @@ static inline void gpspi_flash_ll_set_mosi_bitlen(spi_dev_t *dev, uint32_t bitle */ static inline void gpspi_flash_ll_set_command(spi_dev_t *dev, uint8_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; - abort(); + dev->user.usr_command = 1; + typeof(dev->user2) user2 = { + .usr_command_value = command, + .usr_command_bitlen = (bitlen - 1), + }; + dev->user2.val = user2.val; } /** @@ -330,8 +315,7 @@ static inline void gpspi_flash_ll_set_command(spi_dev_t *dev, uint8_t command, u */ static inline int gpspi_flash_ll_get_addr_bitlen(spi_dev_t *dev) { - // return dev->user.usr_addr ? dev->user1.usr_addr_bitlen + 1 : 0; - abort(); + return dev->user.usr_addr ? dev->user1.usr_addr_bitlen + 1 : 0; } /** @@ -342,9 +326,8 @@ static inline int gpspi_flash_ll_get_addr_bitlen(spi_dev_t *dev) */ static inline void gpspi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitlen) { - // dev->user1.usr_addr_bitlen = (bitlen - 1); - // dev->user.usr_addr = bitlen ? 1 : 0; - abort(); + dev->user1.usr_addr_bitlen = (bitlen - 1); + dev->user.usr_addr = bitlen ? 1 : 0; } /** @@ -356,9 +339,8 @@ static inline void gpspi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitle static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, uint32_t bitlen) { // The blank region should be all ones - // uint32_t padding_ones = (bitlen == 32? 0 : UINT32_MAX >> bitlen); - // dev->addr.val = (addr << (32 - bitlen)) | padding_ones; - abort(); + uint32_t padding_ones = (bitlen == 32 ? 0 : UINT32_MAX >> bitlen); + dev->addr.val = (addr << (32 - bitlen)) | padding_ones; } /** @@ -369,8 +351,7 @@ static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, */ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) { - // dev->addr.val = addr; - abort(); + dev->addr.val = addr; } /** @@ -381,9 +362,10 @@ static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr) */ static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) { - // dev->user.usr_dummy = dummy_n ? 1 : 0; - // HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); - abort(); + dev->user.usr_dummy = dummy_n ? 1 : 0; + if (dummy_n > 0) { + HAL_FORCE_MODIFY_U32_REG_FIELD(dev->user1, usr_dummy_cyclelen, dummy_n - 1); + } } /** @@ -395,10 +377,9 @@ static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n) */ static inline void gpspi_flash_ll_set_dummy_out(spi_dev_t *dev, uint32_t out_en, uint32_t out_lev) { - // dev->ctrl.dummy_out = out_en; - // dev->ctrl.q_pol = out_lev; - // dev->ctrl.d_pol = out_lev; - abort(); + dev->ctrl.dummy_out = out_en; + dev->ctrl.q_pol = out_lev; + dev->ctrl.d_pol = out_lev; } /** @@ -409,16 +390,24 @@ static inline void gpspi_flash_ll_set_dummy_out(spi_dev_t *dev, uint32_t out_en, */ static inline void gpspi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n) { - // dev->user1.cs_hold_time = hold_n - 1; - // dev->user.cs_hold = (hold_n > 0? 1: 0); - abort(); + dev->user.cs_hold = (hold_n > 0 ? 1 : 0); + if (hold_n > 0) { + dev->user1.cs_hold_time = hold_n - 1; + } } +/** + * Set the delay of SPI clocks before the first SPI clock after the CS active edge. + * + * @param dev Beginning address of the peripheral registers. + * @param cs_setup_time Delay of SPI clocks after the CS active edge, 0 to disable the setup phase. + */ static inline void gpspi_flash_ll_set_cs_setup(spi_dev_t *dev, uint32_t cs_setup_time) { - // dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0); - // dev->user1.cs_setup_time = cs_setup_time - 1; - abort(); + dev->user.cs_setup = (cs_setup_time > 0 ? 1 : 0); + if (cs_setup_time > 0) { + dev->user1.cs_setup_time = cs_setup_time - 1; + } } /** @@ -430,31 +419,39 @@ static inline void gpspi_flash_ll_set_cs_setup(spi_dev_t *dev, uint32_t cs_setup */ static inline uint32_t gpspi_flash_ll_calculate_clock_reg(uint8_t clkdiv) { - // uint32_t div_parameter; - // // See comments of `clock` in `spi_struct.h` - // if (clkdiv == 1) { - // div_parameter = (1 << 31); - // } else { - // div_parameter = ((clkdiv - 1) | (((clkdiv/2 - 1) & 0xff) << 6 ) | (((clkdiv - 1) & 0xff) << 12)); - // } - // return div_parameter; - abort(); + uint32_t div_parameter; + // See comments of `clock` in `spi_struct.h` + if (clkdiv == 1) { + div_parameter = (1 << 31); + } else { + div_parameter = ((clkdiv - 1) | (((clkdiv / 2 - 1) & 0xff) << 6) | (((clkdiv - 1) & 0xff) << 12)); + } + return div_parameter; } __attribute__((always_inline)) static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source_t clk_source) { + int clock_id = 0; switch (clk_source) { case SPI_CLK_SRC_RC_FAST: - PCR.spi2_clkm_conf.spi2_clkm_sel = 2; + clock_id = 2; break; case SPI_CLK_SRC_XTAL: - PCR.spi2_clkm_conf.spi2_clkm_sel = 0; + clock_id = 0; break; - default: - PCR.spi2_clkm_conf.spi2_clkm_sel = 1; + default: // PLL_F48M + clock_id = 1; break; } + + if (hw == &GPSPI2) { + PCR.spi2_clkm_conf.spi2_clkm_sel = clock_id; + } else if (hw == &GPSPI3) { + PCR.spi3_clkm_conf.spi3_clkm_sel = clock_id; + } else { + abort(); + } } /** @@ -465,8 +462,31 @@ static inline void gpspi_flash_ll_set_clk_source(spi_dev_t *hw, spi_clock_source */ static inline void gpspi_flash_ll_enable_clock(spi_dev_t *hw, bool enable) { - (void) hw; - PCR.spi2_clkm_conf.spi2_clkm_en = enable; + if (hw == &GPSPI2) { + PCR.spi2_clkm_conf.spi2_clkm_en = enable; + } else if (hw == &GPSPI3) { + PCR.spi3_clkm_conf.spi3_clkm_en = enable; + } else { + abort(); + } +} + +/** +* Enable/disable SPI flash module clock +* +* @param hw Beginning address of the peripheral registers. +* @param enable true to enable, false to disable +*/ +static inline void gpspi_flash_ll_clk_source_pre_div(spi_dev_t *hw, uint8_t hs_div, uint8_t mst_div) +{ + (void) hs_div; + if (hw == &GPSPI2) { + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.spi2_clkm_conf, spi2_clkm_div_num, mst_div - 1); + } else if (hw == &GPSPI3) { + HAL_FORCE_MODIFY_U32_REG_FIELD(PCR.spi3_clkm_conf, spi3_clkm_div_num, mst_div - 1); + } else { + abort(); + } } #ifdef __cplusplus diff --git a/components/esp_hal_mspi/esp32h4/include/hal/psram_ctrlr_ll.h b/components/esp_hal_mspi/esp32h4/include/hal/psram_ctrlr_ll.h index 7ce6c2d9f03..bed423c9983 100644 --- a/components/esp_hal_mspi/esp32h4/include/hal/psram_ctrlr_ll.h +++ b/components/esp_hal_mspi/esp32h4/include/hal/psram_ctrlr_ll.h @@ -20,7 +20,7 @@ #include "soc/spi_mem_struct.h" #include "soc/spi_mem_reg.h" #include "soc/clk_tree_defs.h" -#include "rom/spi_flash.h" +#include "rom/opi_flash.h" #include "hal/psram_types.h" #ifdef __cplusplus diff --git a/components/esp_hal_mspi/esp32h4/include/hal/spi_flash_ll.h b/components/esp_hal_mspi/esp32h4/include/hal/spi_flash_ll.h index e9ae3caa6fd..67465ff2972 100644 --- a/components/esp_hal_mspi/esp32h4/include/hal/spi_flash_ll.h +++ b/components/esp_hal_mspi/esp32h4/include/hal/spi_flash_ll.h @@ -35,7 +35,8 @@ extern "C" { }\ dev_id; \ }) -// Since ESP32-C6, WB_mode is available, we extend 8 bits to occupy `Continuous Read Mode` bits. +#define SPI_FLASH_LL_SUPPORT_WB_MODE_INDEPENDENT_CONTROL (1) +// WB_mode is available, we extend 8 bits to occupy `Continuous Read Mode` bits. #define SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS (8) typedef union { @@ -68,6 +69,7 @@ typedef union { #define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n) #define spi_flash_ll_set_cs_setup(dev, cs_setup_time) gpspi_flash_ll_set_cs_setup((spi_dev_t*)dev, cs_setup_time) #define spi_flash_ll_set_extra_address(dev, extra_addr) { /* Not supported on gpspi on ESP32-H4*/ } +#define spi_flash_ll_wb_mode_enable(dev, wb_mode_enale) { /* Not supported on gpspi on ESP32-H4*/ } #else #define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev) #define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev) @@ -101,6 +103,7 @@ typedef union { #define spi_flash_ll_sync_reset() spimem_flash_ll_sync_reset() #define spi_flash_ll_set_common_command_register_info(dev, ctrl_reg, user_reg, user1_reg, user2_reg) spimem_flash_ll_set_common_command_register_info((spi_mem_dev_t*)dev, ctrl_reg, user_reg, user1_reg, user2_reg) #define spi_flash_ll_get_common_command_register_info(dev, ctrl_reg, user_reg, user1_reg, user2_reg) spimem_flash_ll_get_common_command_register_info((spi_mem_dev_t*)dev, ctrl_reg, user_reg, user1_reg, user2_reg) +#define spi_flash_ll_wb_mode_enable(dev, wb_mode_enale) spimem_flash_ll_wb_mode_enable((spi_mem_dev_t*)dev, wb_mode_enale) #endif diff --git a/components/esp_hal_mspi/esp32h4/include/hal/spimem_flash_ll.h b/components/esp_hal_mspi/esp32h4/include/hal/spimem_flash_ll.h index 423409b0010..1aeeef2e834 100644 --- a/components/esp_hal_mspi/esp32h4/include/hal/spimem_flash_ll.h +++ b/components/esp_hal_mspi/esp32h4/include/hal/spimem_flash_ll.h @@ -60,6 +60,7 @@ static inline void spimem_flash_ll_reset(spi_mem_dev_t *dev) * * @return true if last command is done, otherwise false. */ +__attribute__((always_inline)) static inline bool spimem_flash_ll_cmd_is_done(const spi_mem_dev_t *dev) { return (dev->cmd.val == 0); @@ -374,6 +375,7 @@ static inline void spimem_flash_ll_exit_dpd(spi_mem_dev_t *dev) * @param buffer Buffer to hold the output data * @param read_len Length to get out of the buffer */ +__attribute__((always_inline)) static inline void spimem_flash_ll_get_buffer_data(spi_mem_dev_t *dev, void *buffer, uint32_t read_len) { if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) { @@ -399,6 +401,7 @@ static inline void spimem_flash_ll_get_buffer_data(spi_mem_dev_t *dev, void *buf * @param buffer Buffer holding the data * @param length Length of data in bytes. */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_buffer_data(spi_mem_dev_t *dev, const void *buffer, uint32_t length) { // Load data registers, word at a time @@ -435,6 +438,7 @@ static inline void spimem_flash_ll_program_page(spi_mem_dev_t *dev, const void * * @param dev Beginning address of the peripheral registers. * @param pe_ops Is page program/erase operation or not. */ +__attribute__((always_inline)) static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev, bool pe_ops) { uint32_t usr_pe = (pe_ops ? 0x60000 : 0x40000); @@ -538,6 +542,7 @@ static inline void spimem_flash_ll_set_clock(spi_mem_dev_t *dev, spimem_flash_ll * @param dev Beginning address of the peripheral registers. * @param bitlen Length of input, in bits. */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_miso_bitlen(spi_mem_dev_t *dev, uint32_t bitlen) { dev->user.usr_miso = bitlen > 0; @@ -551,6 +556,7 @@ static inline void spimem_flash_ll_set_miso_bitlen(spi_mem_dev_t *dev, uint32_t * @param dev Beginning address of the peripheral registers. * @param bitlen Length of output, in bits. */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t bitlen) { dev->user.usr_mosi = bitlen > 0; @@ -564,6 +570,7 @@ static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t * @param command Command to send * @param bitlen Length of the command */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen) { dev->user.usr_command = 1; @@ -588,8 +595,10 @@ static inline int spimem_flash_ll_get_addr_bitlen(spi_mem_dev_t *dev) * @param dev Beginning address of the peripheral registers. * @param bitlen Length of the address, in bits */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t bitlen) { + dev->cache_fctrl.usr_addr_4byte = (bitlen == 32) ? 1 : 0; dev->user1.usr_addr_bitlen = (bitlen - 1); dev->user.usr_addr = bitlen ? 1 : 0; } @@ -602,8 +611,19 @@ 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; HAL_FORCE_MODIFY_U32_REG_FIELD(dev->rd_status, wb_mode, extra_addr); + dev->rd_status.wb_mode_bitlen = 7; // 8 - 1 +} + +/** + * Enable extra address for bits M0-M7 in DIO/QIO mode. + * + * @param dev Beginning address of the peripheral registers. + * @param wb_mode_enable true for enabling wb_mode + */ +static inline void spimem_flash_ll_wb_mode_enable(spi_mem_dev_t *dev, bool wb_mode_enable) +{ + dev->rd_status.wb_mode_en = wb_mode_enable; } /** @@ -623,6 +643,7 @@ static inline void spimem_flash_ll_set_address(spi_mem_dev_t *dev, uint32_t addr * @param dev Beginning address of the peripheral registers. * @param addr Address to send */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_usr_address(spi_mem_dev_t *dev, uint32_t addr, uint32_t bitlen) { (void)bitlen; @@ -635,10 +656,13 @@ static inline void spimem_flash_ll_set_usr_address(spi_mem_dev_t *dev, uint32_t * @param dev Beginning address of the peripheral registers. * @param dummy_n Cycles of dummy phases */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_n) { dev->user.usr_dummy = dummy_n ? 1 : 0; - dev->user1.usr_dummy_cyclelen = dummy_n - 1; + if (dummy_n > 0) { + dev->user1.usr_dummy_cyclelen = dummy_n - 1; + } } /** @@ -652,6 +676,12 @@ static inline void spimem_flash_ll_set_hold(spi_mem_dev_t *dev, uint32_t hold_n) //not supported on esp32h4 } +/** + * Set CS setup time + * + * @param dev Beginning address of the peripheral registers. + * @param cs_setup_time CS setup time + */ static inline void spimem_flash_ll_set_cs_setup(spi_mem_dev_t *dev, uint32_t cs_setup_time) { //not supported on esp32h4 @@ -670,10 +700,10 @@ static inline uint8_t spimem_flash_ll_get_source_freq_mhz(void) uint8_t clock_val = 0; switch (PCR.mspi_clk_conf.mspi_func_clk_sel) { case 0: - clock_val = 48; + clock_val = 32; break; case 1: - clock_val = 8; + clock_val = 20; break; case 2: clock_val = 64; @@ -711,6 +741,7 @@ static inline uint32_t spimem_flash_ll_calculate_clock_reg(uint8_t clkdiv) * @param level 1: 1: output high, 0: output low */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_wp_level(spi_mem_dev_t *dev, bool level) { dev->ctrl.wp_reg = level; @@ -747,6 +778,7 @@ static inline void spimem_flash_ll_sync_reset(void) * @param user1_reg user1_reg * @param user2_reg user2_reg */ +__attribute__((always_inline)) static inline void spimem_flash_ll_get_common_command_register_info(spi_mem_dev_t *dev, uint32_t *ctrl_reg, uint32_t *user_reg, uint32_t *user1_reg, uint32_t *user2_reg) { *ctrl_reg = dev->ctrl.val; @@ -763,6 +795,7 @@ static inline void spimem_flash_ll_get_common_command_register_info(spi_mem_dev_ * @param user1_reg user1_reg * @param user2_reg user2_reg */ +__attribute__((always_inline)) static inline void spimem_flash_ll_set_common_command_register_info(spi_mem_dev_t *dev, uint32_t ctrl_reg, uint32_t user_reg, uint32_t user1_reg, uint32_t user2_reg) { dev->ctrl.val = ctrl_reg; diff --git a/components/esp_hal_mspi/esp32s31/include/hal/spi_flash_ll.h b/components/esp_hal_mspi/esp32s31/include/hal/spi_flash_ll.h index 35f2e1969bb..3192e7f7fe6 100644 --- a/components/esp_hal_mspi/esp32s31/include/hal/spi_flash_ll.h +++ b/components/esp_hal_mspi/esp32s31/include/hal/spi_flash_ll.h @@ -35,7 +35,7 @@ extern "C" { }\ dev_id; \ }) -// Since ESP32-P4, WB_mode is available, we extend 8 bits to occupy `Continuous Read Mode` bits. +// WB_mode is available, we extend 8 bits to occupy `Continuous Read Mode` bits. #define SPI_FLASH_LL_CONTINUOUS_MODE_BIT_NUMS (8) typedef union { diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/cache.h b/components/esp_rom/esp32h4/include/esp32h4/rom/cache.h index 3439c4f523a..f0835f77b60 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/cache.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/cache.h @@ -162,7 +162,7 @@ extern const struct cache_internal_stub_table* rom_cache_internal_table_ptr; #define CACHE_MAP_ICACHE0 BIT(0) #define CACHE_MAP_ICACHE1 BIT(1) #define CACHE_MAP_DCACHE BIT(4) -#define CACHE_MAP_ALL (CACHE_MAP_ICACHE0 | CACHE_MAP_ICACHE1 | CACHE_MAP_DCACHE) +#define CACHE_MAP_MASK (CACHE_MAP_ICACHE0 | CACHE_MAP_ICACHE1 | CACHE_MAP_DCACHE) // keep the software flag same as map value #define CACHE_AUTOLOAD_ICACHE0_FLAG BIT(0) diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/opi_flash.h b/components/esp_rom/esp32h4/include/esp32h4/rom/opi_flash.h new file mode 100644 index 00000000000..9c5e5b20bc4 --- /dev/null +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/opi_flash.h @@ -0,0 +1,319 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include +#include "spi_flash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint16_t cmd; /*!< Command value */ + uint16_t cmdBitLen; /*!< Command byte length*/ + uint32_t *addr; /*!< Point to address value*/ + uint32_t addrBitLen; /*!< Address byte length*/ + uint32_t *txData; /*!< Point to send data buffer*/ + uint32_t txDataBitLen; /*!< Send data byte length.*/ + uint32_t *rxData; /*!< Point to receive data buffer*/ + uint32_t rxDataBitLen; /*!< Receive Data byte length.*/ + uint32_t dummyBitLen; +} esp_rom_spi_cmd_t; + +typedef struct { + uint8_t mode; + uint8_t cmd_bit_len; + uint16_t cmd; + uint32_t addr; + uint8_t addr_bit_len; + uint8_t dummy_bit_len; + uint8_t data_bit_len; + uint8_t cs_sel : 4; + uint8_t is_pe : 4; +} esp_rom_opiflash_cmd_t; + +typedef struct { + uint8_t addr_bit_len; + uint8_t dummy_bit_len; + uint16_t cmd; + uint8_t cmd_bit_len; + uint8_t var_dummy_en; +} esp_rom_opiflash_spi0rd_t; + +typedef struct { + esp_rom_opiflash_cmd_t rdid; + esp_rom_opiflash_cmd_t rdsr; + esp_rom_opiflash_cmd_t wren; + esp_rom_opiflash_cmd_t se; + esp_rom_opiflash_cmd_t be64k; + esp_rom_opiflash_cmd_t read; + esp_rom_opiflash_cmd_t pp; + esp_rom_opiflash_spi0rd_t cache_rd_cmd; + bool usr_ecc_en; +} esp_rom_opiflash_def_t; + +#define ESP_ROM_OPIFLASH_SEL_CS0 (BIT(0)) +#define ESP_ROM_OPIFLASH_SEL_CS1 (BIT(1)) + +// Definition of MX25UM25645G Octa Flash +// SPI status register +#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT0 +#define ESP_ROM_SPIFLASH_WRENABLE_FLAG BIT1 +#define ESP_ROM_SPIFLASH_BP0 BIT2 +#define ESP_ROM_SPIFLASH_BP1 BIT3 +#define ESP_ROM_SPIFLASH_BP2 BIT4 +#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) +#define ESP_ROM_SPIFLASH_QE BIT9 + +#define FLASH_OP_MODE_RDCMD_DOUT 0x3B +#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000 +#define ESP_ROM_FLASH_BLOCK_SIZE_64K 0x10000 +#define ESP_ROM_FLASH_PAGE_SIZE 256 + +// FLASH commands +#define ROM_FLASH_CMD_RDID 0x9F +#define ROM_FLASH_CMD_WRSR 0x01 +#define ROM_FLASH_CMD_WRSR2 0x31 /* Not all SPI flash uses this command */ +#define ROM_FLASH_CMD_WREN 0x06 +#define ROM_FLASH_CMD_WRDI 0x04 +#define ROM_FLASH_CMD_RDSR 0x05 +#define ROM_FLASH_CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ +#define ROM_FLASH_CMD_ERASE_SEC 0x20 +#define ROM_FLASH_CMD_ERASE_BLK_32K 0x52 +#define ROM_FLASH_CMD_ERASE_BLK_64K 0xD8 +#define ROM_FLASH_CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */ +#define ROM_FLASH_CMD_RSTEN 0x66 +#define ROM_FLASH_CMD_RST 0x99 + +#define ROM_FLASH_CMD_SE4B 0x21 +#define ROM_FLASH_CMD_SE4B_OCT 0xDE21 +#define ROM_FLASH_CMD_BE4B 0xDC +#define ROM_FLASH_CMD_BE4B_OCT 0x23DC +#define ROM_FLASH_CMD_RSTEN_OCT 0x9966 +#define ROM_FLASH_CMD_RST_OCT 0x6699 + +#define ROM_FLASH_CMD_FSTRD4B_STR 0x13EC +#define ROM_FLASH_CMD_FSTRD4B_DTR 0x11EE +#define ROM_FLASH_CMD_FSTRD4B 0x0C +#define ROM_FLASH_CMD_PP4B 0x12 +#define ROM_FLASH_CMD_PP4B_OCT 0xED12 + +#define ROM_FLASH_CMD_RDID_OCT 0x609F +#define ROM_FLASH_CMD_WREN_OCT 0xF906 +#define ROM_FLASH_CMD_RDSR_OCT 0xFA05 +#define ROM_FLASH_CMD_RDCR2 0x71 +#define ROM_FLASH_CMD_RDCR2_OCT 0x8E71 +#define ROM_FLASH_CMD_WRCR2 0x72 +#define ROM_FLASH_CMD_WRCR2_OCT 0x8D72 + +// Definitions for GigaDevice GD25LX256E Flash +#define ROM_FLASH_CMD_RDFSR_GD 0x70 +#define ROM_FLASH_CMD_RD_GD 0x03 +#define ROM_FLASH_CMD_RD4B_GD 0x13 +#define ROM_FLASH_CMD_FSTRD_GD 0x0B +#define ROM_FLASH_CMD_FSTRD4B_GD 0x0C +#define ROM_FLASH_CMD_FSTRD_OOUT_GD 0x8B +#define ROM_FLASH_CMD_FSTRD4B_OOUT_GD 0x7C +#define ROM_FLASH_CMD_FSTRD_OIOSTR_GD 0xCB +#define ROM_FLASH_CMD_FSTRD4B_OIOSTR_GD 0xCC +#define ROM_FLASH_CMD_FSTRD4B_OIODTR_GD 0xFD + +#define ROM_FLASH_CMD_PP_GD 0x02 +#define ROM_FLASH_CMD_PP4B_GD 0x12 +#define ROM_FLASH_CMD_PP_OOUT_GD 0x82 +#define ROM_FLASH_CMD_PP4B_OOUT_GD 0x84 +#define ROM_FLASH_CMD_PP_OIO_GD 0xC2 +#define ROM_FLASH_CMD_PP4B_OIOSTR_GD 0x8E + +#define ROM_FLASH_CMD_SE_GD 0x20 +#define ROM_FLASH_CMD_SE4B_GD 0x21 +#define ROM_FLASH_CMD_BE32K_GD 0x52 +#define ROM_FLASH_CMD_BE32K4B_GD 0x5C +#define ROM_FLASH_CMD_BE64K_GD 0xD8 +#define ROM_FLASH_CMD_BE64K4B_GD 0xDC + +#define ROM_FLASH_CMD_EN4B_GD 0xB7 +#define ROM_FLASH_CMD_DIS4B_GD 0xE9 + +extern const esp_rom_opiflash_def_t *rom_opiflash_cmd_def; + +/** + * @brief Config the spi user command + * @param spi_num spi port + * @param pcmd pointer to accept the spi command struct + */ +void esp_rom_spi_cmd_config(int spi_num, esp_rom_spi_cmd_t *pcmd); + +/** + * @brief Start a spi user command sequence + * @param spi_num spi port + * @param rx_buf buffer pointer to receive data + * @param rx_len receive data length in byte + * @param cs_en_mask decide which cs to use, 0 for cs0, 1 for cs1 + * @param is_write_erase to indicate whether this is a write or erase operation, since the CPU would check permission + */ +void esp_rom_spi_cmd_start(int spi_num, uint8_t *rx_buf, uint16_t rx_len, uint8_t cs_en_mask, bool is_write_erase); + +/** + * @brief Config opi flash pads according to efuse settings. + */ +void esp_rom_opiflash_pin_config(); + +// set SPI read/write mode +/** + * @brief Set SPI operation mode + * @param spi_num spi port + * @param mode Flash Read Mode + */ +void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief Set data swap mode in DTR(DDR) mode + * @param spi_num spi port + * @param wr_swap to decide whether to swap fifo data in dtr write operation + * @param rd_swap to decide whether to swap fifo data in dtr read operation + */ +void esp_rom_spi_set_dtr_swap_mode(int spi, bool wr_swap, bool rd_swap); + +/** + * @brief to send reset command in spi/opi-str/opi-dtr mode(for MX25UM25645G) + * @param spi_num spi port + */ +void esp_rom_opiflash_mode_reset(int spi_num); + +/** + * @brief To execute a flash operation command + * @param spi_num spi port + * @param mode Flash Read Mode + * @param cmd data to send in command field + * @param cmd_bit_len bit length of command field + * @param addr data to send in address field + * @param addr_bit_len bit length of address field + * @param dummy_bits bit length of dummy field + * @param mosi_data data buffer to be sent in mosi field + * @param mosi_bit_len bit length of data buffer to be sent in mosi field + * @param miso_data data buffer to accept data in miso field + * @param miso_bit_len bit length of data buffer to accept data in miso field + * @param cs_mark decide which cs pin to use. 0: cs0, 1: cs1 + * @param is_write_erase_operation to indicate whether this a write or erase flash operation + */ +void esp_rom_opiflash_exec_cmd(int spi_num, + esp_rom_spiflash_read_mode_t mode, + uint32_t cmd, + int cmd_bit_len, + uint32_t addr, + int addr_bit_len, + int dummy_bits, + uint8_t *mosi_data, + int mosi_bit_len, + uint8_t *miso_data, + int miso_bit_len, + uint32_t cs_mask, + bool is_write_erase_operation); + +/** + * @brief send reset command to opi flash + * @param spi_num spi port + * @param mode Flash Operation Mode + */ +void esp_rom_opiflash_soft_reset(int spi_num, esp_rom_spiflash_read_mode_t mode); + +/** + * @brief to read opi flash ID + * @note command format would be defined in initialization + * @param id buffer to accept id + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_read_id(uint8_t *id); + +/** + * @brief to read opi flash status register + * @note command format would be defined in initialization + * @return opi flash status value + */ +uint8_t esp_rom_opiflash_rdsr(); + +/** + * @brief wait opi flash status register to be idle + * @note command format would be defined in initialization + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_wait_idle(); + +/** + * @brief to erase flash sector + * @note command format would be defined in initialization + * @param sector_num the sector to be erased + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_erase_sector(uint32_t sector_num); + +/** + * @brief to erase flash block + * @note command format would be defined in initialization + * @param block_num the block to be erased + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_erase_block_64k(uint32_t block_num); + +/** + * @brief to erase a flash area define by start address and length + * @note command format would be defined in initialization + * @param start_addr the start address to be erased + * @param area_len the erea length to be erased + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_erase_area(uint32_t start_addr, uint32_t area_len); + +/** + * @brief to read data from opi flash + * @note command format would be defined in initialization + * @param flash_addr flash address to read data from + * @param data_addr data buffer to accept the data + * @param len data length to be read + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_read(uint32_t flash_addr, void *data_addr, int len); + +/** + * @brief to write data to opi flash + * @note command format would be defined in initialization + * @param flash_addr flash address to write data to + * @param data_addr data buffer to write to flash + * @param len data length to write + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_write(uint32_t flash_addr, void *data_addr, uint32_t len); + +/** + * @brief send WREN command + * @note command format would be defined in initialization + * @return flash operation result + */ +esp_rom_spiflash_result_t esp_rom_opiflash_wren(void* arg); + +/** + * @brief to configure SPI0 read flash command format for cache + * @note command format would be defined in initialization + * @param mode spi operation mode + * @cache spi0 cache read command definition + * + */ +void esp_rom_opiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const esp_rom_opiflash_spi0rd_t *cache); + +/** + * @brief init legacy driver for Octal Flash + */ +void esp_rom_opiflash_legacy_driver_init(const esp_rom_opiflash_def_t *flash_cmd_def); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h b/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h index bbef05a3d32..04f669c985f 100644 --- a/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h +++ b/components/esp_rom/esp32h4/include/esp32h4/rom/spi_flash.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -453,124 +453,6 @@ uint16_t esp_rom_spiflash_common_cmd(esp_rom_spiflash_common_cmd_t *cmd); extern const spiflash_legacy_funcs_t *rom_spiflash_legacy_funcs; -typedef struct { - uint16_t cmd; /*!< Command value */ - uint16_t cmdBitLen; /*!< Command byte length*/ - uint32_t *addr; /*!< Point to address value*/ - uint32_t addrBitLen; /*!< Address byte length*/ - uint32_t *txData; /*!< Point to send data buffer*/ - uint32_t txDataBitLen; /*!< Send data byte length.*/ - uint32_t *rxData; /*!< Point to receive data buffer*/ - uint32_t rxDataBitLen; /*!< Receive Data byte length.*/ - uint32_t dummyBitLen; -} esp_rom_spi_cmd_t; - -// Definition of MX25UM25645G Octa Flash -// SPI status register -#define ESP_ROM_SPIFLASH_BUSY_FLAG BIT0 -#define ESP_ROM_SPIFLASH_WRENABLE_FLAG BIT1 -#define ESP_ROM_SPIFLASH_BP0 BIT2 -#define ESP_ROM_SPIFLASH_BP1 BIT3 -#define ESP_ROM_SPIFLASH_BP2 BIT4 -#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) -#define ESP_ROM_SPIFLASH_QE BIT9 - -#define FLASH_OP_MODE_RDCMD_DOUT 0x3B -#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000 -#define ESP_ROM_FLASH_BLOCK_SIZE_64K 0x10000 -#define ESP_ROM_FLASH_PAGE_SIZE 256 - -// FLASH commands -#define ROM_FLASH_CMD_RDID 0x9F -#define ROM_FLASH_CMD_WRSR 0x01 -#define ROM_FLASH_CMD_WRSR2 0x31 /* Not all SPI flash uses this command */ -#define ROM_FLASH_CMD_WREN 0x06 -#define ROM_FLASH_CMD_WRDI 0x04 -#define ROM_FLASH_CMD_RDSR 0x05 -#define ROM_FLASH_CMD_RDSR2 0x35 /* Not all SPI flash uses this command */ -#define ROM_FLASH_CMD_ERASE_SEC 0x20 -#define ROM_FLASH_CMD_ERASE_BLK_32K 0x52 -#define ROM_FLASH_CMD_ERASE_BLK_64K 0xD8 -#define ROM_FLASH_CMD_OTPEN 0x3A /* Enable OTP mode, not all SPI flash uses this command */ -#define ROM_FLASH_CMD_RSTEN 0x66 -#define ROM_FLASH_CMD_RST 0x99 - -#define ROM_FLASH_CMD_SE4B 0x21 -#define ROM_FLASH_CMD_SE4B_OCT 0xDE21 -#define ROM_FLASH_CMD_BE4B 0xDC -#define ROM_FLASH_CMD_BE4B_OCT 0x23DC -#define ROM_FLASH_CMD_RSTEN_OCT 0x9966 -#define ROM_FLASH_CMD_RST_OCT 0x6699 - -#define ROM_FLASH_CMD_FSTRD4B_STR 0x13EC -#define ROM_FLASH_CMD_FSTRD4B_DTR 0x11EE -#define ROM_FLASH_CMD_FSTRD4B 0x0C -#define ROM_FLASH_CMD_PP4B 0x12 -#define ROM_FLASH_CMD_PP4B_OCT 0xED12 - -#define ROM_FLASH_CMD_RDID_OCT 0x609F -#define ROM_FLASH_CMD_WREN_OCT 0xF906 -#define ROM_FLASH_CMD_RDSR_OCT 0xFA05 -#define ROM_FLASH_CMD_RDCR2 0x71 -#define ROM_FLASH_CMD_RDCR2_OCT 0x8E71 -#define ROM_FLASH_CMD_WRCR2 0x72 -#define ROM_FLASH_CMD_WRCR2_OCT 0x8D72 - -// Definitions for GigaDevice GD25LX256E Flash -#define ROM_FLASH_CMD_RDFSR_GD 0x70 -#define ROM_FLASH_CMD_RD_GD 0x03 -#define ROM_FLASH_CMD_RD4B_GD 0x13 -#define ROM_FLASH_CMD_FSTRD_GD 0x0B -#define ROM_FLASH_CMD_FSTRD4B_GD 0x0C -#define ROM_FLASH_CMD_FSTRD_OOUT_GD 0x8B -#define ROM_FLASH_CMD_FSTRD4B_OOUT_GD 0x7C -#define ROM_FLASH_CMD_FSTRD_OIOSTR_GD 0xCB -#define ROM_FLASH_CMD_FSTRD4B_OIOSTR_GD 0xCC -#define ROM_FLASH_CMD_FSTRD4B_OIODTR_GD 0xFD - -#define ROM_FLASH_CMD_PP_GD 0x02 -#define ROM_FLASH_CMD_PP4B_GD 0x12 -#define ROM_FLASH_CMD_PP_OOUT_GD 0x82 -#define ROM_FLASH_CMD_PP4B_OOUT_GD 0x84 -#define ROM_FLASH_CMD_PP_OIO_GD 0xC2 -#define ROM_FLASH_CMD_PP4B_OIOSTR_GD 0x8E - -#define ROM_FLASH_CMD_SE_GD 0x20 -#define ROM_FLASH_CMD_SE4B_GD 0x21 -#define ROM_FLASH_CMD_BE32K_GD 0x52 -#define ROM_FLASH_CMD_BE32K4B_GD 0x5C -#define ROM_FLASH_CMD_BE64K_GD 0xD8 -#define ROM_FLASH_CMD_BE64K4B_GD 0xDC - -#define ROM_FLASH_CMD_EN4B_GD 0xB7 -#define ROM_FLASH_CMD_DIS4B_GD 0xE9 - -// spi user mode command config -/** - * @brief Config the spi user command - * @param spi_num spi port - * @param pcmd pointer to accept the spi command struct - */ -void esp_rom_spi_cmd_config(int spi_num, esp_rom_spi_cmd_t* pcmd); - -/** - * @brief Start a spi user command sequence - * @param spi_num spi port - * @param rx_buf buffer pointer to receive data - * @param rx_len receive data length in byte - * @param cs_en_mask decide which cs to use, 0 for cs0, 1 for cs1 - * @param is_write_erase to indicate whether this is a write or erase operation, since the CPU would check permission - */ -void esp_rom_spi_cmd_start(int spi_num, uint8_t* rx_buf, uint16_t rx_len, uint8_t cs_en_mask, bool is_write_erase); - -// set SPI read/write mode -/** - * @brief Set SPI operation mode - * @param spi_num spi port - * @param mode Flash Read Mode - */ -void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode); - #ifdef __cplusplus } #endif diff --git a/components/esp_rom/include/esp_rom_spiflash.h b/components/esp_rom/include/esp_rom_spiflash.h index 6289da66ebd..b022aa11b66 100644 --- a/components/esp_rom/include/esp_rom_spiflash.h +++ b/components/esp_rom/include/esp_rom_spiflash.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,10 +12,15 @@ #include #include "esp_rom_spiflash_defs.h" -#ifdef __cplusplus -extern "C" { -#endif - +/* These common types must be visible before the per-target ROM headers below, + * because those headers reference them and (re)include this header. With + * `#pragma once` the recursive include is a no-op, so the types have to be + * defined here first. + * + * Typedefs have no language linkage, so leaving them outside the `extern "C"` + * block is fine: it lets the target headers also be included outside any + * enclosing `extern "C"` (the convention for #include statements). + */ typedef enum { ESP_ROM_SPIFLASH_QIO_MODE = 0, ESP_ROM_SPIFLASH_QOUT_MODE, @@ -47,6 +52,36 @@ typedef enum { ESP_ROM_SPIFLASH_RESULT_TIMEOUT } esp_rom_spiflash_result_t; +#if CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/spi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/spi_flash.h" +#include "esp32s3/rom/opi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32P4 +#include "esp32p4/rom/spi_flash.h" +#include "esp32p4/rom/opi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32C5 +#include "esp32c5/rom/spi_flash.h" +#include "esp32c5/rom/opi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32C61 +#include "esp32c61/rom/spi_flash.h" +#include "esp32c61/rom/opi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32H4 +#include "esp32h4/rom/spi_flash.h" +#include "esp32h4/rom/opi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32S31 +#include "esp32s31/rom/spi_flash.h" +#include "esp32s31/rom/opi_flash.h" +#elif CONFIG_IDF_TARGET_ESP32H21 +#include "esp32h21/rom/spi_flash.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + /** * @brief SPI Flash init, clock divisor is 4, use 1 line Slow read mode. * Please do not call this function in SDK. diff --git a/components/esp_rom/patches/esp_rom_spiflash.c b/components/esp_rom/patches/esp_rom_spiflash.c index 997e870f192..e60b6f3ae28 100644 --- a/components/esp_rom/patches/esp_rom_spiflash.c +++ b/components/esp_rom/patches/esp_rom_spiflash.c @@ -17,23 +17,6 @@ #include "riscv/rv_utils.h" #endif #include "esp_rom_spiflash.h" -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/rom/spi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/rom/spi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/spi_flash.h" -#include "esp32s3/rom/opi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32P4 -#include "esp32p4/rom/spi_flash.h" -#include "esp32p4/rom/opi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32C5 -#include "esp32c5/rom/spi_flash.h" -#include "esp32c5/rom/opi_flash.h" -#elif CONFIG_IDF_TARGET_ESP32C61 -#include "esp32c61/rom/spi_flash.h" -#include "esp32c61/rom/opi_flash.h" -#endif #define SPI_IDX 1 @@ -774,7 +757,7 @@ void esp_rom_spiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const REG_SET_BIT(SPI_MEM_C_CTRL_REG, SPI_MEM_C_Q_POL); } } -#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 +#elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32H4 extern void esp_rom_spi_set_address_bit_len(int spi, int addr_bits); void esp_rom_spiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const esp_rom_opiflash_spi0rd_t *cache) { diff --git a/components/esp_system/port/soc/esp32h4/system_internal.c b/components/esp_system/port/soc/esp32h4/system_internal.c index 9b765e5843a..86c43c00268 100644 --- a/components/esp_system/port/soc/esp32h4/system_internal.c +++ b/components/esp_system/port/soc/esp32h4/system_internal.c @@ -96,7 +96,7 @@ static void IRAM_ATTR __attribute__((noinline, noreturn)) esp_restart_noos_inner const uint32_t core_id = esp_cpu_get_core_id(); // Disable cache - Cache_Disable_Cache(CACHE_MAP_ALL); + Cache_Disable_Cache(CACHE_MAP_MASK); esp_system_reset_modules_on_exit(); diff --git a/components/hal/esp32h4/include/hal/cache_ll.h b/components/hal/esp32h4/include/hal/cache_ll.h index 360fdc3622c..febbefb0303 100644 --- a/components/hal/esp32h4/include/hal/cache_ll.h +++ b/components/hal/esp32h4/include/hal/cache_ll.h @@ -742,7 +742,7 @@ static inline void cache_ll_preload(uint32_t cache_level, cache_type_t type, uin break; case CACHE_TYPE_ALL: default: - map = CACHE_MAP_ALL; + map = CACHE_MAP_MASK; break; } Cache_Start_Preload(map, vaddr, size, order); @@ -766,7 +766,7 @@ static inline void cache_ll_preload_wait_done(uint32_t cache_level, cache_type_t break; case CACHE_TYPE_ALL: default: - map = CACHE_MAP_ALL; + map = CACHE_MAP_MASK; break; } while (Cache_Preload_Done(map) == 0) { diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index cefab7261c5..3b30151f0f0 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -211,6 +211,10 @@ config SOC_SPI_FLASH_SUPPORTED bool default y +config SOC_SPI_EXTERNAL_NOR_FLASH_SUPPORTED + bool + default y + config SOC_ECDSA_SUPPORTED bool default y @@ -895,6 +899,10 @@ config SOC_SPI_MEM_SUPPORT_TSUS_TRES_SEPERATE_CTR bool default y +config SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP + bool + default y + config SOC_MEMSPI_IS_INDEPENDENT bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index e7189600992..311fa475658 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -88,6 +88,7 @@ #define SOC_WDT_SUPPORTED 1 #define SOC_RTC_WDT_SUPPORTED 1 #define SOC_SPI_FLASH_SUPPORTED 1 +#define SOC_SPI_EXTERNAL_NOR_FLASH_SUPPORTED 1 #define SOC_ECDSA_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 #define SOC_LIGHT_SLEEP_SUPPORTED 1 @@ -387,6 +388,7 @@ #define SOC_SPI_MEM_SUPPORT_CHECK_SUS (1) #define SOC_SPI_MEM_SUPPORT_WRAP (1) #define SOC_SPI_MEM_SUPPORT_TSUS_TRES_SEPERATE_CTR (1) +#define SOC_SPI_MEM_SUPPORT_CACHE_32BIT_ADDR_MAP (1) #define SOC_MEMSPI_IS_INDEPENDENT 1 #define SOC_MEMSPI_ENCRYPTION_ALIGNMENT 16 /*!< 16-byte alignment restriction to mem addr and size if encryption is enabled */ diff --git a/components/soc/esp32h4/register/soc/spi1_mem_reg.h b/components/soc/esp32h4/register/soc/spi1_mem_reg.h index af2cd56ee8e..579489bdcfc 100644 --- a/components/soc/esp32h4/register/soc/spi1_mem_reg.h +++ b/components/soc/esp32h4/register/soc/spi1_mem_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 OR MIT */ @@ -417,6 +417,30 @@ extern "C" { #define SPI_MEM_STATUS_M (SPI_MEM_STATUS_V << SPI_MEM_STATUS_S) #define SPI_MEM_STATUS_V 0x0000FFFFU #define SPI_MEM_STATUS_S 0 +/** SPI_MEM_WB_MODE : R/W; bitpos: [23:16]; default: 0; + * Mode bits in the flash fast read mode it is combined with spi_mem_fastrd_mode bit. + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_WB_MODE 0x000000FFU +#define SPI_MEM_WB_MODE_M (SPI_MEM_WB_MODE_V << SPI_MEM_WB_MODE_S) +#define SPI_MEM_WB_MODE_V 0x000000FFU +#define SPI_MEM_WB_MODE_S 16 +/** SPI_MEM_WB_MODE_BITLEN : R/W; bitpos: [26:24]; default: 0; + * Mode bits length for flash fast read mode. + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_WB_MODE_BITLEN 0x00000007U +#define SPI_MEM_WB_MODE_BITLEN_M (SPI_MEM_WB_MODE_BITLEN_V << SPI_MEM_WB_MODE_BITLEN_S) +#define SPI_MEM_WB_MODE_BITLEN_V 0x00000007U +#define SPI_MEM_WB_MODE_BITLEN_S 24 +/** SPI_MEM_WB_MODE_EN : R/W; bitpos: [27]; default: 0; + * Mode bits is valid while this bit is enable. 1: enable 0: disable. + * This field is only for internal debugging purposes. Do not use it in applications. + */ +#define SPI_MEM_WB_MODE_EN (BIT(27)) +#define SPI_MEM_WB_MODE_EN_M (SPI_MEM_WB_MODE_EN_V << SPI_MEM_WB_MODE_EN_S) +#define SPI_MEM_WB_MODE_EN_V 0x00000001U +#define SPI_MEM_WB_MODE_EN_S 27 /** SPI_MEM_MISC_REG register * SPI1 misc register diff --git a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h index 37a621e2f30..7a671d0b452 100644 --- a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h +++ b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_def.h @@ -69,7 +69,6 @@ #elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32H21 || CONFIG_IDF_TARGET_ESP32H4 -// Just use the same pins for HSPI #define SPI2_PIN_NUM_MOSI 5 #define SPI2_PIN_NUM_MISO 0 #define SPI2_PIN_NUM_CLK 4 diff --git a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c index 28add675031..e0feb224118 100644 --- a/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c +++ b/components/spi_flash/test_apps/esp_flash/main/test_esp_flash_drv.c @@ -600,7 +600,7 @@ TEST_CASE_MULTI_FLASH_IGNORE("Test esp_flash_write can toggle QE bit", test_togg #if CONFIG_IDF_TARGET_ESP32C2 uint8_t flash_frequency_table[4] = {5, 10, 20, 40}; #elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32H21 || CONFIG_IDF_TARGET_ESP32H4 -uint8_t flash_frequency_table[4] = {6, 12, 24, 48}; +uint8_t flash_frequency_table[3] = {8, 16, 32}; // + 64 #else uint8_t flash_frequency_table[6] = {5, 10, 20, 26, 40, 80}; #endif diff --git a/components/spi_flash/test_apps/esp_flash/main/test_spi_flash.c b/components/spi_flash/test_apps/esp_flash/main/test_spi_flash.c index 0b02995a4bb..c8ceb438abb 100644 --- a/components/spi_flash/test_apps/esp_flash/main/test_spi_flash.c +++ b/components/spi_flash/test_apps/esp_flash/main/test_spi_flash.c @@ -122,7 +122,7 @@ TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_fla } // TODO: This test is disabled on S3 with legacy impl - IDF-3505 -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32P4, ESP32S31) +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32P4, ESP32S31, ESP32H4) #if CONFIG_FREERTOS_NUMBER_OF_CORES > 1 typedef struct { diff --git a/components/spi_flash/test_apps/flash_suspend/main/test_flash_suspend.c b/components/spi_flash/test_apps/flash_suspend/main/test_flash_suspend.c index cb40dffa4a5..9745ffac786 100644 --- a/components/spi_flash/test_apps/flash_suspend/main/test_flash_suspend.c +++ b/components/spi_flash/test_apps/flash_suspend/main/test_flash_suspend.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -75,14 +75,12 @@ static bool IRAM_ATTR gptimer_alarm_suspend_cb(gptimer_handle_t timer, const gpt /*clear content in cache*/ #if CONFIG_IDF_TARGET_ESP32S3 Cache_Invalidate_DCache_All(); -#endif -#if CONFIG_IDF_TARGET_ESP32P4 + Cache_Invalidate_ICache_All(); +#elif CONFIG_IDF_TARGET_ESP32P4 Cache_Invalidate_All(CACHE_MAP_L2_CACHE); -#elif CONFIG_IDF_TARGET_ESP32H4 - cache_ll_invalidate_all(CACHE_LL_LEVEL_ALL, CACHE_TYPE_ALL, CACHE_LL_ID_ALL); #elif CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61 Cache_Invalidate_All(); -#elif CONFIG_IDF_TARGET_ESP32S31 +#elif CONFIG_IDF_TARGET_ESP32S31 || CONFIG_IDF_TARGET_ESP32H4 Cache_Invalidate_All(CACHE_MAP_MASK); #else Cache_Invalidate_ICache_All(); diff --git a/examples/storage/fatfs/ext_flash/README.md b/examples/storage/fatfs/ext_flash/README.md index 41df7c62d7e..a006e5c6abc 100644 --- a/examples/storage/fatfs/ext_flash/README.md +++ b/examples/storage/fatfs/ext_flash/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | -| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | --------- | +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- | # FAT FS on External Flash example