kopia lustrzana https://github.com/espressif/esp-idf
esp_flash:fix bug about clearing WLE automatically after actions
rodzic
1a35b5ac9b
commit
11188d2143
|
@ -543,6 +543,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *sp
|
|||
*/
|
||||
void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num, uint32_t spiconfig);
|
||||
|
||||
/**
|
||||
* @brief Clear WEL bit unconditionally.
|
||||
*
|
||||
* @return always ESP_ROM_SPIFLASH_RESULT_OK
|
||||
*/
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void);
|
||||
|
||||
/** @brief Global esp_rom_spiflash_chip_t structure used by ROM functions
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -554,6 +554,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *sp
|
|||
*/
|
||||
void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num, uint32_t spiconfig);
|
||||
|
||||
/**
|
||||
* @brief Clear WEL bit unconditionally.
|
||||
*
|
||||
* @return always ESP_ROM_SPIFLASH_RESULT_OK
|
||||
*/
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void);
|
||||
|
||||
/** @brief Global esp_rom_spiflash_chip_t structure used by ROM functions
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -541,6 +541,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *sp
|
|||
*/
|
||||
void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num, uint32_t spiconfig);
|
||||
|
||||
/**
|
||||
* @brief Clear WEL bit unconditionally.
|
||||
*
|
||||
* @return always ESP_ROM_SPIFLASH_RESULT_OK
|
||||
*/
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void);
|
||||
|
||||
/** @brief Global esp_rom_spiflash_chip_t structure used by ROM functions
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -3,9 +3,10 @@ if(BOOTLOADER_BUILD)
|
|||
# ESP32 Bootloader needs SPIUnlock from this file, but doesn't
|
||||
# need other parts of this component
|
||||
set(srcs "esp32/spi_flash_rom_patch.c")
|
||||
else()
|
||||
# but on other platforms no source files are needed for bootloader
|
||||
set(srcs)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S2)
|
||||
set(srcs "esp32s2/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
set(srcs "esp32s3/spi_flash_rom_patch.c")
|
||||
endif()
|
||||
set(cache_srcs "")
|
||||
set(priv_requires bootloader_support soc)
|
||||
|
@ -22,6 +23,12 @@ else()
|
|||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
list(APPEND srcs
|
||||
"esp32/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S2)
|
||||
list(APPEND srcs
|
||||
"esp32s2/spi_flash_rom_patch.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
list(APPEND srcs
|
||||
"esp32s3/spi_flash_rom_patch.c")
|
||||
endif()
|
||||
|
||||
# New implementation after IDF v4.0
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "sdkconfig.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
|
||||
#define SPI_IDX 1
|
||||
|
@ -682,4 +683,11 @@ esp_rom_spiflash_result_t esp_rom_spiflash_erase_area(uint32_t start_addr, uint3
|
|||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void)
|
||||
{
|
||||
REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WRDI);
|
||||
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// 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.
|
||||
#include "sdkconfig.h"
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
|
||||
#define SPI_IDX 1
|
||||
extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void)
|
||||
{
|
||||
REG_WRITE(SPI_MEM_CMD_REG(SPI_IDX), SPI_MEM_FLASH_WRDI);
|
||||
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// 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.
|
||||
#include "sdkconfig.h"
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "spi_flash_defs.h"
|
||||
|
||||
|
||||
#define SPI_IDX 1
|
||||
extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void)
|
||||
{
|
||||
REG_WRITE(SPI_MEM_CMD_REG(SPI_IDX), SPI_MEM_FLASH_WRDI);
|
||||
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
|
@ -289,6 +289,8 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_addr, size_t size)
|
|||
COUNTER_STOP(erase);
|
||||
|
||||
spi_flash_guard_start();
|
||||
// Ensure WEL is 0 after the operation, even if the erase failed.
|
||||
esp_rom_spiflash_write_disable();
|
||||
spi_flash_check_and_flush_cache(start_addr, size);
|
||||
spi_flash_guard_end();
|
||||
|
||||
|
@ -461,6 +463,8 @@ out:
|
|||
COUNTER_STOP(write);
|
||||
|
||||
spi_flash_guard_start();
|
||||
// Ensure WEL is 0 after the operation, even if the write failed.
|
||||
esp_rom_spiflash_write_disable();
|
||||
spi_flash_check_and_flush_cache(dst, size);
|
||||
spi_flash_guard_end();
|
||||
|
||||
|
@ -491,6 +495,7 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src,
|
|||
err = spi_flash_write_encrypted_chip(dest_addr, src, size);
|
||||
COUNTER_ADD_BYTES(write, size);
|
||||
spi_flash_guard_start();
|
||||
esp_rom_spiflash_write_disable();
|
||||
spi_flash_check_and_flush_cache(dest_addr, size);
|
||||
spi_flash_guard_end();
|
||||
#else
|
||||
|
@ -525,6 +530,7 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src,
|
|||
COUNTER_ADD_BYTES(write, size);
|
||||
|
||||
spi_flash_guard_start();
|
||||
esp_rom_spiflash_write_disable();
|
||||
spi_flash_check_and_flush_cache(dest_addr, size);
|
||||
spi_flash_guard_end();
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@ struct esp_flash_t {
|
|||
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 chip_id; ///< Detected chip id.
|
||||
uint32_t busy :1; ///< This flag is used to verify chip's status.
|
||||
uint32_t reserved_flags :31; ///< reserved.
|
||||
};
|
||||
|
||||
|
||||
|
@ -159,7 +161,10 @@ esp_err_t esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size);
|
|||
* @param chip Pointer to identify flash chip. Must have been successfully initialised via esp_flash_init()
|
||||
*
|
||||
*
|
||||
* @return ESP_OK on success, or a flash error code if operation failed.
|
||||
* @return
|
||||
* - ESP_OK on success,
|
||||
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
|
||||
* - Other flash error code if operation failed.
|
||||
*/
|
||||
esp_err_t esp_flash_erase_chip(esp_flash_t *chip);
|
||||
|
||||
|
@ -176,7 +181,10 @@ esp_err_t esp_flash_erase_chip(esp_flash_t *chip);
|
|||
* chip->drv->block_erase_size field, typically 65536 bytes). Remaining sectors are erased using individual sector erase
|
||||
* commands.
|
||||
*
|
||||
* @return ESP_OK on success, or a flash error code if operation failed.
|
||||
* @return
|
||||
* - ESP_OK on success,
|
||||
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
|
||||
* - Other flash error code if operation failed.
|
||||
*/
|
||||
esp_err_t esp_flash_erase_region(esp_flash_t *chip, uint32_t start, uint32_t len);
|
||||
|
||||
|
@ -280,7 +288,10 @@ esp_err_t esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint
|
|||
*
|
||||
* There are no alignment constraints on buffer, address or length.
|
||||
*
|
||||
* @return ESP_OK on success, or a flash error code if operation failed.
|
||||
* @return
|
||||
* - ESP_OK on success,
|
||||
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
|
||||
* - Other flash error code if operation failed.
|
||||
*/
|
||||
esp_err_t esp_flash_write(esp_flash_t *chip, const void *buffer, uint32_t address, uint32_t length);
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size);
|
|||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
|
||||
* - or other error passed from the ``set_write_protect``, ``wait_idle`` or ``erase_chip`` function of host driver
|
||||
*/
|
||||
esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip);
|
||||
|
@ -84,6 +85,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip);
|
|||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
|
||||
* - or other error passed from the ``set_write_protect``, ``wait_idle`` or ``erase_sector`` function of host driver
|
||||
*/
|
||||
esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_address);
|
||||
|
@ -96,6 +98,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
|
|||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
|
||||
* - or other error passed from the ``set_write_protect``, ``wait_idle`` or ``erase_block`` function of host driver
|
||||
*/
|
||||
esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_address);
|
||||
|
@ -129,6 +132,7 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t
|
|||
*
|
||||
* @return
|
||||
* - ESP_OK if success
|
||||
* - ESP_ERR_NOT_SUPPORTED if the chip is not able to perform the operation. This is indicated by WREN = 1 after the command is sent.
|
||||
* - or other error passed from the ``wait_idle`` or ``program_page`` function of host driver
|
||||
*/
|
||||
esp_err_t
|
||||
|
|
|
@ -110,4 +110,9 @@ void *heap_caps_malloc( size_t size, uint32_t caps )
|
|||
return NULL;
|
||||
}
|
||||
|
||||
esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void)
|
||||
{
|
||||
return ESP_ROM_SPIFLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
esp_flash_t* esp_flash_default_chip = NULL;
|
||||
|
|
|
@ -117,14 +117,21 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip)
|
|||
if (err == ESP_OK) {
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
//The chip didn't accept the previous write command. Ignore this in preparation stage.
|
||||
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
||||
chip->host->driver->erase_chip(chip->host);
|
||||
chip->busy = 1;
|
||||
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
|
||||
err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT);
|
||||
#else
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->chip_erase_timeout);
|
||||
#endif
|
||||
}
|
||||
// Ensure WEL is 0, even if the erase failed.
|
||||
if (err == ESP_ERR_NOT_SUPPORTED) {
|
||||
err = chip->chip_drv->set_chip_write_protect(chip, true);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -134,14 +141,21 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
|
|||
if (err == ESP_OK) {
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
//The chip didn't accept the previous write command. Ignore this in preparationstage.
|
||||
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
||||
chip->host->driver->erase_sector(chip->host, start_address);
|
||||
chip->busy = 1;
|
||||
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
|
||||
err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT);
|
||||
#else
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->sector_erase_timeout);
|
||||
#endif
|
||||
}
|
||||
// Ensure WEL is 0, even if the erase failed.
|
||||
if (err == ESP_ERR_NOT_SUPPORTED) {
|
||||
err = chip->chip_drv->set_chip_write_protect(chip, true);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -151,14 +165,21 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a
|
|||
if (err == ESP_OK) {
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
||||
}
|
||||
if (err == ESP_OK) {
|
||||
//The chip didn't accept the previous write command. Ignore this in preparationstage.
|
||||
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
||||
chip->host->driver->erase_block(chip->host, start_address);
|
||||
chip->busy = 1;
|
||||
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
|
||||
err = chip->chip_drv->wait_idle(chip, ESP_FLASH_CHIP_GENERIC_NO_TIMEOUT);
|
||||
#else
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->block_erase_timeout);
|
||||
#endif
|
||||
}
|
||||
// Ensure WEL is 0, even if the erase failed.
|
||||
if (err == ESP_ERR_NOT_SUPPORTED) {
|
||||
err = chip->chip_drv->set_chip_write_protect(chip, true);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -199,13 +220,18 @@ esp_err_t spi_flash_chip_generic_page_program(esp_flash_t *chip, const void *buf
|
|||
esp_err_t err;
|
||||
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
//The chip didn't accept the previous write command. Ignore this in preparationstage.
|
||||
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
||||
// Perform the actual Page Program command
|
||||
chip->host->driver->program_page(chip->host, buffer, address, length);
|
||||
chip->busy = 1;
|
||||
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->page_program_timeout);
|
||||
}
|
||||
// Ensure WEL is 0, even if the page program failed.
|
||||
if (err == ESP_ERR_NOT_SUPPORTED) {
|
||||
err = chip->chip_drv->set_chip_write_protect(chip, true);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -247,8 +273,8 @@ esp_err_t spi_flash_chip_generic_set_write_protect(esp_flash_t *chip, bool write
|
|||
esp_err_t err = ESP_OK;
|
||||
|
||||
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
||||
|
||||
if (err == ESP_OK) {
|
||||
//The chip didn't accept the previous write command. Ignore this in preparationstage.
|
||||
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
|
||||
chip->host->driver->set_write_protect(chip->host, write_protect);
|
||||
}
|
||||
|
||||
|
@ -264,9 +290,9 @@ esp_err_t spi_flash_chip_generic_set_write_protect(esp_flash_t *chip, bool write
|
|||
esp_err_t spi_flash_chip_generic_get_write_protect(esp_flash_t *chip, bool *out_write_protect)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
uint8_t status;
|
||||
uint32_t status;
|
||||
assert(out_write_protect!=NULL);
|
||||
err = chip->host->driver->read_status(chip->host, &status);
|
||||
err = chip->chip_drv->read_reg(chip, SPI_FLASH_REG_STATUS, &status);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
@ -344,8 +370,14 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u
|
|||
}
|
||||
status = read;
|
||||
|
||||
if ((status & SR_WIP) == 0) {
|
||||
break; // Write in progress is complete
|
||||
if ((status & SR_WIP) == 0) { // Verify write in progress is complete
|
||||
if (chip->busy == 1) {
|
||||
chip->busy = 0;
|
||||
if ((status & SR_WREN) != 0) { // The previous command is not accepted, leaving the WEL still set.
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (timeout_us > 0 && interval > 0) {
|
||||
int delay = MIN(interval, timeout_us);
|
||||
|
@ -355,7 +387,6 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (timeout_us > 0) ? ESP_OK : ESP_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
|
@ -587,11 +618,19 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t
|
|||
|
||||
ret = (*wrsr_func)(chip, sr_update);
|
||||
if (ret != ESP_OK) {
|
||||
chip->chip_drv->set_chip_write_protect(chip, true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout);
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_ERR_NOT_SUPPORTED) {
|
||||
chip->chip_drv->set_chip_write_protect(chip, true);
|
||||
}
|
||||
/* This function is the fallback approach, so we give it higher tolerance.
|
||||
* When the previous WRSR is rejected by the flash,
|
||||
* the result of this function is determined by the result -whether the value of RDSR meets the expectation.
|
||||
*/
|
||||
if (ret != ESP_OK && ret != ESP_ERR_NOT_SUPPORTED) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -605,8 +644,6 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t
|
|||
if (sr != sr_update) {
|
||||
ret = ESP_ERR_FLASH_NO_RESPONSE;
|
||||
}
|
||||
|
||||
chip->chip_drv->set_chip_write_protect(chip, true);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue