i.MX 8M Mini Cortex-M4 WDOG看门狗

手册

《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出现串口问题时,导致系统卡死后重启了】

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在FreeRTOS中,软看门狗的实现需要以下步骤: 1. 定义一个任务,用于喂狗。该任务的功能是定时向看门狗发送信号,以避免看门狗超时复位系统。 2. 定义一个定时器,用于定时触发任务。在FreeRTOS中,可以使用定时器服务或者定时器任务来实现定时器。 3. 定义一个看门狗任务,用于监控系统运行状态。该任务需要在系统启动时启动,并在任务中启动看门狗。 4. 在看门狗任务中设置看门狗的超时时间。该时间需要根据具体的系统要求进行设置。 5. 在看门狗任务中使用信号量或者消息队列,以便在出现异常情况时通知其他任务进行处理。 下面是一个简单的软看门狗实现示例: ```c void feed_wdog_task(void *pvParameters) { while(1) { feed_watchdog(); // 喂狗 vTaskDelay(pdMS_TO_TICKS(1000)); // 每秒喂一次狗 } } void wdog_task(void *pvParameters) { // 初始化看门狗 init_watchdog(); // 设置看门狗超时时间 set_watchdog_timeout(5000); while(1) { if (watchdog_expired()) { // 看门狗超时,执行异常处理 handle_watchdog_timeout(); } vTaskDelay(pdMS_TO_TICKS(1000)); // 每秒检查一次狗 } } int main(void) { // 创建喂狗任务 xTaskCreate(feed_wdog_task, "feed_wdog_task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); // 创建看门狗任务 xTaskCreate(wdog_task, "wdog_task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); // 启动调度器 vTaskStartScheduler(); return 0; } ``` 在上面的示例中,`feed_wdog_task`函数用于喂狗,每秒喂一次;`wdog_task`函数用于监控系统运行状态,每秒检查一次狗是否超时。在`wdog_task`函数中,如果发现狗超时,则执行异常处理。在`main`函数中,创建了两个任务,分别是`feed_wdog_task`和`wdog_task`。启动调度器后,这两个任务将会被调度执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值