mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
WDT: Add support for XTAL32K Watchdog timer
This commit is contained in:
parent
375145ecdb
commit
4869b3cd4a
@ -646,6 +646,7 @@ menu "ESP32-specific"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config ESP32_RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XN pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config ESP32_RTC_CLK_SRC_INT_8MD256
|
||||
bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
|
||||
endchoice
|
||||
|
@ -157,6 +157,7 @@ menu "ESP32C3-Specific"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config ESP32C3_RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XP pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config ESP32C3_RTC_CLK_SRC_INT_8MD256
|
||||
bool "Internal 8MHz oscillator, divided by 256 (~32kHz)"
|
||||
endchoice
|
||||
|
@ -150,6 +150,7 @@ menu "ESP32H2-Specific"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config ESP32H2_RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XP pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config ESP32H2_RTC_CLK_SRC_INT_8MD256
|
||||
bool "Internal 8MHz oscillator, divided by 256 (~32kHz)"
|
||||
endchoice
|
||||
|
@ -382,6 +382,7 @@ menu "ESP32S2-specific"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config ESP32S2_RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XN pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config ESP32S2_RTC_CLK_SRC_INT_8MD256
|
||||
bool "Internal 8MHz oscillator, divided by 256 (~32kHz)"
|
||||
endchoice
|
||||
|
@ -430,6 +430,7 @@ menu "ESP32S3-Specific"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config ESP32S3_RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XP pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config ESP32S3_RTC_CLK_SRC_INT_8MD256
|
||||
bool "Internal 8MHz oscillator, divided by 256 (~32kHz)"
|
||||
endchoice
|
||||
|
@ -43,7 +43,11 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
} else if (slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
} else if (cal_clk == RTC_CAL_INTERNAL_OSC) {
|
||||
cal_clk = RTC_CAL_RTC_MUX;
|
||||
}
|
||||
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
|
||||
|
@ -141,7 +141,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles, ui
|
||||
} else if (slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
} else if (cal_clk == RTC_CAL_INTERNAL_OSC) {
|
||||
cal_clk = RTC_CAL_RTC_MUX;
|
||||
}
|
||||
|
||||
/* Enable requested clock (90k clock is always on) */
|
||||
int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
|
||||
|
@ -42,7 +42,10 @@ uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
} else if (slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
cal_clk = RTC_CAL_8MD256;
|
||||
}
|
||||
} else if (cal_clk == RTC_CAL_INTERNAL_OSC) {
|
||||
cal_clk = RTC_CAL_RTC_MUX;
|
||||
}
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
|
||||
|
@ -21,7 +21,8 @@ else()
|
||||
"system_time.c"
|
||||
"stack_check.c"
|
||||
"task_wdt.c"
|
||||
"ubsan.c")
|
||||
"ubsan.c"
|
||||
"xt_wdt.c")
|
||||
|
||||
if(NOT (${target} STREQUAL "esp32c3") AND NOT (${target} STREQUAL "esp32h2"))
|
||||
list(APPEND srcs "dbg_stubs.c")
|
||||
|
@ -53,6 +53,12 @@ menu "ESP System Settings"
|
||||
bool
|
||||
default n
|
||||
|
||||
config ESP_SYSTEM_RTC_EXT_OSC
|
||||
# This is a High Layer Kconfig option, invisible, can be selected by other Kconfig option
|
||||
# e.g. It will be selected on when ESPX_RTC_CLK_SRC_EXT_OSC is on
|
||||
bool
|
||||
default n
|
||||
|
||||
config ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES
|
||||
int "Bootstrap cycles for external 32kHz crystal"
|
||||
depends on ESP_SYSTEM_RTC_EXT_XTAL
|
||||
@ -389,6 +395,31 @@ menu "ESP System Settings"
|
||||
If this option is enabled, the Task Wtachdog Timer will wach the CPU1
|
||||
Idle Task.
|
||||
|
||||
config ESP_XT_WDT
|
||||
bool "Initialize XTAL32K watchdog timer on startup"
|
||||
depends on !IDF_TARGET_ESP32 && (ESP_SYSTEM_RTC_EXT_OSC || ESP_SYSTEM_RTC_EXT_XTAL)
|
||||
default n
|
||||
help
|
||||
This watchdog timer can detect oscillation failure of the XTAL32K_CLK. When such a failure
|
||||
is detected the hardware can be set up to automatically switch to BACKUP32K_CLK and generate
|
||||
an interrupt.
|
||||
|
||||
config ESP_XT_WDT_TIMEOUT
|
||||
int "XTAL32K watchdog timeout period"
|
||||
depends on ESP_XT_WDT
|
||||
range 1 255
|
||||
default 200
|
||||
help
|
||||
Timeout period configuration for the XTAL32K watchdog timer based on RTC_CLK.
|
||||
|
||||
config ESP_XT_WDT_BACKUP_CLK_ENABLE
|
||||
bool "Automatically switch to BACKUP32K_CLK when timer expires"
|
||||
depends on ESP_XT_WDT
|
||||
default y
|
||||
help
|
||||
Enable this to automatically switch to BACKUP32K_CLK as the source of RTC_SLOW_CLK when
|
||||
the watchdog timer expires.
|
||||
|
||||
config ESP_PANIC_HANDLER_IRAM
|
||||
bool "Place panic handler code in IRAM"
|
||||
default n
|
||||
|
63
components/esp_system/include/esp_xt_wdt.h
Normal file
63
components/esp_system/include/esp_xt_wdt.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief esp_xt_wdt configuration struct
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t timeout; /*!< Watchdog timeout */
|
||||
bool auto_backup_clk_enable; /*!< Enable automatic switch to backup clock at timeout */
|
||||
} esp_xt_wdt_config_t;
|
||||
|
||||
/* Callback function for WDT interrupt*/
|
||||
typedef void (*esp_xt_callback_t)(void *arg);
|
||||
|
||||
/**
|
||||
* @brief Initializes the xtal32k watchdog timer
|
||||
*
|
||||
* @param cfg Pointer to configuration struct
|
||||
* @return esp_err_t
|
||||
* - ESP_OK: XTWDT was successfully enabled
|
||||
* - ESP_ERR_NO_MEM: Failed to allocate ISR
|
||||
*/
|
||||
esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Register a callback function that will be called when the watchdog
|
||||
* times out.
|
||||
*
|
||||
* @note This function will be called from an interrupt context where the cache might be disabled.
|
||||
* Thus the function should be placed in IRAM and must not perform any blocking operations.
|
||||
*
|
||||
* Only one callback function can be registered, any call to esp_xt_wdt_register_callback
|
||||
* will override the previous callback function.
|
||||
*
|
||||
* @param func The callback function to register
|
||||
* @param arg Pointer to argument that will be passed to the callback function
|
||||
*/
|
||||
void esp_xt_wdt_register_callback(esp_xt_callback_t func, void *arg);
|
||||
|
||||
/**
|
||||
* @brief Restores the xtal32k clock and re-enables the WDT
|
||||
*
|
||||
*/
|
||||
void esp_xt_wdt_restore_clk(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -41,6 +41,7 @@
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_xt_wdt.h"
|
||||
|
||||
/***********************************************/
|
||||
// Headers for other components init functions
|
||||
@ -344,6 +345,15 @@ static void do_core_init(void)
|
||||
// Note: in some configs this may read flash, so placed after flash init
|
||||
esp_secure_boot_init_checks();
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_XT_WDT
|
||||
esp_xt_wdt_config_t cfg = {
|
||||
.timeout = CONFIG_ESP_XT_WDT_TIMEOUT,
|
||||
.auto_backup_clk_enable = CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE,
|
||||
};
|
||||
err = esp_xt_wdt_init(&cfg);
|
||||
assert(err == ESP_OK && "Failed to init xtwdt");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void do_secondary_init(void)
|
||||
|
95
components/esp_system/xt_wdt.c
Normal file
95
components/esp_system/xt_wdt.c
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_xt_wdt.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#if SOC_XT_WDT_SUPPORTED
|
||||
|
||||
#include "driver/rtc_cntl.h"
|
||||
#include "hal/xt_wdt_hal.h"
|
||||
#include "hal/xt_wdt_ll.h"
|
||||
#include "soc/rtc.h"
|
||||
|
||||
#define RTC_CLK_CAL_CYCLES 500
|
||||
|
||||
const static char *TAG = "esp_xt_wdt";
|
||||
|
||||
static xt_wdt_hal_context_t s_hal_ctx;
|
||||
|
||||
static esp_xt_callback_t s_callback_func;
|
||||
static void *s_callback_arg;
|
||||
|
||||
portMUX_TYPE s_xt_wdt_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
static IRAM_ATTR void rtc_xt_wdt_default_isr_handler(void *arg)
|
||||
{
|
||||
ESP_EARLY_LOGE(TAG, "XTAL32K watchdog timer got triggered");
|
||||
|
||||
portENTER_CRITICAL_ISR(&s_xt_wdt_lock);
|
||||
if (s_callback_func) {
|
||||
(*s_callback_func)(s_callback_arg);
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&s_xt_wdt_lock);
|
||||
}
|
||||
|
||||
esp_err_t esp_xt_wdt_init(const esp_xt_wdt_config_t *cfg)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
xt_wdt_hal_config_t hal_config = {
|
||||
.timeout = cfg->timeout,
|
||||
};
|
||||
|
||||
xt_wdt_hal_init(&s_hal_ctx, &hal_config);
|
||||
|
||||
if (cfg->auto_backup_clk_enable) {
|
||||
/* Estimate frequency of internal RTC oscillator */
|
||||
uint32_t rtc_clk_frequency_khz = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_INTERNAL_OSC, RTC_CLK_CAL_CYCLES)) / 1000;
|
||||
ESP_LOGD(TAG, "Calibrating backup clock from rtc clock with frequency %d", 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");
|
||||
|
||||
xt_wdt_hal_enable(&s_hal_ctx, 1);
|
||||
|
||||
return ESP_OK;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void esp_xt_wdt_restore_clk(void)
|
||||
{
|
||||
xt_wdt_hal_enable(&s_hal_ctx, false);
|
||||
|
||||
REG_CLR_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
|
||||
REG_SET_BIT(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
|
||||
|
||||
/* Needs some time after switching to 32khz XTAL before turning on WDT again */
|
||||
esp_rom_delay_us(300);
|
||||
|
||||
xt_wdt_hal_enable(&s_hal_ctx, true);
|
||||
}
|
||||
|
||||
void esp_xt_wdt_register_callback(esp_xt_callback_t func, void *arg)
|
||||
{
|
||||
portENTER_CRITICAL(&s_xt_wdt_lock);
|
||||
s_callback_func = func;
|
||||
s_callback_arg = arg;
|
||||
portEXIT_CRITICAL(&s_xt_wdt_lock);
|
||||
}
|
||||
|
||||
#endif //SOC_XT_WDT_SUPPORTED
|
@ -61,6 +61,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"systimer_hal.c"
|
||||
"touch_sensor_hal.c"
|
||||
"usb_hal.c"
|
||||
"xt_wdt_hal.c"
|
||||
"esp32s2/adc_hal.c"
|
||||
"esp32s2/brownout_hal.c"
|
||||
"esp32s2/cp_dma_hal.c"
|
||||
@ -81,6 +82,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"systimer_hal.c"
|
||||
"touch_sensor_hal.c"
|
||||
"usb_hal.c"
|
||||
"xt_wdt_hal.c"
|
||||
"esp32s3/brownout_hal.c"
|
||||
"esp32s3/hmac_hal.c"
|
||||
"esp32s3/interrupt_descriptor_table.c"
|
||||
@ -95,6 +97,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"spi_flash_hal_gpspi.c"
|
||||
"spi_slave_hd_hal.c"
|
||||
"systimer_hal.c"
|
||||
"xt_wdt_hal.c"
|
||||
"esp32c3/adc_hal.c"
|
||||
"esp32c3/brownout_hal.c"
|
||||
"esp32c3/hmac_hal.c"
|
||||
|
@ -2,7 +2,7 @@ COMPONENT_SRCDIRS := . esp32
|
||||
COMPONENT_ADD_INCLUDEDIRS := esp32/include include platform_port/include
|
||||
COMPONENT_ADD_LDFRAGMENTS += linker.lf
|
||||
|
||||
COMPONENT_OBJEXCLUDE += ./spi_slave_hd_hal.o ./spi_flash_hal_gpspi.o ./spi_slave_hd_hal.o ./ds_hal.o ./gdma_hal.o ./lcd_hal.o ./systimer_hal.o ./usb_hal.o ./usbh_hal.o
|
||||
COMPONENT_OBJEXCLUDE += ./spi_slave_hd_hal.o ./spi_flash_hal_gpspi.o ./spi_slave_hd_hal.o ./ds_hal.o ./gdma_hal.o ./lcd_hal.o ./systimer_hal.o ./usb_hal.o ./usbh_hal.o ./xt_wdt_hal.o
|
||||
|
||||
ifndef CONFIG_ETH_USE_ESP32_EMAC
|
||||
COMPONENT_OBJEXCLUDE += ./emac_hal.o
|
||||
|
101
components/hal/esp32c3/include/hal/xt_wdt_ll.h
Normal file
101
components/hal/esp32c3/include/hal/xt_wdt_ll.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for xtal32k WDT register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "soc/rtc_cntl_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M
|
||||
|
||||
/**
|
||||
* @brief Enable the XT_WDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_wdt_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the XT_WDT is enabled
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @return True if XT WDT is enabled
|
||||
*/
|
||||
inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the watchdog timeout value
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param timeout timeout value in RTC_CLK cycles
|
||||
*/
|
||||
inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout)
|
||||
{
|
||||
hw->xtal32k_conf.xtal32k_wdt_timeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reset the XT_WDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_wdt_reset = 1;
|
||||
hw->ext_xtl_conf.xtal32k_wdt_reset = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the backup clock value
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param backup_clk_val Backup clock value, see TRM for definition
|
||||
*/
|
||||
inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val)
|
||||
{
|
||||
hw->xtal32k_clk_factor = backup_clk_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the auto-backup clock feature
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True - enable, False - disable
|
||||
*/
|
||||
inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_auto_backup = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the timeout interrupt
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True - enable, False - disable
|
||||
*/
|
||||
inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->int_ena.rtc_xtal32k_dead = enable;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
101
components/hal/esp32s2/include/hal/xt_wdt_ll.h
Normal file
101
components/hal/esp32s2/include/hal/xt_wdt_ll.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for xtal32k WDT register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "soc/rtc_cntl_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M
|
||||
|
||||
/**
|
||||
* @brief Enable the XT_WDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_wdt_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the XT_WDT is enabled
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @return True if XT WDT is enabled
|
||||
*/
|
||||
inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the watchdog timeout value
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param timeout timeout value in RTC_CLK cycles
|
||||
*/
|
||||
inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout)
|
||||
{
|
||||
hw->xtal32k_conf.xtal32k_wdt_timeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reset the XT_WDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_wdt_reset = 1;
|
||||
hw->ext_xtl_conf.xtal32k_wdt_reset = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the backup clock value
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param backup_clk_val Backup clock value, see TRM for definition
|
||||
*/
|
||||
inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val)
|
||||
{
|
||||
hw->xtal32k_clk_factor = backup_clk_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the auto-backup clock feature
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True - enable, False - disable
|
||||
*/
|
||||
inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_auto_backup = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the timeout interrupt
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True - enable, False - disable
|
||||
*/
|
||||
inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->int_ena.rtc_xtal32k_dead = enable;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
101
components/hal/esp32s3/include/hal/xt_wdt_ll.h
Normal file
101
components/hal/esp32s3/include/hal/xt_wdt_ll.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
// The LL layer for xtal32k WDT register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "soc/rtc_cntl_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XT_WDT_LL_XTAL32_DEAD_INTR_MASK RTC_CNTL_XTAL32K_DEAD_INT_ST_M
|
||||
|
||||
/**
|
||||
* @brief Enable the XT_WDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
inline void xt_wdt_ll_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_wdt_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the XT_WDT is enabled
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @return True if XT WDT is enabled
|
||||
*/
|
||||
inline bool xt_wdt_ll_check_if_enabled(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
return (hw->ext_xtl_conf.xtal32k_wdt_en) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the watchdog timeout value
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param timeout timeout value in RTC_CLK cycles
|
||||
*/
|
||||
inline void xt_wdt_ll_set_timeout(rtc_cntl_dev_t *hw, uint8_t timeout)
|
||||
{
|
||||
hw->xtal32k_conf.xtal32k_wdt_timeout = timeout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reset the XT_WDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
inline void xt_wdt_ll_reset(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_wdt_reset = 1;
|
||||
hw->ext_xtl_conf.xtal32k_wdt_reset = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the backup clock value
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param backup_clk_val Backup clock value, see TRM for definition
|
||||
*/
|
||||
inline void xt_wdt_ll_set_backup_clk_factor(rtc_cntl_dev_t *hw, uint32_t backup_clk_val)
|
||||
{
|
||||
hw->xtal32k_clk_factor = backup_clk_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the auto-backup clock feature
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True - enable, False - disable
|
||||
*/
|
||||
inline void xt_wdt_ll_auto_backup_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->ext_xtl_conf.xtal32k_auto_backup = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the timeout interrupt
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True - enable, False - disable
|
||||
*/
|
||||
inline void xt_wdt_ll_intr_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->int_ena.rtc_xtal32k_dead = enable;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
61
components/hal/include/hal/xt_wdt_hal.h
Normal file
61
components/hal/include/hal/xt_wdt_hal.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hal/xt_wdt_ll.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
rtc_cntl_dev_t *dev; /* Pointer to the RTC register struct */
|
||||
} xt_wdt_hal_context_t; /* HAL context struct */
|
||||
|
||||
typedef struct {
|
||||
uint32_t timeout; /* Watchdog timer timeout in RTC_CLK cycles*/
|
||||
} xt_wdt_hal_config_t; /* HAL config parameter struct */
|
||||
|
||||
/* ---------------------------- Init and Config ----------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Initialize the WDTs associated HAL context
|
||||
*
|
||||
* Prepares the register for enabling the WDT and sets the timeout value
|
||||
*
|
||||
* @param hal Pointer to the HAL layer context
|
||||
* @param config Pointer to config struct
|
||||
*/
|
||||
void xt_wdt_hal_init(xt_wdt_hal_context_t *hal, const xt_wdt_hal_config_t *config);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the WDT
|
||||
*
|
||||
* @param hal Pointer to the HAL layer context
|
||||
* @param enable true for enable WDT, false for disable
|
||||
*/
|
||||
void xt_wdt_hal_enable(xt_wdt_hal_context_t *hal, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Enable the automatic RTC backup clock with the given frequency
|
||||
*
|
||||
* Calculates and sets the necessary hardware parameters to meet the desired
|
||||
* backup clock frequency
|
||||
*
|
||||
* @param hal Pointer to the HAL layer context
|
||||
* @param rtc_clk_frequency_khz desired frequency for the backup clock
|
||||
* @return uint32_t the calculated clock factor value
|
||||
*/
|
||||
uint32_t xt_wdt_hal_enable_backup_clk(xt_wdt_hal_context_t *hal, uint32_t rtc_clk_frequency_khz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
78
components/hal/xt_wdt_hal.c
Normal file
78
components/hal/xt_wdt_hal.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#include "hal/xt_wdt_hal.h"
|
||||
#include "hal/xt_wdt_ll.h"
|
||||
#include "hal/assert.h"
|
||||
|
||||
#define DIV_COMP_N_MAX 8
|
||||
|
||||
static uint32_t xt_wdt_hal_calculate(uint32_t rtc_clk_frequency_khz)
|
||||
{
|
||||
uint32_t xtal32k_clk_factor = 0;
|
||||
uint8_t divisor_comps[DIV_COMP_N_MAX];
|
||||
|
||||
/* From the TRM:
|
||||
|
||||
Define the frequency of RTC_CLK as f_rtc_clk (unit: kHz), and the eight divisor components as
|
||||
x0, x1, x2, x3, x4, x5, x6, and x7, respectively. S = x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7.
|
||||
The following conditions should be fulfilled:
|
||||
S = f_rtc_clk * (4/32)
|
||||
M + 1 >= xn >= M(0 <= n <= 7)
|
||||
M = f_rtc_clk/32/2
|
||||
xn should be an integer. M and S are rounded up or down. Each divisor component (x0 ~x7) is 4-bit long, and
|
||||
corresponds to the value of RTC_CNTL_XTAL32K_CLK_FACTOR (32-bit) in order.
|
||||
*/
|
||||
|
||||
uint8_t M = ((rtc_clk_frequency_khz / 32) / 2);
|
||||
uint32_t S = ((4 * rtc_clk_frequency_khz) / 32);
|
||||
|
||||
memset(divisor_comps, M, DIV_COMP_N_MAX);
|
||||
|
||||
/* Calculate how far we are away from satisfying S = SUM(x_n) */
|
||||
uint8_t off = S - DIV_COMP_N_MAX * M;
|
||||
|
||||
/* Offset should never be this big */
|
||||
HAL_ASSERT(off <= DIV_COMP_N_MAX);
|
||||
|
||||
for (int i = 0; i < DIV_COMP_N_MAX; i++) {
|
||||
if (off) {
|
||||
divisor_comps[i]++;
|
||||
off--;
|
||||
}
|
||||
/* Sum up all divisors */
|
||||
xtal32k_clk_factor |= (divisor_comps[i] << 4 * i);
|
||||
}
|
||||
|
||||
return xtal32k_clk_factor;
|
||||
}
|
||||
|
||||
void xt_wdt_hal_init(xt_wdt_hal_context_t *hal, const xt_wdt_hal_config_t *config)
|
||||
{
|
||||
hal->dev = &RTCCNTL;
|
||||
|
||||
xt_wdt_ll_enable(hal->dev, false);
|
||||
xt_wdt_ll_set_timeout(hal->dev, config->timeout);
|
||||
}
|
||||
|
||||
uint32_t xt_wdt_hal_enable_backup_clk(xt_wdt_hal_context_t *hal, uint32_t rtc_clk_frequency_khz)
|
||||
{
|
||||
uint32_t xtal32k_clk_factor = xt_wdt_hal_calculate(rtc_clk_frequency_khz);
|
||||
|
||||
xt_wdt_ll_set_backup_clk_factor(hal->dev, xtal32k_clk_factor);
|
||||
xt_wdt_ll_auto_backup_enable(hal->dev, true);
|
||||
|
||||
return xtal32k_clk_factor;
|
||||
}
|
||||
|
||||
void xt_wdt_hal_enable(xt_wdt_hal_context_t *hal, bool enable)
|
||||
{
|
||||
xt_wdt_ll_enable(hal->dev, enable);
|
||||
xt_wdt_ll_intr_enable(hal->dev, enable);
|
||||
}
|
@ -206,7 +206,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL
|
||||
RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL
|
||||
RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator
|
||||
} rtc_cal_sel_t;
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,8 @@
|
||||
#define SOC_USB_SERIAL_JTAG_SUPPORTED 1
|
||||
#define SOC_TEMP_SENSOR_SUPPORTED 1
|
||||
#define SOC_FLASH_ENCRYPTION_XTS_AES 1
|
||||
#define SOC_XT_WDT_SUPPORTED 1
|
||||
|
||||
|
||||
/*-------------------------- COMMON CAPS ---------------------------------------*/
|
||||
#define SOC_SUPPORTS_SECURE_DL_MODE 1
|
||||
|
@ -215,7 +215,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL
|
||||
RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL
|
||||
RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator
|
||||
} rtc_cal_sel_t;
|
||||
|
||||
/**
|
||||
|
@ -59,6 +59,7 @@
|
||||
#define SOC_FLASH_ENCRYPTION_XTS_AES 1
|
||||
#define SOC_FLASH_ENCRYPTION_XTS_AES_256 1
|
||||
#define SOC_PSRAM_DMA_CAPABLE 1
|
||||
#define SOC_XT_WDT_SUPPORTED 1
|
||||
|
||||
/*-------------------------- ADC CAPS ----------------------------------------*/
|
||||
#define SOC_ADC_PERIPH_NUM (2)
|
||||
|
@ -202,7 +202,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = 0, //!< Currently selected RTC SLOW_CLK
|
||||
RTC_CAL_8MD256 = 1, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
RTC_CAL_32K_XTAL = 2 //!< External 32 kHz XTAL
|
||||
RTC_CAL_32K_XTAL = 2, //!< External 32 kHz XTAL
|
||||
RTC_CAL_INTERNAL_OSC = 3 //!< Internal 150 kHz oscillator
|
||||
} rtc_cal_sel_t;
|
||||
|
||||
/**
|
||||
|
@ -28,6 +28,8 @@
|
||||
#define SOC_FLASH_ENCRYPTION_XTS_AES 1
|
||||
#define SOC_FLASH_ENCRYPTION_XTS_AES_256 1
|
||||
#define SOC_PSRAM_DMA_CAPABLE 1
|
||||
#define SOC_XT_WDT_SUPPORTED 1
|
||||
|
||||
|
||||
/*-------------------------- SOC CAPS ----------------------------------------*/
|
||||
#define SOC_APPCPU_HAS_CLOCK_GATING_BUG (1)
|
||||
|
@ -4,7 +4,7 @@ Watchdogs
|
||||
Overview
|
||||
--------
|
||||
|
||||
The ESP-IDF has support for two types of watchdogs: The Interrupt Watchdog Timer
|
||||
The ESP-IDF has support for multiple types of watchdogs, with the two main ones being: The Interrupt Watchdog Timer
|
||||
and the Task Watchdog Timer (TWDT). The Interrupt Watchdog Timer and the TWDT
|
||||
can both be enabled using :ref:`project-configuration-menu`, however the TWDT can also be
|
||||
enabled during runtime. The Interrupt Watchdog is responsible for detecting
|
||||
@ -101,13 +101,13 @@ timeout at runtime by calling :cpp:func:`esp_task_wdt_init`.
|
||||
|
||||
The following config options control TWDT configuration at startup. They are all enabled by default:
|
||||
|
||||
{IDF_TARGET_IDLE_TASK:default="Idle task", esp32="CPU0 Idle task"}
|
||||
{IDF_TARGET_IDLE_TASK:default="Idle task", esp32="CPU0 Idle task", esp32s3="CPU0 Idle task"}
|
||||
|
||||
.. list::
|
||||
|
||||
- :ref:`CONFIG_ESP_TASK_WDT` - the TWDT is initialized automatically during startup. If this option is disabled, it is still possible to initialize the Task WDT at runtime by calling :cpp:func:`esp_task_wdt_init`.
|
||||
- :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0` - {IDF_TARGET_IDLE_TASK} is subscribed to the TWDT during startup. If this option is disabled, it is still possible to subscribe the idle task by calling :cpp:func:`esp_task_wdt_add` at any time.
|
||||
:esp32: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 Idle task is subscribed to the TWDT during startup.
|
||||
:not CONFIG_FREERTOS_UNICORE: - :ref:`CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1` - CPU1 Idle task is subscribed to the TWDT during startup.
|
||||
|
||||
|
||||
JTAG and watchdogs
|
||||
@ -124,6 +124,26 @@ panics from either watchdogs will be generated when the {IDF_TARGET_NAME} is con
|
||||
OpenOCD via JTAG.
|
||||
|
||||
|
||||
.. only:: SOC_XT_WDT_SUPPORTED
|
||||
|
||||
XTAL32K Watchdog Timer (XTWDT)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The XTAL32K watchdog makes sure the (optional) external 32 KHz crystal or oscillator is functioning correctly.
|
||||
|
||||
When `XTAL32K_CLK` works as the clock source of `RTC_SLOW_CLK` and stops oscillating, the XTAL32K watchdog timer will detect this and generate an interrupt.
|
||||
It also provides functionality for automatically switching over to the internal, but less accurate oscillator as the `RTC_SLOW_CLK` source.
|
||||
|
||||
Since the switch to the backup clock is done in hardware it can also happen during deep sleep. This means that even if `XTAL32K_CLK` stops functioning while the chip in deep sleep, waiting for a timer to expire, it will still be able to wake-up as planned.
|
||||
|
||||
If the `XTAL32K_CLK` starts functioning normally again, you can call `esp_xt_wdt_restore_clk` to switch back to this clock source and re-enable the watchdog timer.
|
||||
|
||||
Configuration
|
||||
@@@@@@@@@@@@@
|
||||
|
||||
When the external 32KHz crystal or oscillator is selected (:ref:`CONFIG_{IDF_TARGET_CFG_PREFIX}_RTC_CLK_SRC`) the XTAL32K watchdog can be enabled via the :ref:`CONFIG_ESP_XT_WDT` configuration
|
||||
flag. The timeout is configured by setting :ref:`CONFIG_ESP_XT_WDT_TIMEOUT`. The automatic backup clock functionality is enabled via the ref:`CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE` configuration.
|
||||
|
||||
Interrupt Watchdog API Reference
|
||||
--------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user