手册
《IMX8MMRM.pdf》 - 6.6 Watchdog Timer (WDOG)
代码
SDK_2.5.0_EVK-MIMX8MM/boards/evkmimx8mm/driver_examples/wdog/wdog.c
SDK_2.5.0_EVK-MIMX8MM/devices/MIMX8MM6/drivers/fsl_wdog.c
SDK_2.5.0_EVK-MIMX8MM/devices/MIMX8MM6/drivers/fsl_wdog.h
SDK_2.5.0_EVK-MIMX8MM/devices/MIMX8MM6/MIMX8MM6_cm4.h
获取复位状态标志
uint16_t resetFlag = 0U;
resetFlag = WDOG_GetStatusFlags(DEMO_WDOG_BASE);
This function gets all reset status flags.
uint16_t WDOG_GetStatusFlags(WDOG_Type *base)
{
uint16_t status_flag = 0U;
status_flag |= (base->WCR & WDOG_WCR_WDE_MASK); //Watchdog Enable
status_flag |= (base->WRSR & WDOG_WRSR_POR_MASK); //Power On Reset
status_flag |= (base->WRSR & WDOG_WRSR_TOUT_MASK);//Timeout.
status_flag |= (base->WRSR & WDOG_WRSR_SFTW_MASK);//Software Reset
status_flag |= (base->WICR & WDOG_WICR_WTIS_MASK);//Watchdog Timer Interrupt Status
return status_flag;
}
#define WDOG_WCR_WDE_MASK (0x4U)
#define WDOG_WCR_WDE_SHIFT (2U)
/*! WDE
* 0b0..Disable the Watchdog (Default).
* 0b1..Enable the Watchdog.
*/
#define WDOG_WCR_WDE(x) (((uint16_t)(((uint16_t)(x)) << WDOG_WCR_WDE_SHIFT)) & WDOG_WCR_WDE_MASK)
enum _wdog_status_flags
{
kWDOG_RunningFlag = WDOG_WCR_WDE_MASK, /*!< Running flag, set when WDOG is enabled*/
kWDOG_PowerOnResetFlag = WDOG_WRSR_POR_MASK, /*!< Power On flag, set when reset is the result of a powerOnReset*/
kWDOG_TimeoutResetFlag = WDOG_WRSR_TOUT_MASK, /*!< Timeout flag, set when reset is the result of a timeout*/
kWDOG_SoftwareResetFlag = WDOG_WRSR_SFTW_MASK, /*!< Software flag, set when reset is the result of a software*/
kWDOG_InterruptFlag = WDOG_WICR_WTIS_MASK /*!< interrupt flag,whether interrupt has occurred or not*/
};
switch (resetFlag & (kWDOG_PowerOnResetFlag | kWDOG_TimeoutResetFlag | kWDOG_SoftwareResetFlag))
{
case kWDOG_PowerOnResetFlag:
PRINTF(" Power On Reset!\r\n");
break;
case kWDOG_TimeoutResetFlag:
PRINTF(" Time Out Reset!\r\n");
break;
case kWDOG_SoftwareResetFlag:
PRINTF(" Software Reset!\r\n");
break;
default:
PRINTF(" Error status!\r\n");
break;
}
WDOG寄存器地址
#define DEMO_WDOG_BASE WDOG1
/* WDOG - Peripheral instance base addresses */
/** Peripheral WDOG1 base address */
#define WDOG1_BASE (0x30280000u)
/** Peripheral WDOG1 base pointer */
#define WDOG1 ((WDOG_Type *)WDOG1_BASE)
寄存器地址转结构体数据
/** WDOG - Register Layout Typedef */
typedef struct {
__IO uint16_t WCR; /**< Watchdog Control Register, offset: 0x0 */
__IO uint16_t WSR; /**< Watchdog Service Register, offset: 0x2 */
__I uint16_t WRSR; /**< Watchdog Reset Status Register, offset: 0x4 */
__IO uint16_t WICR; /**< Watchdog Interrupt Control Register, offset: 0x6 */
__IO uint16_t WMCR; /**< Watchdog Miscellaneous Control Register, offset: 0x8 */
} WDOG_Type;
获取默认配置
wdog_config_t config;
WDOG_GetDefaultConfig(&config);
/*! @brief Defines WDOG work mode. */
typedef struct _wdog_work_mode
{
bool enableWait; /*!< continue or suspend WDOG in wait mode */
bool enableStop; /*!< continue or suspend WDOG in stop mode */
bool enableDebug; /*!< continue or suspend WDOG in debug mode */
} wdog_work_mode_t;
/*! @brief Describes WDOG configuration structure. */
typedef struct _wdog_config
{
bool enableWdog; /*!< Enables or disables WDOG */
wdog_work_mode_t workMode; /*!< Configures WDOG work mode in debug stop and wait mode */
bool enableInterrupt; /*!< Enables or disables WDOG interrupt */
uint16_t timeoutValue; /*!< Timeout value */
uint16_t interruptTimeValue; /*!< Interrupt count timeout value */
bool softwareResetExtension; /*!< software reset extension */
bool enablePowerDown; /*!< power down enable bit */
bool enableTimeOutAssert; /*!< Enable WDOG_B timeout assertion. */
} wdog_config_t;
void WDOG_GetDefaultConfig(wdog_config_t *config)
{
assert(config);
/* Initializes the configure structure to zero. */
memset(config, 0, sizeof(*config));
config->enableWdog = true;
config->workMode.enableWait = false;
config->workMode.enableStop = false;
config->workMode.enableDebug = false;
config->enableInterrupt = false;
config->softwareResetExtension = false;
config->enablePowerDown = false;
config->timeoutValue = 0xffu;
config->interruptTimeValue = 0x04u;
config->enableTimeOutAssert = false;
}
初始化WDOG寄存器
把对应的结构体成员值赋值到对应的寄存器地址;
void WDOG_Init(WDOG_Type *base, const wdog_config_t *config)
{
assert(config);
uint16_t value = 0u;
value = WDOG_WCR_WDE(config->enableWdog) | WDOG_WCR_WDW(config->workMode.enableWait) |
WDOG_WCR_WDZST(config->workMode.enableStop) | WDOG_WCR_WDBG(config->workMode.enableDebug) |
WDOG_WCR_SRE(config->softwareResetExtension) | WDOG_WCR_WT(config->timeoutValue) |
WDOG_WCR_WDT(config->enableTimeOutAssert) | WDOG_WCR_SRS_MASK | WDOG_WCR_WDA_MASK;
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
/* Set configuration */
CLOCK_EnableClock(s_wdogClock[WDOG_GetInstance(base)]);
#endif
base->WICR = WDOG_WICR_WICT(config->interruptTimeValue) | WDOG_WICR_WIE(config->enableInterrupt);
base->WMCR = WDOG_WMCR_PDE(config->enablePowerDown);
base->WCR = value;
if (config->enableInterrupt)
{
EnableIRQ(s_wdogIRQ[WDOG_GetInstance(base)]);
}
}
功能一:直接软件重启
/* If system reset from power on, trigger a software reset. */
if (resetFlag & kWDOG_PowerOnResetFlag)
{
PRINTF("\r\n- 1.Testing System reset by software trigger... ");
WDOG_TriggerSystemSoftwareReset(DEMO_WDOG_BASE);
}
/*!
* @brief Trigger the system software reset.
*
* This function will write to the WCR[SRS] bit to trigger a software system reset.
* This bit will automatically resets to "1" after it has been asserted to "0".
* Note: Calling this API will reset the system right now, please using it with more attention.
*
* @param base WDOG peripheral base address
*/
static inline void WDOG_TriggerSystemSoftwareReset(WDOG_Type *base)
{
base->WCR &= ~WDOG_WCR_SRS_MASK;
}
功能二:超时重启
/* If system reset from software trigger, testing the timeout reset. */
if (resetFlag & kWDOG_SoftwareResetFlag)
{
PRINTF("\r\n- 2.Testing system reset by WDOG timeout.\r\n");
/*
* wdogConfig->enableWdog = true;
* wdogConfig->workMode.enableWait = true;
* wdogConfig->workMode.enableStop = false;
* wdogConfig->workMode.enableDebug = false;
* wdogConfig->enableInterrupt = false;
* wdogConfig->enablePowerdown = false;
* wdogConfig->resetExtension = flase;
* wdogConfig->timeoutValue = 0xFFU;
* wdogConfig->interruptTimeValue = 0x04u;
*/
WDOG_GetDefaultConfig(&config);
config.timeoutValue = 0xFU; /* Timeout value is 2.5 sec. */
WDOG_Init(DEMO_WDOG_BASE, &config);
PRINTF("--- wdog Init done---\r\n");
}
config.timeoutValue = 0xFU; /* Timeout value is 2.5 sec. */,公式:time=(WT[7:0] + 1) * 0.5
功能三:设置8秒超时重启,6秒喂狗
/* If system reset from WDOG timeout, testing the refresh function using interrupt. */
if (resetFlag & kWDOG_TimeoutResetFlag)
{
PRINTF("\r\n- 3.Test the WDOG refresh function by using interrupt.\r\n");
WDOG_GetDefaultConfig(&config);
config.timeoutValue = 0xFU; /* Timeout value is 8 sec. */
config.enableInterrupt = true;
config.interruptTimeValue = 0x4U; /* Interrupt occurred 2 sec before WDOG timeout. */
WDOG_Init(DEMO_WDOG_BASE, &config);
PRINTF("--- wdog Init done no interrupt ---\r\n");
}
重写WDOG中断处理函数:
#define DEMO_WDOG_IRQHandler WDOG1_IRQHandler
.long WDOG1_IRQHandler /* Watchdog Timer reset*/
.long WDOG2_IRQHandler /* Watchdog Timer reset*/
def_irq_handler WDOG1_IRQHandler
def_irq_handler WDOG2_IRQHandler
void DEMO_WDOG_IRQHandler(void)
{
WDOG_Refresh(DEMO_WDOG_BASE);
WDOG_ClearInterruptStatus(DEMO_WDOG_BASE, kWDOG_InterruptFlag);
/*User code. */
PRINTF(" \r\nWDOG has be refreshed!");
}
#define WDOG_REFRESH_KEY (0xAAAA5555U)
/*!
* brief Refreshes the WDOG timer.
*
* This function feeds the WDOG.
* This function should be called before the WDOG timer is in timeout. Otherwise, a reset is asserted.
*
* param base WDOG peripheral base address
*/
void WDOG_Refresh(WDOG_Type *base)
{
base->WSR = WDOG_REFRESH_KEY & 0xFFFFU;
base->WSR = (WDOG_REFRESH_KEY >> 16U) & 0xFFFFU;
}
kWDOG_InterruptFlag = WDOG_WICR_WTIS_MASK /*!< interrupt flag,whether interrupt has occurred or not*/
void WDOG_ClearInterruptStatus(WDOG_Type *base, uint16_t mask)
{
if (mask & kWDOG_InterruptFlag)
{
base->WICR |= WDOG_WICR_WTIS_MASK;
}
}
打印:6秒刷新一次,设置8秒超时重启
******** System Start ********
System reset by: Power On Reset!
- 3.Test the WDOG refresh function by using interrupt.
--- wdog Init done---
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed!
扩展测试草稿
IMX8MMRM.pdf - 6.6 Watchdog Timer (WDOG)
m4 wdog
SDK_2.5.0_EVK-MIMX8MM/boards/evkmimx8mm/driver_examples/wdog
******** System Start ********
System reset by: Power On Reset!
- 3.Test the WDOG refresh function by using interrupt.
--- wdog Init done---
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed!
WDOG has be refreshed! 【6秒刷新,8秒超时,超时会重启】
resetFlag = WDOG_GetStatusFlags(DEMO_WDOG_BASE);
#define DEMO_WDOG_BASE WDOG1
#define DEMO_WDOG_IRQHandler WDOG1_IRQHandler
WDOG寄存器地址
wdog_config_t config;
WDOG_GetDefaultConfig(&config);
config.timeoutValue = 0xFU; /* Timeout value is 8 sec. */
config.enableInterrupt = true;
config.interruptTimeValue = 0x4U; /* Interrupt occurred 2 sec before WDOG timeout. */
WDOG_Init(DEMO_WDOG_BASE, &config);
Linux wdog
[ 1.443456] imx2-wdt 30280000.wdog: timeout 60 sec (nowayout=0)
[ 2.087485] init: - watchdog -
[ 5.943331] procd: - watchdog -
[ 6.516459] procd: - watchdog -
crw------- 1 root root 10, 130 Jan 1 1970 /dev/watchdog 【软件看门狗】
crw------- 1 root root 248, 0 Jan 1 1970 /dev/watchdog0 【硬件看门狗】
pinctrl_wdog: wdoggrp {
fsl,pins = <
MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
>;
};
&wdog1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_wdog>;
fsl,ext-reset-output; 【使能使用外部复位WDOG_B】
status = "okay";
};
wdog1: wdog@30280000 {
compatible = "fsl,imx21-wdt";
reg = <0 0x30280000 0 0x10000>;
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MM_CLK_WDOG1_ROOT>;
status = "disabled";
};
驱动
drivers/watchdog/imx2_wdt.c
#
# ACPI INT340X thermal drivers
#
# CONFIG_QCOM_SPMI_TEMP_ALARM is not set
# CONFIG_GENERIC_ADC_THERMAL is not set
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y
# CONFIG_WATCHDOG_SYSFS is not set
1、关闭wdog1,dev下面没有watchdog和watchdog0,reboot卡住重启失败,说明是一体的
2、uboot下短接GND到TP53,重启了
3、linux下短接GND到TP53,重启了
4、内核测试死锁卡住是否重启【】
root@OpenWrt:/# echo 1 > /dev/watchdog
/bin/ash: can't create /dev/watchdog: Resource busy
root@OpenWrt:/# echo 1 > /dev/watchdog0
/bin/ash: can't create /dev/watchdog0: Resource busy
root@OpenWrt:/# ubus call system watchdog
{
"status": "running",
"timeout": 30,
"frequency": 5,
"magicclose": false
}
ubus call system watchdog '{ "timeout": 60 }'
root@OpenWrt:/# ubus call system watchdog '{"magicclose": true}'
{
"status": "running",
"timeout": 30,
"frequency": 5,
"magicclose": true
}
关闭
root@OpenWrt:/# ubus call system watchdog '{"stop": true}'
{
"status": "offline",
"timeout": 30,
"frequency": 5,
"magicclose": true
}
[1/7 星期二 20:01:04] root@OpenWrt:/# echo 1 > /dev/watchdog
[1/7 星期二 20:01:04] [ 68.190784] watchdog: watchdog0: watchdog did not stop!
[1/7 星期二 20:01:35] root@OpenWrt:/# ÿ
[1/7 星期二 20:01:35] U-Boot SPL 2018.03-00013-g0d6d880779-dirty (Nov 08 2019 - 17:00:01 +0800)
【31秒重启】
[1/7 星期二 20:03:11] root@OpenWrt:/# echo 1 > /dev/watchdog0
[1/7 星期二 20:03:11] [ 35.057397] watchdog: watchdog0: watchdog did not stop!
[1/7 星期二 20:03:41] root@OpenWrt:/#
[1/7 星期二 20:03:41] U-Boot SPL 2018.03-00013-g0d6d880779-dirty (Nov 08 2019 - 17:00:01 +0800)
【30秒重启】
谁在喂狗呢?【system下面的watchdog】
controls the watchdog. *ubus call system watchdog '{ “stop”: true“}'* only stops the thread triggering the watchdog. The watchdog is still counting down unless a second process is triggering the watchdog unless you enable 'magicclose', then you can manually tickle '/dev/watchdog'.
荏原板子由watchdog程序喂狗
/sbin/watchdog -t 5 -F /dev/watchdog
怎么测试硬件看门狗有效【ubox板子wk2124出现串口问题时,导致系统卡死后重启了】