From 6a2d3509dcedc2fe67a98ae3a0fd5a089c256ef8 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Mon, 30 May 2022 16:49:19 +0800 Subject: [PATCH] spi_flash: Making XMC flash works more stable when brownout detected --- .../include/bootloader_flash.h | 6 ++ .../bootloader_flash/src/bootloader_flash.c | 41 +++++++++++++ .../port/esp32/Kconfig.hw_support | 2 + components/esp_system/Kconfig | 12 ++++ components/esp_system/port/brownout.c | 60 +++++++++++-------- components/esp_system/startup.c | 5 +- components/hal/esp32/brownout_hal.c | 21 +++---- components/hal/esp32c2/brownout_hal.c | 3 +- components/hal/esp32c3/brownout_hal.c | 3 +- components/hal/esp32h2/brownout_hal.c | 3 +- components/hal/esp32s2/brownout_hal.c | 4 +- components/hal/esp32s3/brownout_hal.c | 3 +- components/hal/include/hal/brownout_hal.h | 18 ++---- components/soc/esp32/include/soc/soc_caps.h | 1 - .../esp32s3/include/soc/Kconfig.soc_caps.in | 8 +-- .../soc/esp32s3/include/soc/brownout_caps.h | 25 -------- components/soc/esp32s3/include/soc/soc_caps.h | 2 +- components/spi_flash/CMakeLists.txt | 1 + components/spi_flash/Kconfig | 22 +++++++ components/spi_flash/flash_brownout_hook.c | 39 ++++++++++++ components/spi_flash/include/esp_flash.h | 23 ++++--- .../include/esp_private/spi_flash_os.h | 24 +++++++- .../spi_flash/include/memspi_host_driver.h | 18 ++---- components/spi_flash/linker.lf | 1 + components/spi_flash/spi_flash_chip_generic.c | 31 ++++++---- components/spi_flash/spi_flash_os_func_app.c | 14 +++++ tools/ci/check_copyright_ignore.txt | 5 -- 27 files changed, 261 insertions(+), 134 deletions(-) delete mode 100644 components/soc/esp32s3/include/soc/brownout_caps.h create mode 100644 components/spi_flash/flash_brownout_hook.c diff --git a/components/bootloader_support/bootloader_flash/include/bootloader_flash.h b/components/bootloader_support/bootloader_flash/include/bootloader_flash.h index 51a466fd82..7c48728cf0 100644 --- a/components/bootloader_support/bootloader_flash/include/bootloader_flash.h +++ b/components/bootloader_support/bootloader_flash/include/bootloader_flash.h @@ -49,6 +49,12 @@ esp_err_t bootloader_flash_xmc_startup(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 } diff --git a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c index 2957737081..531653cc8d 100644 --- a/components/bootloader_support/bootloader_flash/src/bootloader_flash.c +++ b/components/bootloader_support/bootloader_flash/src/bootloader_flash.c @@ -730,3 +730,44 @@ esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void) } #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; +} diff --git a/components/esp_hw_support/port/esp32/Kconfig.hw_support b/components/esp_hw_support/port/esp32/Kconfig.hw_support index 2ed4badd62..91711dc941 100644 --- a/components/esp_hw_support/port/esp32/Kconfig.hw_support +++ b/components/esp_hw_support/port/esp32/Kconfig.hw_support @@ -7,6 +7,8 @@ choice ESP32_REV_MIN config ESP32_REV_MIN_0 bool "Rev 0" + # Brownout on Rev 0 is bugged, must use interrupt + select ESP_SYSTEM_BROWNOUT_INTR config ESP32_REV_MIN_1 bool "Rev 1" config ESP32_REV_MIN_2 diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 5cf117ebbb..a6e4c483fe 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -531,6 +531,18 @@ menu "ESP System Settings" # Insert chip-specific system config 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 menu "IPC (Inter-Processor Call)" diff --git a/components/esp_system/port/brownout.c b/components/esp_system/port/brownout.c index 21ec6800be..9d0d66c165 100644 --- a/components/esp_system/port/brownout.c +++ b/components/esp_system/port/brownout.c @@ -11,6 +11,7 @@ #include "esp_private/system_internal.h" #include "esp_private/rtc_ctrl.h" +#include "esp_private/spi_flash_os.h" #include "esp_rom_sys.h" @@ -18,6 +19,9 @@ #include "esp_cpu.h" #include "soc/rtc_periph.h" #include "hal/cpu_hal.h" +#include "esp_attr.h" +#include "bootloader_flash.h" +#include "esp_intr_alloc.h" #include "hal/brownout_hal.h" @@ -29,48 +33,58 @@ #define BROWNOUT_DET_LVL 0 #endif -#if SOC_BROWNOUT_RESET_SUPPORTED -#define BROWNOUT_RESET_EN true -#else -#define BROWNOUT_RESET_EN false -#endif // SOC_BROWNOUT_RESET_SUPPORTED - -#ifndef SOC_BROWNOUT_RESET_SUPPORTED -static void rtc_brownout_isr_handler(void *arg) +#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR +IRAM_ATTR static void rtc_brownout_isr_handler(void *arg) { /* Normally RTC ISR clears the interrupt flag after the application-supplied * handler returns. Since restart is called here, the flag needs to be * cleared manually. */ brownout_hal_intr_clear(); - /* Stall the other CPU to make sure the code running there doesn't use UART - * at the same time as the following esp_rom_printf. - */ + // Stop the other core. esp_cpu_stall(!cpu_hal_get_core_id()); 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(); } -#endif // not SOC_BROWNOUT_RESET_SUPPORTED +#endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR void esp_brownout_init(void) { +#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR brownout_hal_config_t cfg = { .threshold = BROWNOUT_DET_LVL, .enabled = true, - .reset_enabled = BROWNOUT_RESET_EN, + .reset_enabled = false, .flash_power_down = true, .rf_power_down = true, }; brownout_hal_config(&cfg); - - -#ifndef SOC_BROWNOUT_RESET_SUPPORTED - rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M); - + brownout_hal_intr_clear(); + rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM); 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) @@ -80,10 +94,8 @@ void esp_brownout_disable(void) }; brownout_hal_config(&cfg); - -#ifndef SOC_BROWNOUT_RESET_SUPPORTED +#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR brownout_hal_intr_enable(false); - rtc_isr_deregister(rtc_brownout_isr_handler, NULL); -#endif // not SOC_BROWNOUT_RESET_SUPPORTED +#endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR } diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 786466b652..6bd8d3bac7 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -66,7 +66,7 @@ #include "esp_pthread.h" #include "esp_private/esp_clk.h" - +#include "esp_private/spi_flash_os.h" #include "esp_private/brownout.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(); assert(flash_ret == ESP_OK); (void)flash_ret; +#if CONFIG_SPI_FLASH_BROWNOUT_RESET + spi_flash_needs_reset_check(); +#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET #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!"); diff --git a/components/hal/esp32/brownout_hal.c b/components/hal/esp32/brownout_hal.c index 5fc448601b..0d53698068 100644 --- a/components/hal/esp32/brownout_hal.c +++ b/components/hal/esp32/brownout_hal.c @@ -1,20 +1,13 @@ -// 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. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "hal/brownout_hal.h" #include "soc/rtc_cntl_struct.h" +#include "esp_attr.h" 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; } -void brownout_hal_intr_clear(void) +IRAM_ATTR void brownout_hal_intr_clear(void) { RTCCNTL.int_clr.rtc_brown_out = 1; } diff --git a/components/hal/esp32c2/brownout_hal.c b/components/hal/esp32c2/brownout_hal.c index 7c32faaeda..ee0c7377e6 100644 --- a/components/hal/esp32c2/brownout_hal.c +++ b/components/hal/esp32c2/brownout_hal.c @@ -10,6 +10,7 @@ #include "soc/rtc_cntl_reg.h" #include "esp_private/regi2c_ctrl.h" #include "regi2c_brownout.h" +#include "esp_attr.h" 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; } -void brownout_hal_intr_clear(void) +IRAM_ATTR void brownout_hal_intr_clear(void) { RTCCNTL.int_clr.rtc_brown_out = 1; } diff --git a/components/hal/esp32c3/brownout_hal.c b/components/hal/esp32c3/brownout_hal.c index 7c32faaeda..ee0c7377e6 100644 --- a/components/hal/esp32c3/brownout_hal.c +++ b/components/hal/esp32c3/brownout_hal.c @@ -10,6 +10,7 @@ #include "soc/rtc_cntl_reg.h" #include "esp_private/regi2c_ctrl.h" #include "regi2c_brownout.h" +#include "esp_attr.h" 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; } -void brownout_hal_intr_clear(void) +IRAM_ATTR void brownout_hal_intr_clear(void) { RTCCNTL.int_clr.rtc_brown_out = 1; } diff --git a/components/hal/esp32h2/brownout_hal.c b/components/hal/esp32h2/brownout_hal.c index 70b55e7f55..aff79650c0 100644 --- a/components/hal/esp32h2/brownout_hal.c +++ b/components/hal/esp32h2/brownout_hal.c @@ -11,6 +11,7 @@ #include "i2c_pmu.h" #include "esp_private/regi2c_ctrl.h" #include "regi2c_brownout.h" +#include "esp_attr.h" 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; } -void brownout_hal_intr_clear(void) +IRAM_ATTR void brownout_hal_intr_clear(void) { RTCCNTL.int_clr.rtc_brown_out = 1; } diff --git a/components/hal/esp32s2/brownout_hal.c b/components/hal/esp32s2/brownout_hal.c index 3b95074ee5..04ce19f5c8 100644 --- a/components/hal/esp32s2/brownout_hal.c +++ b/components/hal/esp32s2/brownout_hal.c @@ -10,7 +10,7 @@ #include "soc/rtc_cntl_reg.h" #include "esp_private/regi2c_ctrl.h" #include "regi2c_brownout.h" - +#include "esp_attr.h" 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; } -void brownout_hal_intr_clear(void) +IRAM_ATTR void brownout_hal_intr_clear(void) { RTCCNTL.int_clr.rtc_brown_out = 1; } diff --git a/components/hal/esp32s3/brownout_hal.c b/components/hal/esp32s3/brownout_hal.c index 567adf8acc..558faac017 100644 --- a/components/hal/esp32s3/brownout_hal.c +++ b/components/hal/esp32s3/brownout_hal.c @@ -10,6 +10,7 @@ #include "soc/rtc_cntl_reg.h" #include "esp_private/regi2c_ctrl.h" #include "regi2c_brownout.h" +#include "esp_attr.h" 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; } -void brownout_hal_intr_clear(void) +IRAM_ATTR void brownout_hal_intr_clear(void) { RTCCNTL.int_clr.rtc_brown_out = 1; } diff --git a/components/hal/include/hal/brownout_hal.h b/components/hal/include/hal/brownout_hal.h index b56823b399..07952bbc65 100644 --- a/components/hal/include/hal/brownout_hal.h +++ b/components/hal/include/hal/brownout_hal.h @@ -1,16 +1,8 @@ -// 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. +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ /******************************************************************************* * NOTICE diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 38cbe76484..e957870f6c 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -127,7 +127,6 @@ #define SOC_ADC_RTC_MAX_BITWIDTH (12) #define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1) - /*-------------------------- BROWNOUT CAPS -----------------------------------*/ #if SOC_CAPS_ECO_VER >= 1 #define SOC_BROWNOUT_RESET_SUPPORTED 1 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 443c3da2f5..5e073483b0 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -3,10 +3,6 @@ # using gen_soc_caps_kconfig.py, do not edit manually ##################################################### -config SOC_BROWNOUT_RESET_SUPPORTED - bool - default y - config SOC_CPU_BREAKPOINTS_NUM int default 2 @@ -287,6 +283,10 @@ config SOC_APB_BACKUP_DMA bool default y +config SOC_BROWNOUT_RESET_SUPPORTED + bool + default y + config SOC_DS_SIGNATURE_MAX_BIT_LEN int default 4096 diff --git a/components/soc/esp32s3/include/soc/brownout_caps.h b/components/soc/esp32s3/include/soc/brownout_caps.h deleted file mode 100644 index 797d33ebb9..0000000000 --- a/components/soc/esp32s3/include/soc/brownout_caps.h +++ /dev/null @@ -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 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index bf0a452094..32804c62b3 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -100,7 +100,7 @@ #define SOC_APB_BACKUP_DMA (1) /*-------------------------- BROWNOUT CAPS -----------------------------------*/ -#include "brownout_caps.h" +#define SOC_BROWNOUT_RESET_SUPPORTED 1 /*-------------------------- CPU CAPS ----------------------------------------*/ #include "cpu_caps.h" diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index 55f6638fa0..69b95528f8 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/components/spi_flash/CMakeLists.txt @@ -25,6 +25,7 @@ else() set(srcs "partition.c" "partition_target.c" + "flash_brownout_hook.c" ) if(CONFIG_ESPTOOLPY_OCT_FLASH) diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index ba8c559b12..6bb4716299 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -209,6 +209,28 @@ menu "SPI Flash driver" 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" visible if !SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST diff --git a/components/spi_flash/flash_brownout_hook.c b/components/spi_flash/flash_brownout_hook.c new file mode 100644 index 0000000000..7d070c0b19 --- /dev/null +++ b/components/spi_flash/flash_brownout_hook.c @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#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 diff --git a/components/spi_flash/include/esp_flash.h b/components/spi_flash/include/esp_flash.h index c5adb279dc..a203fe0a09 100644 --- a/components/spi_flash/include/esp_flash.h +++ b/components/spi_flash/include/esp_flash.h @@ -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 + */ #pragma once #include "esp_err.h" @@ -80,6 +72,11 @@ typedef struct { /** Called for get system time. */ 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; /** @brief Structure to describe a SPI flash chip connected to the system. diff --git a/components/spi_flash/include/esp_private/spi_flash_os.h b/components/spi_flash/include/esp_private/spi_flash_os.h index 914ddd8e3b..d4c622bb50 100644 --- a/components/spi_flash/include/esp_private/spi_flash_os.h +++ b/components/spi_flash/include/esp_private/spi_flash_os.h @@ -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 */ @@ -101,6 +101,28 @@ bool spi_timing_is_tuned(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. * diff --git a/components/spi_flash/include/memspi_host_driver.h b/components/spi_flash/include/memspi_host_driver.h index 1c7b3cb29c..29379e21a2 100644 --- a/components/spi_flash/include/memspi_host_driver.h +++ b/components/spi_flash/include/memspi_host_driver.h @@ -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 + */ #pragma once #include "hal/spi_flash_hal.h" diff --git a/components/spi_flash/linker.lf b/components/spi_flash/linker.lf index 2e3376c88c..fa333dea61 100644 --- a/components/spi_flash/linker.lf +++ b/components/spi_flash/linker.lf @@ -9,6 +9,7 @@ entries: spi_flash_chip_boya (noflash) spi_flash_chip_th (noflash) memspi_host_driver (noflash) + flash_brownout_hook (noflash) if IDF_TARGET_ESP32S3 = y: spi_flash_timing_tuning (noflash) diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index c1173c9b83..a2d7f3fe94 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.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 @@ -20,6 +12,7 @@ #include "hal/spi_flash_encrypt_hal.h" #include "esp_log.h" #include "esp_attr.h" +#include "esp_private/spi_flash_os.h" typedef struct flash_chip_dummy { 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, }; +#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"; #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. 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->busy = 1; #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 err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->chip_erase_timeout); #endif + SET_FLASH_ERASE_STATUS(chip, 0); } // Ensure WEL is 0, even if the erase failed. 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. 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->busy = 1; #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 err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->sector_erase_timeout); #endif + SET_FLASH_ERASE_STATUS(chip, 0); } // Ensure WEL is 0, even if the erase failed. 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. 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->busy = 1; #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 err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->block_erase_timeout); #endif + SET_FLASH_ERASE_STATUS(chip, 0); } // Ensure WEL is 0, even if the erase failed. if (err == ESP_ERR_NOT_SUPPORTED) { diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index 94a2e5089c..f5642d4ec1 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/components/spi_flash/spi_flash_os_func_app.c @@ -18,6 +18,7 @@ #include "esp_log.h" #include "esp_compiler.h" #include "esp_rom_sys.h" +#include "esp_private/spi_flash_os.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 = {}; //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, .check_yield = spi1_flash_os_check_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 = { @@ -208,6 +221,7 @@ static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = { .region_protected = NULL, .check_yield = NULL, .yield = NULL, + .set_flash_op_status = NULL, }; static bool use_bus_lock(int host_id) diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 01d5f74b45..591a0e0e2b 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -775,7 +775,6 @@ components/hal/aes_hal.c components/hal/cpu_hal.c components/hal/dac_hal.c components/hal/ds_hal.c -components/hal/esp32/brownout_hal.c components/hal/esp32/gpio_hal_workaround.c components/hal/esp32/include/hal/aes_ll.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/include/hal/aes_hal.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/dac_hal.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/soc_include_legacy_warn.c 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_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_driver.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/spi_flash_chip_boya.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_mxic.c components/spi_flash/spi_flash_chip_mxic_opi.c