xtensa/esp32s3: Add support for Main System Watchdog Timers
Support for RTC Watchdog Timer is currently in place, but not yet functional due to not yet implemented RTC driver. Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
parent
9603b8f67c
commit
b49ee3d4ed
@ -306,6 +306,10 @@ config ESP32S3_TIMER
|
||||
bool
|
||||
default n
|
||||
|
||||
config ESP32S3_WDT
|
||||
bool
|
||||
default n
|
||||
|
||||
config ESP32S3_UART0
|
||||
bool "UART 0"
|
||||
default n
|
||||
@ -355,6 +359,33 @@ config ESP32S3_TIMER3
|
||||
---help---
|
||||
Enables Timer 3
|
||||
|
||||
config ESP32S3_MWDT0
|
||||
bool "Main System Watchdog Timer (Group 0)"
|
||||
default n
|
||||
select ESP32S3_WDT
|
||||
---help---
|
||||
Includes MWDT0. This watchdog timer is part of the Group 0
|
||||
timer submodule.
|
||||
|
||||
config ESP32S3_MWDT1
|
||||
bool "Main System Watchdog Timer (Group 1)"
|
||||
default n
|
||||
select ESP32S3_WDT
|
||||
---help---
|
||||
Includes MWDT1. This watchdog timer is part of the Group 0
|
||||
timer submodule.
|
||||
|
||||
config ESP32S3_RWDT
|
||||
bool "RTC Watchdog Timer"
|
||||
default n
|
||||
select ESP32S3_WDT
|
||||
---help---
|
||||
Includes RWDT. This watchdog timer is from the RTC module.
|
||||
When it is selected, if the developer sets it to reset on expiration
|
||||
it will reset Main System and the RTC module. If you don't want
|
||||
to have the RTC module reset, please, use the Timers' Module WDTs.
|
||||
They will only reset Main System.
|
||||
|
||||
endmenu # ESP32-S3 Peripheral Selection
|
||||
|
||||
menu "UART configuration"
|
||||
|
@ -79,3 +79,7 @@ ifeq ($(CONFIG_TIMER),y)
|
||||
CHIP_CSRCS += esp32s3_tim_lowerhalf.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_WATCHDOG),y)
|
||||
CHIP_CSRCS += esp32s3_wdt_lowerhalf.c
|
||||
endif
|
||||
|
@ -22,15 +22,830 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtensa.h"
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "esp32s3_wdt.h"
|
||||
#include "xtensa.h"
|
||||
#include "hardware/esp32s3_rtccntl.h"
|
||||
#include "hardware/esp32s3_tim.h"
|
||||
#include "hardware/esp32s3_efuse.h"
|
||||
|
||||
#include "esp32s3_irq.h"
|
||||
#include "esp32s3_wdt.h"
|
||||
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
# error "RWDT not yet supported due to missing RTC driver!"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* 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)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct esp32s3_wdt_priv_s
|
||||
{
|
||||
struct esp32s3_wdt_ops_s *ops;
|
||||
uint32_t base; /* WDT register base address */
|
||||
uint8_t cpu; /* CPU ID */
|
||||
uint8_t periph; /* Peripheral ID */
|
||||
uint8_t irq; /* Interrupt ID */
|
||||
int32_t cpuint; /* CPU interrupt assigned to this WDT */
|
||||
bool inuse; /* Flag indicating if this WDT is in use */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* WDT registers access *****************************************************/
|
||||
|
||||
static void wdt_putreg(struct esp32s3_wdt_dev_s *dev, uint32_t offset,
|
||||
uint32_t value);
|
||||
static void wdt_modifyreg32(struct esp32s3_wdt_dev_s *dev, uint32_t offset,
|
||||
uint32_t clearbits, uint32_t setbits);
|
||||
static uint32_t wdt_getreg(struct esp32s3_wdt_dev_s *dev, uint32_t offset);
|
||||
|
||||
/* WDT operations ***********************************************************/
|
||||
|
||||
static void wdt_start(struct esp32s3_wdt_dev_s *dev);
|
||||
static void wdt_stop(struct esp32s3_wdt_dev_s *dev);
|
||||
static void wdt_enablewp(struct esp32s3_wdt_dev_s *dev);
|
||||
static void wdt_disablewp(struct esp32s3_wdt_dev_s *dev);
|
||||
static void wdt_pre(struct esp32s3_wdt_dev_s *dev,
|
||||
uint16_t value);
|
||||
static int32_t wdt_settimeout(struct esp32s3_wdt_dev_s *dev,
|
||||
uint32_t value,
|
||||
enum esp32s3_wdt_stage_e stage);
|
||||
static void wdt_feed(struct esp32s3_wdt_dev_s *dev);
|
||||
static int32_t wdt_config_stage(struct esp32s3_wdt_dev_s *dev,
|
||||
enum esp32s3_wdt_stage_e stage,
|
||||
enum esp32s3_wdt_stage_action_e cfg);
|
||||
static int32_t wdt_setisr(struct esp32s3_wdt_dev_s *dev,
|
||||
xcpt_t handler, void *arg);
|
||||
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);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* ESP32-S3 WDT ops */
|
||||
|
||||
struct esp32s3_wdt_ops_s esp32s3_mwdt_ops =
|
||||
{
|
||||
.start = wdt_start,
|
||||
.stop = wdt_stop,
|
||||
.enablewp = wdt_enablewp,
|
||||
.disablewp = wdt_disablewp,
|
||||
.pre = wdt_pre,
|
||||
.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 = NULL,
|
||||
.setisr = wdt_setisr,
|
||||
.enableint = wdt_enableint,
|
||||
.disableint = wdt_disableint,
|
||||
.ackint = wdt_ackint,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT0
|
||||
struct esp32s3_wdt_priv_s g_esp32s3_mwdt0_priv =
|
||||
{
|
||||
.ops = &esp32s3_mwdt_ops,
|
||||
.base = TIMG_T0CONFIG_REG(0),
|
||||
.periph = ESP32S3_PERIPH_TG_WDT_LEVEL,
|
||||
.irq = ESP32S3_IRQ_TG_WDT_LEVEL,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT1
|
||||
struct esp32s3_wdt_priv_s g_esp32s3_mwdt1_priv =
|
||||
{
|
||||
.ops = &esp32s3_mwdt_ops,
|
||||
.base = TIMG_T0CONFIG_REG(1),
|
||||
.periph = ESP32S3_PERIPH_TG1_WDT_LEVEL,
|
||||
.irq = ESP32S3_IRQ_TG1_WDT_LEVEL,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
struct esp32s3_wdt_priv_s g_esp32s3_rwdt_priv =
|
||||
{
|
||||
.ops = &esp32s3_rwdt_ops,
|
||||
.base = RTC_CNTL_RTC_OPTIONS0_REG,
|
||||
.periph = ESP32S3_PERIPH_RTC_CORE,
|
||||
.irq = ESP32S3_IRQ_RTC_CORE,
|
||||
.cpuint = -ENOMEM,
|
||||
.inuse = false,
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_putreg
|
||||
*
|
||||
* Description:
|
||||
* Write a 32-bit register value by offset.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
* offset - Offset value to the base address of the WDT device.
|
||||
* value - Value to written to the specified memory region.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_putreg(struct esp32s3_wdt_dev_s *dev, uint32_t offset,
|
||||
uint32_t value)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
putreg32(value, ((struct esp32s3_wdt_priv_s *)dev)->base + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_modifyreg32
|
||||
*
|
||||
* Description:
|
||||
* Atomically modify a 32-bit register value by offset.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
* offset - Offset value to the base address of the WDT device.
|
||||
* clearbits - Bits to be cleared on the specified memory region.
|
||||
* setbits - Bits to be set on the specified memory region.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_modifyreg32(struct esp32s3_wdt_dev_s *dev, uint32_t offset,
|
||||
uint32_t clearbits, uint32_t setbits)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
modifyreg32(((struct esp32s3_wdt_priv_s *)dev)->base + offset,
|
||||
clearbits, setbits);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_getreg
|
||||
*
|
||||
* Description:
|
||||
* Read a 32-bit register value by offset.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
* offset - Offset value to the base address of the WDT device.
|
||||
*
|
||||
* Returned Values:
|
||||
* A 32-bit value from the provided memory region of the WDT device.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t wdt_getreg(struct esp32s3_wdt_dev_s *dev, uint32_t offset)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
return getreg32(((struct esp32s3_wdt_priv_s *)dev)->base + offset);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_start
|
||||
*
|
||||
* Description:
|
||||
* Release the counter.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_start(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, 0, RTC_CNTL_WDT_EN);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, 0, TIMG_WDT_EN);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_config_stage
|
||||
*
|
||||
* Description:
|
||||
* Configure the action to be triggered by a stage on expiration.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
* stage - WDT stage to be configured.
|
||||
* cfg - Action to be executed on stage expiration.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned
|
||||
* to indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int32_t wdt_config_stage(struct esp32s3_wdt_dev_s *dev,
|
||||
enum esp32s3_wdt_stage_e stage,
|
||||
enum esp32s3_wdt_stage_action_e cfg)
|
||||
{
|
||||
int32_t ret = OK;
|
||||
uint32_t mask;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
switch (stage)
|
||||
{
|
||||
case ESP32S3_WDT_STAGE0:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << RTC_CNTL_WDT_STG0_S;
|
||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG0_M,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG0_S;
|
||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG0_M, mask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP32S3_WDT_STAGE1:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << RTC_CNTL_WDT_STG1_S;
|
||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG1_M,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG1_S;
|
||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG1_M, mask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP32S3_WDT_STAGE2:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << RTC_CNTL_WDT_STG2_S;
|
||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG2_M,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG2_S;
|
||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG2_M, mask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP32S3_WDT_STAGE3:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
mask = (uint32_t)cfg << RTC_CNTL_WDT_STG3_S;
|
||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_STG3_M,
|
||||
mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = (uint32_t)cfg << TIMG_WDT_STG3_S;
|
||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_STG3_M, mask);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
wderr("ERROR: unsupported stage %d\n", stage);
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_stop
|
||||
*
|
||||
* Description:
|
||||
* Disable the watchdog.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_stop(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_modifyreg32(dev, RWDT_CONFIG0_OFFSET, RTC_CNTL_WDT_EN, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_modifyreg32(dev, MWDT_CONFIG0_OFFSET, TIMG_WDT_EN, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_enablewp
|
||||
*
|
||||
* Description:
|
||||
* Enable write protection (WP) on registers against accidental writing.
|
||||
* TRM recommends to change any WDT register through this sequence:
|
||||
* - Disable WP
|
||||
* - Do the op
|
||||
* - Re-enable WP
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_enablewp(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, RWDT_WP_REG, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_WP_REG, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_disablewp
|
||||
*
|
||||
* Description:
|
||||
* Disable write protection (WP) on registers against accidental writing.
|
||||
* TRM recommends to change any WDT register through this sequence:
|
||||
* - Disable WP
|
||||
* - Do the op
|
||||
* - Re-enable WP
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_disablewp(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, RWDT_WP_REG, RTC_CNTL_WDT_WKEY_VALUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_WP_REG, TIMG_WDT_WKEY_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_pre
|
||||
*
|
||||
* Description:
|
||||
* Set a prescale value.
|
||||
* The MWDT clock period is 12.5 ns * value (pre).
|
||||
* NOTE: There's no prescaler register for RWDT and its source clock is
|
||||
* clocked from the RTC slow clock.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
* pre - Prescaler value to be configured.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_pre(struct esp32s3_wdt_dev_s *dev, uint16_t pre)
|
||||
{
|
||||
uint32_t mask = (uint32_t)pre << TIMG_WDT_CLK_PRESCALE_S;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
wdt_modifyreg32(dev, MWDT_CLK_PRESCALE_OFFSET, TIMG_WDT_CLK_PRESCALE_M,
|
||||
mask);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_settimeout
|
||||
*
|
||||
* Description:
|
||||
* Set the WDT timeout.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
* value - Timeout value in number of WDT cycles.
|
||||
* stage - Stage whose timeout value needs to be configured.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned
|
||||
* to indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int32_t wdt_settimeout(struct esp32s3_wdt_dev_s *dev, uint32_t value,
|
||||
enum esp32s3_wdt_stage_e stage)
|
||||
{
|
||||
int32_t ret = OK;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
switch (stage)
|
||||
{
|
||||
case ESP32S3_WDT_STAGE0:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
/* The timeout of only stage 0 happens at:
|
||||
* Thold0 = RTC_CNTL_WDT_STG0_HOLD << (EFUSE_WDT_DELAY_SEL + 1)
|
||||
*/
|
||||
|
||||
uint32_t delay;
|
||||
delay = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG,
|
||||
EFUSE_WDT_DELAY_SEL);
|
||||
value = value >> (delay + 1);
|
||||
wdt_putreg(dev, RWDT_STAGE0_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_STAGE0_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP32S3_WDT_STAGE1:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, RWDT_STAGE1_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_STAGE1_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP32S3_WDT_STAGE2:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, RWDT_STAGE2_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_STAGE2_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ESP32S3_WDT_STAGE3:
|
||||
{
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, RWDT_STAGE3_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_STAGE3_TIMEOUT_OFFSET, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
wderr("ERROR: unsupported stage %d\n", stage);
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_feed
|
||||
*
|
||||
* Description:
|
||||
* Feed the watchdog.
|
||||
* The watchdog timer returns to stage 0 and its counter restarts from 0.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_feed(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_modifyreg32(dev, RWDT_FEED_OFFSET, 0, RTC_CNTL_RTC_WDT_FEED);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_FEED_OFFSET, TIMG_WDT_FEED);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_setisr
|
||||
*
|
||||
* Description:
|
||||
* Allocate a Level CPU Interrupt, connect the peripheral source to this
|
||||
* Interrupt, register the callback and enable the interrupt.
|
||||
* In case a NULL handler is provided, deallocate the interrupt and
|
||||
* unregister the previously provided handler.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
* handler - Callback to be invoked on watchdog timer interrupt.
|
||||
* arg - Argument to be passed to the handler callback.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success; A negated errno value is returned
|
||||
* to indicate the nature of any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int32_t wdt_setisr(struct esp32s3_wdt_dev_s *dev, xcpt_t handler,
|
||||
void *arg)
|
||||
{
|
||||
struct esp32s3_wdt_priv_s *wdt = NULL;
|
||||
int32_t ret = OK;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
wdt = (struct esp32s3_wdt_priv_s *)dev;
|
||||
|
||||
/* Disable interrupt when callback is removed. */
|
||||
|
||||
if (handler == NULL)
|
||||
{
|
||||
/* If a CPU Interrupt was previously allocated, then deallocate it */
|
||||
|
||||
if (wdt->cpuint >= 0)
|
||||
{
|
||||
/* Disable CPU Interrupt, free a previously allocated
|
||||
* CPU Interrupt
|
||||
*/
|
||||
|
||||
up_disable_irq(wdt->irq);
|
||||
esp32s3_teardown_irq(wdt->cpu, wdt->periph, wdt->cpuint);
|
||||
irq_detach(wdt->irq);
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Otherwise set callback and enable interrupt. */
|
||||
|
||||
else
|
||||
{
|
||||
/* Set up to receive peripheral interrupts on the current CPU */
|
||||
|
||||
wdt->cpu = up_cpu_index();
|
||||
wdt->cpuint = esp32s3_setup_irq(wdt->cpu, wdt->periph,
|
||||
1, ESP32S3_CPUINT_LEVEL);
|
||||
if (wdt->cpuint < 0)
|
||||
{
|
||||
wderr("ERROR: No CPU Interrupt available");
|
||||
ret = wdt->cpuint;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Associate an IRQ Number (from the WDT) to an ISR */
|
||||
|
||||
ret = irq_attach(wdt->irq, handler, arg);
|
||||
|
||||
if (ret != OK)
|
||||
{
|
||||
esp32s3_teardown_irq(wdt->cpu, wdt->periph, wdt->cpuint);
|
||||
wderr("ERROR: Failed to associate an IRQ Number");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Enable the CPU Interrupt that is linked to the WDT */
|
||||
|
||||
up_enable_irq(wdt->irq);
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_enableint
|
||||
*
|
||||
* Description:
|
||||
* Enable a Level Interrupt at timeout.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_enableint(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, 0,
|
||||
RTC_CNTL_RTC_WDT_INT_ENA);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, 0, TIMG_WDT_INT_ENA);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_disableint
|
||||
*
|
||||
* Description:
|
||||
* Disable a Level Interrupt at timeout.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_disableint(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_modifyreg32(dev, RWDT_INT_ENA_REG_OFFSET, RTC_CNTL_RTC_WDT_INT_ENA,
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_modifyreg32(dev, MWDT_INT_ENA_REG_OFFSET, TIMG_WDT_INT_ENA, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_ackint
|
||||
*
|
||||
* Description:
|
||||
* Acknowledge an interrupt.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void wdt_ackint(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
wdt_putreg(dev, RWDT_INT_CLR_REG_OFFSET, RTC_CNTL_RTC_WDT_INT_CLR);
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt_putreg(dev, MWDT_INT_CLR_REG_OFFSET, TIMG_WDT_INT_CLR);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_wdt_init
|
||||
*
|
||||
* Description:
|
||||
* Initialize WDT device.
|
||||
*
|
||||
* Parameters:
|
||||
* wdt_id - A Watchdog Timer instance to be initialized.
|
||||
*
|
||||
* Return Values:
|
||||
* Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct esp32s3_wdt_dev_s *esp32s3_wdt_init(enum esp32s3_wdt_inst_e wdt_id)
|
||||
{
|
||||
struct esp32s3_wdt_priv_s *wdt = NULL;
|
||||
|
||||
/* Get WDT instance */
|
||||
|
||||
switch (wdt_id)
|
||||
{
|
||||
#ifdef CONFIG_ESP32S3_MWDT0
|
||||
case ESP32S3_WDT_MWDT0:
|
||||
{
|
||||
wdt = &g_esp32s3_mwdt0_priv;
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT1
|
||||
case ESP32S3_WDT_MWDT1:
|
||||
{
|
||||
wdt = &g_esp32s3_mwdt1_priv;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
case ESP32S3_WDT_RWDT:
|
||||
{
|
||||
wdt = &g_esp32s3_rwdt_priv;
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
wderr("ERROR: unsupported WDT %d\n", wdt_id);
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* If some code is using it then sends an error message,
|
||||
* Otherwise, inform it has been used.
|
||||
*/
|
||||
|
||||
if (wdt->inuse == true)
|
||||
{
|
||||
wderr("ERROR: WDT %d is already in use\n", wdt_id);
|
||||
wdt = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
wdt->inuse = true;
|
||||
}
|
||||
|
||||
errout:
|
||||
return (struct esp32s3_wdt_dev_s *)wdt;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_wdt_early_deinit
|
||||
*
|
||||
@ -48,3 +863,65 @@ void esp32s3_wdt_early_deinit(void)
|
||||
putreg32(regval, RTC_CNTL_RTC_WDTCONFIG0_REG);
|
||||
putreg32(0, RTC_CNTL_RTC_WDTWPROTECT_REG);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_wdt_deinit
|
||||
*
|
||||
* Description:
|
||||
* Deinitialize a WDT device.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void esp32s3_wdt_deinit(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
struct esp32s3_wdt_priv_s *wdt = NULL;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
wdt = (struct esp32s3_wdt_priv_s *)dev;
|
||||
|
||||
wdt->inuse = false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_wdt_is_running
|
||||
*
|
||||
* Description:
|
||||
* Check whether the WDT is already started.
|
||||
*
|
||||
* Parameters:
|
||||
* dev - Pointer to the driver state structure.
|
||||
*
|
||||
* Returned Values:
|
||||
* true if the Watchdog Timer is already started, false otherwise.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool esp32s3_wdt_is_running(struct esp32s3_wdt_dev_s *dev)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
|
||||
DEBUGASSERT(dev != NULL);
|
||||
|
||||
if (IS_RWDT(dev))
|
||||
{
|
||||
status = wdt_getreg(dev, RWDT_CONFIG0_OFFSET);
|
||||
if ((status & RTC_CNTL_WDT_EN) == RTC_CNTL_WDT_EN)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = wdt_getreg(dev, MWDT_CONFIG0_OFFSET);
|
||||
if ((status & TIMG_WDT_EN) == TIMG_WDT_EN)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -25,10 +25,125 @@
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Helpers ******************************************************************/
|
||||
|
||||
#define ESP32S3_WDT_START(d) ((d)->ops->start(d))
|
||||
#define ESP32S3_WDT_STOP(d) ((d)->ops->stop(d))
|
||||
#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_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_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))
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Instances of Watchdog Timer */
|
||||
|
||||
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) */
|
||||
};
|
||||
|
||||
/* Stages of a Watchdog Timer. A WDT has 4 stages. */
|
||||
|
||||
enum esp32s3_wdt_stage_e
|
||||
{
|
||||
ESP32S3_WDT_STAGE0 = 0, /* Stage 0 */
|
||||
ESP32S3_WDT_STAGE1 = 1, /* Stage 1 */
|
||||
ESP32S3_WDT_STAGE2 = 2, /* Stage 2 */
|
||||
ESP32S3_WDT_STAGE3 = 3 /* Stage 3 */
|
||||
};
|
||||
|
||||
/**
|
||||
* Behavior of the WDT stage if it times out.
|
||||
*
|
||||
* @note These enum values should be compatible with the
|
||||
* corresponding register field values.
|
||||
*/
|
||||
|
||||
enum esp32s3_wdt_stage_action_e
|
||||
{
|
||||
ESP32S3_WDT_STAGE_ACTION_OFF = 0, /* Disabled. This stage will have no effects on the system. */
|
||||
ESP32S3_WDT_STAGE_ACTION_INT = 1, /* Trigger an interrupt when the stage expires. */
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_CPU = 2, /* Reset a CPU core when the stage expires. */
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_SYSTEM = 3, /* Reset the main system when the stage expires.
|
||||
* This includes the CPU and all peripherals.
|
||||
* The RTC is an exception and will not be reset.
|
||||
*/
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_RTC = 4 /* Reset the main system and the RTC when the stage expires.
|
||||
* ONLY AVAILABLE FOR RWDT.
|
||||
*/
|
||||
};
|
||||
|
||||
/* ESP32-S3 WDT device */
|
||||
|
||||
struct esp32s3_wdt_dev_s
|
||||
{
|
||||
struct esp32s3_wdt_ops_s *ops;
|
||||
};
|
||||
|
||||
/* ESP32-S3 WDT operations
|
||||
*
|
||||
* This is a struct containing the pointers to the WDT operations.
|
||||
*/
|
||||
|
||||
struct esp32s3_wdt_ops_s
|
||||
{
|
||||
/* WDT tasks */
|
||||
|
||||
void (*start)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*stop)(struct esp32s3_wdt_dev_s *dev);
|
||||
|
||||
/* WDT configuration */
|
||||
|
||||
void (*enablewp)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*disablewp)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*pre)(struct esp32s3_wdt_dev_s *dev, uint16_t value);
|
||||
int32_t (*settimeout)(struct esp32s3_wdt_dev_s *dev,
|
||||
uint32_t value,
|
||||
enum esp32s3_wdt_stage_e stage);
|
||||
void (*feed)(struct esp32s3_wdt_dev_s *dev);
|
||||
int32_t (*stg_conf)(struct esp32s3_wdt_dev_s *dev,
|
||||
enum esp32s3_wdt_stage_e stage,
|
||||
enum esp32s3_wdt_stage_action_e conf);
|
||||
uint16_t (*rtc_clk)(struct esp32s3_wdt_dev_s *dev);
|
||||
|
||||
/* WDT interrupts */
|
||||
|
||||
int32_t (*setisr)(struct esp32s3_wdt_dev_s *dev, xcpt_t handler,
|
||||
void *arg);
|
||||
void (*enableint)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*disableint)(struct esp32s3_wdt_dev_s *dev);
|
||||
void (*ackint)(struct esp32s3_wdt_dev_s *dev);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
struct esp32s3_wdt_dev_s *esp32s3_wdt_init(enum esp32s3_wdt_inst_e wdt_id);
|
||||
void esp32s3_wdt_early_deinit(void);
|
||||
void esp32s3_wdt_deinit(struct esp32s3_wdt_dev_s *dev);
|
||||
bool esp32s3_wdt_is_running(struct esp32s3_wdt_dev_s *dev);
|
||||
|
||||
#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WDT_H */
|
||||
|
741
arch/xtensa/src/esp32s3/esp32s3_wdt_lowerhalf.c
Normal file
741
arch/xtensa/src/esp32s3/esp32s3_wdt_lowerhalf.c
Normal file
@ -0,0 +1,741 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/esp32s3/esp32s3_wdt_lowerhalf.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/timers/watchdog.h>
|
||||
|
||||
#include "xtensa.h"
|
||||
#include "hardware/esp32s3_soc.h"
|
||||
|
||||
#include "esp32s3_wdt.h"
|
||||
#include "esp32s3_wdt_lowerhalf.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* MWDT clock period in microseconds */
|
||||
|
||||
#define MWDT_CLK_PERIOD_US (500)
|
||||
|
||||
/* Number of MWDT cycles per microseconds */
|
||||
|
||||
#define MWDT_CYCLES_PER_MS (USEC_PER_MSEC / MWDT_CLK_PERIOD_US)
|
||||
|
||||
/* Convert MWDT timeout cycles to milliseconds */
|
||||
|
||||
#define MWDT_TIMEOUT_MS(t) ((t) * MWDT_CYCLES_PER_MS)
|
||||
|
||||
/* Maximum number of MWDT cycles supported for timeout */
|
||||
|
||||
#define MWDT_MAX_TIMEOUT_MS (UINT32_MAX / MWDT_CYCLES_PER_MS)
|
||||
|
||||
/* MWDT clock prescaler value */
|
||||
|
||||
#define MWDT_CLK_PRESCALER_VALUE (MWDT_CLK_PERIOD_US * NSEC_PER_USEC / 12.5)
|
||||
|
||||
/* Maximum number of cycles supported for a RWDT stage timeout */
|
||||
|
||||
#define RWDT_FULL_STAGE (UINT32_MAX)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum wdt_peripheral_e
|
||||
{
|
||||
RTC,
|
||||
TIMER,
|
||||
};
|
||||
|
||||
/* This structure provides the private representation of the "lower-half"
|
||||
* driver state structure. This structure must be cast-compatible with the
|
||||
* well-known watchdog_lowerhalf_s structure.
|
||||
*/
|
||||
|
||||
struct esp32s3_wdt_lowerhalf_s
|
||||
{
|
||||
const struct watchdog_ops_s *ops; /* Lower half operations */
|
||||
struct esp32s3_wdt_dev_s *wdt; /* ESP32-S3 watchdog driver */
|
||||
uint32_t timeout; /* The current timeout */
|
||||
enum wdt_peripheral_e peripheral; /* Indicates if it is from RTC or Timer Module */
|
||||
uint32_t lastreset; /* The last reset time */
|
||||
bool started; /* True: Timer has been started */
|
||||
xcpt_t handler; /* User Handler */
|
||||
void *upper; /* Pointer to watchdog_upperhalf_s */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/* Interrupt handling *******************************************************/
|
||||
|
||||
static int wdt_handler(int irq, void *context, void *arg);
|
||||
|
||||
/* "Lower half" driver methods **********************************************/
|
||||
|
||||
static int wdt_lh_start(struct watchdog_lowerhalf_s *lower);
|
||||
static int wdt_lh_stop(struct watchdog_lowerhalf_s *lower);
|
||||
static int wdt_lh_keepalive(struct watchdog_lowerhalf_s *lower);
|
||||
static int wdt_lh_getstatus(struct watchdog_lowerhalf_s *lower,
|
||||
struct watchdog_status_s *status);
|
||||
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);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* "Lower half" driver methods */
|
||||
|
||||
static const struct watchdog_ops_s g_esp32s3_wdg_ops =
|
||||
{
|
||||
.start = wdt_lh_start,
|
||||
.stop = wdt_lh_stop,
|
||||
.keepalive = wdt_lh_keepalive,
|
||||
.getstatus = wdt_lh_getstatus,
|
||||
.settimeout = wdt_lh_settimeout,
|
||||
.capture = wdt_lh_capture,
|
||||
.ioctl = NULL,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT0
|
||||
/* MWDT0 lower-half */
|
||||
|
||||
static struct esp32s3_wdt_lowerhalf_s g_esp32s3_mwdt0_lowerhalf =
|
||||
{
|
||||
.ops = &g_esp32s3_wdg_ops,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT1
|
||||
/* MWDT1 lower-half */
|
||||
|
||||
static struct esp32s3_wdt_lowerhalf_s g_esp32s3_mwdt1_lowerhalf =
|
||||
{
|
||||
.ops = &g_esp32s3_wdg_ops,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
/* RWDT lower-half */
|
||||
|
||||
static struct esp32s3_wdt_lowerhalf_s g_esp32s3_rwdt_lowerhalf =
|
||||
{
|
||||
.ops = &g_esp32s3_wdg_ops,
|
||||
};
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_lh_start
|
||||
*
|
||||
* Description:
|
||||
* Start the watchdog timer, register a callback if there is one and
|
||||
* enables interrupt, otherwise, configure it to reset system on
|
||||
* expiration.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int wdt_lh_start(struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *priv =
|
||||
(struct esp32s3_wdt_lowerhalf_s *)lower;
|
||||
int ret = OK;
|
||||
|
||||
wdinfo("Entry: wdt_lh_start\n");
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
if (priv->started == true)
|
||||
{
|
||||
/* Return EBUSY to indicate that the timer was already running */
|
||||
|
||||
ret = -EBUSY;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* If WDT was not started yet */
|
||||
|
||||
else
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
priv->started = true;
|
||||
|
||||
/* Unlock WDT */
|
||||
|
||||
ESP32S3_WDT_UNLOCK(priv->wdt);
|
||||
|
||||
/* No User Handler */
|
||||
|
||||
if (priv->handler == NULL)
|
||||
{
|
||||
/* Then configure it to reset on wdt expiration */
|
||||
|
||||
if (priv->peripheral == TIMER)
|
||||
{
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_RTC);
|
||||
}
|
||||
}
|
||||
|
||||
/* User handler was already provided */
|
||||
|
||||
else
|
||||
{
|
||||
/* Then configure it to call the user handler on wdt expiration */
|
||||
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_INT);
|
||||
|
||||
/* Set the lower-half handler and enable interrupt */
|
||||
|
||||
flags = enter_critical_section();
|
||||
ESP32S3_WDT_SETISR(priv->wdt, wdt_handler, priv);
|
||||
leave_critical_section(flags);
|
||||
ESP32S3_WDT_ENABLEINT(priv->wdt);
|
||||
}
|
||||
|
||||
flags = enter_critical_section();
|
||||
priv->lastreset = clock_systime_ticks();
|
||||
ESP32S3_WDT_START(priv->wdt);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Lock it again */
|
||||
|
||||
ESP32S3_WDT_LOCK(priv->wdt);
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_lh_stop
|
||||
*
|
||||
* Description:
|
||||
* Stop the watchdog timer. In case a callback was previously configured,
|
||||
* unregister and deallocate it.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int wdt_lh_stop(struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *priv =
|
||||
(struct esp32s3_wdt_lowerhalf_s *)lower;
|
||||
|
||||
/* Unlock WDT */
|
||||
|
||||
ESP32S3_WDT_UNLOCK(priv->wdt);
|
||||
|
||||
/* Disable the WDT */
|
||||
|
||||
ESP32S3_WDT_STOP(priv->wdt);
|
||||
|
||||
/* In case there is some callback registered, disable and deallocate */
|
||||
|
||||
if (priv->handler != NULL)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
ESP32S3_WDT_DISABLEINT(priv->wdt);
|
||||
|
||||
flags = enter_critical_section();
|
||||
ESP32S3_WDT_SETISR(priv->wdt, NULL, NULL);
|
||||
leave_critical_section(flags);
|
||||
}
|
||||
|
||||
/* Lock it again */
|
||||
|
||||
ESP32S3_WDT_LOCK(priv->wdt);
|
||||
|
||||
priv->started = false;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_lh_keepalive
|
||||
*
|
||||
* Description:
|
||||
* Reset the watchdog timer, prevent any
|
||||
* imminent watchdog timeouts. This is sometimes referred as "pinging"
|
||||
* the watchdog timer or "petting the dog".
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
*
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int wdt_lh_keepalive(struct watchdog_lowerhalf_s *lower)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *priv =
|
||||
(struct esp32s3_wdt_lowerhalf_s *)lower;
|
||||
irqstate_t flags;
|
||||
|
||||
wdinfo("Entry\n");
|
||||
|
||||
/* Unlock */
|
||||
|
||||
ESP32S3_WDT_UNLOCK(priv->wdt);
|
||||
|
||||
/* Feed the dog and updates the lastreset variable */
|
||||
|
||||
flags = enter_critical_section();
|
||||
priv->lastreset = clock_systime_ticks();
|
||||
ESP32S3_WDT_FEED(priv->wdt);
|
||||
leave_critical_section(flags);
|
||||
|
||||
/* Lock */
|
||||
|
||||
ESP32S3_WDT_LOCK(priv->wdt);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_lh_getstatus
|
||||
*
|
||||
* Description:
|
||||
* Get the current watchdog timer status
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of
|
||||
* the "lower-half" driver state structure.
|
||||
* status - The location to return the watchdog status information.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int wdt_lh_getstatus(struct watchdog_lowerhalf_s *lower,
|
||||
struct watchdog_status_s *status)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *priv =
|
||||
(struct esp32s3_wdt_lowerhalf_s *)lower;
|
||||
uint32_t ticks;
|
||||
uint32_t elapsed;
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Flags */
|
||||
|
||||
status->flags = 0;
|
||||
|
||||
/* If no handler was settled, then RESET on expiration.
|
||||
* Otherwise, call the user handler.
|
||||
*/
|
||||
|
||||
if (priv->handler == NULL)
|
||||
{
|
||||
status->flags |= WDFLAGS_RESET;
|
||||
}
|
||||
else
|
||||
{
|
||||
status->flags |= WDFLAGS_CAPTURE;
|
||||
}
|
||||
|
||||
if (priv->started)
|
||||
{
|
||||
status->flags |= WDFLAGS_ACTIVE;
|
||||
}
|
||||
|
||||
/* Return the current timeout in milliseconds */
|
||||
|
||||
status->timeout = priv->timeout;
|
||||
|
||||
/* Get the elapsed time since the last ping */
|
||||
|
||||
ticks = clock_systime_ticks() - priv->lastreset;
|
||||
elapsed = (uint32_t)TICK2MSEC(ticks);
|
||||
|
||||
if (elapsed < priv->timeout)
|
||||
{
|
||||
/* Return the approximate time until the watchdog timer expiration */
|
||||
|
||||
status->timeleft = priv->timeout - elapsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
status->timeleft = 0;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_lh_settimeout
|
||||
*
|
||||
* Description:
|
||||
* Set a new timeout value (and reset the watchdog timer)
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of
|
||||
* the "lower-half" driver state structure.
|
||||
* timeout - The new timeout value in milliseconds.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int wdt_lh_settimeout(struct watchdog_lowerhalf_s *lower,
|
||||
uint32_t timeout)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *priv =
|
||||
(struct esp32s3_wdt_lowerhalf_s *)lower;
|
||||
uint16_t rtc_cycles = 0;
|
||||
uint32_t rtc_ms_max = 0;
|
||||
|
||||
wdinfo("Entry: timeout=%" PRIu32 "\n", timeout);
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
/* Unlock WDT */
|
||||
|
||||
ESP32S3_WDT_UNLOCK(priv->wdt);
|
||||
|
||||
/* Write the timeout value */
|
||||
|
||||
priv->timeout = timeout;
|
||||
|
||||
/* Watchdog from Timer Module */
|
||||
|
||||
if (priv->peripheral == TIMER)
|
||||
{
|
||||
/* Is this timeout a valid value for Timer's WDT? */
|
||||
|
||||
if (timeout == 0 || timeout > MWDT_MAX_TIMEOUT_MS)
|
||||
{
|
||||
wderr("Cannot represent timeout=%" PRIu32 " > %" PRIu32 "\n",
|
||||
timeout, MWDT_MAX_TIMEOUT_MS);
|
||||
return -ERANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP32S3_WDT_STO(priv->wdt, MWDT_TIMEOUT_MS(timeout),
|
||||
ESP32S3_WDT_STAGE0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Watchdog from RTC Module */
|
||||
|
||||
else
|
||||
{
|
||||
rtc_cycles = ESP32S3_RWDT_CLK(priv->wdt);
|
||||
rtc_ms_max = (RWDT_FULL_STAGE / (uint32_t)rtc_cycles);
|
||||
|
||||
/* Is this timeout a valid value for RTC WDT? */
|
||||
|
||||
if (timeout == 0 || timeout > rtc_ms_max)
|
||||
{
|
||||
wderr("Cannot represent timeout=%" PRIu32 " > %" PRIu32 "\n",
|
||||
timeout, rtc_ms_max);
|
||||
return -ERANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeout = timeout * rtc_cycles;
|
||||
ESP32S3_WDT_STO(priv->wdt, timeout, ESP32S3_WDT_STAGE0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the wdt */
|
||||
|
||||
ESP32S3_WDT_FEED(priv->wdt);
|
||||
|
||||
/* Lock it again */
|
||||
|
||||
ESP32S3_WDT_LOCK(priv->wdt);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: wdt_lh_capture
|
||||
*
|
||||
* Description:
|
||||
* Don't reset on watchdog timer timeout; instead, call this user provider
|
||||
* timeout handler. NOTE: Providing handler==NULL will restore the reset
|
||||
* behavior.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer the publicly visible representation of the
|
||||
* "lower-half" driver state structure.
|
||||
* newhandler - The new watchdog expiration function pointer. If this
|
||||
* function pointer is NULL, then the reset-on-expiration
|
||||
* behavior is restored,
|
||||
*
|
||||
* Returned Value:
|
||||
* The previous watchdog expiration function pointer or NULL if there was
|
||||
* no previous function pointer, i.e., if the previous behavior was
|
||||
* reset-on-expiration (NULL is also returned if an error occurs).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static xcpt_t wdt_lh_capture(struct watchdog_lowerhalf_s *lower,
|
||||
xcpt_t handler)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *priv =
|
||||
(struct esp32s3_wdt_lowerhalf_s *)lower;
|
||||
irqstate_t flags;
|
||||
xcpt_t oldhandler;
|
||||
|
||||
DEBUGASSERT(priv);
|
||||
|
||||
wdinfo("Entry: handler=0x%" PRIxPTR "\n", (uintptr_t) handler);
|
||||
|
||||
/* Get the old handler to return it */
|
||||
|
||||
oldhandler = priv->handler;
|
||||
|
||||
ESP32S3_WDT_UNLOCK(priv->wdt);
|
||||
|
||||
flags = enter_critical_section();
|
||||
|
||||
/* Save the new user handler */
|
||||
|
||||
priv->handler = handler;
|
||||
|
||||
/* There is a user callback and the timer has already been started.
|
||||
* The user wants to set a callback after starting the wdt or wants to
|
||||
* change the callback function once a callback has already been settled.
|
||||
*/
|
||||
|
||||
if (priv->handler != NULL && priv->started == true)
|
||||
{
|
||||
/* Deallocate the previous allocated interrupt
|
||||
* If there is a previous allocated interrupt.
|
||||
*/
|
||||
|
||||
if (oldhandler != NULL)
|
||||
{
|
||||
ESP32S3_WDT_SETISR(priv->wdt, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If it was previous configured to reset on timeout
|
||||
* then change to interrupt.
|
||||
*/
|
||||
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_INT);
|
||||
}
|
||||
|
||||
/* Set the lower-half handler and enable interrupt */
|
||||
|
||||
ESP32S3_WDT_SETISR(priv->wdt, wdt_handler, priv);
|
||||
ESP32S3_WDT_ENABLEINT(priv->wdt);
|
||||
}
|
||||
|
||||
/* In case the user wants to disable the callback */
|
||||
|
||||
else
|
||||
{
|
||||
ESP32S3_WDT_DISABLEINT(priv->wdt);
|
||||
ESP32S3_WDT_SETISR(priv->wdt, NULL, NULL);
|
||||
|
||||
/* Then configure it to reset on WDT expiration */
|
||||
|
||||
if (priv->peripheral == TIMER)
|
||||
{
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||
}
|
||||
else
|
||||
{
|
||||
ESP32S3_WDT_STG_CONF(priv->wdt, ESP32S3_WDT_STAGE0,
|
||||
ESP32S3_WDT_STAGE_ACTION_RESET_RTC);
|
||||
}
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
ESP32S3_WDT_LOCK(priv->wdt);
|
||||
return oldhandler;
|
||||
}
|
||||
|
||||
/* Interrupt handling *******************************************************/
|
||||
|
||||
static int wdt_handler(int irq, void *context, void *arg)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *priv = arg;
|
||||
|
||||
/* Run the user callback */
|
||||
|
||||
priv->handler(irq, context, priv->upper);
|
||||
|
||||
/* Clear the Interrupt */
|
||||
|
||||
ESP32S3_WDT_UNLOCK(priv->wdt);
|
||||
|
||||
ESP32S3_WDT_ACKINT(priv->wdt);
|
||||
|
||||
ESP32S3_WDT_LOCK(priv->wdt);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_wdt_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the watchdog timer. The watchdog timer is initialized
|
||||
* and registered as 'devpath'.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the watchdog. This should
|
||||
* be of the form /dev/watchdogX
|
||||
* wdt - WDT instance to be initialized.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32s3_wdt_initialize(const char *devpath, enum esp32s3_wdt_inst_e wdt)
|
||||
{
|
||||
struct esp32s3_wdt_lowerhalf_s *lower = NULL;
|
||||
int ret = OK;
|
||||
|
||||
DEBUGASSERT(devpath);
|
||||
|
||||
switch (wdt)
|
||||
{
|
||||
#ifdef CONFIG_ESP32S3_MWDT0
|
||||
case ESP32S3_WDT_MWDT0:
|
||||
{
|
||||
lower = &g_esp32s3_mwdt0_lowerhalf;
|
||||
lower->peripheral = TIMER;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_MWDT1
|
||||
case ESP32S3_WDT_MWDT1:
|
||||
{
|
||||
lower = &g_esp32s3_mwdt1_lowerhalf;
|
||||
lower->peripheral = TIMER;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ESP32S3_RWDT
|
||||
case ESP32S3_WDT_RWDT:
|
||||
{
|
||||
lower = &g_esp32s3_rwdt_lowerhalf;
|
||||
lower->peripheral = RTC;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
{
|
||||
ret = -ENODEV;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the elements of lower-half state structure */
|
||||
|
||||
lower->handler = NULL;
|
||||
lower->timeout = 0;
|
||||
lower->wdt = esp32s3_wdt_init(wdt);
|
||||
|
||||
if (lower->wdt == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
lower->started = esp32s3_wdt_is_running(lower->wdt);
|
||||
|
||||
ESP32S3_WDT_UNLOCK(lower->wdt);
|
||||
|
||||
/* If it is a Main System Watchdog Timer configure the Prescale to
|
||||
* have a 500us period.
|
||||
*/
|
||||
|
||||
if (lower->peripheral == TIMER)
|
||||
{
|
||||
ESP32S3_MWDT_PRE(lower->wdt, MWDT_CLK_PRESCALER_VALUE);
|
||||
}
|
||||
|
||||
ESP32S3_WDT_LOCK(lower->wdt);
|
||||
|
||||
/* Register the watchdog driver as /dev/watchdogX. If the registration goes
|
||||
* right the returned value from watchdog_register is a pointer to
|
||||
* watchdog_upperhalf_s that can be either used with watchdog_unregister()
|
||||
* or with the handler's arg.
|
||||
*/
|
||||
|
||||
lower->upper = watchdog_register(devpath,
|
||||
(struct watchdog_lowerhalf_s *)lower);
|
||||
if (lower->upper == NULL)
|
||||
{
|
||||
/* The actual cause of the failure may have been a failure to allocate
|
||||
* perhaps a failure to register the watchdog driver (such as if the
|
||||
* 'devpath' were not unique). We know here but we return EEXIST to
|
||||
* indicate the failure (implying the non-unique devpath).
|
||||
*/
|
||||
|
||||
ret = -EEXIST;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
57
arch/xtensa/src/esp32s3/esp32s3_wdt_lowerhalf.h
Normal file
57
arch/xtensa/src/esp32s3/esp32s3_wdt_lowerhalf.h
Normal file
@ -0,0 +1,57 @@
|
||||
/****************************************************************************
|
||||
* arch/xtensa/src/esp32s3/esp32s3_wdt_lowerhalf.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WDT_LOWERHALF_H
|
||||
#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WDT_LOWERHALF_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "esp32s3_wdt.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_wdt_initialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize the watchdog timer. The watchdog timer is initialized
|
||||
* and registered as 'devpath'.
|
||||
*
|
||||
* Input Parameters:
|
||||
* devpath - The full path to the watchdog.
|
||||
* wdt - WDT instance to be initialized.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned on
|
||||
* any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int esp32s3_wdt_initialize(const char *devpath, enum esp32s3_wdt_inst_e wdt);
|
||||
|
||||
#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_WDT_LOWERHALF_H */
|
3245
arch/xtensa/src/esp32s3/hardware/esp32s3_efuse.h
Normal file
3245
arch/xtensa/src/esp32s3/hardware/esp32s3_efuse.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -31,12 +31,49 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Offset relative to each watchdog timer instance memory base */
|
||||
|
||||
#define RWDT_CONFIG0_OFFSET 0x0090
|
||||
|
||||
/* RWDT */
|
||||
|
||||
#define RWDT_STAGE0_TIMEOUT_OFFSET 0x0094
|
||||
#define RWDT_STAGE1_TIMEOUT_OFFSET 0x0098
|
||||
#define RWDT_STAGE2_TIMEOUT_OFFSET 0x009c
|
||||
#define RWDT_STAGE3_TIMEOUT_OFFSET 0x00a0
|
||||
#define RWDT_FEED_OFFSET 0x00a4
|
||||
#define RWDT_WP_REG 0x00a8
|
||||
#define RWDT_INT_ENA_REG_OFFSET 0x0040
|
||||
#define RWDT_INT_CLR_REG_OFFSET 0x004c
|
||||
|
||||
/* The value that needs to be written to RTC_CNTL_WDT_WKEY to
|
||||
* write-enable the wdt registers
|
||||
*/
|
||||
|
||||
#define RTC_CNTL_WDT_WKEY_VALUE 0x50d83aa1
|
||||
|
||||
/* The value that needs to be written to RTC_CNTL_SWD_WPROTECT_REG
|
||||
* to write-enable the wdt registers
|
||||
*/
|
||||
|
||||
#define RTC_CNTL_SWD_WKEY_VALUE 0x8f1d312a
|
||||
|
||||
/* Possible values for RTC_CNTL_WDT_CPU_RESET_LENGTH
|
||||
* and RTC_CNTL_WDT_SYS_RESET_LENGTH
|
||||
*/
|
||||
|
||||
#define RTC_WDT_RESET_LENGTH_100_NS 0
|
||||
#define RTC_WDT_RESET_LENGTH_200_NS 1
|
||||
#define RTC_WDT_RESET_LENGTH_300_NS 2
|
||||
#define RTC_WDT_RESET_LENGTH_400_NS 3
|
||||
#define RTC_WDT_RESET_LENGTH_500_NS 4
|
||||
#define RTC_WDT_RESET_LENGTH_800_NS 5
|
||||
#define RTC_WDT_RESET_LENGTH_1600_NS 6
|
||||
#define RTC_WDT_RESET_LENGTH_3200_NS 7
|
||||
|
||||
#define RTC_CNTL_TIME0_REG RTC_CNTL_TIME_LOW0_REG
|
||||
#define RTC_CNTL_TIME1_REG RTC_CNTL_TIME_HIGH0_REG
|
||||
|
||||
/* RTC_CNTL_RTC_OPTIONS0_REG register
|
||||
* RTC common configure register
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user