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
|
||||
SJW: 3
|
||||
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
|
||||
|
||||
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.
|
||||
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
|
||||
bool "Real Time Clock (RTC)"
|
||||
default y
|
||||
|
@ -131,23 +131,32 @@
|
||||
|
||||
#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_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_MEM_FOLLOW_CPU BIT(4) /* RTC FAST and SLOW memories 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_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_VDDSDIO BIT(5) /* Power down VDDSDIO
|
||||
* regulator */
|
||||
#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 */
|
||||
|
||||
/* These flags are not power domains, but will affect some sleep parameters */
|
||||
|
||||
#define RTC_SLEEP_DIG_USE_8M BIT(16)
|
||||
#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,
|
||||
* in which RTCIO cannot be used as input,
|
||||
* and RTCMEM can't work under high temperature */
|
||||
#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) /* Avoid using ultra low
|
||||
* power in deep sleep, in
|
||||
* 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)
|
||||
|
||||
@ -173,14 +182,14 @@
|
||||
* Valid if RTC_CNTL_DBG_ATTEN is 0.
|
||||
*/
|
||||
|
||||
#define RTC_CNTL_DBIAS_0V90 0 /* sleep dig_dbias & rtc_dbias */
|
||||
#define RTC_CNTL_DBIAS_0V95 1 /* digital voltage */
|
||||
#define RTC_CNTL_DBIAS_0V90 0 /* Sleep dig_dbias & rtc_dbias */
|
||||
#define RTC_CNTL_DBIAS_0V95 1 /* Digital voltage */
|
||||
#define RTC_CNTL_DBIAS_1V00 2
|
||||
#define RTC_CNTL_DBIAS_1V05 3
|
||||
#define RTC_CNTL_DBIAS_1V10 4
|
||||
#define RTC_CNTL_DBIAS_1V15 5
|
||||
#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
|
||||
* This initializer sets all fields to "reasonable" values
|
||||
@ -265,10 +274,12 @@
|
||||
|
||||
/* 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_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_ENTRY_ADDR_REG RTC_CNTL_STORE6_REG /* FAST_RTC_MEMORY_ENTRY */
|
||||
#define RTC_RESET_CAUSE_REG RTC_CNTL_STORE6_REG
|
||||
@ -282,45 +293,63 @@
|
||||
|
||||
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 xtal_wait : 8; /* Number of rtc_fast_clk cycles to wait for XTAL clock to be ready */
|
||||
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 ck8m_wait : 8; /* Number of rtc_fast_clk cycles to wait
|
||||
* for 8M clock to be ready */
|
||||
uint32_t xtal_wait : 8; /* Number of rtc_fast_clk cycles to wait
|
||||
* for XTAL clock to be ready */
|
||||
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 xtal_fpu : 1;
|
||||
uint32_t bbpll_fpu : 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 */
|
||||
|
||||
struct esp32s2_rtc_sleep_config_s
|
||||
{
|
||||
uint32_t lslp_mem_inf_fpu : 1; /* force normal voltage in sleep mode (digital domain memory) */
|
||||
uint32_t rtc_mem_inf_follow_cpu : 1; /* keep low voltage in sleep mode (even if ULP/touch is used) */
|
||||
uint32_t rtc_fastmem_pd_en : 1; /* power down RTC fast memory */
|
||||
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 lslp_mem_inf_fpu : 1; /* Force normal voltage in sleep mode
|
||||
* (digital domain memory) */
|
||||
uint32_t rtc_mem_inf_follow_cpu : 1; /* Keep low voltage in sleep mode
|
||||
* (even if ULP/touch is used) */
|
||||
uint32_t rtc_fastmem_pd_en : 1; /* Power down RTC fast memory */
|
||||
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 deep_slp : 1; /* power down digital domain */
|
||||
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_slp : 3; /* set bias for digital domain, in sleep mode */
|
||||
uint32_t rtc_dbias_wak : 3; /* set bias for RTC domain, in active mode */
|
||||
uint32_t rtc_dbias_slp : 3; /* set bias for RTC domain, in sleep mode */
|
||||
uint32_t bias_sleep_monitor : 1; /* circuit control parameter, in monitor mode */
|
||||
uint32_t dbg_atten_slp : 4; /* voltage parameter, in sleep mode */
|
||||
uint32_t bias_sleep_slp : 1; /* circuit control parameter, in sleep mode */
|
||||
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 */
|
||||
uint32_t deep_slp : 1; /* Power down digital domain */
|
||||
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_slp : 3; /* Set bias for digital domain,
|
||||
* in sleep mode */
|
||||
uint32_t rtc_dbias_wak : 3; /* Set bias for RTC domain,
|
||||
* in active mode */
|
||||
uint32_t rtc_dbias_slp : 3; /* Set bias for RTC domain,
|
||||
* in sleep mode */
|
||||
uint32_t bias_sleep_monitor : 1; /* Circuit control parameter,
|
||||
* in monitor mode */
|
||||
uint32_t dbg_atten_slp : 4; /* Voltage parameter, in sleep mode */
|
||||
uint32_t bias_sleep_slp : 1; /* Circuit control parameter,
|
||||
* in sleep mode */
|
||||
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 */
|
||||
@ -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 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 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 */
|
||||
@ -341,7 +371,8 @@ struct alm_cbinfo_s
|
||||
{
|
||||
struct rt_timer_s *alarm_hdl; /* Timer id point to here */
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -650,6 +681,20 @@ static uint32_t IRAM_ATTR esp32s2_rtc_clk_cal_internal(
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
if (d256_en)
|
||||
@ -1070,14 +1115,15 @@ static void esp32s2_rtc_calibrate_ocode(void)
|
||||
uint64_t max_delay_time_us = 10000;
|
||||
struct esp32s2_cpu_freq_config_s freq_config;
|
||||
|
||||
/* Bandgap output voltage is not precise when calibrate o-code by hardware
|
||||
* sometimes, so need software o-code calibration (must turn off PLL).
|
||||
/* Band gap output voltage is sometimes not precise when calibrating
|
||||
* the o-code by hardware, so we need a software o-code calibration
|
||||
* (must turn off PLL).
|
||||
* Method:
|
||||
* 1. read current cpu config, save in old_config
|
||||
* 2. switch cpu to xtal because PLL will be closed when o-code calibration
|
||||
* 3. begin o-code calibration
|
||||
* 4. wait o-code calibration done flag or timeout
|
||||
* 5. set cpu to 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
|
||||
* 3. Begin o-code calibration
|
||||
* 4. Wait o-code calibration done flag or timeout
|
||||
* 5. Set cpu to old-config
|
||||
*/
|
||||
|
||||
enum esp32s2_rtc_slow_freq_e slow_clk_freq =
|
||||
@ -1129,6 +1175,20 @@ static void esp32s2_rtc_calibrate_ocode(void)
|
||||
* 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)
|
||||
{
|
||||
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:
|
||||
* 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:
|
||||
* 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 */
|
||||
|
||||
/* set shortest possible sleep time limit */
|
||||
/* Set shortest possible sleep time limit */
|
||||
|
||||
REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL,
|
||||
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_WAIT_TIMER, 1);
|
||||
@ -1455,27 +1515,27 @@ void IRAM_ATTR esp32s2_rtc_init(void)
|
||||
|
||||
if (cfg.clkctl_init)
|
||||
{
|
||||
/* clear CMMU clock force on */
|
||||
/* Clear CMMU clock force on */
|
||||
|
||||
modifyreg32(EXTMEM_PRO_CACHE_MMU_POWER_CTRL_REG,
|
||||
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);
|
||||
|
||||
/* clear tag clock force on */
|
||||
/* Clear tag clock force on */
|
||||
|
||||
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,
|
||||
EXTMEM_PRO_DCACHE_TAG_MEM_FORCE_ON, 0);
|
||||
modifyreg32(EXTMEM_PRO_ICACHE_TAG_POWER_CTRL_REG,
|
||||
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(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);
|
||||
}
|
||||
|
||||
/* cancel digital pu force */
|
||||
/* Cancel digital pu force */
|
||||
|
||||
modifyreg32(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU |
|
||||
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);
|
||||
|
||||
/* cancel digital PADS force no iso */
|
||||
/* Cancel digital PADS force no iso */
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* enable VDDSDIO control by state machine */
|
||||
/* Enable VDDSDIO control by state machine */
|
||||
|
||||
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,
|
||||
@ -2067,7 +2155,7 @@ int IRAM_ATTR esp32s2_rtc_sleep_start(uint32_t wakeup_opt,
|
||||
modifyreg32(RTC_CNTL_INT_CLR_RTC_REG, 0,
|
||||
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,
|
||||
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_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 */
|
||||
@ -241,7 +242,7 @@ enum esp32s2_rtc_slow_freq_e esp32s2_rtc_get_slow_clk(void);
|
||||
*
|
||||
* Input Parameters:
|
||||
* 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:
|
||||
* Average slow clock period in microseconds, Q13.19 fixed point format
|
||||
|
@ -32,28 +32,44 @@
|
||||
#include "xtensa.h"
|
||||
#include "esp32s2_irq.h"
|
||||
#include "esp32s2_rtc_gpio.h"
|
||||
#include "esp32s2_rtc.h"
|
||||
#include "esp32s2_wdt.h"
|
||||
#include "hardware/esp32s2_efuse.h"
|
||||
#include "hardware/esp32s2_rtccntl.h"
|
||||
#include "hardware/esp32s2_tim.h"
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RWDT
|
||||
# error "RWDT not yet supported due to missing RTC driver!"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* 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 */
|
||||
|
||||
#define IS_RWDT(dev) (((struct esp32s2_wdt_priv_s *)(dev))->base == \
|
||||
RTC_CNTL_OPTIONS0_REG)
|
||||
#define IS_RWDT(dev) (((struct esp32s2_wdt_priv_s *)dev)->type == RTC)
|
||||
|
||||
/* 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
|
||||
****************************************************************************/
|
||||
|
||||
enum wdt_peripheral_e
|
||||
{
|
||||
RTC,
|
||||
TIMER,
|
||||
XTAL32K,
|
||||
};
|
||||
|
||||
struct esp32s2_wdt_priv_s
|
||||
{
|
||||
struct esp32s2_wdt_ops_s *ops;
|
||||
@ -62,8 +78,15 @@ struct esp32s2_wdt_priv_s
|
||||
uint8_t irq; /* Interrupt ID */
|
||||
int32_t cpuint; /* CPU interrupt assigned to this WDT */
|
||||
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
|
||||
****************************************************************************/
|
||||
@ -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_disableint(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
|
||||
@ -103,7 +128,7 @@ static void wdt_ackint(struct esp32s2_wdt_dev_s *dev);
|
||||
|
||||
/* ESP32-S2 WDT ops */
|
||||
|
||||
struct esp32s2_wdt_ops_s esp32s2_mwdt_ops =
|
||||
struct esp32s2_wdt_ops_s esp32s2_wdt_ops =
|
||||
{
|
||||
.start = wdt_start,
|
||||
.stop = wdt_stop,
|
||||
@ -113,63 +138,63 @@ struct esp32s2_wdt_ops_s esp32s2_mwdt_ops =
|
||||
.settimeout = wdt_settimeout,
|
||||
.feed = wdt_feed,
|
||||
.stg_conf = wdt_config_stage,
|
||||
.rtc_clk = NULL,
|
||||
.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,
|
||||
.rtc_clk = wdt_rtc_clk,
|
||||
.setisr = wdt_setisr,
|
||||
.enableint = wdt_enableint,
|
||||
.disableint = wdt_disableint,
|
||||
.ackint = wdt_ackint,
|
||||
.rstclk = wdt_rstclk,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESP32S2_MWDT0
|
||||
struct esp32s2_wdt_priv_s g_esp32s2_mwdt0_priv =
|
||||
{
|
||||
.ops = &esp32s2_mwdt_ops,
|
||||
.ops = &esp32s2_wdt_ops,
|
||||
.base = TIMG_T0CONFIG_REG(0),
|
||||
.periph = ESP32S2_PERIPH_TG_WDT_LEVEL,
|
||||
.irq = ESP32S2_IRQ_TG_WDT_LEVEL,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
.type = TIMER,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S2_MWDT1
|
||||
struct esp32s2_wdt_priv_s g_esp32s2_mwdt1_priv =
|
||||
{
|
||||
.ops = &esp32s2_mwdt_ops,
|
||||
.ops = &esp32s2_wdt_ops,
|
||||
.base = TIMG_T0CONFIG_REG(1),
|
||||
.periph = ESP32S2_PERIPH_TG1_WDT_LEVEL,
|
||||
.irq = ESP32S2_IRQ_TG1_WDT_LEVEL,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
.type = TIMER,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RWDT
|
||||
struct esp32s2_wdt_priv_s g_esp32s2_rwdt_priv =
|
||||
{
|
||||
.ops = &esp32s2_rwdt_ops,
|
||||
.ops = &esp32s2_wdt_ops,
|
||||
.base = RTC_CNTL_OPTIONS0_REG,
|
||||
.periph = ESP32S2_PERIPH_RTC_CORE,
|
||||
.irq = ESP32S2_IRQ_RTC_WDT,
|
||||
.cpuint = -ENOMEM,
|
||||
.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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG0_S;
|
||||
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,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG1_S;
|
||||
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,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG2_S;
|
||||
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,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG3_S;
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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)
|
||||
{
|
||||
uint32_t mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALER_S;
|
||||
|
||||
uint32_t mask = 0;
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET, TIMG_WDT_CLK_PRESCALER_M,
|
||||
mask);
|
||||
if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
wdt_putreg(dev, RWDT_STAGE0_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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
|
||||
*
|
||||
@ -635,8 +755,9 @@ static int32_t wdt_setisr(struct esp32s2_wdt_dev_s *dev, xcpt_t handler,
|
||||
|
||||
if (wdt->cpuint >= 0)
|
||||
{
|
||||
#ifdef CONFIG_ESP32S2_RWDT
|
||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT)
|
||||
#if defined(CONFIG_ESP32S2_RWDT) || defined(CONFIG_ESP32S2_XTWDT)
|
||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT ||
|
||||
wdt->irq == ESP32S2_IRQ_RTC_XTAL32K_DEAD)
|
||||
{
|
||||
esp32s2_rtcioirqdisable(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 */
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RWDT
|
||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT)
|
||||
#if defined(CONFIG_ESP32S2_RWDT) || defined(CONFIG_ESP32S2_XTWDT)
|
||||
if (wdt->irq == ESP32S2_IRQ_RTC_WDT ||
|
||||
wdt->irq == ESP32S2_IRQ_RTC_XTAL32K_DEAD)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S2_XTWDT
|
||||
case ESP32S2_WDT_XTWDT:
|
||||
{
|
||||
wdt = &g_esp32s2_xtwdt_priv;
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
@ -928,7 +1108,7 @@ bool esp32s2_wdt_is_running(struct esp32s2_wdt_dev_s *dev)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
status = wdt_getreg(dev, MWDT_CONFIG0_OFFSET);
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = wdt_getreg(dev, XTWDT_CONFIG0_OFFSET);
|
||||
if ((status & RTC_CNTL_XTAL32K_WDT_EN) == RTC_CNTL_XTAL32K_WDT_EN)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -35,6 +35,23 @@
|
||||
* 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 ******************************************************************/
|
||||
|
||||
#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_UNLOCK(d) ((d)->ops->disablewp(d))
|
||||
#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_FEED(d) ((d)->ops->feed(d))
|
||||
#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_XTWDT_CLK(d) ((d)->ops->rtc_clk(d))
|
||||
#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_DISABLEINT(d) ((d)->ops->disableint(d))
|
||||
#define ESP32S2_WDT_ACKINT(d) ((d)->ops->ackint(d))
|
||||
#define ESP32S2_XTWDT_RST_CLK(d) ((d)->ops->rstclk(d))
|
||||
|
||||
/****************************************************************************
|
||||
* 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_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. */
|
||||
@ -134,6 +155,7 @@ struct esp32s2_wdt_ops_s
|
||||
void (*enableint)(struct esp32s2_wdt_dev_s *dev);
|
||||
void (*disableint)(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 "esp32s2_wdt.h"
|
||||
#include "esp32s2_rtc.h"
|
||||
#include "esp32s2_wdt_lowerhalf.h"
|
||||
#include "hardware/esp32s2_soc.h"
|
||||
|
||||
@ -68,6 +69,24 @@
|
||||
|
||||
#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
|
||||
****************************************************************************/
|
||||
@ -75,7 +94,8 @@
|
||||
enum wdt_peripheral_e
|
||||
{
|
||||
RTC,
|
||||
TIMER
|
||||
TIMER,
|
||||
XTAL32K,
|
||||
};
|
||||
|
||||
/* 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);
|
||||
static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
||||
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
|
||||
@ -129,7 +155,7 @@ static const struct watchdog_ops_s g_esp32s2_wdg_ops =
|
||||
.getstatus = wdt_lh_getstatus,
|
||||
.settimeout = wdt_lh_settimeout,
|
||||
.capture = wdt_lh_capture,
|
||||
.ioctl = NULL
|
||||
.ioctl = wdt_lh_ioctl,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESP32S2_MWDT0
|
||||
@ -159,6 +185,15 @@ static struct esp32s2_wdt_lowerhalf_s g_esp32s2_rwdt_lowerhalf =
|
||||
};
|
||||
#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
|
||||
*
|
||||
@ -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_STAGE_ACTION_RESET_SYSTEM);
|
||||
}
|
||||
else
|
||||
else if (priv->peripheral == RTC)
|
||||
{
|
||||
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
||||
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;
|
||||
uint16_t rtc_cycles = 0;
|
||||
uint32_t rtc_ms_max = 0;
|
||||
uint16_t xtal32k_cycles = 0;
|
||||
uint32_t xtal32k_ms_max = 0;
|
||||
|
||||
wdinfo("Entry: timeout=%" PRIu32 "\n", timeout);
|
||||
DEBUGASSERT(priv);
|
||||
@ -466,7 +503,7 @@ static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
||||
|
||||
/* Watchdog from RTC Module */
|
||||
|
||||
else
|
||||
else if (priv->peripheral == RTC)
|
||||
{
|
||||
rtc_cycles = ESP32S2_RWDT_CLK(priv->wdt);
|
||||
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 */
|
||||
|
||||
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_STAGE_ACTION_RESET_SYSTEM);
|
||||
}
|
||||
else
|
||||
else if (priv->peripheral == RTC)
|
||||
{
|
||||
ESP32S2_WDT_STG_CONF(priv->wdt, ESP32S2_WDT_STAGE0,
|
||||
ESP32S2_WDT_STAGE_ACTION_RESET_RTC);
|
||||
@ -600,6 +659,47 @@ static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
||||
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 *******************************************************/
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* 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
|
||||
****************************************************************************/
|
||||
@ -680,6 +855,15 @@ int esp32s2_wdt_initialize(const char *devpath, enum esp32s2_wdt_inst_e wdt)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S2_XTWDT
|
||||
case ESP32S2_WDT_XTWDT:
|
||||
{
|
||||
lower = &g_esp32s2_xtwdt_lowerhalf;
|
||||
lower->peripheral = XTAL32K;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* Register the watchdog driver as /dev/watchdogX. If the registration goes
|
||||
|
@ -34,6 +34,7 @@
|
||||
/* Offset relative to each watchdog timer instance memory base */
|
||||
|
||||
#define RWDT_CONFIG0_OFFSET 0x0094
|
||||
#define XTWDT_CONFIG0_OFFSET 0x0060
|
||||
|
||||
/* RWDT */
|
||||
|
||||
@ -46,6 +47,12 @@
|
||||
#define RWDT_INT_ENA_REG_OFFSET 0x0040
|
||||
#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
|
||||
* write-enable the wdt registers
|
||||
*/
|
||||
|
@ -215,6 +215,7 @@ PROVIDE ( dummy_len_plus = 0x3ffffd54 );
|
||||
PROVIDE ( Enable_QMode = 0x40016690 );
|
||||
PROVIDE ( esp_crc8 = 0x40011a78 );
|
||||
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_exec_cmd = 0x40017e30 );
|
||||
PROVIDE ( esp_rom_opiflash_exit_continuous_read_mode = 0x40017ee8 );
|
||||
|
@ -31,8 +31,6 @@
|
||||
#include "esp32s2_wdt_lowerhalf.h"
|
||||
#include "esp32s2_wdt.h"
|
||||
|
||||
#include "esp32s2-saola-1.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -84,6 +82,15 @@ int board_wdt_init(void)
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@ -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_ESP32S2_MWDT0=y
|
||||
CONFIG_ESP32S2_MWDT1=y
|
||||
CONFIG_ESP32S2_RWDT=y
|
||||
CONFIG_ESP32S2_UART0=y
|
||||
CONFIG_EXAMPLES_WATCHDOG=y
|
||||
CONFIG_FS_PROCFS=y
|
||||
|
Loading…
Reference in New Issue
Block a user