spi_flash: Making XMC flash works more stable when brownout detected

This commit is contained in:
Cao Sen Miao 2022-05-30 16:49:19 +08:00
parent 890f046ee9
commit 6a2d3509dc
27 changed files with 261 additions and 134 deletions

View File

@ -49,6 +49,12 @@ esp_err_t bootloader_flash_xmc_startup(void);
*/ */
esp_err_t __attribute__((weak)) bootloader_flash_unlock(void); esp_err_t __attribute__((weak)) bootloader_flash_unlock(void);
/**
* @brief Reset the flash chip (66H + 99H).
*
* @return ESP_OK if success, otherwise ESP_FAIL.
*/
esp_err_t bootloader_flash_reset_chip(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -730,3 +730,44 @@ esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
} }
#endif //XMC_SUPPORT #endif //XMC_SUPPORT
FORCE_INLINE_ATTR void bootloader_mspi_reset(void)
{
#if CONFIG_IDF_TARGET_ESP32
SPI1.slave.sync_reset = 0;
SPI0.slave.sync_reset = 0;
SPI1.slave.sync_reset = 1;
SPI0.slave.sync_reset = 1;
SPI1.slave.sync_reset = 0;
SPI0.slave.sync_reset = 0;
#else
SPIMEM1.ctrl2.sync_reset = 0;
SPIMEM0.ctrl2.sync_reset = 0;
SPIMEM1.ctrl2.sync_reset = 1;
SPIMEM0.ctrl2.sync_reset = 1;
SPIMEM1.ctrl2.sync_reset = 0;
SPIMEM0.ctrl2.sync_reset = 0;
#endif
}
esp_err_t IRAM_ATTR bootloader_flash_reset_chip(void)
{
bootloader_mspi_reset();
// Seems that sync_reset cannot make host totally idle.'
// Sending an extra(useless) command to make the host idle in order to send reset command.
bootloader_execute_flash_command(0x05, 0, 0, 0);
#if CONFIG_IDF_TARGET_ESP32
if (SPI1.ext2.st != 0)
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (SPIMEM1.fsm.st != 0)
#else
if (SPIMEM1.fsm.spi0_mst_st != 0)
#endif
{
return ESP_FAIL;
}
bootloader_execute_flash_command(0x66, 0, 0, 0);
bootloader_execute_flash_command(0x99, 0, 0, 0);
return ESP_OK;
}

View File

@ -7,6 +7,8 @@ choice ESP32_REV_MIN
config ESP32_REV_MIN_0 config ESP32_REV_MIN_0
bool "Rev 0" bool "Rev 0"
# Brownout on Rev 0 is bugged, must use interrupt
select ESP_SYSTEM_BROWNOUT_INTR
config ESP32_REV_MIN_1 config ESP32_REV_MIN_1
bool "Rev 1" bool "Rev 1"
config ESP32_REV_MIN_2 config ESP32_REV_MIN_2

View File

@ -531,6 +531,18 @@ menu "ESP System Settings"
# Insert chip-specific system config # Insert chip-specific system config
rsource "./port/soc/$IDF_TARGET/Kconfig.system" rsource "./port/soc/$IDF_TARGET/Kconfig.system"
config ESP_SYSTEM_BROWNOUT_INTR
bool
default n
help
This config allows to trigger an interrupt when brownout detected. Software restart will be done
at the end of the default callback.
Two occasions need to restart the chip with interrupt so far.
(1). For ESP32 version 1, brown-out reset function doesn't work (see ESP32 errata 3.4).
So that we must restart from interrupt.
(2). For special workflow, the chip needs do more things instead of restarting directly. This part
needs to be done in callback function of interrupt.
endmenu # ESP System Settings endmenu # ESP System Settings
menu "IPC (Inter-Processor Call)" menu "IPC (Inter-Processor Call)"

View File

@ -11,6 +11,7 @@
#include "esp_private/system_internal.h" #include "esp_private/system_internal.h"
#include "esp_private/rtc_ctrl.h" #include "esp_private/rtc_ctrl.h"
#include "esp_private/spi_flash_os.h"
#include "esp_rom_sys.h" #include "esp_rom_sys.h"
@ -18,6 +19,9 @@
#include "esp_cpu.h" #include "esp_cpu.h"
#include "soc/rtc_periph.h" #include "soc/rtc_periph.h"
#include "hal/cpu_hal.h" #include "hal/cpu_hal.h"
#include "esp_attr.h"
#include "bootloader_flash.h"
#include "esp_intr_alloc.h"
#include "hal/brownout_hal.h" #include "hal/brownout_hal.h"
@ -29,48 +33,58 @@
#define BROWNOUT_DET_LVL 0 #define BROWNOUT_DET_LVL 0
#endif #endif
#if SOC_BROWNOUT_RESET_SUPPORTED #if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
#define BROWNOUT_RESET_EN true IRAM_ATTR static void rtc_brownout_isr_handler(void *arg)
#else
#define BROWNOUT_RESET_EN false
#endif // SOC_BROWNOUT_RESET_SUPPORTED
#ifndef SOC_BROWNOUT_RESET_SUPPORTED
static void rtc_brownout_isr_handler(void *arg)
{ {
/* Normally RTC ISR clears the interrupt flag after the application-supplied /* Normally RTC ISR clears the interrupt flag after the application-supplied
* handler returns. Since restart is called here, the flag needs to be * handler returns. Since restart is called here, the flag needs to be
* cleared manually. * cleared manually.
*/ */
brownout_hal_intr_clear(); brownout_hal_intr_clear();
/* Stall the other CPU to make sure the code running there doesn't use UART // Stop the other core.
* at the same time as the following esp_rom_printf.
*/
esp_cpu_stall(!cpu_hal_get_core_id()); esp_cpu_stall(!cpu_hal_get_core_id());
esp_reset_reason_set_hint(ESP_RST_BROWNOUT); esp_reset_reason_set_hint(ESP_RST_BROWNOUT);
esp_rom_printf("\r\nBrownout detector was triggered\r\n\r\n"); #if CONFIG_SPI_FLASH_BROWNOUT_RESET
if (spi_flash_brownout_need_reset()) {
bootloader_flash_reset_chip();
} else
#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET
{
esp_rom_printf("\r\nBrownout detector was triggered\r\n\r\n");
}
esp_restart_noos(); esp_restart_noos();
} }
#endif // not SOC_BROWNOUT_RESET_SUPPORTED #endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR
void esp_brownout_init(void) void esp_brownout_init(void)
{ {
#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
brownout_hal_config_t cfg = { brownout_hal_config_t cfg = {
.threshold = BROWNOUT_DET_LVL, .threshold = BROWNOUT_DET_LVL,
.enabled = true, .enabled = true,
.reset_enabled = BROWNOUT_RESET_EN, .reset_enabled = false,
.flash_power_down = true, .flash_power_down = true,
.rf_power_down = true, .rf_power_down = true,
}; };
brownout_hal_config(&cfg); brownout_hal_config(&cfg);
brownout_hal_intr_clear();
rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM);
#ifndef SOC_BROWNOUT_RESET_SUPPORTED
rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M);
brownout_hal_intr_enable(true); brownout_hal_intr_enable(true);
#endif // not SOC_BROWNOUT_RESET_SUPPORTED
#else // brownout without interrupt
brownout_hal_config_t cfg = {
.threshold = BROWNOUT_DET_LVL,
.enabled = true,
.reset_enabled = true,
.flash_power_down = true,
.rf_power_down = true,
};
brownout_hal_config(&cfg);
#endif
} }
void esp_brownout_disable(void) void esp_brownout_disable(void)
@ -80,10 +94,8 @@ void esp_brownout_disable(void)
}; };
brownout_hal_config(&cfg); brownout_hal_config(&cfg);
#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
#ifndef SOC_BROWNOUT_RESET_SUPPORTED
brownout_hal_intr_enable(false); brownout_hal_intr_enable(false);
rtc_isr_deregister(rtc_brownout_isr_handler, NULL); rtc_isr_deregister(rtc_brownout_isr_handler, NULL);
#endif // not SOC_BROWNOUT_RESET_SUPPORTED #endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR
} }

View File

@ -66,7 +66,7 @@
#include "esp_pthread.h" #include "esp_pthread.h"
#include "esp_private/esp_clk.h" #include "esp_private/esp_clk.h"
#include "esp_private/spi_flash_os.h"
#include "esp_private/brownout.h" #include "esp_private/brownout.h"
#include "esp_rom_sys.h" #include "esp_rom_sys.h"
@ -301,6 +301,9 @@ static void do_core_init(void)
esp_err_t flash_ret = esp_flash_init_default_chip(); esp_err_t flash_ret = esp_flash_init_default_chip();
assert(flash_ret == ESP_OK); assert(flash_ret == ESP_OK);
(void)flash_ret; (void)flash_ret;
#if CONFIG_SPI_FLASH_BROWNOUT_RESET
spi_flash_needs_reset_check();
#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET
#ifdef CONFIG_EFUSE_VIRTUAL #ifdef CONFIG_EFUSE_VIRTUAL
ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!"); ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");

View File

@ -1,20 +1,13 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 "hal/brownout_hal.h" #include "hal/brownout_hal.h"
#include "soc/rtc_cntl_struct.h" #include "soc/rtc_cntl_struct.h"
#include "esp_attr.h"
void brownout_hal_config(const brownout_hal_config_t *cfg) void brownout_hal_config(const brownout_hal_config_t *cfg)
{ {
@ -35,7 +28,7 @@ void brownout_hal_intr_enable(bool enable)
RTCCNTL.int_ena.rtc_brown_out = enable; RTCCNTL.int_ena.rtc_brown_out = enable;
} }
void brownout_hal_intr_clear(void) IRAM_ATTR void brownout_hal_intr_clear(void)
{ {
RTCCNTL.int_clr.rtc_brown_out = 1; RTCCNTL.int_clr.rtc_brown_out = 1;
} }

View File

@ -10,6 +10,7 @@
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "esp_private/regi2c_ctrl.h" #include "esp_private/regi2c_ctrl.h"
#include "regi2c_brownout.h" #include "regi2c_brownout.h"
#include "esp_attr.h"
void brownout_hal_config(const brownout_hal_config_t *cfg) void brownout_hal_config(const brownout_hal_config_t *cfg)
@ -31,7 +32,7 @@ void brownout_hal_intr_enable(bool enable)
RTCCNTL.int_ena.rtc_brown_out = enable; RTCCNTL.int_ena.rtc_brown_out = enable;
} }
void brownout_hal_intr_clear(void) IRAM_ATTR void brownout_hal_intr_clear(void)
{ {
RTCCNTL.int_clr.rtc_brown_out = 1; RTCCNTL.int_clr.rtc_brown_out = 1;
} }

View File

@ -10,6 +10,7 @@
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "esp_private/regi2c_ctrl.h" #include "esp_private/regi2c_ctrl.h"
#include "regi2c_brownout.h" #include "regi2c_brownout.h"
#include "esp_attr.h"
void brownout_hal_config(const brownout_hal_config_t *cfg) void brownout_hal_config(const brownout_hal_config_t *cfg)
@ -31,7 +32,7 @@ void brownout_hal_intr_enable(bool enable)
RTCCNTL.int_ena.rtc_brown_out = enable; RTCCNTL.int_ena.rtc_brown_out = enable;
} }
void brownout_hal_intr_clear(void) IRAM_ATTR void brownout_hal_intr_clear(void)
{ {
RTCCNTL.int_clr.rtc_brown_out = 1; RTCCNTL.int_clr.rtc_brown_out = 1;
} }

View File

@ -11,6 +11,7 @@
#include "i2c_pmu.h" #include "i2c_pmu.h"
#include "esp_private/regi2c_ctrl.h" #include "esp_private/regi2c_ctrl.h"
#include "regi2c_brownout.h" #include "regi2c_brownout.h"
#include "esp_attr.h"
void brownout_hal_config(const brownout_hal_config_t *cfg) void brownout_hal_config(const brownout_hal_config_t *cfg)
@ -32,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
RTCCNTL.int_ena.rtc_brown_out = enable; RTCCNTL.int_ena.rtc_brown_out = enable;
} }
void brownout_hal_intr_clear(void) IRAM_ATTR void brownout_hal_intr_clear(void)
{ {
RTCCNTL.int_clr.rtc_brown_out = 1; RTCCNTL.int_clr.rtc_brown_out = 1;
} }

View File

@ -10,7 +10,7 @@
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "esp_private/regi2c_ctrl.h" #include "esp_private/regi2c_ctrl.h"
#include "regi2c_brownout.h" #include "regi2c_brownout.h"
#include "esp_attr.h"
void brownout_hal_config(const brownout_hal_config_t *cfg) void brownout_hal_config(const brownout_hal_config_t *cfg)
{ {
@ -33,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
RTCCNTL.int_ena.rtc_brown_out = enable; RTCCNTL.int_ena.rtc_brown_out = enable;
} }
void brownout_hal_intr_clear(void) IRAM_ATTR void brownout_hal_intr_clear(void)
{ {
RTCCNTL.int_clr.rtc_brown_out = 1; RTCCNTL.int_clr.rtc_brown_out = 1;
} }

View File

@ -10,6 +10,7 @@
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "esp_private/regi2c_ctrl.h" #include "esp_private/regi2c_ctrl.h"
#include "regi2c_brownout.h" #include "regi2c_brownout.h"
#include "esp_attr.h"
void brownout_hal_config(const brownout_hal_config_t *cfg) void brownout_hal_config(const brownout_hal_config_t *cfg)
@ -32,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
RTCCNTL.int_ena.rtc_brown_out = enable; RTCCNTL.int_ena.rtc_brown_out = enable;
} }
void brownout_hal_intr_clear(void) IRAM_ATTR void brownout_hal_intr_clear(void)
{ {
RTCCNTL.int_clr.rtc_brown_out = 1; RTCCNTL.int_clr.rtc_brown_out = 1;
} }

View File

@ -1,16 +1,8 @@
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
/******************************************************************************* /*******************************************************************************
* NOTICE * NOTICE

View File

@ -127,7 +127,6 @@
#define SOC_ADC_RTC_MAX_BITWIDTH (12) #define SOC_ADC_RTC_MAX_BITWIDTH (12)
#define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1) #define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1)
/*-------------------------- BROWNOUT CAPS -----------------------------------*/ /*-------------------------- BROWNOUT CAPS -----------------------------------*/
#if SOC_CAPS_ECO_VER >= 1 #if SOC_CAPS_ECO_VER >= 1
#define SOC_BROWNOUT_RESET_SUPPORTED 1 #define SOC_BROWNOUT_RESET_SUPPORTED 1

View File

@ -3,10 +3,6 @@
# using gen_soc_caps_kconfig.py, do not edit manually # using gen_soc_caps_kconfig.py, do not edit manually
##################################################### #####################################################
config SOC_BROWNOUT_RESET_SUPPORTED
bool
default y
config SOC_CPU_BREAKPOINTS_NUM config SOC_CPU_BREAKPOINTS_NUM
int int
default 2 default 2
@ -287,6 +283,10 @@ config SOC_APB_BACKUP_DMA
bool bool
default y default y
config SOC_BROWNOUT_RESET_SUPPORTED
bool
default y
config SOC_DS_SIGNATURE_MAX_BIT_LEN config SOC_DS_SIGNATURE_MAX_BIT_LEN
int int
default 4096 default 4096

View File

@ -1,25 +0,0 @@
// Copyright 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define SOC_BROWNOUT_RESET_SUPPORTED 1
#ifdef __cplusplus
}
#endif

View File

@ -100,7 +100,7 @@
#define SOC_APB_BACKUP_DMA (1) #define SOC_APB_BACKUP_DMA (1)
/*-------------------------- BROWNOUT CAPS -----------------------------------*/ /*-------------------------- BROWNOUT CAPS -----------------------------------*/
#include "brownout_caps.h" #define SOC_BROWNOUT_RESET_SUPPORTED 1
/*-------------------------- CPU CAPS ----------------------------------------*/ /*-------------------------- CPU CAPS ----------------------------------------*/
#include "cpu_caps.h" #include "cpu_caps.h"

View File

@ -25,6 +25,7 @@ else()
set(srcs set(srcs
"partition.c" "partition.c"
"partition_target.c" "partition_target.c"
"flash_brownout_hook.c"
) )
if(CONFIG_ESPTOOLPY_OCT_FLASH) if(CONFIG_ESPTOOLPY_OCT_FLASH)

View File

@ -209,6 +209,28 @@ menu "SPI Flash driver"
See example: custom_chip_driver under examples/storage for more details. See example: custom_chip_driver under examples/storage for more details.
menu "SPI Flash behavior when brownout"
config SPI_FLASH_BROWNOUT_RESET_XMC
bool "Enable sending reset when brownout for XMC flash chips"
default y
select SPI_FLASH_BROWNOUT_RESET
help
When this option is selected, the patch will be enabled for XMC.
Follow the recommended flow by XMC for better stability.
DO NOT DISABLE UNLESS YOU KNOW WHAT YOU ARE DOING.
config SPI_FLASH_BROWNOUT_RESET
bool
default y
select ESP_SYSTEM_BROWNOUT_INTR
help
When brownout happens during flash erase/write operations,
send reset command to stop the flash operations to improve stability.
endmenu
menu "Auto-detect flash chips" menu "Auto-detect flash chips"
visible if !SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST visible if !SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST

View File

@ -0,0 +1,39 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include "esp_attr.h"
#include "sdkconfig.h"
#include "esp_rom_spiflash.h"
#if CONFIG_SPI_FLASH_BROWNOUT_RESET
static bool flash_brownout_needs_reset = false;
static bool flash_erasing = false;
// This function could be called in startup
void spi_flash_needs_reset_check(void)
{
// Currently only XMC is suggested to reset when brownout
#if CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC
if ((g_rom_flashchip.device_id >> 16) == 0x20) {
flash_brownout_needs_reset = true;
}
#endif
}
void spi_flash_set_erasing_flag(bool status)
{
flash_erasing = status;
}
bool spi_flash_brownout_need_reset(void)
{
return (flash_brownout_needs_reset && flash_erasing);
}
#endif //CONFIG_SPI_FLASH_BROWNOUT_RESET

View File

@ -1,16 +1,8 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
#pragma once #pragma once
#include "esp_err.h" #include "esp_err.h"
@ -80,6 +72,11 @@ typedef struct {
/** Called for get system time. */ /** Called for get system time. */
int64_t (*get_system_time)(void *arg); int64_t (*get_system_time)(void *arg);
#define SPI_FLASH_OS_IS_ERASING_STATUS_FLAG BIT(0)
/** Call to set flash operation status */
void (*set_flash_op_status)(uint32_t op_status);
} esp_flash_os_functions_t; } esp_flash_os_functions_t;
/** @brief Structure to describe a SPI flash chip connected to the system. /** @brief Structure to describe a SPI flash chip connected to the system.

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -101,6 +101,28 @@ bool spi_timing_is_tuned(void);
*/ */
void spi_flash_set_vendor_required_regs(void); void spi_flash_set_vendor_required_regs(void);
/**
* @brief Judge whether need to reset flash when brownout.
* Set` flash_brownout_needs_reset` inside the function if really need reset.
*/
void spi_flash_needs_reset_check(void);
/**
* @brief Set flag to reset flash. set when erase chip or program chip
*
* @param bool status. True if flash is eraing. False if flash is not erasing.
*
* @return None.
*/
void spi_flash_set_erasing_flag(bool status);
/**
* @brief Judge whether need to reset flash when brownout.
*
* @return true if need reset, otherwise false.
*/
bool spi_flash_brownout_need_reset(void);
/** /**
* @brief Enable SPI flash high performance mode. * @brief Enable SPI flash high performance mode.
* *

View File

@ -1,16 +1,8 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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.
#pragma once #pragma once
#include "hal/spi_flash_hal.h" #include "hal/spi_flash_hal.h"

View File

@ -9,6 +9,7 @@ entries:
spi_flash_chip_boya (noflash) spi_flash_chip_boya (noflash)
spi_flash_chip_th (noflash) spi_flash_chip_th (noflash)
memspi_host_driver (noflash) memspi_host_driver (noflash)
flash_brownout_hook (noflash)
if IDF_TARGET_ESP32S3 = y: if IDF_TARGET_ESP32S3 = y:
spi_flash_timing_tuning (noflash) spi_flash_timing_tuning (noflash)

View File

@ -1,16 +1,8 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// 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 <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -20,6 +12,7 @@
#include "hal/spi_flash_encrypt_hal.h" #include "hal/spi_flash_encrypt_hal.h"
#include "esp_log.h" #include "esp_log.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_private/spi_flash_os.h"
typedef struct flash_chip_dummy { typedef struct flash_chip_dummy {
uint8_t dio_dummy_bitlen; uint8_t dio_dummy_bitlen;
@ -69,6 +62,12 @@ const DRAM_ATTR flash_chip_op_timeout_t spi_flash_chip_generic_timeout = {
.page_program_timeout = SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000, .page_program_timeout = SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000,
}; };
#define SET_FLASH_ERASE_STATUS(CHIP, status) do { \
if (CHIP->os_func->set_flash_op_status) { \
CHIP->os_func->set_flash_op_status(status); \
} \
} while(0)
static const char TAG[] = "chip_generic"; static const char TAG[] = "chip_generic";
#ifndef CONFIG_SPI_FLASH_ROM_IMPL #ifndef CONFIG_SPI_FLASH_ROM_IMPL
@ -130,6 +129,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip)
} }
//The chip didn't accept the previous write command. Ignore this in preparation stage. //The chip didn't accept the previous write command. Ignore this in preparation stage.
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
chip->host->driver->erase_chip(chip->host); chip->host->driver->erase_chip(chip->host);
chip->busy = 1; chip->busy = 1;
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED #ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
@ -137,6 +137,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip)
#else #else
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->chip_erase_timeout); err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->chip_erase_timeout);
#endif #endif
SET_FLASH_ERASE_STATUS(chip, 0);
} }
// Ensure WEL is 0, even if the erase failed. // Ensure WEL is 0, even if the erase failed.
if (err == ESP_ERR_NOT_SUPPORTED) { if (err == ESP_ERR_NOT_SUPPORTED) {
@ -154,6 +155,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
} }
//The chip didn't accept the previous write command. Ignore this in preparationstage. //The chip didn't accept the previous write command. Ignore this in preparationstage.
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
chip->host->driver->erase_sector(chip->host, start_address); chip->host->driver->erase_sector(chip->host, start_address);
chip->busy = 1; chip->busy = 1;
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED #ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
@ -161,6 +163,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_
#else #else
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->sector_erase_timeout); err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->sector_erase_timeout);
#endif #endif
SET_FLASH_ERASE_STATUS(chip, 0);
} }
// Ensure WEL is 0, even if the erase failed. // Ensure WEL is 0, even if the erase failed.
if (err == ESP_ERR_NOT_SUPPORTED) { if (err == ESP_ERR_NOT_SUPPORTED) {
@ -178,6 +181,7 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a
} }
//The chip didn't accept the previous write command. Ignore this in preparationstage. //The chip didn't accept the previous write command. Ignore this in preparationstage.
if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) { if (err == ESP_OK || err == ESP_ERR_NOT_SUPPORTED) {
SET_FLASH_ERASE_STATUS(chip, SPI_FLASH_OS_IS_ERASING_STATUS_FLAG);
chip->host->driver->erase_block(chip->host, start_address); chip->host->driver->erase_block(chip->host, start_address);
chip->busy = 1; chip->busy = 1;
#ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED #ifdef CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED
@ -185,6 +189,7 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a
#else #else
err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->block_erase_timeout); err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->block_erase_timeout);
#endif #endif
SET_FLASH_ERASE_STATUS(chip, 0);
} }
// Ensure WEL is 0, even if the erase failed. // Ensure WEL is 0, even if the erase failed.
if (err == ESP_ERR_NOT_SUPPORTED) { if (err == ESP_ERR_NOT_SUPPORTED) {

View File

@ -18,6 +18,7 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_compiler.h" #include "esp_compiler.h"
#include "esp_rom_sys.h" #include "esp_rom_sys.h"
#include "esp_private/spi_flash_os.h"
#include "driver/spi_common_internal.h" #include "driver/spi_common_internal.h"
@ -185,6 +186,13 @@ static IRAM_ATTR esp_err_t main_flash_region_protected(void* arg, size_t start_a
} }
} }
static IRAM_ATTR void main_flash_op_status(uint32_t op_status)
{
bool is_erasing = op_status & SPI_FLASH_OS_IS_ERASING_STATUS_FLAG;
spi_flash_set_erasing_flag(is_erasing);
}
static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {}; static DRAM_ATTR spi1_app_func_arg_t main_flash_arg = {};
//for SPI1, we have to disable the cache and interrupts before using the SPI bus //for SPI1, we have to disable the cache and interrupts before using the SPI bus
@ -197,6 +205,11 @@ static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functi
.release_temp_buffer = release_buffer_malloc, .release_temp_buffer = release_buffer_malloc,
.check_yield = spi1_flash_os_check_yield, .check_yield = spi1_flash_os_check_yield,
.yield = spi1_flash_os_yield, .yield = spi1_flash_os_yield,
#if CONFIG_SPI_FLASH_BROWNOUT_RESET
.set_flash_op_status = main_flash_op_status,
#else
.set_flash_op_status = NULL,
#endif
}; };
static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = { static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
@ -208,6 +221,7 @@ static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = {
.region_protected = NULL, .region_protected = NULL,
.check_yield = NULL, .check_yield = NULL,
.yield = NULL, .yield = NULL,
.set_flash_op_status = NULL,
}; };
static bool use_bus_lock(int host_id) static bool use_bus_lock(int host_id)

View File

@ -775,7 +775,6 @@ components/hal/aes_hal.c
components/hal/cpu_hal.c components/hal/cpu_hal.c
components/hal/dac_hal.c components/hal/dac_hal.c
components/hal/ds_hal.c components/hal/ds_hal.c
components/hal/esp32/brownout_hal.c
components/hal/esp32/gpio_hal_workaround.c components/hal/esp32/gpio_hal_workaround.c
components/hal/esp32/include/hal/aes_ll.h components/hal/esp32/include/hal/aes_ll.h
components/hal/esp32/include/hal/can_hal.h components/hal/esp32/include/hal/can_hal.h
@ -859,7 +858,6 @@ components/hal/esp32s3/include/hal/usb_serial_jtag_ll.h
components/hal/esp32s3/interrupt_descriptor_table.c components/hal/esp32s3/interrupt_descriptor_table.c
components/hal/include/hal/aes_hal.h components/hal/include/hal/aes_hal.h
components/hal/include/hal/aes_types.h components/hal/include/hal/aes_types.h
components/hal/include/hal/brownout_hal.h
components/hal/include/hal/cpu_types.h components/hal/include/hal/cpu_types.h
components/hal/include/hal/dac_hal.h components/hal/include/hal/dac_hal.h
components/hal/include/hal/dac_types.h components/hal/include/hal/dac_types.h
@ -1536,10 +1534,8 @@ components/soc/include/soc/usb_periph.h
components/soc/lldesc.c components/soc/lldesc.c
components/soc/soc_include_legacy_warn.c components/soc/soc_include_legacy_warn.c
components/spi_flash/cache_utils.h components/spi_flash/cache_utils.h
components/spi_flash/include/esp_flash.h
components/spi_flash/include/esp_spi_flash.h components/spi_flash/include/esp_spi_flash.h
components/spi_flash/include/esp_spi_flash_counters.h components/spi_flash/include/esp_spi_flash_counters.h
components/spi_flash/include/memspi_host_driver.h
components/spi_flash/include/spi_flash_chip_boya.h components/spi_flash/include/spi_flash_chip_boya.h
components/spi_flash/include/spi_flash_chip_driver.h components/spi_flash/include/spi_flash_chip_driver.h
components/spi_flash/include/spi_flash_chip_gd.h components/spi_flash/include/spi_flash_chip_gd.h
@ -1553,7 +1549,6 @@ components/spi_flash/sim/flash_mock_util.c
components/spi_flash/sim/sdkconfig/sdkconfig.h components/spi_flash/sim/sdkconfig/sdkconfig.h
components/spi_flash/spi_flash_chip_boya.c components/spi_flash/spi_flash_chip_boya.c
components/spi_flash/spi_flash_chip_gd.c components/spi_flash/spi_flash_chip_gd.c
components/spi_flash/spi_flash_chip_generic.c
components/spi_flash/spi_flash_chip_issi.c components/spi_flash/spi_flash_chip_issi.c
components/spi_flash/spi_flash_chip_mxic.c components/spi_flash/spi_flash_chip_mxic.c
components/spi_flash/spi_flash_chip_mxic_opi.c components/spi_flash/spi_flash_chip_mxic_opi.c