Merge branch 'bugfix/lock_up_if_supply_is_varying' into 'master'
bootloader_support: Fix enable wdt for resolve issue with varying supply See merge request idf/esp-idf!2769
This commit is contained in:
commit
49656656c3
8 changed files with 110 additions and 3 deletions
|
@ -127,6 +127,38 @@ config BOOTLOADER_HOLD_TIME_GPIO
|
||||||
The GPIO must be held low continuously for this period of time after reset
|
The GPIO must be held low continuously for this period of time after reset
|
||||||
before a factory reset or test partition boot (as applicable) is performed.
|
before a factory reset or test partition boot (as applicable) is performed.
|
||||||
|
|
||||||
|
config BOOTLOADER_WDT_ENABLE
|
||||||
|
bool "Use RTC watchdog in start code"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Tracks the execution time of startup code.
|
||||||
|
If the execution time is exceeded, the RTC_WDT will restart system.
|
||||||
|
It is also useful to prevent a lock up in start code caused by an unstable power source.
|
||||||
|
NOTE: Tracks the execution time starts from the bootloader code - re-set timeout, while selecting the source for slow_clk - and ends calling app_main.
|
||||||
|
Re-set timeout is needed due to WDT uses a SLOW_CLK clock source. After changing a frequency slow_clk a time of WDT needs to re-set for new frequency.
|
||||||
|
slow_clk depends on ESP32_RTC_CLOCK_SOURCE (INTERNAL_RC or EXTERNAL_CRYSTAL).
|
||||||
|
|
||||||
|
config BOOTLOADER_WDT_DISABLE_IN_USER_CODE
|
||||||
|
bool "Allows RTC watchdog disable in user code"
|
||||||
|
depends on BOOTLOADER_WDT_ENABLE
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
If it is set, the client must itself reset or disable rtc_wdt in their code (app_main()).
|
||||||
|
Otherwise rtc_wdt will be disabled before calling app_main function.
|
||||||
|
Use function rtc_wdt_feed() for resetting counter of rtc_wdt.
|
||||||
|
Use function rtc_wdt_disable() for disabling rtc_wdt.
|
||||||
|
|
||||||
|
config BOOTLOADER_WDT_TIME_MS
|
||||||
|
int "Timeout for RTC watchdog (ms)"
|
||||||
|
depends on BOOTLOADER_WDT_ENABLE
|
||||||
|
default 9000
|
||||||
|
range 0 120000
|
||||||
|
help
|
||||||
|
Verify that this parameter is correct and more then the execution time.
|
||||||
|
Pay attention to options such as reset to factory, trigger test partition and encryption on boot
|
||||||
|
- these options can increase the execution time.
|
||||||
|
Note: RTC_WDT will reset while encryption operations will be performed.
|
||||||
|
|
||||||
endmenu # Bootloader
|
endmenu # Bootloader
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,8 @@ static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_e
|
||||||
* @note Take care not to power off the device while this function
|
* @note Take care not to power off the device while this function
|
||||||
* is running, or the partition currently being encrypted will be lost.
|
* is running, or the partition currently being encrypted will be lost.
|
||||||
*
|
*
|
||||||
|
* @note RTC_WDT will reset while encryption operations will be performed (if RTC_WDT is configured).
|
||||||
|
*
|
||||||
* @return ESP_OK if all operations succeeded, ESP_ERR_INVALID_STATE
|
* @return ESP_OK if all operations succeeded, ESP_ERR_INVALID_STATE
|
||||||
* if a fatal error occured during encryption of all partitions.
|
* if a fatal error occured during encryption of all partitions.
|
||||||
*/
|
*/
|
||||||
|
@ -91,6 +93,7 @@ esp_err_t esp_flash_encrypt_check_and_update(void);
|
||||||
|
|
||||||
/** @brief Encrypt-in-place a block of flash sectors
|
/** @brief Encrypt-in-place a block of flash sectors
|
||||||
*
|
*
|
||||||
|
* @note This function resets RTC_WDT between operations with sectors.
|
||||||
* @param src_addr Source offset in flash. Should be multiple of 4096 bytes.
|
* @param src_addr Source offset in flash. Should be multiple of 4096 bytes.
|
||||||
* @param data_length Length of data to encrypt in bytes. Will be rounded up to next multiple of 4096 bytes.
|
* @param data_length Length of data to encrypt in bytes. Will be rounded up to next multiple of 4096 bytes.
|
||||||
*
|
*
|
||||||
|
|
|
@ -143,8 +143,21 @@ static esp_err_t bootloader_main()
|
||||||
ESP_LOGI(TAG, "compile time " __TIME__ );
|
ESP_LOGI(TAG, "compile time " __TIME__ );
|
||||||
ets_set_appcpu_boot_addr(0);
|
ets_set_appcpu_boot_addr(0);
|
||||||
|
|
||||||
|
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||||
|
ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||||
|
rtc_wdt_protect_off();
|
||||||
|
rtc_wdt_disable();
|
||||||
|
rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
|
||||||
|
rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_3_2us);
|
||||||
|
rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_RTC);
|
||||||
|
rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||||
|
rtc_wdt_enable();
|
||||||
|
rtc_wdt_protect_on();
|
||||||
|
#else
|
||||||
/* disable watch dog here */
|
/* disable watch dog here */
|
||||||
rtc_wdt_disable();
|
rtc_wdt_disable();
|
||||||
|
#endif
|
||||||
|
REG_SET_FIELD(TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY, TIMG_WDT_WKEY_VALUE);
|
||||||
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
||||||
|
|
||||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "rom/secure_boot.h"
|
#include "rom/secure_boot.h"
|
||||||
|
#include "soc/rtc_wdt.h"
|
||||||
|
|
||||||
#include "rom/cache.h"
|
#include "rom/cache.h"
|
||||||
#include "rom/spi_flash.h" /* TODO: Remove this */
|
#include "rom/spi_flash.h" /* TODO: Remove this */
|
||||||
|
@ -317,6 +318,7 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
|
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
|
||||||
|
rtc_wdt_feed();
|
||||||
uint32_t sec_start = i + src_addr;
|
uint32_t sec_start = i + src_addr;
|
||||||
err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
|
err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "rom/rtc.h"
|
#include "rom/rtc.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
|
#include "soc/rtc_wdt.h"
|
||||||
#include "soc/rtc_cntl_reg.h"
|
#include "soc/rtc_cntl_reg.h"
|
||||||
#include "soc/i2s_reg.h"
|
#include "soc/i2s_reg.h"
|
||||||
#include "driver/periph_ctrl.h"
|
#include "driver/periph_ctrl.h"
|
||||||
|
@ -87,6 +88,18 @@ void esp_clk_init(void)
|
||||||
|
|
||||||
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
|
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
|
||||||
|
|
||||||
|
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||||
|
// WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
|
||||||
|
// If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times.
|
||||||
|
// Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
|
||||||
|
// This prevents excessive delay before resetting in case the supply voltage is drawdown.
|
||||||
|
// (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec).
|
||||||
|
rtc_wdt_protect_off();
|
||||||
|
rtc_wdt_feed();
|
||||||
|
rtc_wdt_set_time(RTC_WDT_STAGE0, 1600);
|
||||||
|
rtc_wdt_protect_on();
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL)
|
#if defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL)
|
||||||
select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
|
select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
|
||||||
#elif defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC)
|
#elif defined(CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC)
|
||||||
|
@ -97,6 +110,14 @@ void esp_clk_init(void)
|
||||||
select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
|
select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||||
|
// After changing a frequency WDT timeout needs to be set for new frequency.
|
||||||
|
rtc_wdt_protect_off();
|
||||||
|
rtc_wdt_feed();
|
||||||
|
rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||||
|
rtc_wdt_protect_on();
|
||||||
|
#endif
|
||||||
|
|
||||||
rtc_cpu_freq_config_t old_config, new_config;
|
rtc_cpu_freq_config_t old_config, new_config;
|
||||||
rtc_clk_cpu_freq_get_config(&old_config);
|
rtc_clk_cpu_freq_get_config(&old_config);
|
||||||
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
||||||
|
|
|
@ -137,7 +137,9 @@ void IRAM_ATTR call_start_cpu0()
|
||||||
|| rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET
|
|| rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
|
#ifndef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||||
rtc_wdt_disable();
|
rtc_wdt_disable();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this.
|
//Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this.
|
||||||
|
@ -427,9 +429,6 @@ static void do_global_ctors(void)
|
||||||
|
|
||||||
static void main_task(void* args)
|
static void main_task(void* args)
|
||||||
{
|
{
|
||||||
// Now that the application is about to start, disable boot watchdogs
|
|
||||||
REG_CLR_BIT(TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN_S);
|
|
||||||
rtc_wdt_disable();
|
|
||||||
#if !CONFIG_FREERTOS_UNICORE
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
// Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
|
// Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
|
||||||
while (port_xSchedulerRunning[1] == 0) {
|
while (port_xSchedulerRunning[1] == 0) {
|
||||||
|
@ -470,6 +469,10 @@ static void main_task(void* args)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Now that the application is about to start, disable boot watchdog
|
||||||
|
#ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
|
||||||
|
rtc_wdt_disable();
|
||||||
|
#endif
|
||||||
app_main();
|
app_main();
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,27 @@ esp_err_t rtc_wdt_set_time(rtc_wdt_stage_t stage, unsigned int timeout_ms)
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t rtc_wdt_get_timeout(rtc_wdt_stage_t stage, unsigned int* timeout_ms)
|
||||||
|
{
|
||||||
|
if (stage > 3) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
uint32_t time_tick;
|
||||||
|
if (stage == RTC_WDT_STAGE0) {
|
||||||
|
time_tick = READ_PERI_REG(RTC_CNTL_WDTCONFIG1_REG);
|
||||||
|
} else if (stage == RTC_WDT_STAGE1) {
|
||||||
|
time_tick = READ_PERI_REG(RTC_CNTL_WDTCONFIG2_REG);
|
||||||
|
} else if (stage == RTC_WDT_STAGE2) {
|
||||||
|
time_tick = READ_PERI_REG(RTC_CNTL_WDTCONFIG3_REG);
|
||||||
|
} else {
|
||||||
|
time_tick = READ_PERI_REG(RTC_CNTL_WDTCONFIG4_REG);
|
||||||
|
}
|
||||||
|
|
||||||
|
*timeout_ms = time_tick * 1000 / rtc_clk_slow_freq_get_hz();
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t rtc_wdt_set_stage(rtc_wdt_stage_t stage, rtc_wdt_stage_action_t stage_sel)
|
esp_err_t rtc_wdt_set_stage(rtc_wdt_stage_t stage, rtc_wdt_stage_action_t stage_sel)
|
||||||
{
|
{
|
||||||
if (stage > 3 || stage_sel > 4) {
|
if (stage > 3 || stage_sel > 4) {
|
||||||
|
|
|
@ -142,6 +142,18 @@ void rtc_wdt_feed();
|
||||||
*/
|
*/
|
||||||
esp_err_t rtc_wdt_set_time(rtc_wdt_stage_t stage, unsigned int timeout_ms);
|
esp_err_t rtc_wdt_set_time(rtc_wdt_stage_t stage, unsigned int timeout_ms);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the timeout set for the required stage.
|
||||||
|
*
|
||||||
|
* @param[in] stage Stage of rtc_wdt.
|
||||||
|
* @param[out] timeout_ms Timeout set for this stage. (not elapsed time).
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK In case of success
|
||||||
|
* - ESP_ERR_INVALID_ARG If stage has invalid value
|
||||||
|
*/
|
||||||
|
esp_err_t rtc_wdt_get_timeout(rtc_wdt_stage_t stage, unsigned int* timeout_ms);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set an action for required stage.
|
* @brief Set an action for required stage.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue