Skip to content

Commit 6a2d350

Browse files
committed
spi_flash: Making XMC flash works more stable when brownout detected
1 parent 890f046 commit 6a2d350

File tree

27 files changed

+259
-132
lines changed

27 files changed

+259
-132
lines changed

components/bootloader_support/bootloader_flash/include/bootloader_flash.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ esp_err_t bootloader_flash_xmc_startup(void);
4949
*/
5050
esp_err_t __attribute__((weak)) bootloader_flash_unlock(void);
5151

52+
/**
53+
* @brief Reset the flash chip (66H + 99H).
54+
*
55+
* @return ESP_OK if success, otherwise ESP_FAIL.
56+
*/
57+
esp_err_t bootloader_flash_reset_chip(void);
5258

5359
#ifdef __cplusplus
5460
}

components/bootloader_support/bootloader_flash/src/bootloader_flash.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,3 +730,44 @@ esp_err_t IRAM_ATTR bootloader_flash_xmc_startup(void)
730730
}
731731

732732
#endif //XMC_SUPPORT
733+
734+
FORCE_INLINE_ATTR void bootloader_mspi_reset(void)
735+
{
736+
#if CONFIG_IDF_TARGET_ESP32
737+
SPI1.slave.sync_reset = 0;
738+
SPI0.slave.sync_reset = 0;
739+
SPI1.slave.sync_reset = 1;
740+
SPI0.slave.sync_reset = 1;
741+
SPI1.slave.sync_reset = 0;
742+
SPI0.slave.sync_reset = 0;
743+
#else
744+
SPIMEM1.ctrl2.sync_reset = 0;
745+
SPIMEM0.ctrl2.sync_reset = 0;
746+
SPIMEM1.ctrl2.sync_reset = 1;
747+
SPIMEM0.ctrl2.sync_reset = 1;
748+
SPIMEM1.ctrl2.sync_reset = 0;
749+
SPIMEM0.ctrl2.sync_reset = 0;
750+
#endif
751+
}
752+
753+
esp_err_t IRAM_ATTR bootloader_flash_reset_chip(void)
754+
{
755+
bootloader_mspi_reset();
756+
// Seems that sync_reset cannot make host totally idle.'
757+
// Sending an extra(useless) command to make the host idle in order to send reset command.
758+
bootloader_execute_flash_command(0x05, 0, 0, 0);
759+
#if CONFIG_IDF_TARGET_ESP32
760+
if (SPI1.ext2.st != 0)
761+
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
762+
if (SPIMEM1.fsm.st != 0)
763+
#else
764+
if (SPIMEM1.fsm.spi0_mst_st != 0)
765+
#endif
766+
{
767+
return ESP_FAIL;
768+
}
769+
bootloader_execute_flash_command(0x66, 0, 0, 0);
770+
bootloader_execute_flash_command(0x99, 0, 0, 0);
771+
772+
return ESP_OK;
773+
}

components/esp_hw_support/port/esp32/Kconfig.hw_support

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ choice ESP32_REV_MIN
77

88
config ESP32_REV_MIN_0
99
bool "Rev 0"
10+
# Brownout on Rev 0 is bugged, must use interrupt
11+
select ESP_SYSTEM_BROWNOUT_INTR
1012
config ESP32_REV_MIN_1
1113
bool "Rev 1"
1214
config ESP32_REV_MIN_2

components/esp_system/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,18 @@ menu "ESP System Settings"
531531
# Insert chip-specific system config
532532
rsource "./port/soc/$IDF_TARGET/Kconfig.system"
533533

534+
config ESP_SYSTEM_BROWNOUT_INTR
535+
bool
536+
default n
537+
help
538+
This config allows to trigger an interrupt when brownout detected. Software restart will be done
539+
at the end of the default callback.
540+
Two occasions need to restart the chip with interrupt so far.
541+
(1). For ESP32 version 1, brown-out reset function doesn't work (see ESP32 errata 3.4).
542+
So that we must restart from interrupt.
543+
(2). For special workflow, the chip needs do more things instead of restarting directly. This part
544+
needs to be done in callback function of interrupt.
545+
534546
endmenu # ESP System Settings
535547

536548
menu "IPC (Inter-Processor Call)"

components/esp_system/port/brownout.c

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111

1212
#include "esp_private/system_internal.h"
1313
#include "esp_private/rtc_ctrl.h"
14+
#include "esp_private/spi_flash_os.h"
1415

1516
#include "esp_rom_sys.h"
1617

1718
#include "soc/soc.h"
1819
#include "esp_cpu.h"
1920
#include "soc/rtc_periph.h"
2021
#include "hal/cpu_hal.h"
22+
#include "esp_attr.h"
23+
#include "bootloader_flash.h"
24+
#include "esp_intr_alloc.h"
2125

2226
#include "hal/brownout_hal.h"
2327

@@ -29,48 +33,58 @@
2933
#define BROWNOUT_DET_LVL 0
3034
#endif
3135

32-
#if SOC_BROWNOUT_RESET_SUPPORTED
33-
#define BROWNOUT_RESET_EN true
34-
#else
35-
#define BROWNOUT_RESET_EN false
36-
#endif // SOC_BROWNOUT_RESET_SUPPORTED
37-
38-
#ifndef SOC_BROWNOUT_RESET_SUPPORTED
39-
static void rtc_brownout_isr_handler(void *arg)
36+
#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
37+
IRAM_ATTR static void rtc_brownout_isr_handler(void *arg)
4038
{
4139
/* Normally RTC ISR clears the interrupt flag after the application-supplied
4240
* handler returns. Since restart is called here, the flag needs to be
4341
* cleared manually.
4442
*/
4543
brownout_hal_intr_clear();
46-
/* Stall the other CPU to make sure the code running there doesn't use UART
47-
* at the same time as the following esp_rom_printf.
48-
*/
44+
// Stop the other core.
4945
esp_cpu_stall(!cpu_hal_get_core_id());
5046
esp_reset_reason_set_hint(ESP_RST_BROWNOUT);
51-
esp_rom_printf("\r\nBrownout detector was triggered\r\n\r\n");
47+
#if CONFIG_SPI_FLASH_BROWNOUT_RESET
48+
if (spi_flash_brownout_need_reset()) {
49+
bootloader_flash_reset_chip();
50+
} else
51+
#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET
52+
{
53+
esp_rom_printf("\r\nBrownout detector was triggered\r\n\r\n");
54+
}
55+
5256
esp_restart_noos();
5357
}
54-
#endif // not SOC_BROWNOUT_RESET_SUPPORTED
58+
#endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR
5559

5660
void esp_brownout_init(void)
5761
{
62+
#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
5863
brownout_hal_config_t cfg = {
5964
.threshold = BROWNOUT_DET_LVL,
6065
.enabled = true,
61-
.reset_enabled = BROWNOUT_RESET_EN,
66+
.reset_enabled = false,
6267
.flash_power_down = true,
6368
.rf_power_down = true,
6469
};
6570

6671
brownout_hal_config(&cfg);
72+
brownout_hal_intr_clear();
73+
rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M, RTC_INTR_FLAG_IRAM);
74+
brownout_hal_intr_enable(true);
6775

76+
#else // brownout without interrupt
6877

69-
#ifndef SOC_BROWNOUT_RESET_SUPPORTED
70-
rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M);
78+
brownout_hal_config_t cfg = {
79+
.threshold = BROWNOUT_DET_LVL,
80+
.enabled = true,
81+
.reset_enabled = true,
82+
.flash_power_down = true,
83+
.rf_power_down = true,
84+
};
7185

72-
brownout_hal_intr_enable(true);
73-
#endif // not SOC_BROWNOUT_RESET_SUPPORTED
86+
brownout_hal_config(&cfg);
87+
#endif
7488
}
7589

7690
void esp_brownout_disable(void)
@@ -80,10 +94,8 @@ void esp_brownout_disable(void)
8094
};
8195

8296
brownout_hal_config(&cfg);
83-
84-
#ifndef SOC_BROWNOUT_RESET_SUPPORTED
97+
#if CONFIG_ESP_SYSTEM_BROWNOUT_INTR
8598
brownout_hal_intr_enable(false);
86-
8799
rtc_isr_deregister(rtc_brownout_isr_handler, NULL);
88-
#endif // not SOC_BROWNOUT_RESET_SUPPORTED
100+
#endif // CONFIG_ESP_SYSTEM_BROWNOUT_INTR
89101
}

components/esp_system/startup.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666

6767
#include "esp_pthread.h"
6868
#include "esp_private/esp_clk.h"
69-
69+
#include "esp_private/spi_flash_os.h"
7070
#include "esp_private/brownout.h"
7171

7272
#include "esp_rom_sys.h"
@@ -301,6 +301,9 @@ static void do_core_init(void)
301301
esp_err_t flash_ret = esp_flash_init_default_chip();
302302
assert(flash_ret == ESP_OK);
303303
(void)flash_ret;
304+
#if CONFIG_SPI_FLASH_BROWNOUT_RESET
305+
spi_flash_needs_reset_check();
306+
#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET
304307

305308
#ifdef CONFIG_EFUSE_VIRTUAL
306309
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!");

components/hal/esp32/brownout_hal.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11

2-
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
3-
//
4-
// Licensed under the Apache License, Version 2.0 (the "License");
5-
// you may not use this file except in compliance with the License.
6-
// You may obtain a copy of the License at
7-
//
8-
// http://www.apache.org/licenses/LICENSE-2.0
9-
//
10-
// Unless required by applicable law or agreed to in writing, software
11-
// distributed under the License is distributed on an "AS IS" BASIS,
12-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
// See the License for the specific language governing permissions and
14-
// limitations under the License.
2+
/*
3+
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
4+
*
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
157

168
#include "hal/brownout_hal.h"
179
#include "soc/rtc_cntl_struct.h"
10+
#include "esp_attr.h"
1811

1912
void brownout_hal_config(const brownout_hal_config_t *cfg)
2013
{
@@ -35,7 +28,7 @@ void brownout_hal_intr_enable(bool enable)
3528
RTCCNTL.int_ena.rtc_brown_out = enable;
3629
}
3730

38-
void brownout_hal_intr_clear(void)
31+
IRAM_ATTR void brownout_hal_intr_clear(void)
3932
{
4033
RTCCNTL.int_clr.rtc_brown_out = 1;
4134
}

components/hal/esp32c2/brownout_hal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "soc/rtc_cntl_reg.h"
1111
#include "esp_private/regi2c_ctrl.h"
1212
#include "regi2c_brownout.h"
13+
#include "esp_attr.h"
1314

1415

1516
void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -31,7 +32,7 @@ void brownout_hal_intr_enable(bool enable)
3132
RTCCNTL.int_ena.rtc_brown_out = enable;
3233
}
3334

34-
void brownout_hal_intr_clear(void)
35+
IRAM_ATTR void brownout_hal_intr_clear(void)
3536
{
3637
RTCCNTL.int_clr.rtc_brown_out = 1;
3738
}

components/hal/esp32c3/brownout_hal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "soc/rtc_cntl_reg.h"
1111
#include "esp_private/regi2c_ctrl.h"
1212
#include "regi2c_brownout.h"
13+
#include "esp_attr.h"
1314

1415

1516
void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -31,7 +32,7 @@ void brownout_hal_intr_enable(bool enable)
3132
RTCCNTL.int_ena.rtc_brown_out = enable;
3233
}
3334

34-
void brownout_hal_intr_clear(void)
35+
IRAM_ATTR void brownout_hal_intr_clear(void)
3536
{
3637
RTCCNTL.int_clr.rtc_brown_out = 1;
3738
}

components/hal/esp32h2/brownout_hal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "i2c_pmu.h"
1212
#include "esp_private/regi2c_ctrl.h"
1313
#include "regi2c_brownout.h"
14+
#include "esp_attr.h"
1415

1516

1617
void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -32,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
3233
RTCCNTL.int_ena.rtc_brown_out = enable;
3334
}
3435

35-
void brownout_hal_intr_clear(void)
36+
IRAM_ATTR void brownout_hal_intr_clear(void)
3637
{
3738
RTCCNTL.int_clr.rtc_brown_out = 1;
3839
}

components/hal/esp32s2/brownout_hal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include "soc/rtc_cntl_reg.h"
1111
#include "esp_private/regi2c_ctrl.h"
1212
#include "regi2c_brownout.h"
13-
13+
#include "esp_attr.h"
1414

1515
void brownout_hal_config(const brownout_hal_config_t *cfg)
1616
{
@@ -33,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
3333
RTCCNTL.int_ena.rtc_brown_out = enable;
3434
}
3535

36-
void brownout_hal_intr_clear(void)
36+
IRAM_ATTR void brownout_hal_intr_clear(void)
3737
{
3838
RTCCNTL.int_clr.rtc_brown_out = 1;
3939
}

components/hal/esp32s3/brownout_hal.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "soc/rtc_cntl_reg.h"
1111
#include "esp_private/regi2c_ctrl.h"
1212
#include "regi2c_brownout.h"
13+
#include "esp_attr.h"
1314

1415

1516
void brownout_hal_config(const brownout_hal_config_t *cfg)
@@ -32,7 +33,7 @@ void brownout_hal_intr_enable(bool enable)
3233
RTCCNTL.int_ena.rtc_brown_out = enable;
3334
}
3435

35-
void brownout_hal_intr_clear(void)
36+
IRAM_ATTR void brownout_hal_intr_clear(void)
3637
{
3738
RTCCNTL.int_clr.rtc_brown_out = 1;
3839
}

components/hal/include/hal/brownout_hal.h

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
1-
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2-
//
3-
// Licensed under the Apache License, Version 2.0 (the "License");
4-
// you may not use this file except in compliance with the License.
5-
// You may obtain a copy of the License at
6-
//
7-
// http://www.apache.org/licenses/LICENSE-2.0
8-
//
9-
// Unless required by applicable law or agreed to in writing, software
10-
// distributed under the License is distributed on an "AS IS" BASIS,
11-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
// See the License for the specific language governing permissions and
13-
// limitations under the License.
1+
/*
2+
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
146

157
/*******************************************************************************
168
* NOTICE

components/soc/esp32/include/soc/soc_caps.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@
127127
#define SOC_ADC_RTC_MAX_BITWIDTH (12)
128128
#define SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256 (1)
129129

130-
131130
/*-------------------------- BROWNOUT CAPS -----------------------------------*/
132131
#if SOC_CAPS_ECO_VER >= 1
133132
#define SOC_BROWNOUT_RESET_SUPPORTED 1

components/soc/esp32s3/include/soc/Kconfig.soc_caps.in

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,6 @@
33
# using gen_soc_caps_kconfig.py, do not edit manually
44
#####################################################
55

6-
config SOC_BROWNOUT_RESET_SUPPORTED
7-
bool
8-
default y
9-
106
config SOC_CPU_BREAKPOINTS_NUM
117
int
128
default 2
@@ -287,6 +283,10 @@ config SOC_APB_BACKUP_DMA
287283
bool
288284
default y
289285

286+
config SOC_BROWNOUT_RESET_SUPPORTED
287+
bool
288+
default y
289+
290290
config SOC_DS_SIGNATURE_MAX_BIT_LEN
291291
int
292292
default 4096

0 commit comments

Comments
 (0)