diff --git a/components/spi_flash/esp_flash_api.c b/components/spi_flash/esp_flash_api.c index dacfda2580..253b409bba 100644 --- a/components/spi_flash/esp_flash_api.c +++ b/components/spi_flash/esp_flash_api.c @@ -69,6 +69,17 @@ static const char TAG[] = "spi_flash"; } while(0) #endif // CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED +/* Convenience macro for beginning of all API functions. + * Check the return value of `rom_spiflash_api_funcs->chip_check` is correct, + * and the chip supports the operation in question. + */ +#define VERIFY_CHIP_OP(op) do { \ + if (err != ESP_OK) return err; \ + if (chip->chip_drv->op == NULL) { \ + return ESP_ERR_FLASH_UNSUPPORTED_CHIP; \ + } \ + } while (0) + #define IO_STR_LEN 10 static const char io_mode_str[][IO_STR_LEN] = { @@ -227,7 +238,7 @@ esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip) // Detect flash size uint32_t size; - err = esp_flash_get_size(chip, &size); + err = esp_flash_get_physical_size(chip, &size); if (err != ESP_OK) { ESP_LOGE(TAG, "failed to get chip size"); return err; @@ -305,7 +316,7 @@ esp_err_t IRAM_ATTR esp_flash_init_main(esp_flash_t *chip) // Detect flash size uint32_t size; - err = esp_flash_get_size(chip, &size); + err = esp_flash_get_physical_size(chip, &size); if (err != ESP_OK) { ESP_LOGE(TAG, "failed to get chip size"); return err; @@ -463,32 +474,15 @@ static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip) return ESP_OK; } -#ifndef CONFIG_SPI_FLASH_ROM_IMPL - -/* Convenience macro for beginning of all API functions. - * Check the return value of `rom_spiflash_api_funcs->chip_check` is correct, - * and the chip supports the operation in question. - */ -#define VERIFY_CHIP_OP(OP) do { \ - if (err != ESP_OK) return err; \ - if (chip->chip_drv->OP == NULL) { \ - return ESP_ERR_FLASH_UNSUPPORTED_CHIP; \ - } \ - } while (0) - -/* Return true if regions 'a' and 'b' overlap at all, based on their start offsets and lengths. */ -inline static bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len); - -esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size) +esp_err_t IRAM_ATTR esp_flash_get_physical_size(esp_flash_t *chip, uint32_t *flash_size) { esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); - VERIFY_CHIP_OP(detect_size); - if (out_size == NULL) { - return ESP_ERR_INVALID_ARG; + if (err != ESP_OK) { + return err; } - if (chip->size != 0) { - *out_size = chip->size; - return ESP_OK; + VERIFY_CHIP_OP(detect_size); + if (flash_size == NULL) { + return ESP_ERR_INVALID_ARG; } err = rom_spiflash_api_funcs->start(chip); @@ -498,12 +492,38 @@ esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size) uint32_t detect_size; err = chip->chip_drv->detect_size(chip, &detect_size); if (err == ESP_OK) { - chip->size = detect_size; - *out_size = chip->size; + if (chip->size == 0) { + // chip->size will not be changed if detected, it will always be equal to configured flash size. + chip->size = detect_size; + } + *flash_size = detect_size; } return rom_spiflash_api_funcs->end(chip, err); } +#ifndef CONFIG_SPI_FLASH_ROM_IMPL + +/* Return true if regions 'a' and 'b' overlap at all, based on their start offsets and lengths. */ +inline static bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len); + +esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size) +{ + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + if (err != ESP_OK) { + return err; + } + if (out_size == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (chip->size != 0) { + *out_size = chip->size; + return ESP_OK; + } + //Return flash chip physical size, when this API is called before flash initialisation, + //After initialization will return available size. + return esp_flash_get_physical_size(chip, out_size); +} + esp_err_t IRAM_ATTR esp_flash_erase_chip(esp_flash_t *chip) { esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index aaac870284..6b69a0352d 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -322,6 +322,7 @@ esp_err_t esp_flash_init_default_chip(void) if (default_chip.size > legacy_chip->chip_size) { ESP_EARLY_LOGW(TAG, "Detected size(%dk) larger than the size in the binary image header(%dk). Using the size in the binary image header.", default_chip.size/1024, legacy_chip->chip_size/1024); } + // Set chip->size equal to ROM flash size(also equal to the size in binary image header), which means the available size that can be used default_chip.size = legacy_chip->chip_size; esp_flash_default_chip = &default_chip; diff --git a/components/spi_flash/include/esp_flash.h b/components/spi_flash/include/esp_flash.h index 3529898bce..bfb7e88c1e 100644 --- a/components/spi_flash/include/esp_flash.h +++ b/components/spi_flash/include/esp_flash.h @@ -100,7 +100,7 @@ struct esp_flash_t { void *os_func_data; ///< Pointer to argument for os-specific hooks. Left NULL and will be initialized with ``os_func``. esp_flash_io_mode_t read_mode; ///< Configured SPI flash read mode. Set before ``esp_flash_init`` is called. - uint32_t size; ///< Size of SPI flash in bytes. If 0, size will be detected during initialisation. + uint32_t size; ///< Size of SPI flash in bytes. If 0, size will be detected during initialisation. Note: this stands for the size in the binary image header. If you want to get the flash physical size, please call `esp_flash_get_physical_size`. uint32_t chip_id; ///< Detected chip id. uint32_t busy :1; ///< This flag is used to verify chip's status. uint32_t hpm_dummy_ena :1; ///< This flag is used to verify whether flash works under HPM status. @@ -148,14 +148,28 @@ esp_err_t esp_flash_read_id(esp_flash_t *chip, uint32_t *out_id); /** @brief Detect flash size based on flash ID. * * @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init() - * @param[out] out_size Detected size in bytes. + * @param[out] out_size Detected size in bytes, standing for the size in the binary image header. + * + * @note 1. Most flash chips use a common format for flash ID, where the lower 4 bits specify the size as a power of 2. If + * the manufacturer doesn't follow this convention, the size may be incorrectly detected. + * 2. The out_size returned only stands for The out_size stands for the size in the binary image header. + * If you want to get the real size of the chip, please call `esp_flash_get_physical_size` instead. + * + * @return ESP_OK on success, or a flash error code if operation failed. + */ +esp_err_t esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size); + +/** @brief Detect flash size based on flash ID. + * + * @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init() + * @param[out] flash_size Detected size in bytes. * * @note Most flash chips use a common format for flash ID, where the lower 4 bits specify the size as a power of 2. If * the manufacturer doesn't follow this convention, the size may be incorrectly detected. * * @return ESP_OK on success, or a flash error code if operation failed. */ -esp_err_t esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size); +esp_err_t esp_flash_get_physical_size(esp_flash_t *chip, uint32_t *flash_size); /** @brief Read flash unique ID via the common "RDUID" SPI flash command. * diff --git a/components/spi_flash/spi_flash_chip_gd.c b/components/spi_flash/spi_flash_chip_gd.c index b36c25e549..d8696177dd 100644 --- a/components/spi_flash/spi_flash_chip_gd.c +++ b/components/spi_flash/spi_flash_chip_gd.c @@ -1,16 +1,8 @@ -// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -47,6 +39,21 @@ spi_flash_caps_t spi_flash_chip_gd_get_caps(esp_flash_t *chip) return caps_flags; } +esp_err_t spi_flash_chip_gd_detect_size(esp_flash_t *chip, uint32_t *size) +{ + uint32_t id = chip->chip_id; + *size = 0; + + /* Can't detect size unless the high byte of the product ID matches the same convention, which is usually 0x40 or + * 0xC0 or similar. */ + if (((id & 0xFFFF) == 0x0000) || ((id & 0xFFFF) == 0xFFFF)) { + return ESP_ERR_FLASH_UNSUPPORTED_CHIP; + } + + *size = 1 << (id & 0xFF); + return ESP_OK; +} + #ifndef CONFIG_SPI_FLASH_ROM_IMPL #define FLASH_ID_MASK 0xFF00 @@ -114,7 +121,7 @@ const spi_flash_chip_t esp_flash_chip_gd = { .timeout = &spi_flash_chip_generic_timeout, .probe = spi_flash_chip_gd_probe, .reset = spi_flash_chip_generic_reset, - .detect_size = spi_flash_chip_generic_detect_size, + .detect_size = spi_flash_chip_gd_detect_size, .erase_chip = spi_flash_chip_generic_erase_chip, .erase_sector = spi_flash_chip_gd_erase_sector, .erase_block = spi_flash_chip_gd_erase_block, diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index ea7d766937..6726c4feea 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -73,6 +73,9 @@ DRAM_ATTR flash_chip_dummy_t *rom_flash_chip_dummy_hpm = (flash_chip_dummy_t *)& #define HOST_DELAY_INTERVAL_US 1 #define CHIP_WAIT_IDLE_INTERVAL_US 20 +#define SPI_FLASH_LINEAR_DENSITY_LAST_VALUE (0x19) +#define SPI_FLASH_HEX_A_F_RANGE (6) + const DRAM_ATTR flash_chip_op_timeout_t spi_flash_chip_generic_timeout = { .idle_timeout = SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000, .chip_erase_timeout = SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT_MS * 1000, @@ -83,6 +86,30 @@ const DRAM_ATTR flash_chip_op_timeout_t spi_flash_chip_generic_timeout = { static const char TAG[] = "chip_generic"; +esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size) +{ + uint32_t id = chip->chip_id; + *size = 0; + + /* Can't detect size unless the high byte of the product ID matches the same convention, which is usually 0x40 or + * 0xC0 or similar. */ + if (((id & 0xFFFF) == 0x0000) || ((id & 0xFFFF) == 0xFFFF)) { + return ESP_ERR_FLASH_UNSUPPORTED_CHIP; + } + + /* Get flash capacity from flash chip id depends on different vendors. According to majority of flash datasheets, + Flash 256Mb to 512Mb directly from 0x19 to 0x20, instead of from 0x19 to 0x1a. So here we leave the common behavior. + However, some other flash vendors also have their own rule, we will add them in chip specific files. + */ + uint32_t mem_density = (id & 0xFF); + if (mem_density > SPI_FLASH_LINEAR_DENSITY_LAST_VALUE) { + mem_density -= SPI_FLASH_HEX_A_F_RANGE; + } + + *size = 1 << mem_density; + return ESP_OK; +} + #ifndef CONFIG_SPI_FLASH_ROM_IMPL esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id) @@ -116,22 +143,6 @@ esp_err_t spi_flash_chip_generic_reset(esp_flash_t *chip) return err; } -esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size) -{ - uint32_t id = chip->chip_id; - *size = 0; - - /* Can't detect size unless the high byte of the product ID matches the same convention, which is usually 0x40 or - * 0xC0 or similar. */ - if (((id & 0xFFFF) == 0x0000) || ((id & 0xFFFF) == 0xFFFF)) { - return ESP_ERR_FLASH_UNSUPPORTED_CHIP; - } - - *size = 1 << (id & 0xFF); - return ESP_OK; -} - - esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip) { esp_err_t err; diff --git a/components/spi_flash/spi_flash_chip_mxic_opi.c b/components/spi_flash/spi_flash_chip_mxic_opi.c index 0ddd233aa1..d19488fa53 100644 --- a/components/spi_flash/spi_flash_chip_mxic_opi.c +++ b/components/spi_flash/spi_flash_chip_mxic_opi.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include "spi_flash_chip_generic.h" @@ -46,6 +38,21 @@ esp_err_t spi_flash_chip_mxic_opi_probe(esp_flash_t *chip, uint32_t flash_id) return ESP_OK; } +esp_err_t spi_flash_chip_mxic_opi_detect_size(esp_flash_t *chip, uint32_t *size) +{ + uint32_t id = chip->chip_id; + *size = 0; + + /* Can't detect size unless the high byte of the product ID matches the same convention, which is usually 0x40 or + * 0xC0 or similar. */ + if (((id & 0xFFFF) == 0x0000) || ((id & 0xFFFF) == 0xFFFF)) { + return ESP_ERR_FLASH_UNSUPPORTED_CHIP; + } + + *size = 1 << ((id & 0xFF) - 0x20); + return ESP_OK; +} + spi_flash_caps_t spi_flash_chip_mxic_opi_get_caps(esp_flash_t *chip) { spi_flash_caps_t caps_flags = 0; @@ -384,7 +391,7 @@ const spi_flash_chip_t esp_flash_chip_mxic_opi = { .timeout = &spi_flash_chip_generic_timeout, .probe = spi_flash_chip_mxic_opi_probe, .reset = spi_flash_chip_generic_reset, - .detect_size = spi_flash_chip_generic_detect_size, + .detect_size = spi_flash_chip_mxic_opi_detect_size, .erase_chip = spi_flash_chip_mxic_opi_erase_chip, .erase_sector = spi_flash_chip_mxic_opi_erase_sector, .erase_block = spi_flash_chip_mxic_opi_erase_block,