From 559c1ac3f9824dcad30ff9189ab06e5213f4c32f Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Tue, 29 Jun 2021 15:32:50 +0800 Subject: [PATCH] esp_flash: add support mxic as a main flash under spi mode --- components/esptool_py/Kconfig.projbuild | 9 ++++ components/spi_flash/esp_flash_spi_init.c | 4 ++ components/spi_flash/flash_ops.c | 6 +++ .../spi_flash/include/spi_flash_chip_driver.h | 9 ++++ components/spi_flash/spi_flash_chip_generic.c | 9 ---- components/spi_flash/spi_flash_chip_mxic.c | 41 +++++++++++++++++++ components/spi_flash/test/test_read_write.c | 29 +++++++++++-- 7 files changed, 95 insertions(+), 12 deletions(-) diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index 72e06ebbcd..61f63fda44 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -91,6 +91,7 @@ menu "Serial flasher config" choice ESPTOOLPY_FLASHMODE prompt "Flash SPI mode" default ESPTOOLPY_FLASHMODE_DIO + depends on !ESPTOOLPY_OCT_FLASH help Mode the flash chip is flashed in, as well as the default mode for the binary to run in. @@ -103,6 +104,10 @@ menu "Serial flasher config" bool "DIO" config ESPTOOLPY_FLASHMODE_DOUT bool "DOUT" + config ESPTOOLPY_FLASHMODE_FASTRD + bool "FASTRD" + config ESPTOOLPY_FLASHMODE_SLOWRD + bool "SLOWRD" endchoice # Note: we use esptool.py to flash bootloader in @@ -114,6 +119,10 @@ menu "Serial flasher config" default "dio" if ESPTOOLPY_FLASHMODE_QOUT default "dio" if ESPTOOLPY_FLASHMODE_DIO default "dout" if ESPTOOLPY_FLASHMODE_DOUT + default "dout" if ESPTOOLPY_FLASHMODE_FASTRD + default "dout" if ESPTOOLPY_FLASHMODE_SLOWRD + default "dout" if ESPTOOLPY_FLASHMODE_OPI_STR + default "dout" if ESPTOOLPY_FLASHMODE_OPI_DTR choice ESPTOOLPY_FLASHFREQ prompt "Flash SPI speed" diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 126547c20f..68c26f8102 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -68,6 +68,10 @@ esp_flash_t *esp_flash_default_chip = NULL; #define DEFAULT_FLASH_MODE SPI_FLASH_DIO #elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT) #define DEFAULT_FLASH_MODE SPI_FLASH_DOUT +#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_FASTRD) +#define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD +#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_SLOWRD) +#define DEFAULT_FLASH_MODE SPI_FLASH_SLOWRD #else #define DEFAULT_FLASH_MODE SPI_FLASH_FASTRD #endif diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 53fbe269f6..66dfb38673 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -518,6 +518,7 @@ out: #endif // CONFIG_SPI_FLASH_USE_LEGACY_IMPL #if !CONFIG_SPI_FLASH_USE_LEGACY_IMPL +#if !CONFIG_ESPTOOLPY_OCT_FLASH extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode); extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); void IRAM_ATTR flash_rom_init(void) @@ -557,6 +558,10 @@ void IRAM_ATTR flash_rom_init(void) read_mode = ESP_ROM_SPIFLASH_DIO_MODE; #elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT read_mode = ESP_ROM_SPIFLASH_DOUT_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_FASTRD + read_mode = ESP_ROM_SPIFLASH_FASTRD_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_SLOWRD + read_mode = ESP_ROM_SPIFLASH_SLOWRD_MODE; #endif #endif //!CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32 @@ -571,6 +576,7 @@ void IRAM_ATTR flash_rom_init(void) #endif //!CONFIG_IDF_TARGET_ESP32S2 esp_rom_spiflash_config_clk(freqdiv, 1); } +#endif //CONFIG_ESPTOOLPY_OCT_FLASH #else void IRAM_ATTR flash_rom_init(void) { diff --git a/components/spi_flash/include/spi_flash_chip_driver.h b/components/spi_flash/include/spi_flash_chip_driver.h index 9a143d84d2..9d879c9e3e 100644 --- a/components/spi_flash/include/spi_flash_chip_driver.h +++ b/components/spi_flash/include/spi_flash_chip_driver.h @@ -30,6 +30,15 @@ typedef struct { uint32_t page_program_timeout; ///< Timeout for page program operation } flash_chip_op_timeout_t; +typedef struct flash_chip_dummy { + uint8_t dio_dummy_bitlen; + uint8_t qio_dummy_bitlen; + uint8_t qout_dummy_bitlen; + uint8_t dout_dummy_bitlen; + uint8_t fastrd_dummy_bitlen; + uint8_t slowrd_dummy_bitlen; +} flash_chip_dummy_t; + typedef enum { SPI_FLASH_REG_STATUS = 1, } spi_flash_register_t; diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index 0dc3062fd5..13b42c3e63 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -21,15 +21,6 @@ #include "esp_log.h" #include "esp_attr.h" -typedef struct flash_chip_dummy { - uint8_t dio_dummy_bitlen; - uint8_t qio_dummy_bitlen; - uint8_t qout_dummy_bitlen; - uint8_t dout_dummy_bitlen; - uint8_t fastrd_dummy_bitlen; - uint8_t slowrd_dummy_bitlen; -} flash_chip_dummy_t; - // These parameters can be placed in the ROM. For now we use the code in IDF. DRAM_ATTR const static flash_chip_dummy_t default_flash_chip_dummy = { .dio_dummy_bitlen = SPI_FLASH_DIO_DUMMY_BITLEN, diff --git a/components/spi_flash/spi_flash_chip_mxic.c b/components/spi_flash/spi_flash_chip_mxic.c index f88486dfd4..c40e4f5b7b 100644 --- a/components/spi_flash/spi_flash_chip_mxic.c +++ b/components/spi_flash/spi_flash_chip_mxic.c @@ -16,9 +16,13 @@ #include "spi_flash_chip_generic.h" #include "spi_flash_defs.h" #include "esp_log.h" +#include "string.h" +#include // For MIN/MAX /* Driver for MXIC flash chip */ +extern flash_chip_dummy_t *rom_flash_chip_dummy; + esp_err_t spi_flash_chip_mxic_probe(esp_flash_t *chip, uint32_t flash_id) { /* Check manufacturer and product IDs match our desired masks */ @@ -47,6 +51,43 @@ esp_err_t spi_flash_chip_mxic_read_unique_id(esp_flash_t *chip, uint64_t* flash_ return ESP_ERR_NOT_SUPPORTED; } +esp_err_t spi_flash_chip_mxic_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length) +{ + esp_err_t err = ESP_OK; + const uint32_t page_size = chip->chip_drv->page_size; + uint32_t align_address; + uint8_t temp_buffer[64]; //spiflash hal max length of read no longer than 64byte + + // Configure the host, and return + uint32_t addr_bitlen = SPI_FLASH_FASTRD_ADDR_BITLEN; + uint32_t dummy_cyclelen_base = rom_flash_chip_dummy->fastrd_dummy_bitlen;; + uint32_t read_command = CMD_FASTRD; + uint32_t read_mode = SPI_FLASH_FASTRD; + + err = chip->host->driver->configure_host_io_mode(chip->host, read_command, addr_bitlen, dummy_cyclelen_base, read_mode); + + if (err == ESP_ERR_NOT_SUPPORTED) { + ESP_LOGE(chip_name, "configure host io mode failed - unsupported"); + return err; + } + + while (err == ESP_OK && length > 0) { + memset(temp_buffer, 0xFF, sizeof(temp_buffer)); + uint32_t read_len = chip->host->driver->read_data_slicer(chip->host, address, length, &align_address, page_size); + uint32_t left_off = address - align_address; + uint32_t data_len = MIN(align_address + read_len, address + length) - address; + err = chip->host->driver->read(chip->host, temp_buffer, align_address, read_len); + + memcpy(buffer, temp_buffer + left_off, data_len); + + address += data_len; + buffer = (void *)((intptr_t)buffer + data_len); + length = length - data_len; + } + + return err; +} + spi_flash_caps_t spi_flash_chip_mxic_get_caps(esp_flash_t *chip) { spi_flash_caps_t caps_flags = 0; diff --git a/components/spi_flash/test/test_read_write.c b/components/spi_flash/test/test_read_write.c index 57db40dae7..3ca559f083 100644 --- a/components/spi_flash/test/test_read_write.c +++ b/components/spi_flash/test/test_read_write.c @@ -23,15 +23,25 @@ #include #include #include -#include #include "../cache_utils.h" #include "soc/timer_periph.h" #include "esp_heap_caps.h" +#if CONFIG_IDF_TARGET_ESP32 +#include +#elif CONFIG_IDF_TARGET_ESP32S2 +#include +#elif CONFIG_IDF_TARGET_ESP32S3 +#include +#elif CONFIG_IDF_TARGET_ESP32C3 +#include +#endif + #define MIN_BLOCK_SIZE 12 /* Base offset in flash for tests. */ static size_t start; +extern spiflash_legacy_data_t *rom_spiflash_legacy_data; static void setup_tests(void) { @@ -141,11 +151,13 @@ TEST_CASE("Test spi_flash_read", "[spi_flash][esp_flash]") #endif } +#if !CONFIG_ESPTOOLPY_OCT_FLASH extern void spi_common_set_dummy_output(esp_rom_spiflash_read_mode_t mode); extern void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv); static void IRAM_ATTR fix_rom_func(void) { uint32_t freqdiv = 0; + uint32_t vendor_id = (rom_spiflash_legacy_data->chip.device_id >> 16); #if CONFIG_ESPTOOLPY_FLASHFREQ_80M freqdiv = 1; @@ -182,14 +194,24 @@ static void IRAM_ATTR fix_rom_func(void) read_mode = ESP_ROM_SPIFLASH_DIO_MODE; #elif CONFIG_ESPTOOLPY_FLASHMODE_DOUT read_mode = ESP_ROM_SPIFLASH_DOUT_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_FASTRD + read_mode = ESP_ROM_SPIFLASH_FASTRD_MODE; +#elif CONFIG_ESPTOOLPY_FLASHMODE_SLOWRD + read_mode = ESP_ROM_SPIFLASH_SLOWRD_MODE; #endif #if !CONFIG_IDF_TARGET_ESP32S2 && !CONFIG_IDF_TARGET_ESP32 spi_common_set_dummy_output(read_mode); #endif //!CONFIG_IDF_TARGET_ESP32S2 esp_rom_spiflash_config_clk(freqdiv, 1); - esp_rom_spiflash_config_readmode(read_mode); + if (vendor_id == 0xc2) { + // If the flash vendor is mxic, it dones't support the read mode mentioned above. + // So, do nothing + } else { + esp_rom_spiflash_config_readmode(read_mode); + } } +#endif static void IRAM_ATTR test_write(int dst_off, int src_off, int len) { @@ -211,8 +233,9 @@ static void IRAM_ATTR test_write(int dst_off, int src_off, int len) fill(dst_gold + dst_off, src_off, len); } ESP_ERROR_CHECK(spi_flash_write(start + dst_off, src_buf + src_off, len)); - +#if !CONFIG_ESPTOOLPY_OCT_FLASH fix_rom_func(); +#endif spi_flash_disable_interrupts_caches_and_other_cpu(); esp_rom_spiflash_result_t rc = esp_rom_spiflash_read(start, dst_buf, sizeof(dst_buf));