xtensa/esp32s2: Add xtwdt and rwdt support
This commit is contained in:
parent
26b7de0f34
commit
c15392d9b7
@ -330,3 +330,21 @@ the ``Device Drivers -> CAN Driver Support -> CAN loopback mode`` option and run
|
|||||||
TSEG2: 4
|
TSEG2: 4
|
||||||
SJW: 3
|
SJW: 3
|
||||||
ID: 1 DLC: 1
|
ID: 1 DLC: 1
|
||||||
|
|
||||||
|
watchdog
|
||||||
|
--------
|
||||||
|
|
||||||
|
This config test the watchdog timers. It includes the 2 MWDTs,
|
||||||
|
adds driver support, registers the WDTs as devices and includes the watchdog
|
||||||
|
example.
|
||||||
|
|
||||||
|
To test it, just run the following::
|
||||||
|
|
||||||
|
nsh> wdog -i /dev/watchdogx
|
||||||
|
|
||||||
|
Where x is the watchdog instance.
|
||||||
|
|
||||||
|
To test the XTWDT(/dev/watchdog3) an interrupt handler needs to be
|
||||||
|
implemented because XTWDT does not have system reset feature. To implement
|
||||||
|
an interrupt handler `WDIOC_CAPTURE` command can be used. When interrupt
|
||||||
|
rises, XTAL32K clock can be restored with `WDIOC_RSTCLK` command.
|
||||||
|
@ -394,3 +394,8 @@ To test it, just run the following::
|
|||||||
nsh> wdog -i /dev/watchdogx
|
nsh> wdog -i /dev/watchdogx
|
||||||
|
|
||||||
Where x is the watchdog instance.
|
Where x is the watchdog instance.
|
||||||
|
|
||||||
|
To test the XTWDT(/dev/watchdog3) an interrupt handler needs to be
|
||||||
|
implemented because XTWDT does not have system reset feature. To implement
|
||||||
|
an interrupt handler `WDIOC_CAPTURE` command can be used. When interrupt
|
||||||
|
rises, XTAL32K clock can be restored with `WDIOC_RSTCLK` command.
|
||||||
|
@ -420,6 +420,28 @@ config ESP32S2_RWDT
|
|||||||
to have the RTC module reset, please, use the Timers' Module WDTs.
|
to have the RTC module reset, please, use the Timers' Module WDTs.
|
||||||
They will only reset Main System.
|
They will only reset Main System.
|
||||||
|
|
||||||
|
config ESP32S2_XTWDT
|
||||||
|
bool "XTAL32K Watchdog Timer"
|
||||||
|
depends on ESP32S2_RTC_CLK_EXT_OSC || ESP32S2_RTC_CLK_EXT_XTAL
|
||||||
|
default n
|
||||||
|
select ESP32S2_WDT
|
||||||
|
select ESP32S2_RTCIO_IRQ
|
||||||
|
---help---
|
||||||
|
Includes XTWDT. This watchdog timer monitors the status of the
|
||||||
|
external 32 kHz crystal oscillator (XTAL32K). When XTAL32K_CLK works
|
||||||
|
as the clock source of RTC_SLOW_CLK and it stops oscillating, the
|
||||||
|
XTAL32K watchdog timer first switches to BACKUP32K_CLK derived from
|
||||||
|
RC_SLOW_CLK (if ESP32S2_XTWDT_BACKUP_CLK_ENABLE) and, then, generates
|
||||||
|
an interrupt that could be captured by WDIOC_CAPTURE.
|
||||||
|
|
||||||
|
config ESP32S2_XTWDT_BACKUP_CLK_ENABLE
|
||||||
|
bool "Automatically switch to BACKUP32K_CLK when timer expires"
|
||||||
|
depends on ESP32S2_XTWDT
|
||||||
|
default y
|
||||||
|
---help---
|
||||||
|
Enable this to automatically switch to BACKUP32K_CLK as the source of
|
||||||
|
RTC_SLOW_CLK when the watchdog timer expires.
|
||||||
|
|
||||||
config ESP32S2_RTC
|
config ESP32S2_RTC
|
||||||
bool "Real Time Clock (RTC)"
|
bool "Real Time Clock (RTC)"
|
||||||
default y
|
default y
|
||||||
|
@ -131,23 +131,32 @@
|
|||||||
|
|
||||||
#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16))
|
#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16))
|
||||||
|
|
||||||
#define RTC_SLEEP_PD_DIG BIT(0) /* Deep sleep (power down digital domain) */
|
#define RTC_SLEEP_PD_DIG BIT(0) /* Deep sleep (power down
|
||||||
|
* digital domain) */
|
||||||
#define RTC_SLEEP_PD_RTC_PERIPH BIT(1) /* Power down RTC peripherals */
|
#define RTC_SLEEP_PD_RTC_PERIPH BIT(1) /* Power down RTC peripherals */
|
||||||
#define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) /* Power down RTC SLOW memory */
|
#define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) /* Power down RTC SLOW memory */
|
||||||
#define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) /* Power down RTC FAST memory */
|
#define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) /* Power down RTC FAST memory */
|
||||||
#define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) /* RTC FAST and SLOW memories are automatically powered up and down along with the CPU */
|
#define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) /* RTC FAST and SLOW memories
|
||||||
#define RTC_SLEEP_PD_VDDSDIO BIT(5) /* Power down VDDSDIO regulator */
|
* are automatically powered
|
||||||
|
* up and down along with the
|
||||||
|
* CPU */
|
||||||
|
#define RTC_SLEEP_PD_VDDSDIO BIT(5) /* Power down VDDSDIO
|
||||||
|
* regulator */
|
||||||
#define RTC_SLEEP_PD_WIFI BIT(6) /* Power down WIFI */
|
#define RTC_SLEEP_PD_WIFI BIT(6) /* Power down WIFI */
|
||||||
#define RTC_SLEEP_PD_INT_8M BIT(7) /* Power down Internal 8M oscillator */
|
#define RTC_SLEEP_PD_INT_8M BIT(7) /* Power down Internal 8M
|
||||||
|
* oscillator */
|
||||||
#define RTC_SLEEP_PD_XTAL BIT(8) /* Power down main XTAL */
|
#define RTC_SLEEP_PD_XTAL BIT(8) /* Power down main XTAL */
|
||||||
|
|
||||||
/* These flags are not power domains, but will affect some sleep parameters */
|
/* These flags are not power domains, but will affect some sleep parameters */
|
||||||
|
|
||||||
#define RTC_SLEEP_DIG_USE_8M BIT(16)
|
#define RTC_SLEEP_DIG_USE_8M BIT(16)
|
||||||
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17)
|
||||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) /* Avoid using ultra low power in deep sleep,
|
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) /* Avoid using ultra low
|
||||||
* in which RTCIO cannot be used as input,
|
* power in deep sleep, in
|
||||||
* and RTCMEM can't work under high temperature */
|
* which RTCIO cannot be used
|
||||||
|
* as input, and RTCMEM can't
|
||||||
|
* work under high
|
||||||
|
* temperature */
|
||||||
|
|
||||||
#define is_dslp(pd_flags) ((pd_flags) & RTC_SLEEP_PD_DIG)
|
#define is_dslp(pd_flags) ((pd_flags) & RTC_SLEEP_PD_DIG)
|
||||||
|
|
||||||
@ -173,14 +182,14 @@
|
|||||||
* Valid if RTC_CNTL_DBG_ATTEN is 0.
|
* Valid if RTC_CNTL_DBG_ATTEN is 0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RTC_CNTL_DBIAS_0V90 0 /* sleep dig_dbias & rtc_dbias */
|
#define RTC_CNTL_DBIAS_0V90 0 /* Sleep dig_dbias & rtc_dbias */
|
||||||
#define RTC_CNTL_DBIAS_0V95 1 /* digital voltage */
|
#define RTC_CNTL_DBIAS_0V95 1 /* Digital voltage */
|
||||||
#define RTC_CNTL_DBIAS_1V00 2
|
#define RTC_CNTL_DBIAS_1V00 2
|
||||||
#define RTC_CNTL_DBIAS_1V05 3
|
#define RTC_CNTL_DBIAS_1V05 3
|
||||||
#define RTC_CNTL_DBIAS_1V10 4
|
#define RTC_CNTL_DBIAS_1V10 4
|
||||||
#define RTC_CNTL_DBIAS_1V15 5
|
#define RTC_CNTL_DBIAS_1V15 5
|
||||||
#define RTC_CNTL_DBIAS_1V20 6
|
#define RTC_CNTL_DBIAS_1V20 6
|
||||||
#define RTC_CNTL_DBIAS_1V25 7 /* voltage is about 1.34v in fact */
|
#define RTC_CNTL_DBIAS_1V25 7 /* Voltage is about 1.34v in fact */
|
||||||
|
|
||||||
/* Default initializer for esp32s2_rtc_sleep_config_t
|
/* Default initializer for esp32s2_rtc_sleep_config_t
|
||||||
* This initializer sets all fields to "reasonable" values
|
* This initializer sets all fields to "reasonable" values
|
||||||
@ -265,10 +274,12 @@
|
|||||||
|
|
||||||
/* RTC Memory & Store Register usage */
|
/* RTC Memory & Store Register usage */
|
||||||
|
|
||||||
#define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG /* RTC_SLOW_CLK calibration value */
|
#define RTC_SLOW_CLK_CAL_REG RTC_CNTL_STORE1_REG /* RTC_SLOW_CLK
|
||||||
|
* calibration value */
|
||||||
#define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG /* Boot time, low word */
|
#define RTC_BOOT_TIME_LOW_REG RTC_CNTL_STORE2_REG /* Boot time, low word */
|
||||||
#define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG /* Boot time, high word */
|
#define RTC_BOOT_TIME_HIGH_REG RTC_CNTL_STORE3_REG /* Boot time, high word */
|
||||||
#define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG /* External XTAL frequency */
|
#define RTC_XTAL_FREQ_REG RTC_CNTL_STORE4_REG /* External XTAL
|
||||||
|
* frequency */
|
||||||
#define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG /* APB bus frequency */
|
#define RTC_APB_FREQ_REG RTC_CNTL_STORE5_REG /* APB bus frequency */
|
||||||
#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG /* FAST_RTC_MEMORY_ENTRY */
|
#define RTC_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG /* FAST_RTC_MEMORY_ENTRY */
|
||||||
#define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG
|
#define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG
|
||||||
@ -282,45 +293,63 @@
|
|||||||
|
|
||||||
struct esp32s2_rtc_priv_s
|
struct esp32s2_rtc_priv_s
|
||||||
{
|
{
|
||||||
uint32_t ck8m_wait : 8; /* Number of rtc_fast_clk cycles to wait for 8M clock to be ready */
|
uint32_t ck8m_wait : 8; /* Number of rtc_fast_clk cycles to wait
|
||||||
uint32_t xtal_wait : 8; /* Number of rtc_fast_clk cycles to wait for XTAL clock to be ready */
|
* for 8M clock to be ready */
|
||||||
uint32_t pll_wait : 8; /* Number of rtc_fast_clk cycles to wait for PLL to be ready */
|
uint32_t xtal_wait : 8; /* Number of rtc_fast_clk cycles to wait
|
||||||
uint32_t clkctl_init : 1; /* Perform clock control related initialization */
|
* for XTAL clock to be ready */
|
||||||
uint32_t pwrctl_init : 1; /* Perform power control related initialization */
|
uint32_t pll_wait : 8; /* Number of rtc_fast_clk cycles to wait
|
||||||
|
* for PLL to be ready */
|
||||||
|
uint32_t clkctl_init : 1; /* Perform clock control related
|
||||||
|
* initialization */
|
||||||
|
uint32_t pwrctl_init : 1; /* Perform power control related
|
||||||
|
* initialization */
|
||||||
uint32_t rtc_dboost_fpd : 1; /* Force power down RTC_DBOOST */
|
uint32_t rtc_dboost_fpd : 1; /* Force power down RTC_DBOOST */
|
||||||
uint32_t xtal_fpu : 1;
|
uint32_t xtal_fpu : 1;
|
||||||
uint32_t bbpll_fpu : 1;
|
uint32_t bbpll_fpu : 1;
|
||||||
uint32_t cpu_waiti_clk_gate : 1;
|
uint32_t cpu_waiti_clk_gate : 1;
|
||||||
uint32_t cali_ocode : 1; /* Calibrate Ocode to make bangap voltage more precise. */
|
uint32_t cali_ocode : 1; /* Calibrate Ocode to make bangap voltage
|
||||||
|
* more precise. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* sleep configuration for rtc_sleep_init function */
|
/* sleep configuration for rtc_sleep_init function */
|
||||||
|
|
||||||
struct esp32s2_rtc_sleep_config_s
|
struct esp32s2_rtc_sleep_config_s
|
||||||
{
|
{
|
||||||
uint32_t lslp_mem_inf_fpu : 1; /* force normal voltage in sleep mode (digital domain memory) */
|
uint32_t lslp_mem_inf_fpu : 1; /* Force normal voltage in sleep mode
|
||||||
uint32_t rtc_mem_inf_follow_cpu : 1; /* keep low voltage in sleep mode (even if ULP/touch is used) */
|
* (digital domain memory) */
|
||||||
uint32_t rtc_fastmem_pd_en : 1; /* power down RTC fast memory */
|
uint32_t rtc_mem_inf_follow_cpu : 1; /* Keep low voltage in sleep mode
|
||||||
uint32_t rtc_slowmem_pd_en : 1; /* power down RTC slow memory */
|
* (even if ULP/touch is used) */
|
||||||
uint32_t rtc_peri_pd_en : 1; /* power down RTC peripherals */
|
uint32_t rtc_fastmem_pd_en : 1; /* Power down RTC fast memory */
|
||||||
uint32_t wifi_pd_en : 1; /* power down WiFi */
|
uint32_t rtc_slowmem_pd_en : 1; /* Power down RTC slow memory */
|
||||||
|
uint32_t rtc_peri_pd_en : 1; /* Power down RTC peripherals */
|
||||||
|
uint32_t wifi_pd_en : 1; /* Power down WiFi */
|
||||||
uint32_t int_8m_pd_en : 1; /* Power down Internal 8M oscillator */
|
uint32_t int_8m_pd_en : 1; /* Power down Internal 8M oscillator */
|
||||||
uint32_t deep_slp : 1; /* power down digital domain */
|
uint32_t deep_slp : 1; /* Power down digital domain */
|
||||||
uint32_t wdt_flashboot_mod_en : 1; /* enable WDT flashboot mode */
|
uint32_t wdt_flashboot_mod_en : 1; /* Enable WDT flashboot mode */
|
||||||
uint32_t dig_dbias_wak : 3; /* set bias for digital domain, in active mode */
|
uint32_t dig_dbias_wak : 3; /* Set bias for digital domain,
|
||||||
uint32_t dig_dbias_slp : 3; /* set bias for digital domain, in sleep mode */
|
* in active mode */
|
||||||
uint32_t rtc_dbias_wak : 3; /* set bias for RTC domain, in active mode */
|
uint32_t dig_dbias_slp : 3; /* Set bias for digital domain,
|
||||||
uint32_t rtc_dbias_slp : 3; /* set bias for RTC domain, in sleep mode */
|
* in sleep mode */
|
||||||
uint32_t bias_sleep_monitor : 1; /* circuit control parameter, in monitor mode */
|
uint32_t rtc_dbias_wak : 3; /* Set bias for RTC domain,
|
||||||
uint32_t dbg_atten_slp : 4; /* voltage parameter, in sleep mode */
|
* in active mode */
|
||||||
uint32_t bias_sleep_slp : 1; /* circuit control parameter, in sleep mode */
|
uint32_t rtc_dbias_slp : 3; /* Set bias for RTC domain,
|
||||||
uint32_t pd_cur_monitor : 1; /* circuit control parameter, in monitor mode */
|
* in sleep mode */
|
||||||
uint32_t pd_cur_slp : 1; /* circuit control parameter, in sleep mode */
|
uint32_t bias_sleep_monitor : 1; /* Circuit control parameter,
|
||||||
uint32_t vddsdio_pd_en : 1; /* power down VDDSDIO regulator */
|
* in monitor mode */
|
||||||
uint32_t xtal_fpu : 1; /* keep main XTAL powered up in sleep */
|
uint32_t dbg_atten_slp : 4; /* Voltage parameter, in sleep mode */
|
||||||
uint32_t rtc_regulator_fpu : 1; /* keep rtc regulator powered up in sleep */
|
uint32_t bias_sleep_slp : 1; /* Circuit control parameter,
|
||||||
uint32_t deep_slp_reject : 1; /* enable deep sleep reject */
|
* in sleep mode */
|
||||||
uint32_t light_slp_reject : 1; /* enable light sleep reject */
|
uint32_t pd_cur_monitor : 1; /* Circuit control parameter,
|
||||||
|
* in monitor mode */
|
||||||
|
uint32_t pd_cur_slp : 1; /* Circuit control parameter,
|
||||||
|
* in sleep mode */
|
||||||
|
uint32_t vddsdio_pd_en : 1; /* Power down VDDSDIO regulator */
|
||||||
|
uint32_t xtal_fpu : 1; /* Keep main XTAL powered up in
|
||||||
|
* sleep */
|
||||||
|
uint32_t rtc_regulator_fpu : 1; /* Keep rtc regulator powered up
|
||||||
|
* in sleep */
|
||||||
|
uint32_t deep_slp_reject : 1; /* Enable deep sleep reject */
|
||||||
|
uint32_t light_slp_reject : 1; /* Enable light sleep reject */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Power down flags for rtc_sleep_pd function */
|
/* Power down flags for rtc_sleep_pd function */
|
||||||
@ -329,7 +358,8 @@ struct esp32s2_rtc_sleep_pd_config_s
|
|||||||
{
|
{
|
||||||
uint32_t dig_fpu : 1; /* Set to 1 to power down digital part in sleep */
|
uint32_t dig_fpu : 1; /* Set to 1 to power down digital part in sleep */
|
||||||
uint32_t rtc_fpu : 1; /* Set to 1 to power down RTC memories in sleep */
|
uint32_t rtc_fpu : 1; /* Set to 1 to power down RTC memories in sleep */
|
||||||
uint32_t cpu_fpu : 1; /* Set to 1 to power down digital memories and CPU in sleep */
|
uint32_t cpu_fpu : 1; /* Set to 1 to power down digital memories
|
||||||
|
* and CPU in sleep */
|
||||||
uint32_t i2s_fpu : 1; /* Set to 1 to power down I2S in sleep */
|
uint32_t i2s_fpu : 1; /* Set to 1 to power down I2S in sleep */
|
||||||
uint32_t bb_fpu : 1; /* Set to 1 to power down Wi-Fi in sleep */
|
uint32_t bb_fpu : 1; /* Set to 1 to power down Wi-Fi in sleep */
|
||||||
uint32_t nrx_fpu : 1; /* Set to 1 to power down Wi-Fi in sleep */
|
uint32_t nrx_fpu : 1; /* Set to 1 to power down Wi-Fi in sleep */
|
||||||
@ -341,7 +371,8 @@ struct alm_cbinfo_s
|
|||||||
{
|
{
|
||||||
struct rt_timer_s *alarm_hdl; /* Timer id point to here */
|
struct rt_timer_s *alarm_hdl; /* Timer id point to here */
|
||||||
volatile alm_callback_t ac_cb; /* Client callback function */
|
volatile alm_callback_t ac_cb; /* Client callback function */
|
||||||
volatile void *ac_arg; /* Argument to pass with the callback function */
|
volatile void *ac_arg; /* Argument to pass with the
|
||||||
|
* callback function */
|
||||||
uint64_t deadline_us;
|
uint64_t deadline_us;
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
};
|
};
|
||||||
@ -600,7 +631,7 @@ static uint32_t IRAM_ATTR esp32s2_rtc_clk_cal_internal(
|
|||||||
|
|
||||||
if (cal_clk == RTC_CAL_32K_XTAL || slow_freq == RTC_SLOW_FREQ_32K_XTAL)
|
if (cal_clk == RTC_CAL_32K_XTAL || slow_freq == RTC_SLOW_FREQ_32K_XTAL)
|
||||||
{
|
{
|
||||||
expected_freq = 32768; /* standard 32KHz XTAL */
|
expected_freq = 32768; /* Standard 32KHz XTAL */
|
||||||
}
|
}
|
||||||
else if (cal_clk == RTC_CAL_8MD256 || slow_freq == RTC_SLOW_FREQ_8MD256)
|
else if (cal_clk == RTC_CAL_8MD256 || slow_freq == RTC_SLOW_FREQ_8MD256)
|
||||||
{
|
{
|
||||||
@ -650,6 +681,20 @@ static uint32_t IRAM_ATTR esp32s2_rtc_clk_cal_internal(
|
|||||||
return cal_val;
|
return cal_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s2_wait_dig_dbias_valid
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Wait digtial dbias valid
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* rtc_cycles - RTC count
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
static void esp32s2_wait_dig_dbias_valid(uint64_t rtc_cycles)
|
static void esp32s2_wait_dig_dbias_valid(uint64_t rtc_cycles)
|
||||||
{
|
{
|
||||||
int slow_clk_freq = esp32s2_rtc_clk_slow_freq_get();
|
int slow_clk_freq = esp32s2_rtc_clk_slow_freq_get();
|
||||||
@ -792,7 +837,7 @@ static void IRAM_ATTR esp32s2_rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
|
|||||||
{
|
{
|
||||||
modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M, 0);
|
modifyreg32(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M, 0);
|
||||||
|
|
||||||
/* no need to wait once enabled by software */
|
/* No need to wait once enabled by software */
|
||||||
|
|
||||||
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, 1);
|
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, 1);
|
||||||
if (d256_en)
|
if (d256_en)
|
||||||
@ -1070,14 +1115,15 @@ static void esp32s2_rtc_calibrate_ocode(void)
|
|||||||
uint64_t max_delay_time_us = 10000;
|
uint64_t max_delay_time_us = 10000;
|
||||||
struct esp32s2_cpu_freq_config_s freq_config;
|
struct esp32s2_cpu_freq_config_s freq_config;
|
||||||
|
|
||||||
/* Bandgap output voltage is not precise when calibrate o-code by hardware
|
/* Band gap output voltage is sometimes not precise when calibrating
|
||||||
* sometimes, so need software o-code calibration (must turn off PLL).
|
* the o-code by hardware, so we need a software o-code calibration
|
||||||
|
* (must turn off PLL).
|
||||||
* Method:
|
* Method:
|
||||||
* 1. read current cpu config, save in old_config
|
* 1. Read current cpu config, save in old_config
|
||||||
* 2. switch cpu to xtal because PLL will be closed when o-code calibration
|
* 2. Switch cpu to xtal because PLL will be closed when o-code calibration
|
||||||
* 3. begin o-code calibration
|
* 3. Begin o-code calibration
|
||||||
* 4. wait o-code calibration done flag or timeout
|
* 4. Wait o-code calibration done flag or timeout
|
||||||
* 5. set cpu to old-config
|
* 5. Set cpu to old-config
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum esp32s2_rtc_slow_freq_e slow_clk_freq =
|
enum esp32s2_rtc_slow_freq_e slow_clk_freq =
|
||||||
@ -1129,6 +1175,20 @@ static void esp32s2_rtc_calibrate_ocode(void)
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s2_rtc_clk_slow_freq_get_hz
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get the approximate frequency of RTC_SLOW_CLK, in Hz
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* RTC_SLOW_CLK frequency, in Hz
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
static int IRAM_ATTR esp32s2_rtc_clk_slow_freq_get(void)
|
static int IRAM_ATTR esp32s2_rtc_clk_slow_freq_get(void)
|
||||||
{
|
{
|
||||||
return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
|
return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
|
||||||
@ -1224,7 +1284,7 @@ enum esp32s2_rtc_slow_freq_e IRAM_ATTR esp32s2_rtc_get_slow_clk(void)
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cal_clk - clock to be measured
|
* cal_clk - clock to be measured
|
||||||
* slowclk_cycles - number of slow clock cycles to average
|
* slowclk_cycles - number of slow clock cycles what is to be averaged
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Average slow clock period in microseconds, Q13.19 fixed point format
|
* Average slow clock period in microseconds, Q13.19 fixed point format
|
||||||
@ -1436,12 +1496,12 @@ void IRAM_ATTR esp32s2_rtc_init(void)
|
|||||||
|
|
||||||
/* Moved from rtc sleep to rtc init to save sleep function running time */
|
/* Moved from rtc sleep to rtc init to save sleep function running time */
|
||||||
|
|
||||||
/* set shortest possible sleep time limit */
|
/* Set shortest possible sleep time limit */
|
||||||
|
|
||||||
REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL,
|
REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL,
|
||||||
RTC_CNTL_MIN_SLP_VAL_MIN);
|
RTC_CNTL_MIN_SLP_VAL_MIN);
|
||||||
|
|
||||||
/* set wifi timer */
|
/* Set wifi timer */
|
||||||
|
|
||||||
REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, 1);
|
REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, 1);
|
||||||
REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, 1);
|
REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, 1);
|
||||||
@ -1455,27 +1515,27 @@ void IRAM_ATTR esp32s2_rtc_init(void)
|
|||||||
|
|
||||||
if (cfg.clkctl_init)
|
if (cfg.clkctl_init)
|
||||||
{
|
{
|
||||||
/* clear CMMU clock force on */
|
/* Clear CMMU clock force on */
|
||||||
|
|
||||||
modifyreg32(EXTMEM_PRO_CACHE_MMU_POWER_CTRL_REG,
|
modifyreg32(EXTMEM_PRO_CACHE_MMU_POWER_CTRL_REG,
|
||||||
EXTMEM_PRO_CACHE_MMU_MEM_FORCE_ON, 0);
|
EXTMEM_PRO_CACHE_MMU_MEM_FORCE_ON, 0);
|
||||||
|
|
||||||
/* clear rom clock force on */
|
/* Clear rom clock force on */
|
||||||
|
|
||||||
REG_SET_FIELD(SYSTEM_ROM_CTRL_0_REG, SYSTEM_ROM_FO, 0);
|
REG_SET_FIELD(SYSTEM_ROM_CTRL_0_REG, SYSTEM_ROM_FO, 0);
|
||||||
|
|
||||||
/* clear tag clock force on */
|
/* Clear tag clock force on */
|
||||||
|
|
||||||
REG_SET_FIELD(SYSTEM_SRAM_CTRL_0_REG, SYSTEM_SRAM_FO, 0);
|
REG_SET_FIELD(SYSTEM_SRAM_CTRL_0_REG, SYSTEM_SRAM_FO, 0);
|
||||||
|
|
||||||
/* clear tag clock force on */
|
/* Clear tag clock force on */
|
||||||
|
|
||||||
modifyreg32(EXTMEM_PRO_DCACHE_TAG_POWER_CTRL_REG,
|
modifyreg32(EXTMEM_PRO_DCACHE_TAG_POWER_CTRL_REG,
|
||||||
EXTMEM_PRO_DCACHE_TAG_MEM_FORCE_ON, 0);
|
EXTMEM_PRO_DCACHE_TAG_MEM_FORCE_ON, 0);
|
||||||
modifyreg32(EXTMEM_PRO_ICACHE_TAG_POWER_CTRL_REG,
|
modifyreg32(EXTMEM_PRO_ICACHE_TAG_POWER_CTRL_REG,
|
||||||
EXTMEM_PRO_ICACHE_TAG_MEM_FORCE_ON, 0);
|
EXTMEM_PRO_ICACHE_TAG_MEM_FORCE_ON, 0);
|
||||||
|
|
||||||
/* clear register clock force on */
|
/* Clear register clock force on */
|
||||||
|
|
||||||
modifyreg32(SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLK_EN, 0);
|
modifyreg32(SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLK_EN, 0);
|
||||||
modifyreg32(SPI_MEM_CLOCK_GATE_REG(1), SPI_MEM_CLK_EN, 0);
|
modifyreg32(SPI_MEM_CLOCK_GATE_REG(1), SPI_MEM_CLK_EN, 0);
|
||||||
@ -1540,7 +1600,7 @@ void IRAM_ATTR esp32s2_rtc_init(void)
|
|||||||
modifyreg32(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD, 0);
|
modifyreg32(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cancel digital pu force */
|
/* Cancel digital pu force */
|
||||||
|
|
||||||
modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU |
|
modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU |
|
||||||
RTC_CNTL_FASTMEM_FORCE_PU, 0);
|
RTC_CNTL_FASTMEM_FORCE_PU, 0);
|
||||||
@ -1572,7 +1632,7 @@ void IRAM_ATTR esp32s2_rtc_init(void)
|
|||||||
|
|
||||||
modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_FORCE_NOISO, 0);
|
modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_FORCE_NOISO, 0);
|
||||||
|
|
||||||
/* cancel digital PADS force no iso */
|
/* Cancel digital PADS force no iso */
|
||||||
|
|
||||||
if (cfg.cpu_waiti_clk_gate)
|
if (cfg.cpu_waiti_clk_gate)
|
||||||
{
|
{
|
||||||
@ -1753,11 +1813,39 @@ void IRAM_ATTR esp32s2_rtc_wait_for_slow_cycle(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s2_rtc_clk_apb_freq_update
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Store new APB frequency value into RTC_APB_FREQ_REG
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* apb_freq - New APB frequency, in Hz
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void esp32s2_rtc_clk_apb_freq_update(uint32_t apb_freq)
|
void esp32s2_rtc_clk_apb_freq_update(uint32_t apb_freq)
|
||||||
{
|
{
|
||||||
g_apb_freq = apb_freq;
|
g_apb_freq = apb_freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: esp32s2_rtc_clk_apb_freq_get
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get the current stored APB frequency
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* The APB frequency value, in Hz.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
uint32_t esp32s2_rtc_clk_apb_freq_get(void)
|
uint32_t esp32s2_rtc_clk_apb_freq_get(void)
|
||||||
{
|
{
|
||||||
return g_apb_freq;
|
return g_apb_freq;
|
||||||
@ -2014,7 +2102,7 @@ void IRAM_ATTR esp32s2_rtc_sleep_init(uint32_t flags)
|
|||||||
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
REG_SET_BIT(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enable VDDSDIO control by state machine */
|
/* Enable VDDSDIO control by state machine */
|
||||||
|
|
||||||
modifyreg32(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE, 0);
|
modifyreg32(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE, 0);
|
||||||
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_REG_PD_EN,
|
REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_REG_PD_EN,
|
||||||
@ -2067,7 +2155,7 @@ int IRAM_ATTR esp32s2_rtc_sleep_start(uint32_t wakeup_opt,
|
|||||||
modifyreg32(RTC_CNTL_INT_CLR_RTC_REG, 0,
|
modifyreg32(RTC_CNTL_INT_CLR_RTC_REG, 0,
|
||||||
RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
|
RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
|
||||||
|
|
||||||
/* restore DBG_ATTEN to the default value */
|
/* Restore DBG_ATTEN to the default value */
|
||||||
|
|
||||||
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP,
|
REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN_DEEP_SLP,
|
||||||
RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT);
|
RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT);
|
||||||
|
@ -96,7 +96,8 @@ enum esp32s2_rtc_slow_freq_e
|
|||||||
{
|
{
|
||||||
RTC_SLOW_FREQ_RTC = 0, /* Internal 150 kHz RC oscillator */
|
RTC_SLOW_FREQ_RTC = 0, /* Internal 150 kHz RC oscillator */
|
||||||
RTC_SLOW_FREQ_32K_XTAL = 1, /* External 32 kHz XTAL */
|
RTC_SLOW_FREQ_32K_XTAL = 1, /* External 32 kHz XTAL */
|
||||||
RTC_SLOW_FREQ_8MD256 = 2, /* Internal 8 MHz RC oscillator, divided by 256 */
|
RTC_SLOW_FREQ_8MD256 = 2, /* Internal 8 MHz RC oscillator, divided
|
||||||
|
* by 256 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* RTC FAST_CLK frequency values */
|
/* RTC FAST_CLK frequency values */
|
||||||
@ -241,7 +242,7 @@ enum esp32s2_rtc_slow_freq_e esp32s2_rtc_get_slow_clk(void);
|
|||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* cal_clk - clock to be measured
|
* cal_clk - clock to be measured
|
||||||
* slowclk_cycles - number of slow clock cycles to average
|
* slowclk_cycles - number of slow clock cycles what is to be averaged
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Average slow clock period in microseconds, Q13.19 fixed point format
|
* Average slow clock period in microseconds, Q13.19 fixed point format
|
||||||
|
@ -32,28 +32,44 @@
|
|||||||
#include "xtensa.h"
|
#include "xtensa.h"
|
||||||
#include "esp32s2_irq.h"
|
#include "esp32s2_irq.h"
|
||||||
#include "esp32s2_rtc_gpio.h"
|
#include "esp32s2_rtc_gpio.h"
|
||||||
|
#include "esp32s2_rtc.h"
|
||||||
#include "esp32s2_wdt.h"
|
#include "esp32s2_wdt.h"
|
||||||
#include "hardware/esp32s2_efuse.h"
|
#include "hardware/esp32s2_efuse.h"
|
||||||
#include "hardware/esp32s2_rtccntl.h"
|
#include "hardware/esp32s2_rtccntl.h"
|
||||||
#include "hardware/esp32s2_tim.h"
|
#include "hardware/esp32s2_tim.h"
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S2_RWDT
|
|
||||||
# error "RWDT not yet supported due to missing RTC driver!"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Helpers for converting from Q13.19 fixed-point format to float */
|
||||||
|
|
||||||
|
#define N 19
|
||||||
|
#define Q_TO_FLOAT(x) ((float)x/(float)(1<<N))
|
||||||
|
|
||||||
/* Check whether the provided device is a RTC Watchdog Timer */
|
/* Check whether the provided device is a RTC Watchdog Timer */
|
||||||
|
|
||||||
#define IS_RWDT(dev) (((struct esp32s2_wdt_priv_s *)(dev))->base == \
|
#define IS_RWDT(dev) (((struct esp32s2_wdt_priv_s *)dev)->type == RTC)
|
||||||
RTC_CNTL_OPTIONS0_REG)
|
|
||||||
|
/* Check whether the provided device is a Main Watchdog Timer */
|
||||||
|
|
||||||
|
#define IS_MWDT(dev) (((struct esp32s2_wdt_priv_s *)dev)->type == TIMER)
|
||||||
|
|
||||||
|
/* Check whether the provided device is a XTAL32K Watchdog Timer */
|
||||||
|
|
||||||
|
#define IS_XTWDT(dev) (((struct esp32s2_wdt_priv_s *)dev)->type == XTAL32K)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
enum wdt_peripheral_e
|
||||||
|
{
|
||||||
|
RTC,
|
||||||
|
TIMER,
|
||||||
|
XTAL32K,
|
||||||
|
};
|
||||||
|
|
||||||
struct esp32s2_wdt_priv_s
|
struct esp32s2_wdt_priv_s
|
||||||
{
|
{
|
||||||
struct esp32s2_wdt_ops_s *ops;
|
struct esp32s2_wdt_ops_s *ops;
|
||||||
@ -62,8 +78,15 @@ struct esp32s2_wdt_priv_s
|
|||||||
uint8_t irq; /* Interrupt ID */
|
uint8_t irq; /* Interrupt ID */
|
||||||
int32_t cpuint; /* CPU interrupt assigned to this WDT */
|
int32_t cpuint; /* CPU interrupt assigned to this WDT */
|
||||||
bool inuse; /* Flag indicating if this WDT is in use */
|
bool inuse; /* Flag indicating if this WDT is in use */
|
||||||
|
enum wdt_peripheral_e type; /* Type of the WDT Peripheral */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* External Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
extern void esp_rom_delay_us(uint32_t us);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -96,6 +119,8 @@ static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev,
|
|||||||
static void wdt_enableint(struct esp32s2_wdt_dev_s *dev);
|
static void wdt_enableint(struct esp32s2_wdt_dev_s *dev);
|
||||||
static void wdt_disableint(struct esp32s2_wdt_dev_s *dev);
|
static void wdt_disableint(struct esp32s2_wdt_dev_s *dev);
|
||||||
static void wdt_ackint(struct esp32s2_wdt_dev_s *dev);
|
static void wdt_ackint(struct esp32s2_wdt_dev_s *dev);
|
||||||
|
static uint16_t wdt_rtc_clk(struct esp32s2_wdt_dev_s *dev);
|
||||||
|
static void wdt_rstclk(struct esp32s2_wdt_dev_s *dev);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@ -103,7 +128,7 @@ static void wdt_ackint(struct esp32s2_wdt_dev_s *dev);
|
|||||||
|
|
||||||
/* ESP32-S2 WDT ops */
|
/* ESP32-S2 WDT ops */
|
||||||
|
|
||||||
struct esp32s2_wdt_ops_s esp32s2_mwdt_ops =
|
struct esp32s2_wdt_ops_s esp32s2_wdt_ops =
|
||||||
{
|
{
|
||||||
.start = wdt_start,
|
.start = wdt_start,
|
||||||
.stop = wdt_stop,
|
.stop = wdt_stop,
|
||||||
@ -113,63 +138,63 @@ struct esp32s2_wdt_ops_s esp32s2_mwdt_ops =
|
|||||||
.settimeout = wdt_settimeout,
|
.settimeout = wdt_settimeout,
|
||||||
.feed = wdt_feed,
|
.feed = wdt_feed,
|
||||||
.stg_conf = wdt_config_stage,
|
.stg_conf = wdt_config_stage,
|
||||||
.rtc_clk = NULL,
|
.rtc_clk = wdt_rtc_clk,
|
||||||
.setisr = wdt_setisr,
|
|
||||||
.enableint = wdt_enableint,
|
|
||||||
.disableint = wdt_disableint,
|
|
||||||
.ackint = wdt_ackint,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct esp32s2_wdt_ops_s esp32s2_rwdt_ops =
|
|
||||||
{
|
|
||||||
.start = wdt_start,
|
|
||||||
.stop = wdt_stop,
|
|
||||||
.enablewp = wdt_enablewp,
|
|
||||||
.disablewp = wdt_disablewp,
|
|
||||||
.pre = NULL,
|
|
||||||
.settimeout = wdt_settimeout,
|
|
||||||
.feed = wdt_feed,
|
|
||||||
.stg_conf = wdt_config_stage,
|
|
||||||
.rtc_clk = NULL,
|
|
||||||
.setisr = wdt_setisr,
|
.setisr = wdt_setisr,
|
||||||
.enableint = wdt_enableint,
|
.enableint = wdt_enableint,
|
||||||
.disableint = wdt_disableint,
|
.disableint = wdt_disableint,
|
||||||
.ackint = wdt_ackint,
|
.ackint = wdt_ackint,
|
||||||
|
.rstclk = wdt_rstclk,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S2_MWDT0
|
#ifdef CONFIG_ESP32S2_MWDT0
|
||||||
struct esp32s2_wdt_priv_s g_esp32s2_mwdt0_priv =
|
struct esp32s2_wdt_priv_s g_esp32s2_mwdt0_priv =
|
||||||
{
|
{
|
||||||
.ops = &esp32s2_mwdt_ops,
|
.ops = &esp32s2_wdt_ops,
|
||||||
.base = TIMG_T0CONFIG_REG(0),
|
.base = TIMG_T0CONFIG_REG(0),
|
||||||
.periph = ESP32S2_PERIPH_TG_WDT_LEVEL,
|
.periph = ESP32S2_PERIPH_TG_WDT_LEVEL,
|
||||||
.irq = ESP32S2_IRQ_TG_WDT_LEVEL,
|
.irq = ESP32S2_IRQ_TG_WDT_LEVEL,
|
||||||
.cpuint = -ENOMEM,
|
.cpuint = -ENOMEM,
|
||||||
.inuse = false,
|
.inuse = false,
|
||||||
|
.type = TIMER,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S2_MWDT1
|
#ifdef CONFIG_ESP32S2_MWDT1
|
||||||
struct esp32s2_wdt_priv_s g_esp32s2_mwdt1_priv =
|
struct esp32s2_wdt_priv_s g_esp32s2_mwdt1_priv =
|
||||||
{
|
{
|
||||||
.ops = &esp32s2_mwdt_ops,
|
.ops = &esp32s2_wdt_ops,
|
||||||
.base = TIMG_T0CONFIG_REG(1),
|
.base = TIMG_T0CONFIG_REG(1),
|
||||||
.periph = ESP32S2_PERIPH_TG1_WDT_LEVEL,
|
.periph = ESP32S2_PERIPH_TG1_WDT_LEVEL,
|
||||||
.irq = ESP32S2_IRQ_TG1_WDT_LEVEL,
|
.irq = ESP32S2_IRQ_TG1_WDT_LEVEL,
|
||||||
.cpuint = -ENOMEM,
|
.cpuint = -ENOMEM,
|
||||||
.inuse = false,
|
.inuse = false,
|
||||||
|
.type = TIMER,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S2_RWDT
|
#ifdef CONFIG_ESP32S2_RWDT
|
||||||
struct esp32s2_wdt_priv_s g_esp32s2_rwdt_priv =
|
struct esp32s2_wdt_priv_s g_esp32s2_rwdt_priv =
|
||||||
{
|
{
|
||||||
.ops = &esp32s2_rwdt_ops,
|
.ops = &esp32s2_wdt_ops,
|
||||||
.base = RTC_CNTL_OPTIONS0_REG,
|
.base = RTC_CNTL_OPTIONS0_REG,
|
||||||
.periph = ESP32S2_PERIPH_RTC_CORE,
|
.periph = ESP32S2_PERIPH_RTC_CORE,
|
||||||
.irq = ESP32S2_IRQ_RTC_WDT,
|
.irq = ESP32S2_IRQ_RTC_WDT,
|
||||||
.cpuint = -ENOMEM,
|
.cpuint = -ENOMEM,
|
||||||
.inuse = false,
|
.inuse = false,
|
||||||
|
.type = RTC,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT
|
||||||
|
struct esp32s2_wdt_priv_s g_esp32s2_xtwdt_priv =
|
||||||
|
{
|
||||||
|
.ops = &esp32s2_wdt_ops,
|
||||||
|
.base = RTC_CNTL_OPTIONS0_REG,
|
||||||
|
.periph = ESP32S2_PERIPH_RTC_CORE,
|
||||||
|
.irq = ESP32S2_IRQ_RTC_XTAL32K_DEAD,
|
||||||
|
.cpuint = -ENOMEM,
|
||||||
|
.inuse = false,
|
||||||
|
.type = XTAL32K,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -262,10 +287,18 @@ static void wdt_start(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, 0, RTC_CNTL_WDT_EN);
|
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, 0, RTC_CNTL_WDT_EN);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, 0, TIMG_WDT_EN);
|
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, 0, TIMG_WDT_EN);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wdt_modifyreg32(dev, XTWDT_CONFIG0_OFFSET, 0, RTC_CNTL_XTAL32K_WDT_EN);
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT_BACKUP_CLK_ENABLE
|
||||||
|
wdt_modifyreg32(dev, XTWDT_CONFIG0_OFFSET,
|
||||||
|
0, RTC_CNTL_XTAL32K_AUTO_BACKUP);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -303,7 +336,7 @@ static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
|
|||||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG0_M,
|
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG0_M,
|
||||||
mask);
|
mask);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
mask = (uint32_t)cfg << TIMG_WDT_STG0_S;
|
mask = (uint32_t)cfg << TIMG_WDT_STG0_S;
|
||||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG0_M, mask);
|
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG0_M, mask);
|
||||||
@ -319,7 +352,7 @@ static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
|
|||||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG1_M,
|
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG1_M,
|
||||||
mask);
|
mask);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
mask = (uint32_t)cfg << TIMG_WDT_STG1_S;
|
mask = (uint32_t)cfg << TIMG_WDT_STG1_S;
|
||||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG1_M, mask);
|
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG1_M, mask);
|
||||||
@ -335,7 +368,7 @@ static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
|
|||||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG2_M,
|
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG2_M,
|
||||||
mask);
|
mask);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
mask = (uint32_t)cfg << TIMG_WDT_STG2_S;
|
mask = (uint32_t)cfg << TIMG_WDT_STG2_S;
|
||||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG2_M, mask);
|
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG2_M, mask);
|
||||||
@ -351,7 +384,7 @@ static int32_t wdt_config_stage(struct esp32s2_wdt_dev_s *dev,
|
|||||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG3_M,
|
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG3_M,
|
||||||
mask);
|
mask);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
mask = (uint32_t)cfg << TIMG_WDT_STG3_S;
|
mask = (uint32_t)cfg << TIMG_WDT_STG3_S;
|
||||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG3_M, mask);
|
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG3_M, mask);
|
||||||
@ -388,10 +421,14 @@ static void wdt_stop(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_EN, 0);
|
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_EN, 0);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_EN, 0);
|
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_EN, 0);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wdt_modifyreg32(dev, XTWDT_CONFIG0_OFFSET, RTC_CNTL_XTAL32K_WDT_EN, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -417,7 +454,7 @@ static void wdt_enablewp(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_putreg(dev, RWDT_WP_REG, 0);
|
wdt_putreg(dev, RWDT_WP_REG, 0);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_WP_REG, 0);
|
wdt_putreg(dev, MWDT_WP_REG, 0);
|
||||||
}
|
}
|
||||||
@ -446,7 +483,7 @@ static void wdt_disablewp(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_putreg(dev, RWDT_WP_REG, RTC_CNTL_WDT_WKEY_VALUE);
|
wdt_putreg(dev, RWDT_WP_REG, RTC_CNTL_WDT_WKEY_VALUE);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_WP_REG, TIMG_WDT_WKEY_VALUE);
|
wdt_putreg(dev, MWDT_WP_REG, TIMG_WDT_WKEY_VALUE);
|
||||||
}
|
}
|
||||||
@ -469,12 +506,23 @@ static void wdt_disablewp(struct esp32s2_wdt_dev_s *dev)
|
|||||||
|
|
||||||
static void wdt_pre(struct esp32s2_wdt_dev_s *dev, uint16_t pre)
|
static void wdt_pre(struct esp32s2_wdt_dev_s *dev, uint16_t pre)
|
||||||
{
|
{
|
||||||
uint32_t mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALER_S;
|
uint32_t mask = 0;
|
||||||
|
|
||||||
DEBUGASSERT(dev != NULL);
|
DEBUGASSERT(dev != NULL);
|
||||||
|
|
||||||
wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET, TIMG_WDT_CLK_PRESCALER_M,
|
if (IS_MWDT(dev))
|
||||||
mask);
|
{
|
||||||
|
mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALER_S;
|
||||||
|
wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET,
|
||||||
|
TIMG_WDT_CLK_PRESCALER_M, mask);
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT_BACKUP_CLK_ENABLE
|
||||||
|
else if (IS_XTWDT(dev))
|
||||||
|
{
|
||||||
|
mask = (uint32_t)pre;
|
||||||
|
wdt_modifyreg32(dev, XTWDT_CLK_PRESCALE_OFFSET,
|
||||||
|
RTC_CNTL_XTAL32K_CLK_FACTOR_M, mask);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -499,6 +547,14 @@ static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev, uint32_t value,
|
|||||||
{
|
{
|
||||||
DEBUGASSERT(dev != NULL);
|
DEBUGASSERT(dev != NULL);
|
||||||
|
|
||||||
|
if (IS_XTWDT(dev))
|
||||||
|
{
|
||||||
|
value = value << RTC_CNTL_XTAL32K_WDT_TIMEOUT_S;
|
||||||
|
wdt_modifyreg32(dev, XTWDT_TIMEOUT_OFFSET,
|
||||||
|
RTC_CNTL_XTAL32K_WDT_TIMEOUT_M, value);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
switch (stage)
|
switch (stage)
|
||||||
{
|
{
|
||||||
case ESP32S2_WDT_STAGE0:
|
case ESP32S2_WDT_STAGE0:
|
||||||
@ -515,7 +571,7 @@ static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev, uint32_t value,
|
|||||||
value = value >> (delay + 1);
|
value = value >> (delay + 1);
|
||||||
wdt_putreg(dev, RWDT_STAGE0_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, RWDT_STAGE0_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_STAGE0_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, MWDT_STAGE0_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
@ -528,7 +584,7 @@ static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev, uint32_t value,
|
|||||||
{
|
{
|
||||||
wdt_putreg(dev, RWDT_STAGE1_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, RWDT_STAGE1_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_STAGE1_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, MWDT_STAGE1_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
@ -541,7 +597,7 @@ static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev, uint32_t value,
|
|||||||
{
|
{
|
||||||
wdt_putreg(dev, RWDT_STAGE2_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, RWDT_STAGE2_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_STAGE2_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, MWDT_STAGE2_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
@ -554,7 +610,7 @@ static int32_t wdt_settimeout(struct esp32s2_wdt_dev_s *dev, uint32_t value,
|
|||||||
{
|
{
|
||||||
wdt_putreg(dev, RWDT_STAGE3_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, RWDT_STAGE3_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_STAGE3_TIMEOUT_OFFSET, value);
|
wdt_putreg(dev, MWDT_STAGE3_TIMEOUT_OFFSET, value);
|
||||||
}
|
}
|
||||||
@ -591,12 +647,76 @@ static void wdt_feed(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, RWDT_FEED_OFFSET, 0, RTC_CNTL_WDT_FEED);
|
wdt_modifyreg32(dev, RWDT_FEED_OFFSET, 0, RTC_CNTL_WDT_FEED);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_FEED_OFFSET, TIMG_WDT_FEED);
|
wdt_putreg(dev, MWDT_FEED_OFFSET, TIMG_WDT_FEED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: wdt_rtc_clk
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check the RTC clock source and return the necessary cycles to complete
|
||||||
|
* 1 ms.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* dev - Pointer to the driver state structure.
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* Number of cycles to complete 1 ms.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static uint16_t wdt_rtc_clk(struct esp32s2_wdt_dev_s *dev)
|
||||||
|
{
|
||||||
|
enum esp32s2_rtc_slow_freq_e slow_clk_rtc;
|
||||||
|
uint32_t period_13q19;
|
||||||
|
float period;
|
||||||
|
float cycles_ms;
|
||||||
|
uint16_t cycles_ms_int;
|
||||||
|
|
||||||
|
/* Calibration map: Maps each RTC SLOW_CLK source to the number
|
||||||
|
* used to calibrate this source.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const enum esp32s2_rtc_cal_sel_e cal_map[] =
|
||||||
|
{
|
||||||
|
RTC_CAL_RTC_MUX,
|
||||||
|
RTC_CAL_32K_XTAL,
|
||||||
|
RTC_CAL_8MD256
|
||||||
|
};
|
||||||
|
|
||||||
|
DEBUGASSERT(dev);
|
||||||
|
|
||||||
|
/* Check which clock is sourcing the slow_clk_rtc */
|
||||||
|
|
||||||
|
slow_clk_rtc = esp32s2_rtc_get_slow_clk();
|
||||||
|
|
||||||
|
/* Get the slow_clk_rtc period in us in Q13.19 fixed point format */
|
||||||
|
|
||||||
|
period_13q19 = esp32s2_rtc_clk_cal(cal_map[slow_clk_rtc],
|
||||||
|
SLOW_CLK_CAL_CYCLES);
|
||||||
|
|
||||||
|
/* Assert no error happened during the calibration */
|
||||||
|
|
||||||
|
DEBUGASSERT(period_13q19 != 0);
|
||||||
|
|
||||||
|
/* Convert from Q13.19 format to float */
|
||||||
|
|
||||||
|
period = Q_TO_FLOAT(period_13q19);
|
||||||
|
|
||||||
|
/* Get the number of cycles necessary to count 1 ms */
|
||||||
|
|
||||||
|
cycles_ms = 1000.0 / period;
|
||||||
|
|
||||||
|
/* Get the integer number of cycles */
|
||||||
|
|
||||||
|
cycles_ms_int = (uint16_t)cycles_ms;
|
||||||
|
|
||||||
|
return cycles_ms_int;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: wdt_setisr
|
* Name: wdt_setisr
|
||||||
*
|
*
|
||||||
@ -635,8 +755,9 @@ static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev, xcpt_t handler,
|
|||||||
|
|
||||||
if (wdt->cpuint >= 0)
|
if (wdt->cpuint >= 0)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ESP32S2_RWDT
|
#if defined(CONFIG_ESP32S2_RWDT) || defined(CONFIG_ESP32S2_XTWDT)
|
||||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT)
|
if (wdt->irq == ESP32S2_IRQ_RTC_WDT ||
|
||||||
|
wdt->irq == ESP32S2_IRQ_RTC_XTAL32K_DEAD)
|
||||||
{
|
{
|
||||||
esp32s2_rtcioirqdisable(wdt->irq);
|
esp32s2_rtcioirqdisable(wdt->irq);
|
||||||
irq_detach(wdt->irq);
|
irq_detach(wdt->irq);
|
||||||
@ -663,8 +784,9 @@ static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev, xcpt_t handler,
|
|||||||
{
|
{
|
||||||
/* Set up to receive peripheral interrupts on the current CPU */
|
/* Set up to receive peripheral interrupts on the current CPU */
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S2_RWDT
|
#if defined(CONFIG_ESP32S2_RWDT) || defined(CONFIG_ESP32S2_XTWDT)
|
||||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT)
|
if (wdt->irq == ESP32S2_IRQ_RTC_WDT ||
|
||||||
|
wdt->irq == ESP32S2_IRQ_RTC_XTAL32K_DEAD)
|
||||||
{
|
{
|
||||||
ret = irq_attach(wdt->irq, handler, arg);
|
ret = irq_attach(wdt->irq, handler, arg);
|
||||||
|
|
||||||
@ -728,10 +850,15 @@ static void wdt_enableint(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, 0, RTC_CNTL_WDT_INT_ENA);
|
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, 0, RTC_CNTL_WDT_INT_ENA);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, 0, TIMG_WDT_INT_ENA);
|
wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, 0, TIMG_WDT_INT_ENA);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wdt_modifyreg32(dev, XTWDT_INT_ENA_REG_OFFSET, 0,
|
||||||
|
RTC_CNTL_XTAL32K_DEAD_INT_ENA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -753,10 +880,15 @@ static void wdt_disableint(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, RTC_CNTL_WDT_INT_ENA, 0);
|
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, RTC_CNTL_WDT_INT_ENA, 0);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, TIMG_WDT_INT_ENA, 0);
|
wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, TIMG_WDT_INT_ENA, 0);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wdt_modifyreg32(dev, XTWDT_INT_ENA_REG_OFFSET,
|
||||||
|
RTC_CNTL_XTAL32K_DEAD_INT_ENA, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -778,10 +910,49 @@ static void wdt_ackint(struct esp32s2_wdt_dev_s *dev)
|
|||||||
{
|
{
|
||||||
wdt_putreg(dev, RWDT_INT_CLR_REG_OFFSET, RTC_CNTL_WDT_INT_CLR);
|
wdt_putreg(dev, RWDT_INT_CLR_REG_OFFSET, RTC_CNTL_WDT_INT_CLR);
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
wdt_putreg(dev, MWDT_INT_CLR_REG_OFFSET, TIMG_WDT_INT_CLR);
|
wdt_putreg(dev, MWDT_INT_CLR_REG_OFFSET, TIMG_WDT_INT_CLR);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wdt_putreg(dev, MWDT_INT_CLR_REG_OFFSET,
|
||||||
|
RTC_CNTL_XTAL32K_DEAD_INT_CLR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: wdt_rstclk
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Restores the xtal32k clock.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* dev - Pointer to the driver state structure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void wdt_rstclk(struct esp32s2_wdt_dev_s *dev)
|
||||||
|
{
|
||||||
|
DEBUGASSERT(dev != NULL);
|
||||||
|
|
||||||
|
struct esp32s2_wdt_priv_s *wdt = (struct esp32s2_wdt_priv_s *)dev;
|
||||||
|
|
||||||
|
if (IS_XTWDT(dev))
|
||||||
|
{
|
||||||
|
wdt->ops->stop(dev);
|
||||||
|
|
||||||
|
wdt_modifyreg32(dev, XTWDT_CONFIG0_OFFSET, RTC_CNTL_XPD_XTAL_32K, 0);
|
||||||
|
wdt_modifyreg32(dev, XTWDT_CONFIG0_OFFSET, 0, RTC_CNTL_XPD_XTAL_32K);
|
||||||
|
|
||||||
|
/* Needs some time after switching to 32khz XTAL
|
||||||
|
* before turning on WDT again
|
||||||
|
*/
|
||||||
|
|
||||||
|
esp_rom_delay_us(300);
|
||||||
|
|
||||||
|
wdt->ops->start(dev);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -834,6 +1005,15 @@ struct esp32s2_wdt_dev_s *esp32s2_wdt_init(enum esp32s2_wdt_inst_e wdt_id)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT
|
||||||
|
case ESP32S2_WDT_XTWDT:
|
||||||
|
{
|
||||||
|
wdt = &g_esp32s2_xtwdt_priv;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -928,7 +1108,7 @@ bool esp32s2_wdt_is_running(struct esp32s2_wdt_dev_s *dev)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (IS_MWDT(dev))
|
||||||
{
|
{
|
||||||
status = wdt_getreg(dev, MWDT_CONFIG0_OFFSET);
|
status = wdt_getreg(dev, MWDT_CONFIG0_OFFSET);
|
||||||
if ((status & TIMG_WDT_EN) == TIMG_WDT_EN)
|
if ((status & TIMG_WDT_EN) == TIMG_WDT_EN)
|
||||||
@ -936,6 +1116,14 @@ bool esp32s2_wdt_is_running(struct esp32s2_wdt_dev_s *dev)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = wdt_getreg(dev, XTWDT_CONFIG0_OFFSET);
|
||||||
|
if ((status & RTC_CNTL_XTAL32K_WDT_EN) == RTC_CNTL_XTAL32K_WDT_EN)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,23 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* IOCTL Commands ***********************************************************/
|
||||||
|
|
||||||
|
/* The watchdog driver uses a standard character driver framework. However,
|
||||||
|
* since the watchdog driver is a device control interface and not a data
|
||||||
|
* transfer interface, the majority of the functionality is implemented in
|
||||||
|
* driver ioctl calls.
|
||||||
|
*
|
||||||
|
* See nuttx/timers/watchdog.h for the IOCTLs handled by the upper half.
|
||||||
|
*
|
||||||
|
* These are detected and handled by the "lower half" watchdog timer driver.
|
||||||
|
*
|
||||||
|
* WDIOC_RSTCLK - Restores the xtal32k clock
|
||||||
|
* Argument: Ignored
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WDIOC_RSTCLK _WDIOC(0x032)
|
||||||
|
|
||||||
/* Helpers ******************************************************************/
|
/* Helpers ******************************************************************/
|
||||||
|
|
||||||
#define ESP32S2_WDT_START(d) ((d)->ops->start(d))
|
#define ESP32S2_WDT_START(d) ((d)->ops->start(d))
|
||||||
@ -42,14 +59,17 @@
|
|||||||
#define ESP32S2_WDT_LOCK(d) ((d)->ops->enablewp(d))
|
#define ESP32S2_WDT_LOCK(d) ((d)->ops->enablewp(d))
|
||||||
#define ESP32S2_WDT_UNLOCK(d) ((d)->ops->disablewp(d))
|
#define ESP32S2_WDT_UNLOCK(d) ((d)->ops->disablewp(d))
|
||||||
#define ESP32S2_MWDT_PRE(d, v) ((d)->ops->pre(d, v))
|
#define ESP32S2_MWDT_PRE(d, v) ((d)->ops->pre(d, v))
|
||||||
|
#define ESP32S2_XTWDT_PRE(d, v) ((d)->ops->pre(d, v))
|
||||||
#define ESP32S2_WDT_STO(d, v, s) ((d)->ops->settimeout(d, v, s))
|
#define ESP32S2_WDT_STO(d, v, s) ((d)->ops->settimeout(d, v, s))
|
||||||
#define ESP32S2_WDT_FEED(d) ((d)->ops->feed(d))
|
#define ESP32S2_WDT_FEED(d) ((d)->ops->feed(d))
|
||||||
#define ESP32S2_WDT_STG_CONF(d, s, c) ((d)->ops->stg_conf(d, s, c))
|
#define ESP32S2_WDT_STG_CONF(d, s, c) ((d)->ops->stg_conf(d, s, c))
|
||||||
#define ESP32S2_RWDT_CLK(d) ((d)->ops->rtc_clk(d))
|
#define ESP32S2_RWDT_CLK(d) ((d)->ops->rtc_clk(d))
|
||||||
|
#define ESP32S2_XTWDT_CLK(d) ((d)->ops->rtc_clk(d))
|
||||||
#define ESP32S2_WDT_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg))
|
#define ESP32S2_WDT_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg))
|
||||||
#define ESP32S2_WDT_ENABLEINT(d) ((d)->ops->enableint(d))
|
#define ESP32S2_WDT_ENABLEINT(d) ((d)->ops->enableint(d))
|
||||||
#define ESP32S2_WDT_DISABLEINT(d) ((d)->ops->disableint(d))
|
#define ESP32S2_WDT_DISABLEINT(d) ((d)->ops->disableint(d))
|
||||||
#define ESP32S2_WDT_ACKINT(d) ((d)->ops->ackint(d))
|
#define ESP32S2_WDT_ACKINT(d) ((d)->ops->ackint(d))
|
||||||
|
#define ESP32S2_XTWDT_RST_CLK(d) ((d)->ops->rstclk(d))
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
@ -61,7 +81,8 @@ enum esp32s2_wdt_inst_e
|
|||||||
{
|
{
|
||||||
ESP32S2_WDT_MWDT0 = 0, /* Main System Watchdog Timer (MWDT) of Timer Group 0 */
|
ESP32S2_WDT_MWDT0 = 0, /* Main System Watchdog Timer (MWDT) of Timer Group 0 */
|
||||||
ESP32S2_WDT_MWDT1, /* Main System Watchdog Timer (MWDT) of Timer Group 1 */
|
ESP32S2_WDT_MWDT1, /* Main System Watchdog Timer (MWDT) of Timer Group 1 */
|
||||||
ESP32S2_WDT_RWDT /* RTC Watchdog Timer (RWDT) */
|
ESP32S2_WDT_RWDT, /* RTC Watchdog Timer (RWDT) */
|
||||||
|
ESP32S2_WDT_XTWDT /* XTAL32K Watchdog Timer (XTWDT) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stages of a Watchdog Timer. A WDT has 4 stages. */
|
/* Stages of a Watchdog Timer. A WDT has 4 stages. */
|
||||||
@ -134,6 +155,7 @@ struct esp32s2_wdt_ops_s
|
|||||||
void (*enableint)(struct esp32s2_wdt_dev_s *dev);
|
void (*enableint)(struct esp32s2_wdt_dev_s *dev);
|
||||||
void (*disableint)(struct esp32s2_wdt_dev_s *dev);
|
void (*disableint)(struct esp32s2_wdt_dev_s *dev);
|
||||||
void (*ackint)(struct esp32s2_wdt_dev_s *dev);
|
void (*ackint)(struct esp32s2_wdt_dev_s *dev);
|
||||||
|
void (*rstclk)(struct esp32s2_wdt_dev_s *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
#include "xtensa.h"
|
#include "xtensa.h"
|
||||||
#include "esp32s2_wdt.h"
|
#include "esp32s2_wdt.h"
|
||||||
|
#include "esp32s2_rtc.h"
|
||||||
#include "esp32s2_wdt_lowerhalf.h"
|
#include "esp32s2_wdt_lowerhalf.h"
|
||||||
#include "hardware/esp32s2_soc.h"
|
#include "hardware/esp32s2_soc.h"
|
||||||
|
|
||||||
@ -68,6 +69,24 @@
|
|||||||
|
|
||||||
#define RWDT_FULL_STAGE (UINT32_MAX)
|
#define RWDT_FULL_STAGE (UINT32_MAX)
|
||||||
|
|
||||||
|
/* XTWDT clock period in nanoseconds */
|
||||||
|
|
||||||
|
#define XTWDT_CLK_PERIOD_NS (30)
|
||||||
|
|
||||||
|
/* Maximum number of cycles supported for a XTWDT stage timeout */
|
||||||
|
|
||||||
|
#define XTWDT_FULL_STAGE (UINT8_MAX)
|
||||||
|
|
||||||
|
/* Number of cycles for RTC_SLOW_CLK calibration */
|
||||||
|
|
||||||
|
#define XT_WDT_CLK_CAL_CYCLES (500)
|
||||||
|
|
||||||
|
/* Maximum number of divisor components
|
||||||
|
* according to the frequency of RC_SLOW_CLK
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XT_WDT_DIV_COMP_N_MAX 8
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -75,7 +94,8 @@
|
|||||||
enum wdt_peripheral_e
|
enum wdt_peripheral_e
|
||||||
{
|
{
|
||||||
RTC,
|
RTC,
|
||||||
TIMER
|
TIMER,
|
||||||
|
XTAL32K,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure provides the private representation of the "lower-half"
|
/* This structure provides the private representation of the "lower-half"
|
||||||
@ -114,6 +134,12 @@ static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
|||||||
uint32_t timeout);
|
uint32_t timeout);
|
||||||
static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
||||||
xcpt_t handler);
|
xcpt_t handler);
|
||||||
|
static int wdt_lh_ioctl(struct watchdog_lowerhalf_s *lower, int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT_BACKUP_CLK_ENABLE
|
||||||
|
static uint32_t wdt_lh_xt_calculate(uint32_t rtc_clk_frequency_khz);
|
||||||
|
static uint32_t wdt_lh_clk_freq_cal(uint32_t rtc_clk_period_us);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@ -129,7 +155,7 @@ static const struct watchdog_ops_s g_esp32s2_wdg_ops =
|
|||||||
.getstatus = wdt_lh_getstatus,
|
.getstatus = wdt_lh_getstatus,
|
||||||
.settimeout = wdt_lh_settimeout,
|
.settimeout = wdt_lh_settimeout,
|
||||||
.capture = wdt_lh_capture,
|
.capture = wdt_lh_capture,
|
||||||
.ioctl = NULL
|
.ioctl = wdt_lh_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ESP32S2_MWDT0
|
#ifdef CONFIG_ESP32S2_MWDT0
|
||||||
@ -159,6 +185,15 @@ static struct esp32s2_wdt_lowerhalf_s g_esp32s2_rwdt_lowerhalf =
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT
|
||||||
|
/* XTWDT lower-half */
|
||||||
|
|
||||||
|
static struct esp32s2_wdt_lowerhalf_s g_esp32s2_xtwdt_lowerhalf =
|
||||||
|
{
|
||||||
|
.ops = &g_esp32s2_wdg_ops,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: wdt_lh_start
|
* Name: wdt_lh_start
|
||||||
*
|
*
|
||||||
@ -216,7 +251,7 @@ static int wdt_lh_start(struct watchdog_lowerhalf_s *lower)
|
|||||||
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
||||||
ESP32S2_WDT_STAGE_ACTION_RESET_SYSTEM);
|
ESP32S2_WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||||
}
|
}
|
||||||
else
|
else if (priv->peripheral == RTC)
|
||||||
{
|
{
|
||||||
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
||||||
ESP32S2_WDT_STAGE_ACTION_RESET_RTC);
|
ESP32S2_WDT_STAGE_ACTION_RESET_RTC);
|
||||||
@ -433,6 +468,8 @@ static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
|||||||
(struct esp32s2_wdt_lowerhalf_s *)lower;
|
(struct esp32s2_wdt_lowerhalf_s *)lower;
|
||||||
uint16_t rtc_cycles = 0;
|
uint16_t rtc_cycles = 0;
|
||||||
uint32_t rtc_ms_max = 0;
|
uint32_t rtc_ms_max = 0;
|
||||||
|
uint16_t xtal32k_cycles = 0;
|
||||||
|
uint32_t xtal32k_ms_max = 0;
|
||||||
|
|
||||||
wdinfo("Entry: timeout=%" PRIu32 "\n", timeout);
|
wdinfo("Entry: timeout=%" PRIu32 "\n", timeout);
|
||||||
DEBUGASSERT(priv);
|
DEBUGASSERT(priv);
|
||||||
@ -466,7 +503,7 @@ static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
|||||||
|
|
||||||
/* Watchdog from RTC Module */
|
/* Watchdog from RTC Module */
|
||||||
|
|
||||||
else
|
else if (priv->peripheral == RTC)
|
||||||
{
|
{
|
||||||
rtc_cycles = ESP32S2_RWDT_CLK(priv->wdt);
|
rtc_cycles = ESP32S2_RWDT_CLK(priv->wdt);
|
||||||
rtc_ms_max = (RWDT_FULL_STAGE / (uint32_t)rtc_cycles);
|
rtc_ms_max = (RWDT_FULL_STAGE / (uint32_t)rtc_cycles);
|
||||||
@ -486,6 +523,28 @@ static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Watchdog from XTAL32K Module */
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xtal32k_cycles = XTWDT_CLK_PERIOD_NS;
|
||||||
|
xtal32k_ms_max = (XTWDT_FULL_STAGE * NSEC_PER_USEC / xtal32k_cycles);
|
||||||
|
|
||||||
|
/* Is this timeout a valid value for RTC WDT? */
|
||||||
|
|
||||||
|
if (timeout == 0 || timeout > xtal32k_ms_max)
|
||||||
|
{
|
||||||
|
wderr("Cannot represent timeout=%" PRIu32 " > %" PRIu32 "\n",
|
||||||
|
timeout, rtc_ms_max);
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timeout = timeout * xtal32k_cycles;
|
||||||
|
ESP32S2_WDT_STO(priv->wdt, timeout, ESP32S2_WDT_STAGE0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset the wdt */
|
/* Reset the wdt */
|
||||||
|
|
||||||
ESP32S2_WDT_FEED(priv->wdt);
|
ESP32S2_WDT_FEED(priv->wdt);
|
||||||
@ -588,7 +647,7 @@ static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
|||||||
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
||||||
ESP32S2_WDT_STAGE_ACTION_RESET_SYSTEM);
|
ESP32S2_WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||||
}
|
}
|
||||||
else
|
else if (priv->peripheral == RTC)
|
||||||
{
|
{
|
||||||
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
||||||
ESP32S2_WDT_STAGE_ACTION_RESET_RTC);
|
ESP32S2_WDT_STAGE_ACTION_RESET_RTC);
|
||||||
@ -600,6 +659,47 @@ static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
|||||||
return oldhandler;
|
return oldhandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: wdt_lh_ioctl
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Any ioctl commands that are not recognized by the "upper-half" driver
|
||||||
|
* are forwarded to the lower half driver through this method.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* lower - A pointer the publicly visible representation of the
|
||||||
|
* "lower-half" driver state structure.
|
||||||
|
* cmd - Command number to process.
|
||||||
|
* arg - Argument that sent to the command.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* OK if success or a negative value if fail.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int wdt_lh_ioctl(struct watchdog_lowerhalf_s *lower, int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
struct esp32s2_wdt_lowerhalf_s *priv =
|
||||||
|
(struct esp32s2_wdt_lowerhalf_s *)lower;
|
||||||
|
|
||||||
|
wdinfo("ioctl Call: cmd=0x%x arg=0x%lx", cmd, arg);
|
||||||
|
|
||||||
|
/* Process the IOCTL command */
|
||||||
|
|
||||||
|
switch (cmd)
|
||||||
|
{
|
||||||
|
case WDIOC_RSTCLK:
|
||||||
|
ESP32S2_XTWDT_RST_CLK(priv->wdt);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -ENOTTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Interrupt handling *******************************************************/
|
/* Interrupt handling *******************************************************/
|
||||||
|
|
||||||
static int wdt_handler(int irq, void *context, void *arg)
|
static int wdt_handler(int irq, void *context, void *arg)
|
||||||
@ -622,6 +722,81 @@ static int wdt_handler(int irq, void *context, void *arg)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: wdt_lh_xt_calculate
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Calculate the actual frequency of RC_SLOW_CLK to calibrate the backup
|
||||||
|
* RTC_SLOW_CLK. This is necessary to compensate for clock deviations.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* rtc_clk_frequency_khz - Frequency of RTC SLOW CLK in khz
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* The divisor of BACKUP32K_CLK used to calibrate the RTC_SLOW_CLK
|
||||||
|
* according to the actual frequency of the RC_SLOW_CLK.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT_BACKUP_CLK_ENABLE
|
||||||
|
static uint32_t wdt_lh_xt_calculate(uint32_t rtc_clk_frequency_khz)
|
||||||
|
{
|
||||||
|
uint32_t xtal32k_clk_factor = 0;
|
||||||
|
uint8_t divisor_comps[XT_WDT_DIV_COMP_N_MAX];
|
||||||
|
|
||||||
|
uint8_t M = ((rtc_clk_frequency_khz / 32) / 2);
|
||||||
|
uint32_t S = ((4 * rtc_clk_frequency_khz) / 32);
|
||||||
|
|
||||||
|
memset(divisor_comps, M, XT_WDT_DIV_COMP_N_MAX);
|
||||||
|
|
||||||
|
/* Calculate how far we are away from satisfying S = SUM(x_n) */
|
||||||
|
|
||||||
|
uint8_t off = S - XT_WDT_DIV_COMP_N_MAX * M;
|
||||||
|
|
||||||
|
/* Offset should never be this big */
|
||||||
|
|
||||||
|
ASSERT(off <= XT_WDT_DIV_COMP_N_MAX);
|
||||||
|
|
||||||
|
for (int i = 0; i < XT_WDT_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: wdt_lh_clk_freq_cal
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Calculate the clock frequency from period in microseconds.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* rtc_clk_period_us - Average slow clock period in microseconds.
|
||||||
|
*
|
||||||
|
* Returned Values:
|
||||||
|
* Frequency of the clock in Hz.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static uint32_t wdt_lh_clk_freq_cal(uint32_t rtc_clk_period_us)
|
||||||
|
{
|
||||||
|
if (rtc_clk_period_us == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / rtc_clk_period_us;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -680,6 +855,15 @@ int esp32s2_wdt_initialize(const char *devpath, enum esp32s2_wdt_inst_e wdt)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT
|
||||||
|
case ESP32S2_WDT_XTWDT:
|
||||||
|
{
|
||||||
|
lower = &g_esp32s2_xtwdt_lowerhalf;
|
||||||
|
lower->peripheral = XTAL32K;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
@ -712,6 +896,26 @@ int esp32s2_wdt_initialize(const char *devpath, enum esp32s2_wdt_inst_e wdt)
|
|||||||
ESP32S2_MWDT_PRE(lower->wdt, MWDT_CLK_PRESCALER_VALUE);
|
ESP32S2_MWDT_PRE(lower->wdt, MWDT_CLK_PRESCALER_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Configure auto backup clock when XTAL32K fails */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT_BACKUP_CLK_ENABLE
|
||||||
|
if (lower->peripheral == XTAL32K)
|
||||||
|
{
|
||||||
|
/* Estimate frequency of internal RTC oscillator */
|
||||||
|
|
||||||
|
uint32_t rtc_clk_period_us =
|
||||||
|
esp32s2_rtc_clk_cal(RTC_CAL_INTERNAL_OSC, XT_WDT_CLK_CAL_CYCLES);
|
||||||
|
|
||||||
|
uint32_t rtc_clk_frequency_khz = wdt_lh_clk_freq_cal(rtc_clk_period_us)
|
||||||
|
/ 1000;
|
||||||
|
|
||||||
|
uint32_t xtal32k_clk_factor =
|
||||||
|
wdt_lh_xt_calculate(rtc_clk_frequency_khz);
|
||||||
|
|
||||||
|
ESP32S2_XTWDT_PRE(lower->wdt, xtal32k_clk_factor);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ESP32S2_WDT_LOCK(lower->wdt);
|
ESP32S2_WDT_LOCK(lower->wdt);
|
||||||
|
|
||||||
/* Register the watchdog driver as /dev/watchdogX. If the registration goes
|
/* Register the watchdog driver as /dev/watchdogX. If the registration goes
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
/* Offset relative to each watchdog timer instance memory base */
|
/* Offset relative to each watchdog timer instance memory base */
|
||||||
|
|
||||||
#define RWDT_CONFIG0_OFFSET 0x0094
|
#define RWDT_CONFIG0_OFFSET 0x0094
|
||||||
|
#define XTWDT_CONFIG0_OFFSET 0x0060
|
||||||
|
|
||||||
/* RWDT */
|
/* RWDT */
|
||||||
|
|
||||||
@ -46,6 +47,12 @@
|
|||||||
#define RWDT_INT_ENA_REG_OFFSET 0x0040
|
#define RWDT_INT_ENA_REG_OFFSET 0x0040
|
||||||
#define RWDT_INT_CLR_REG_OFFSET 0x004c
|
#define RWDT_INT_CLR_REG_OFFSET 0x004c
|
||||||
|
|
||||||
|
/* XTWDT */
|
||||||
|
|
||||||
|
#define XTWDT_TIMEOUT_OFFSET 0x00f4
|
||||||
|
#define XTWDT_CLK_PRESCALE_OFFSET 0x00f0
|
||||||
|
#define XTWDT_INT_ENA_REG_OFFSET 0x0040
|
||||||
|
|
||||||
/* The value that needs to be written to RTC_CNTL_WDT_WKEY to
|
/* The value that needs to be written to RTC_CNTL_WDT_WKEY to
|
||||||
* write-enable the wdt registers
|
* write-enable the wdt registers
|
||||||
*/
|
*/
|
||||||
|
@ -215,6 +215,7 @@ PROVIDE ( dummy_len_plus = 0x3ffffd54 );
|
|||||||
PROVIDE ( Enable_QMode = 0x40016690 );
|
PROVIDE ( Enable_QMode = 0x40016690 );
|
||||||
PROVIDE ( esp_crc8 = 0x40011a78 );
|
PROVIDE ( esp_crc8 = 0x40011a78 );
|
||||||
PROVIDE ( esp_rom_config_pad_power_select = 0x40016e58 );
|
PROVIDE ( esp_rom_config_pad_power_select = 0x40016e58 );
|
||||||
|
PROVIDE ( esp_rom_delay_us = ets_delay_us );
|
||||||
PROVIDE ( esp_rom_opiflash_cache_mode_config = 0x40016754 );
|
PROVIDE ( esp_rom_opiflash_cache_mode_config = 0x40016754 );
|
||||||
PROVIDE ( esp_rom_opiflash_exec_cmd = 0x40017e30 );
|
PROVIDE ( esp_rom_opiflash_exec_cmd = 0x40017e30 );
|
||||||
PROVIDE ( esp_rom_opiflash_exit_continuous_read_mode = 0x40017ee8 );
|
PROVIDE ( esp_rom_opiflash_exit_continuous_read_mode = 0x40017ee8 );
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
#include "esp32s2_wdt_lowerhalf.h"
|
#include "esp32s2_wdt_lowerhalf.h"
|
||||||
#include "esp32s2_wdt.h"
|
#include "esp32s2_wdt.h"
|
||||||
|
|
||||||
#include "esp32s2-saola-1.h"
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -84,6 +82,15 @@ int board_wdt_init(void)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_ESP32S2_RWDT */
|
#endif /* CONFIG_ESP32S2_RWDT */
|
||||||
|
|
||||||
|
#ifdef CONFIG_ESP32S2_XTWDT
|
||||||
|
ret = esp32s2_wdt_initialize("/dev/watchdog3", ESP32S2_WDT_XTWDT);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "Failed to initialize XTWDT: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_ESP32S2_XTWDT */
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
#
|
||||||
|
# This file is autogenerated: PLEASE DO NOT EDIT IT.
|
||||||
|
#
|
||||||
|
# You can use "make menuconfig" to make any modifications to the installed .config file.
|
||||||
|
# You can then do "make savedefconfig" to generate a new defconfig file that includes your
|
||||||
|
# modifications.
|
||||||
|
#
|
||||||
|
# CONFIG_ARCH_LEDS is not set
|
||||||
|
# CONFIG_NSH_ARGCAT is not set
|
||||||
|
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
|
||||||
|
CONFIG_ARCH="xtensa"
|
||||||
|
CONFIG_ARCH_BOARD="esp32s2-kaluga-1"
|
||||||
|
CONFIG_ARCH_BOARD_COMMON=y
|
||||||
|
CONFIG_ARCH_BOARD_ESP32S2_KALUGA_1=y
|
||||||
|
CONFIG_ARCH_CHIP="esp32s2"
|
||||||
|
CONFIG_ARCH_CHIP_ESP32S2=y
|
||||||
|
CONFIG_ARCH_CHIP_ESP32S2WROVER=y
|
||||||
|
CONFIG_ARCH_STACKDUMP=y
|
||||||
|
CONFIG_ARCH_XTENSA=y
|
||||||
|
CONFIG_BOARD_LOOPSPERMSEC=16717
|
||||||
|
CONFIG_BUILTIN=y
|
||||||
|
CONFIG_DEBUG_FULLOPT=y
|
||||||
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
|
CONFIG_ESP32S2_MWDT0=y
|
||||||
|
CONFIG_ESP32S2_MWDT1=y
|
||||||
|
CONFIG_ESP32S2_RWDT=y
|
||||||
|
CONFIG_ESP32S2_UART0=y
|
||||||
|
CONFIG_EXAMPLES_WATCHDOG=y
|
||||||
|
CONFIG_FS_PROCFS=y
|
||||||
|
CONFIG_HAVE_CXX=y
|
||||||
|
CONFIG_HAVE_CXXINITIALIZE=y
|
||||||
|
CONFIG_IDLETHREAD_STACKSIZE=3072
|
||||||
|
CONFIG_INIT_ENTRYPOINT="nsh_main"
|
||||||
|
CONFIG_INTELHEX_BINARY=y
|
||||||
|
CONFIG_NSH_ARCHINIT=y
|
||||||
|
CONFIG_NSH_BUILTIN_APPS=y
|
||||||
|
CONFIG_NSH_FILEIOSIZE=512
|
||||||
|
CONFIG_NSH_LINELEN=64
|
||||||
|
CONFIG_NSH_READLINE=y
|
||||||
|
CONFIG_PREALLOC_TIMERS=4
|
||||||
|
CONFIG_RAM_SIZE=114688
|
||||||
|
CONFIG_RAM_START=0x20000000
|
||||||
|
CONFIG_RR_INTERVAL=200
|
||||||
|
CONFIG_SCHED_WAITPID=y
|
||||||
|
CONFIG_START_DAY=6
|
||||||
|
CONFIG_START_MONTH=12
|
||||||
|
CONFIG_START_YEAR=2011
|
||||||
|
CONFIG_SYSLOG_BUFFER=y
|
||||||
|
CONFIG_SYSTEM_NSH=y
|
||||||
|
CONFIG_UART0_SERIAL_CONSOLE=y
|
||||||
|
CONFIG_WATCHDOG=y
|
@ -23,6 +23,7 @@ CONFIG_DEBUG_FULLOPT=y
|
|||||||
CONFIG_DEBUG_SYMBOLS=y
|
CONFIG_DEBUG_SYMBOLS=y
|
||||||
CONFIG_ESP32S2_MWDT0=y
|
CONFIG_ESP32S2_MWDT0=y
|
||||||
CONFIG_ESP32S2_MWDT1=y
|
CONFIG_ESP32S2_MWDT1=y
|
||||||
|
CONFIG_ESP32S2_RWDT=y
|
||||||
CONFIG_ESP32S2_UART0=y
|
CONFIG_ESP32S2_UART0=y
|
||||||
CONFIG_EXAMPLES_WATCHDOG=y
|
CONFIG_EXAMPLES_WATCHDOG=y
|
||||||
CONFIG_FS_PROCFS=y
|
CONFIG_FS_PROCFS=y
|
||||||
|
Loading…
Reference in New Issue
Block a user