Merge branch 'feature/xtwdt' into 'master'

WDT: Add support for XTAL32K Watchdog timer

Closes IDF-2575

See merge request espressif/esp-idf!15000
This commit is contained in:
Marius Vikhammer
2021-09-02 02:44:47 +00:00
27 changed files with 697 additions and 9 deletions

View File

@@ -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

View File

@@ -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

View File

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

View File

@@ -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

View File

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

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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")

View File

@@ -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

View 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

View File

@@ -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)

View 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

View File

@@ -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"

View File

@@ -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

View 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

View 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

View 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

View 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

View 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);
}

View File

@@ -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;
/**

View File

@@ -14,7 +14,9 @@
#define SOC_ASYNC_MEMCPY_SUPPORTED 1
#define SOC_USB_SERIAL_JTAG_SUPPORTED 1
#define SOC_TEMP_SENSOR_SUPPORTED 1
#define SOC_FLASH_ENCRYPTION_XTS_AES 1
#define SOC_FLASH_ENCRYPTION_XTS_AES 1
#define SOC_XT_WDT_SUPPORTED 1
/*-------------------------- COMMON CAPS ---------------------------------------*/
#define SOC_SUPPORTS_SECURE_DL_MODE 1

View File

@@ -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;
/**

View File

@@ -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)

View File

@@ -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;
/**

View File

@@ -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)