xtensa/esp32s3: Add XTWDT support
This commit is contained in:
parent
d63034994e
commit
4033018a72
@ -372,6 +372,22 @@ To test it, just run ``rand`` to get 32 randomly generated bytes::
|
||||
0000 98 b9 66 a2 a2 c0 a2 ae 09 70 93 d1 b5 91 86 c8 ..f......p......
|
||||
0010 8f 0e 0b 04 29 64 21 72 01 92 7c a2 27 60 6f 90 ....)d!r..|.'`o.
|
||||
|
||||
rtc
|
||||
---
|
||||
|
||||
This configuration demonstrates the use of the RTC driver through alarms.
|
||||
You can set an alarm, check its progress and receive a notification after it expires::
|
||||
|
||||
nsh> alarm 10
|
||||
alarm_daemon started
|
||||
alarm_daemon: Running
|
||||
Opening /dev/rtc0
|
||||
Alarm 0 set in 10 seconds
|
||||
nsh> alarm -r
|
||||
Opening /dev/rtc0
|
||||
Alarm 0 is active with 10 seconds to expiration
|
||||
nsh> alarm_daemon: alarm 0 received
|
||||
|
||||
smp
|
||||
---
|
||||
|
||||
@ -534,3 +550,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.
|
||||
|
@ -1153,7 +1153,7 @@ void esp32_rtc_clk_set(void)
|
||||
enum esp32_rtc_fast_freq_e fast_freq = RTC_FAST_FREQ_8M;
|
||||
enum esp32_slow_clk_sel_e slow_clk = SLOW_CLK_150K;
|
||||
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS)
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_XTAL)
|
||||
slow_clk = SLOW_CLK_32K_XTAL;
|
||||
#elif defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC)
|
||||
slow_clk = SLOW_CLK_32K_EXT_OSC;
|
||||
|
@ -703,6 +703,28 @@ config ESP32S3_RWDT
|
||||
to have the RTC module reset, please, use the Timers' Module WDTs.
|
||||
They will only reset Main System.
|
||||
|
||||
config ESP32S3_XTWDT
|
||||
bool "XTAL32K Watchdog Timer"
|
||||
depends on ESP32S3_RTC_CLK_EXT_OSC || ESP32S3_RTC_CLK_EXT_XTAL
|
||||
default n
|
||||
select ESP32S3_WDT
|
||||
select ESP32S3_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 ESP32S3_XTWDT_BACKUP_CLK_ENABLE) and, then, generates
|
||||
an interrupt that could be captured by WDIOC_CAPTURE.
|
||||
|
||||
config ESP32S3_XTWDT_BACKUP_CLK_ENABLE
|
||||
bool "Automatically switch to BACKUP32K_CLK when timer expires"
|
||||
depends on ESP32S3_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 ESP32S3_RT_TIMER
|
||||
bool "Real-Time Timer"
|
||||
default n
|
||||
@ -1523,6 +1545,50 @@ config ESP32S3_FREERUN
|
||||
|
||||
endmenu # Timer/Counter Configuration
|
||||
|
||||
menu "RTC Configuration"
|
||||
depends on ESP32S3_RTC
|
||||
|
||||
choice ESP32S3_RTC_CLK_SRC
|
||||
prompt "RTC clock source"
|
||||
default ESP32S3_RTC_CLK_INT_RC
|
||||
---help---
|
||||
Choose which clock is used as RTC clock source.
|
||||
|
||||
- "Internal 150kHz oscillator" option provides lowest deep sleep current
|
||||
consumption, and does not require extra external components. However
|
||||
frequency stability with respect to temperature is poor, so time may
|
||||
drift in deep/light sleep modes.
|
||||
- "External 32kHz crystal" provides better frequency stability, at the
|
||||
expense of slightly higher (1uA) deep sleep current consumption.
|
||||
- "External 32kHz oscillator" allows using 32kHz clock generated by an
|
||||
external circuit. In this case, external clock signal must be connected
|
||||
to 32K_XN pin. Amplitude should be <1.2V in case of sine wave signal,
|
||||
and <1V in case of square wave signal. Common mode voltage should be
|
||||
0.1 < Vcm < 0.5Vamp, where Vamp is the signal amplitude.
|
||||
Additionally, 1nF capacitor must be connected between 32K_XP pin and
|
||||
ground. 32K_XP pin can not be used as a GPIO in this case.
|
||||
- "Internal 8.5MHz oscillator divided by 256" option results in higher
|
||||
deep sleep current (by 5uA) but has better frequency stability than
|
||||
the internal 150kHz oscillator. It does not require external components.
|
||||
|
||||
config ESP32S3_RTC_CLK_INT_RC
|
||||
bool "Internal 150kHz RC oscillator"
|
||||
|
||||
config ESP32S3_RTC_CLK_EXT_XTAL
|
||||
bool "External 32kHz crystal"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
|
||||
config ESP32S3_RTC_CLK_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XN pin"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
|
||||
config ESP32S3_RTC_CLK_INT_8MD256
|
||||
bool "Internal 8.5MHz oscillator, divided by 256 (~33kHz)"
|
||||
|
||||
endchoice
|
||||
endmenu # "RTC Configuration"
|
||||
|
||||
|
||||
menu "Real-Time Timer Configuration"
|
||||
depends on ESP32S3_RT_TIMER
|
||||
|
||||
|
@ -1465,11 +1465,11 @@ void esp32s3_rtc_clk_set(void)
|
||||
enum esp32s3_rtc_fast_freq_e fast_freq = RTC_FAST_FREQ_8M;
|
||||
enum esp32s3_slow_clk_sel_e slow_clk = SLOW_CLK_150K;
|
||||
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS)
|
||||
#if defined(CONFIG_ESP32S3_RTC_CLK_EXT_XTAL)
|
||||
slow_clk = SLOW_CLK_32K_XTAL;
|
||||
#elif defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC)
|
||||
#elif defined(CONFIG_ESP32S3_RTC_CLK_EXT_OSC)
|
||||
slow_clk = SLOW_CLK_32K_EXT_OSC;
|
||||
#elif defined(CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256)
|
||||
#elif defined(CONFIG_ESP32S3_RTC_CLK_INT_8MD256)
|
||||
slow_clk = SLOW_CLK_8MD256;
|
||||
#endif
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32_rtc_driverinit
|
||||
* Name: esp32s3_rtc_driverinit
|
||||
*
|
||||
* Description:
|
||||
* Bind the configuration timer to a timer lower half instance and register
|
||||
@ -49,7 +49,7 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32_rtc_driverinit(void);
|
||||
int esp32s3_rtc_driverinit(void);
|
||||
|
||||
#endif /* CONFIG_RTC_DRIVER */
|
||||
|
||||
|
@ -50,13 +50,27 @@
|
||||
|
||||
/* Check whether the provided device is a RTC Watchdog Timer */
|
||||
|
||||
#define IS_RWDT(dev) (((struct esp32s3_wdt_priv_s *)dev)->base == \
|
||||
RTC_CNTL_RTC_OPTIONS0_REG)
|
||||
#define IS_RWDT(dev) (((struct esp32s3_wdt_priv_s *)dev)->type == RTC)
|
||||
|
||||
/* Check whether the provided device is a Main Watchdog Timer */
|
||||
|
||||
#define IS_MWDT(dev) (((struct esp32s3_wdt_priv_s *)dev)->type == TIMER)
|
||||
|
||||
/* Check whether the provided device is a XTAL32K Watchdog Timer */
|
||||
|
||||
#define IS_XTWDT(dev) (((struct esp32s3_wdt_priv_s *)dev)->type == XTAL32K)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum wdt_peripheral_e
|
||||
{
|
||||
RTC,
|
||||
TIMER,
|
||||
XTAL32K,
|
||||
};
|
||||
|
||||
struct esp32s3_wdt_priv_s
|
||||
{
|
||||
struct esp32s3_wdt_ops_s *ops;
|
||||
@ -66,8 +80,15 @@ struct esp32s3_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
|
||||
****************************************************************************/
|
||||
@ -101,6 +122,7 @@ static void wdt_enableint(struct esp32s3_wdt_dev_s *dev);
|
||||
static void wdt_disableint(struct esp32s3_wdt_dev_s *dev);
|
||||
static void wdt_ackint(struct esp32s3_wdt_dev_s *dev);
|
||||
static uint16_t wdt_rtc_clk(struct esp32s3_wdt_dev_s *dev);
|
||||
static void wdt_rstclk(struct esp32s3_wdt_dev_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
@ -108,7 +130,7 @@ static uint16_t wdt_rtc_clk(struct esp32s3_wdt_dev_s *dev);
|
||||
|
||||
/* ESP32-S3 WDT ops */
|
||||
|
||||
struct esp32s3_wdt_ops_s esp32s3_mwdt_ops =
|
||||
struct esp32s3_wdt_ops_s esp32s3_wdt_ops =
|
||||
{
|
||||
.start = wdt_start,
|
||||
.stop = wdt_stop,
|
||||
@ -118,63 +140,63 @@ struct esp32s3_wdt_ops_s esp32s3_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 esp32s3_wdt_ops_s esp32s3_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 = wdt_rtc_clk,
|
||||
.setisr = wdt_setisr,
|
||||
.enableint = wdt_enableint,
|
||||
.disableint = wdt_disableint,
|
||||
.ackint = wdt_ackint,
|
||||
.rstclk = wdt_rstclk,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT0
|
||||
struct esp32s3_wdt_priv_s g_esp32s3_mwdt0_priv =
|
||||
{
|
||||
.ops = &esp32s3_mwdt_ops,
|
||||
.ops = &esp32s3_wdt_ops,
|
||||
.base = TIMG_T0CONFIG_REG(0),
|
||||
.periph = ESP32S3_PERIPH_TG_WDT_LEVEL,
|
||||
.irq = ESP32S3_IRQ_TG_WDT_LEVEL,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
.type = TIMER,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT1
|
||||
struct esp32s3_wdt_priv_s g_esp32s3_mwdt1_priv =
|
||||
{
|
||||
.ops = &esp32s3_mwdt_ops,
|
||||
.ops = &esp32s3_wdt_ops,
|
||||
.base = TIMG_T0CONFIG_REG(1),
|
||||
.periph = ESP32S3_PERIPH_TG1_WDT_LEVEL,
|
||||
.irq = ESP32S3_IRQ_TG1_WDT_LEVEL,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
.type = TIMER,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
struct esp32s3_wdt_priv_s g_esp32s3_rwdt_priv =
|
||||
{
|
||||
.ops = &esp32s3_rwdt_ops,
|
||||
.ops = &esp32s3_wdt_ops,
|
||||
.base = RTC_CNTL_RTC_OPTIONS0_REG,
|
||||
.periph = ESP32S3_PERIPH_RTC_CORE,
|
||||
.irq = ESP32S3_IRQ_RTC_WDT,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
.type = RTC,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_XTWDT
|
||||
struct esp32s3_wdt_priv_s g_esp32s3_xtwdt_priv =
|
||||
{
|
||||
.ops = &esp32s3_wdt_ops,
|
||||
.base = RTC_CNTL_RTC_OPTIONS0_REG,
|
||||
.periph = ESP32S3_PERIPH_RTC_CORE,
|
||||
.irq = ESP32S3_IRQ_RTC_XTAL32K_DEAD,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
.type = XTAL32K,
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -267,10 +289,18 @@ static void wdt_start(struct esp32s3_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_ESP32S3_XTWDT_BACKUP_CLK_ENABLE
|
||||
wdt_modifyreg32(dev, XTWDT_CONFIG0_OFFSET,
|
||||
0, RTC_CNTL_XTAL32K_AUTO_BACKUP);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -308,7 +338,7 @@ static int32_t wdt_config_stage(struct esp32s3_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);
|
||||
@ -324,7 +354,7 @@ static int32_t wdt_config_stage(struct esp32s3_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);
|
||||
@ -340,7 +370,7 @@ static int32_t wdt_config_stage(struct esp32s3_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);
|
||||
@ -356,7 +386,7 @@ static int32_t wdt_config_stage(struct esp32s3_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);
|
||||
@ -393,10 +423,14 @@ static void wdt_stop(struct esp32s3_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);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -422,7 +456,7 @@ static void wdt_enablewp(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
wdt_putreg(dev, RWDT_WP_REG, 0);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, MWDT_WP_REG, 0);
|
||||
}
|
||||
@ -451,7 +485,7 @@ static void wdt_disablewp(struct esp32s3_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);
|
||||
}
|
||||
@ -474,12 +508,23 @@ static void wdt_disablewp(struct esp32s3_wdt_dev_s *dev)
|
||||
|
||||
static void wdt_pre(struct esp32s3_wdt_dev_s *dev, uint16_t pre)
|
||||
{
|
||||
uint32_t mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALE_S;
|
||||
|
||||
uint32_t mask = 0;
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET, TIMG_WDT_CLK_PRESCALE_M,
|
||||
mask);
|
||||
if (IS_MWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALE_S;
|
||||
wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET, TIMG_WDT_CLK_PRESCALE_M,
|
||||
mask);
|
||||
}
|
||||
#ifdef CONFIG_ESP32S3_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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -504,6 +549,14 @@ static int32_t wdt_settimeout(struct esp32s3_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 ESP32S3_WDT_STAGE0:
|
||||
@ -596,7 +649,7 @@ static void wdt_feed(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
wdt_modifyreg32(dev, RWDT_FEED_OFFSET, 0, RTC_CNTL_RTC_WDT_FEED);
|
||||
}
|
||||
else
|
||||
else if (IS_MWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, MWDT_FEED_OFFSET, TIMG_WDT_FEED);
|
||||
}
|
||||
@ -704,8 +757,9 @@ static int32_t wdt_setisr(struct esp32s3_wdt_dev_s *dev, xcpt_t handler,
|
||||
|
||||
if (wdt->cpuint >= 0)
|
||||
{
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
if (wdt->irq == ESP32S3_IRQ_RTC_WDT)
|
||||
#if defined(CONFIG_ESP32S3_RWDT) || defined(CONFIG_ESP32S3_XTWDT)
|
||||
if (wdt->irq == ESP32S3_IRQ_RTC_WDT ||
|
||||
wdt->irq == ESP32S3_IRQ_RTC_XTAL32K_DEAD)
|
||||
{
|
||||
esp32s3_rtcioirqdisable(wdt->irq);
|
||||
irq_detach(wdt->irq);
|
||||
@ -732,8 +786,9 @@ static int32_t wdt_setisr(struct esp32s3_wdt_dev_s *dev, xcpt_t handler,
|
||||
{
|
||||
/* Set up to receive peripheral interrupts on the current CPU */
|
||||
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
if (wdt->irq == ESP32S3_IRQ_RTC_WDT)
|
||||
#if defined(CONFIG_ESP32S3_RWDT) || defined(CONFIG_ESP32S3_XTWDT)
|
||||
if (wdt->irq == ESP32S3_IRQ_RTC_WDT ||
|
||||
wdt->irq == ESP32S3_IRQ_RTC_XTAL32K_DEAD)
|
||||
{
|
||||
ret = irq_attach(wdt->irq, handler, arg);
|
||||
|
||||
@ -799,10 +854,15 @@ static void wdt_enableint(struct esp32s3_wdt_dev_s *dev)
|
||||
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, 0,
|
||||
RTC_CNTL_RTC_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_RTC_XTAL32K_DEAD_INT_ENA);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -825,10 +885,15 @@ static void wdt_disableint(struct esp32s3_wdt_dev_s *dev)
|
||||
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, RTC_CNTL_RTC_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_RTC_XTAL32K_DEAD_INT_ENA, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -850,10 +915,49 @@ static void wdt_ackint(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
wdt_putreg(dev, RWDT_INT_CLR_REG_OFFSET, RTC_CNTL_RTC_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_RTC_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 esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
struct esp32s3_wdt_priv_s *wdt = (struct esp32s3_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);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -906,6 +1010,15 @@ struct esp32s3_wdt_dev_s *esp32s3_wdt_init(enum esp32s3_wdt_inst_e wdt_id)
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_XTWDT
|
||||
case ESP32S3_WDT_XTWDT:
|
||||
{
|
||||
wdt = &g_esp32s3_xtwdt_priv;
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
@ -1000,7 +1113,7 @@ bool esp32s3_wdt_is_running(struct esp32s3_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)
|
||||
@ -1008,6 +1121,14 @@ bool esp32s3_wdt_is_running(struct esp32s3_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 ESP32S3_WDT_START(d) ((d)->ops->start(d))
|
||||
@ -42,14 +59,17 @@
|
||||
#define ESP32S3_WDT_LOCK(d) ((d)->ops->enablewp(d))
|
||||
#define ESP32S3_WDT_UNLOCK(d) ((d)->ops->disablewp(d))
|
||||
#define ESP32S3_MWDT_PRE(d, v) ((d)->ops->pre(d, v))
|
||||
#define ESP32S3_XTWDT_PRE(d, v) ((d)->ops->pre(d, v))
|
||||
#define ESP32S3_WDT_STO(d, v, s) ((d)->ops->settimeout(d, v, s))
|
||||
#define ESP32S3_WDT_FEED(d) ((d)->ops->feed(d))
|
||||
#define ESP32S3_WDT_STG_CONF(d, s, c) ((d)->ops->stg_conf(d, s, c))
|
||||
#define ESP32S3_RWDT_CLK(d) ((d)->ops->rtc_clk(d))
|
||||
#define ESP32S3_XTWDT_CLK(d) ((d)->ops->rtc_clk(d))
|
||||
#define ESP32S3_WDT_SETISR(d, hnd, arg) ((d)->ops->setisr(d, hnd, arg))
|
||||
#define ESP32S3_WDT_ENABLEINT(d) ((d)->ops->enableint(d))
|
||||
#define ESP32S3_WDT_DISABLEINT(d) ((d)->ops->disableint(d))
|
||||
#define ESP32S3_WDT_ACKINT(d) ((d)->ops->ackint(d))
|
||||
#define ESP32S3_XTWDT_RST_CLK(d) ((d)->ops->rstclk(d))
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
@ -61,7 +81,8 @@ enum esp32s3_wdt_inst_e
|
||||
{
|
||||
ESP32S3_WDT_MWDT0 = 0, /* Main System Watchdog Timer (MWDT) of Timer Group 0 */
|
||||
ESP32S3_WDT_MWDT1, /* Main System Watchdog Timer (MWDT) of Timer Group 1 */
|
||||
ESP32S3_WDT_RWDT /* RTC Watchdog Timer (RWDT) */
|
||||
ESP32S3_WDT_RWDT, /* RTC Watchdog Timer (RWDT) */
|
||||
ESP32S3_WDT_XTWDT /* XTAL32K Watchdog Timer (XTWDT) */
|
||||
};
|
||||
|
||||
/* Stages of a Watchdog Timer. A WDT has 4 stages. */
|
||||
@ -135,6 +156,7 @@ struct esp32s3_wdt_ops_s
|
||||
void (*enableint)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*disableint)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*ackint)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*rstclk)(struct esp32s3_wdt_dev_s *dev);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "xtensa.h"
|
||||
#include "esp32s3_wdt.h"
|
||||
#include "esp32s3_rtc.h"
|
||||
#include "esp32s3_wdt_lowerhalf.h"
|
||||
#include "hardware/esp32s3_soc.h"
|
||||
|
||||
@ -69,6 +70,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
|
||||
****************************************************************************/
|
||||
@ -77,6 +96,7 @@ enum wdt_peripheral_e
|
||||
{
|
||||
RTC,
|
||||
TIMER,
|
||||
XTAL32K,
|
||||
};
|
||||
|
||||
/* This structure provides the private representation of the "lower-half"
|
||||
@ -116,6 +136,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_ESP32S3_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
|
||||
@ -131,7 +157,7 @@ static const struct watchdog_ops_s g_esp32s3_wdg_ops =
|
||||
.getstatus = wdt_lh_getstatus,
|
||||
.settimeout = wdt_lh_settimeout,
|
||||
.capture = wdt_lh_capture,
|
||||
.ioctl = NULL,
|
||||
.ioctl = wdt_lh_ioctl,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT0
|
||||
@ -161,6 +187,15 @@ static struct esp32s3_wdt_lowerhalf_s g_esp32s3_rwdt_lowerhalf =
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_XTWDT
|
||||
/* XTWDT lower-half */
|
||||
|
||||
static struct esp32s3_wdt_lowerhalf_s g_esp32s3_xtwdt_lowerhalf =
|
||||
{
|
||||
.ops = &g_esp32s3_wdg_ops,
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_lh_start
|
||||
*
|
||||
@ -217,7 +252,7 @@ static int wdt_lh_start(struct watchdog_lowerhalf_s *lower)
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||
}
|
||||
else
|
||||
else if (priv->peripheral == RTC)
|
||||
{
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_RTC);
|
||||
@ -434,6 +469,8 @@ static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
||||
(struct esp32s3_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);
|
||||
@ -467,7 +504,7 @@ static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
||||
|
||||
/* Watchdog from RTC Module */
|
||||
|
||||
else
|
||||
else if (priv->peripheral == RTC)
|
||||
{
|
||||
rtc_cycles = ESP32S3_RWDT_CLK(priv->wdt);
|
||||
rtc_ms_max = (RWDT_FULL_STAGE / (uint32_t)rtc_cycles);
|
||||
@ -487,6 +524,29 @@ 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
|
||||
/ (uint32_t)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;
|
||||
ESP32S3_WDT_STO(priv->wdt, timeout, ESP32S3_WDT_STAGE0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the wdt */
|
||||
|
||||
ESP32S3_WDT_FEED(priv->wdt);
|
||||
@ -589,7 +649,7 @@ static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||
}
|
||||
else
|
||||
else if (priv->peripheral == RTC)
|
||||
{
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_RTC);
|
||||
@ -601,6 +661,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 esp32s3_wdt_lowerhalf_s *priv =
|
||||
(struct esp32s3_wdt_lowerhalf_s *)lower;
|
||||
|
||||
wdinfo("ioctl Call: cmd=0x%x arg=0x%lx", cmd, arg);
|
||||
|
||||
/* Process the IOCTL command */
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case WDIOC_RSTCLK:
|
||||
ESP32S3_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 +723,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_ESP32S3_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 +856,15 @@ int esp32s3_wdt_initialize(const char *devpath, enum esp32s3_wdt_inst_e wdt)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_XTWDT
|
||||
case ESP32S3_WDT_XTWDT:
|
||||
{
|
||||
lower = &g_esp32s3_xtwdt_lowerhalf;
|
||||
lower->peripheral = XTAL32K;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
ret = -ENODEV;
|
||||
@ -712,6 +897,26 @@ int esp32s3_wdt_initialize(const char *devpath, enum esp32s3_wdt_inst_e wdt)
|
||||
ESP32S3_MWDT_PRE(lower->wdt, MWDT_CLK_PRESCALER_VALUE);
|
||||
}
|
||||
|
||||
/* Configure auto backup clock when XTAL32K fails */
|
||||
|
||||
#ifdef CONFIG_ESP32S3_XTWDT_BACKUP_CLK_ENABLE
|
||||
if (lower->peripheral == XTAL32K)
|
||||
{
|
||||
/* Estimate frequency of internal RTC oscillator */
|
||||
|
||||
uint32_t rtc_clk_period_us =
|
||||
esp32s3_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);
|
||||
|
||||
ESP32S3_XTWDT_PRE(lower->wdt, xtal32k_clk_factor);
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP32S3_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 0x0098
|
||||
#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 0x00f8
|
||||
#define XTWDT_CLK_PRESCALE_OFFSET 0x00f4
|
||||
#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
|
||||
*/
|
||||
|
@ -82,6 +82,15 @@ int board_wdt_init(void)
|
||||
}
|
||||
#endif /* CONFIG_ESP32S3_RWDT */
|
||||
|
||||
#ifdef CONFIG_ESP32S3_XTWDT
|
||||
ret = esp32s3_wdt_initialize("/dev/watchdog3", ESP32S3_WDT_XTWDT);
|
||||
if (ret < 0)
|
||||
{
|
||||
syslog(LOG_ERR, "Failed to initialize XTWDT: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_ESP32S3_XTWDT */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user