Merge branch 'feature/support_refresh_brownout_v1' into 'master'

spi_flash: send reset when brownout detected on XMC flash

Closes IDF-3882

See merge request espressif/esp-idf!16873
This commit is contained in:
Michael (XIAO Xufeng)
2022-06-06 16:27:58 +08:00
36 changed files with 362 additions and 150 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

@@ -70,13 +70,13 @@ static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, t
esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use) esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
{ {
ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG, "Touch_Pad ISR null"); ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG, "Touch_Pad ISR null");
return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M); return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M, 0);
} }
esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg) esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg)
{ {
ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG, "Touch_Pad ISR null"); ESP_RETURN_ON_FALSE(fn, ESP_ERR_INVALID_ARG, TOUCH_TAG, "Touch_Pad ISR null");
return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M); return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M, 0);
} }
static uint32_t _touch_filter_iir(uint32_t in_now, uint32_t out_last, uint32_t k) static uint32_t _touch_filter_iir(uint32_t in_now, uint32_t out_last, uint32_t k)

View File

@@ -106,10 +106,10 @@ esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_ma
en_msk |= RTC_CNTL_TOUCH_APPROACH_LOOP_DONE_INT_ST_M; en_msk |= RTC_CNTL_TOUCH_APPROACH_LOOP_DONE_INT_ST_M;
} }
#endif #endif
esp_err_t ret = rtc_isr_register(fn, arg, en_msk); esp_err_t ret = rtc_isr_register(fn, arg, en_msk, 0);
/* Must ensure: After being registered, it is executed first. */ /* Must ensure: After being registered, it is executed first. */
if ( (ret == ESP_OK) && (reg_flag == false) && (intr_mask & (TOUCH_PAD_INTR_MASK_SCAN_DONE | TOUCH_PAD_INTR_MASK_TIMEOUT)) ) { if ( (ret == ESP_OK) && (reg_flag == false) && (intr_mask & (TOUCH_PAD_INTR_MASK_SCAN_DONE | TOUCH_PAD_INTR_MASK_TIMEOUT)) ) {
rtc_isr_register(touch_pad_workaround_isr_internal, NULL, RTC_CNTL_TOUCH_SCAN_DONE_INT_ST_M | RTC_CNTL_TOUCH_TIMEOUT_INT_ST_M); rtc_isr_register(touch_pad_workaround_isr_internal, NULL, RTC_CNTL_TOUCH_SCAN_DONE_INT_ST_M | RTC_CNTL_TOUCH_TIMEOUT_INT_ST_M, 0);
reg_flag = true; reg_flag = true;
} }

View File

@@ -85,7 +85,7 @@ esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_ma
en_msk |= RTC_CNTL_TOUCH_APPROACH_LOOP_DONE_INT_ST_M; en_msk |= RTC_CNTL_TOUCH_APPROACH_LOOP_DONE_INT_ST_M;
} }
#endif #endif
esp_err_t ret = rtc_isr_register(fn, arg, en_msk); esp_err_t ret = rtc_isr_register(fn, arg, en_msk, 0);
return ret; return ret;
} }

View File

@@ -14,6 +14,8 @@
extern "C" { extern "C" {
#endif #endif
#define RTC_INTR_FLAG_IRAM (BIT(0)) /*< Some rtc interrupts can be called with cache disabled */
/** /**
* @brief Register a handler for specific RTC_CNTL interrupts * @brief Register a handler for specific RTC_CNTL interrupts
* *
@@ -25,13 +27,17 @@ extern "C" {
* @param handler_arg argument to be passed to the handler * @param handler_arg argument to be passed to the handler
* @param rtc_intr_mask combination of RTC_CNTL_*_INT_ENA bits indicating the * @param rtc_intr_mask combination of RTC_CNTL_*_INT_ENA bits indicating the
* sources to call the handler for * sources to call the handler for
* @param flags An ORred mask of the RTC_INTR_FLAG_* defines. You can pass different
* flags to it to realize different purpose. If 0, the interrupt will
* not handle anything special. If you pass `RTC_INTR_FLAG_IRAM`, means
* the interrupt can be triggered with cache disabled.
* @return * @return
* - ESP_OK on success * - ESP_OK on success
* - ESP_ERR_NO_MEM not enough memory to allocate handler structure * - ESP_ERR_NO_MEM not enough memory to allocate handler structure
* - other errors returned by esp_intr_alloc * - other errors returned by esp_intr_alloc
*/ */
esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg,
uint32_t rtc_intr_mask); uint32_t rtc_intr_mask, uint32_t flags);
/** /**
* @brief Deregister the handler previously registered using rtc_isr_register * @brief Deregister the handler previously registered using rtc_isr_register
* @param handler handler function to call (as passed to rtc_isr_register) * @param handler handler function to call (as passed to rtc_isr_register)
@@ -43,6 +49,24 @@ esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg,
*/ */
esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg); esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg);
/**
* @brief Disable the RTC interrupt that is allowed to be executed when cache is disabled.
* cache disabled. Internal interrupt handle function will call this function in interrupt
* handler function. Disable bits when `esp_intr_noniram_disable` is called.
*
* @param cpu CPU number.
*/
void rtc_isr_noniram_disable(uint32_t cpu);
/**
* @brief Enable the RTC interrupt that is allowed to be executed when cache is disabled.
* cache disabled. Internal interrupt handle function will call this function in interrupt
* handler function. Enable bits when `esp_intr_noniram_enable` is called.
*
* @param cpu CPU number.
*/
void rtc_isr_noniram_enable(uint32_t cpu);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -20,6 +20,7 @@
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "hal/cpu_hal.h" #include "hal/cpu_hal.h"
#include "esp_private/rtc_ctrl.h"
#include "hal/interrupt_controller_hal.h" #include "hal/interrupt_controller_hal.h"
#if !CONFIG_FREERTOS_UNICORE #if !CONFIG_FREERTOS_UNICORE
@@ -797,6 +798,8 @@ void IRAM_ATTR esp_intr_noniram_disable(void)
non_iram_int_disabled_flag[cpu] = true; non_iram_int_disabled_flag[cpu] = true;
oldint = interrupt_controller_hal_read_interrupt_mask(); oldint = interrupt_controller_hal_read_interrupt_mask();
interrupt_controller_hal_disable_interrupts(non_iram_ints); interrupt_controller_hal_disable_interrupts(non_iram_ints);
// Disable the RTC bit which don't want to be put in IRAM.
rtc_isr_noniram_disable(cpu);
// Save disabled ints // Save disabled ints
non_iram_int_disabled[cpu] = oldint & non_iram_ints; non_iram_int_disabled[cpu] = oldint & non_iram_ints;
portEXIT_CRITICAL_SAFE(&spinlock); portEXIT_CRITICAL_SAFE(&spinlock);
@@ -812,6 +815,7 @@ void IRAM_ATTR esp_intr_noniram_enable(void)
} }
non_iram_int_disabled_flag[cpu] = false; non_iram_int_disabled_flag[cpu] = false;
interrupt_controller_hal_enable_interrupts(non_iram_ints); interrupt_controller_hal_enable_interrupts(non_iram_ints);
rtc_isr_noniram_enable(cpu);
portEXIT_CRITICAL_SAFE(&spinlock); portEXIT_CRITICAL_SAFE(&spinlock);
} }

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

@@ -19,6 +19,7 @@
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "sys/lock.h" #include "sys/lock.h"
#include "esp_private/rtc_ctrl.h" #include "esp_private/rtc_ctrl.h"
#include "esp_attr.h"
#ifndef NDEBUG #ifndef NDEBUG
// Enable built-in checks in queue.h in debug builds // Enable built-in checks in queue.h in debug builds
@@ -26,7 +27,15 @@
#endif #endif
#include "sys/queue.h" #include "sys/queue.h"
#define NOT_REGISTERED (-1)
portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED; portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
// Disable the interrupt which cannot work without cache.
static DRAM_ATTR uint32_t rtc_intr_cache;
static DRAM_ATTR uint32_t rtc_intr_enabled;
static DRAM_ATTR int rtc_isr_cpu = NOT_REGISTERED; // Unused number
static void s_rtc_isr_noniram_hook(uint32_t rtc_intr_mask);
static void s_rtc_isr_noniram_hook_relieve(uint32_t rtc_intr_mask);
/*--------------------------------------------------------------- /*---------------------------------------------------------------
INTERRUPT HANDLER INTERRUPT HANDLER
@@ -37,15 +46,16 @@ typedef struct rtc_isr_handler_ {
uint32_t mask; uint32_t mask;
intr_handler_t handler; intr_handler_t handler;
void* handler_arg; void* handler_arg;
uint32_t flags;
SLIST_ENTRY(rtc_isr_handler_) next; SLIST_ENTRY(rtc_isr_handler_) next;
} rtc_isr_handler_t; } rtc_isr_handler_t;
static SLIST_HEAD(rtc_isr_handler_list_, rtc_isr_handler_) s_rtc_isr_handler_list = static DRAM_ATTR SLIST_HEAD(rtc_isr_handler_list_, rtc_isr_handler_) s_rtc_isr_handler_list =
SLIST_HEAD_INITIALIZER(s_rtc_isr_handler_list); SLIST_HEAD_INITIALIZER(s_rtc_isr_handler_list);
portMUX_TYPE s_rtc_isr_handler_list_lock = portMUX_INITIALIZER_UNLOCKED; static DRAM_ATTR portMUX_TYPE s_rtc_isr_handler_list_lock = portMUX_INITIALIZER_UNLOCKED;
static intr_handle_t s_rtc_isr_handle; static intr_handle_t s_rtc_isr_handle;
static void rtc_isr(void* arg) IRAM_ATTR static void rtc_isr(void* arg)
{ {
uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG); uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG);
rtc_isr_handler_t* it; rtc_isr_handler_t* it;
@@ -71,32 +81,37 @@ static esp_err_t rtc_isr_ensure_installed(void)
REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_ENA_REG, 0);
REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX);
err = esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, 0, &rtc_isr, NULL, &s_rtc_isr_handle); err = esp_intr_alloc(ETS_RTC_CORE_INTR_SOURCE, ESP_INTR_FLAG_IRAM, &rtc_isr, NULL, &s_rtc_isr_handle);
if (err != ESP_OK) { if (err != ESP_OK) {
goto out; goto out;
} }
rtc_isr_cpu = esp_intr_get_cpu(s_rtc_isr_handle);
out: out:
portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock); portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
return err; return err;
} }
esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t rtc_intr_mask, uint32_t flags)
esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t rtc_intr_mask)
{ {
esp_err_t err = rtc_isr_ensure_installed(); esp_err_t err = rtc_isr_ensure_installed();
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
rtc_isr_handler_t* item = malloc(sizeof(*item)); rtc_isr_handler_t* item = heap_caps_malloc(sizeof(*item), MALLOC_CAP_INTERNAL);
if (item == NULL) { if (item == NULL) {
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
item->handler = handler; item->handler = handler;
item->handler_arg = handler_arg; item->handler_arg = handler_arg;
item->mask = rtc_intr_mask; item->mask = rtc_intr_mask;
item->flags = flags;
portENTER_CRITICAL(&s_rtc_isr_handler_list_lock); portENTER_CRITICAL(&s_rtc_isr_handler_list_lock);
if (flags & RTC_INTR_FLAG_IRAM) {
s_rtc_isr_noniram_hook(rtc_intr_mask);
} else {
s_rtc_isr_noniram_hook_relieve(rtc_intr_mask);
}
SLIST_INSERT_HEAD(&s_rtc_isr_handler_list, item, next); SLIST_INSERT_HEAD(&s_rtc_isr_handler_list, item, next);
portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock); portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
return ESP_OK; return ESP_OK;
@@ -116,6 +131,9 @@ esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
SLIST_REMOVE_AFTER(prev, next); SLIST_REMOVE_AFTER(prev, next);
} }
found = true; found = true;
if (it->flags & RTC_INTR_FLAG_IRAM) {
s_rtc_isr_noniram_hook_relieve(it->mask);
}
free(it); free(it);
break; break;
} }
@@ -124,3 +142,37 @@ esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock); portEXIT_CRITICAL(&s_rtc_isr_handler_list_lock);
return found ? ESP_OK : ESP_ERR_INVALID_STATE; return found ? ESP_OK : ESP_ERR_INVALID_STATE;
} }
/**
* @brief This helper function can be used to avoid the interrupt to be triggered with cache disabled.
* There are lots of different signals on RTC module (i.e. sleep_wakeup, wdt, brownout_detect, etc.)
* We might want some of them can be triggered with cache disabled, some are not. Therefore, this function
* is created to avoid those which do not want to be triggered with cache disabled.
*
* @param rtc_intr_mask the mask of the rtc interrupt.
*/
static void s_rtc_isr_noniram_hook(uint32_t rtc_intr_mask)
{
rtc_intr_cache |= rtc_intr_mask;
}
static void s_rtc_isr_noniram_hook_relieve(uint32_t rtc_intr_mask)
{
rtc_intr_cache &= ~rtc_intr_mask;
}
IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu)
{
if (rtc_isr_cpu == cpu) {
rtc_intr_enabled |= RTCCNTL.int_ena.val;
RTCCNTL.int_ena.val &= rtc_intr_cache;
}
}
IRAM_ATTR void rtc_isr_noniram_enable(uint32_t cpu)
{
if (rtc_isr_cpu == cpu) {
RTCCNTL.int_ena.val = rtc_intr_enabled;
rtc_intr_enabled = 0;
}
}

View File

@@ -533,6 +533,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

@@ -62,7 +62,7 @@ esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg)
xt_wdt_hal_enable_backup_clk(&s_hal_ctx, rtc_clk_frequency_khz); xt_wdt_hal_enable_backup_clk(&s_hal_ctx, rtc_clk_frequency_khz);
} }
ESP_GOTO_ON_ERROR(rtc_isr_register(rtc_xt_wdt_default_isr_handler, NULL, XT_WDT_LL_XTAL32_DEAD_INTR_MASK), err, TAG, "Failed to register isr"); ESP_GOTO_ON_ERROR(rtc_isr_register(rtc_xt_wdt_default_isr_handler, NULL, XT_WDT_LL_XTAL32_DEAD_INTR_MASK, 0), err, TAG, "Failed to register isr");
xt_wdt_hal_enable(&s_hal_ctx, 1); xt_wdt_hal_enable(&s_hal_ctx, 1);

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

@@ -126,7 +126,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
@@ -283,6 +279,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

@@ -99,7 +99,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

@@ -774,7 +774,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
@@ -858,7 +857,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
@@ -1530,10 +1528,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
@@ -1547,7 +1543,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

View File

@@ -1,4 +1,5 @@
# This config is split between targets since different component needs to be included (esp32, esp32s2) # This config is split between targets since different component needs to be included (esp32, esp32s2)
# IRAM is full... split some component to default_32_2
CONFIG_IDF_TARGET="esp32" CONFIG_IDF_TARGET="esp32"
TEST_COMPONENTS=freertos esp_hw_support esp_ipc esp_system esp_timer driver heap pthread soc spi_flash vfs TEST_COMPONENTS=freertos esp_hw_support esp_ipc esp_system esp_timer driver heap
CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y

View File

@@ -0,0 +1,4 @@
# continue from default
CONFIG_IDF_TARGET="esp32"
TEST_COMPONENTS=pthread soc spi_flash vfs
CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y