wdt_test case

本文提供了一个watchdog测试案例代码,该代码可用于测试watchdog设备的功能。案例包括打开watchdog设备文件、设置超时时间并读取状态等操作。此外还展示了如何通过ioctl系统调用与watchdog设备交互。

这是一个watch dog test case的代码,可以用来测试watchdog的功能:

#include <stdio.h>   
#include <stdlib.h>
#include <string.h>   
#include <sys/types.h>   
#include <sys/stat.h>   
#include <unistd.h>   
#include <fcntl.h>   
#include <sys/ioctl.h>   
#include <errno.h>   
#include <sys/time.h>   
#include <unistd.h>   
#include <time.h>   
#include <getopt.h>   
#include <sys/signal.h>   
#include "watchdog.h"   
#define  OPTION_REBOOT		0
#define  OPTION_BASIC		1

#define  REBOOT		"reboot"

int zsleep(int millisecond)   
{   
	unsigned long usec;   
	usec=1000*millisecond;   
	usleep(usec);   
}
/*      
void keep_alive(void)
{
    int dummy;

    ioctl(fd, WDIOC_KEEPALIVE, &dummy);
}

void wdt_getstatus(int *arg)
{
    ioctl(fd, WDIOC_KEEPALIVE, *arg);
}

void keep_getbootstatus(int *arg)
{
    ioctl(fd, WDIOC_KEEPALIVE, *arg);
}
*/
int Init()   
{
	int fd;
	//open device file
	fd = open("/dev/watchdog",O_RDWR);
	if(fd < 0)
	{
	    printf("device open fail\n");
	    return -1;
	}
	else
	    printf("enable watchdog\n");

	return fd;
}

int main(int argc,char **argv)   
{
        int fd,ch;
        int i,j,k=1,option,timeout;
	char *arg;
        struct watchdog_info wi;
        fd=Init();
	if(argv[1]!=NULL){
		if(strcmp(argv[1],REBOOT)==0){
			printf("reboot mode\n");
			arg = argv[2];
			i = strtoul(arg,&arg,10);
			option = OPTION_REBOOT;
		}
		else{
			printf("invalid option arguments,only do the basic action\n");
			option = OPTION_BASIC;
		}	
	}
	else{
		printf("only basic action\n");
		option = OPTION_BASIC;
	}
	if(option == OPTION_BASIC){
        	//read watchdog information
        	ioctl(fd,WDIOC_GETSUPPORT,&wi); 
        	printf("%d,%s\n",wi.options,wi.identity);

        	//set watchdog timeout   
        	//set the timeout is 10s,if success return 0,else return -1   
        	i=5;
		j=ioctl(fd,WDIOC_SETTIMEOUT,&i);
		if(j==0)
            		printf("Set watchdog timeout success!\nSet watchdog timeout: %ds\n",i*2);
		else
	    		printf("Set watchdog timeout failed!\n");

        	//read watchdog timeout
		j=ioctl(fd,WDIOC_GETTIMEOUT,&i);
		if(j==0)
            		printf("Read watchdog timeout success!\nRead watchdog timeout: %ds\n",i*2);
		else
	    		printf("Read watchdog timeout failed!\n");

        	//disable watchdog
        	close(fd);
		printf("disable watchdog\n");
	}
	else{
 		//read watchdog information
                ioctl(fd,WDIOC_GETSUPPORT,&wi);
                printf("%d,%s\n",wi.options,wi.identity);

                //set watchdog timeout   
                //set the timeout is 10s,if success return 0,else return -1   
                timeout = i/2;
                j=ioctl(fd,WDIOC_SETTIMEOUT,&timeout);
                if(j==0)
                        printf("Set watchdog timeout success!\nSet watchdog timeout: %ds\n",timeout*2);
                else
                        printf("Set watchdog timeout failed!\n");

                //read watchdog timeout
                j=ioctl(fd,WDIOC_GETTIMEOUT,&timeout);
                if(j==0)
                        printf("Read watchdog timeout success!\nRead watchdog timeout: %ds\n",timeout*2);
                else
                        printf("Read watchdog timeout failed!\n");

                timeout = timeout*2;
                while(1){
                        printf("I 'll do the reboot after %d seconds\n",timeout--);
			sleep(1);
                }
                //disable watchdog
                close(fd);
                printf("disable watchdog\n");
	}
        return 0;
}

watchdog.h 代码如下

/*
 *	Generic watchdog defines. Derived from..
 *
 * Berkshire PC Watchdog Defines
 * by Ken Hollis <khollis@bitgate.com>
 *
 */

#ifndef _LINUX_WATCHDOG_H
#define _LINUX_WATCHDOG_H

#include <linux/ioctl.h>

#define	WATCHDOG_IOCTL_BASE	'W'

struct watchdog_info {
	unsigned int options;		/* Options the card/driver supports */
	unsigned int firmware_version;	/* Firmware version of the card */
	unsigned char identity[32];	/* Identity of the board */
};

#define	WDIOC_GETSUPPORT	_IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
#define	WDIOC_GETSTATUS		_IOR(WATCHDOG_IOCTL_BASE, 1, int)
#define	WDIOC_GETBOOTSTATUS	_IOR(WATCHDOG_IOCTL_BASE, 2, int)
#define	WDIOC_GETTEMP		_IOR(WATCHDOG_IOCTL_BASE, 3, int)
#define	WDIOC_SETOPTIONS	_IOR(WATCHDOG_IOCTL_BASE, 4, int)
#define	WDIOC_KEEPALIVE		_IOR(WATCHDOG_IOCTL_BASE, 5, int)
#define	WDIOC_SETTIMEOUT        _IOWR(WATCHDOG_IOCTL_BASE, 6, int)
#define	WDIOC_GETTIMEOUT        _IOR(WATCHDOG_IOCTL_BASE, 7, int)

#define	WDIOF_UNKNOWN		-1	/* Unknown flag error */
#define	WDIOS_UNKNOWN		-1	/* Unknown status error */

#define	WDIOF_OVERHEAT		0x0001	/* Reset due to CPU overheat */
#define	WDIOF_FANFAULT		0x0002	/* Fan failed */
#define	WDIOF_EXTERN1		0x0004	/* External relay 1 */
#define	WDIOF_EXTERN2		0x0008	/* External relay 2 */
#define	WDIOF_POWERUNDER	0x0010	/* Power bad/power fault */
#define	WDIOF_CARDRESET		0x0020	/* Card previously reset the CPU */
#define WDIOF_POWEROVER		0x0040	/* Power over voltage */
#define WDIOF_SETTIMEOUT	0x0080	/* Set timeout (in seconds) */
#define WDIOF_MAGICCLOSE	0x0100	/* Supports magic close char */
#define	WDIOF_KEEPALIVEPING	0x8000	/* Keep alive ping reply */

#define	WDIOS_DISABLECARD	0x0001	/* Turn off the watchdog timer */
#define	WDIOS_ENABLECARD	0x0002	/* Turn on the watchdog timer */
#define	WDIOS_TEMPPANIC		0x0004	/* Kernel panic on temperature trip */

#endif  /* ifndef _LINUX_WATCHDOG_H */




/* * Copyright (c) HiSilicon (Shanghai) Technologies Co., Ltd. 2022-2022. All rights reserved. * Description: adm706_wdt.c * Author: BSP * Create: 2022/09/30 */ /* * drivers/watchdog/adm706_wdt.c * * WDT driver for adm706 * Copyright (C) 2010, Huawei Corporation. * * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place - Suite 330, Boston, MA 02111-1307 USA. * */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/device.h> #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/uaccess.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/gpio.h> #include <linux/delay.h> #include <linux/timer.h> #include <linux/of_gpio.h> #include <linux/types.h> static int nowayout = WATCHDOG_NOWAYOUT; static unsigned long wdt_status; static long boot_status; int wdt_reboot_time = 6000; /* 内核停止喂狗倒计时10分钟 */ int wdt__min_reboot_time = 600; /* 内核至少喂狗600*100ms:60秒 */ int wdt_timer_stop = 0; int disable_wdt_file = 0; /* 0表示记文件,1表示不记文件 */ #define WDT_IN_USE 0 #define WDT_OK_TO_CLOSE 1 #define WDT_ENABLED 2 #define WDT_REBOOT_TIME 50 /* 上层接管后50*100ms不喂狗系统则重启 */ #define WDT_HIGH_LEVEL 1 #define WDT_LOW_LEVEL 0 /* 喂狗寄存器 */ static uintptr_t g_wtd_reg_base_addr_mapped; void set_wdt_reg_val(unsigned int val) { if (g_wtd_reg_base_addr_mapped) { writel(val, (volatile void __iomem *)g_wtd_reg_base_addr_mapped); } } static long adm706_watchdog_timeout(void) { return (1600); // 1600 超时时间 } static void wdt_enable(void) { set_wdt_reg_val(WDT_HIGH_LEVEL); msleep(10); // 时间缓冲10ms set_wdt_reg_val(WDT_LOW_LEVEL); } /* returns 0 if the timer was successfully disabled */ static int wdt_disable(void) { printk(KERN_INFO "WATCHDOG: can't be Disabled by software\n"); return 0; } static int adm706_wdt_open(struct inode *inode, struct file *file) { if (test_and_set_bit(WDT_IN_USE, &wdt_status)) return -EBUSY; clear_bit(WDT_OK_TO_CLOSE, &wdt_status); wdt_enable(); set_bit(WDT_ENABLED, &wdt_status); return nonseekable_open(inode, file); } static ssize_t adm706_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) { if (len) { if (!nowayout) { size_t i; clear_bit(WDT_OK_TO_CLOSE, &wdt_status); for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) return -EFAULT; if (c == 'V') set_bit(WDT_OK_TO_CLOSE, &wdt_status); } } wdt_reboot_time = WDT_REBOOT_TIME; } return len; } static const struct watchdog_info ident = { .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .identity = "adm706 watchdog", }; static long adm706_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int options; int ret = -ENOTTY; int __user *argp = (int __user *)compat_ptr(arg); switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof ident)) { ret = -EFAULT; } else { ret = 0; } break; case WDIOC_GETSTATUS: ret = put_user(0, argp); break; case WDIOC_GETBOOTSTATUS: ret = put_user(boot_status, argp); break; case WDIOC_SETOPTIONS: options = (int) arg; if ((unsigned int)options & WDIOS_DISABLECARD) { if (!nowayout) { if (wdt_disable() == 0) { set_bit(WDT_OK_TO_CLOSE, &wdt_status); ret = 0; } else { ret = -ENXIO; } } else { ret = 0; } } if ((unsigned int)options & WDIOS_ENABLECARD) { wdt_enable(); ret = 0; } break; case WDIOC_KEEPALIVE: wdt_enable(); ret = 0; break; case WDIOC_SETTIMEOUT: ret = _IOC_SIZE(cmd); break; case WDIOC_GETTIMEOUT: ret = put_user(adm706_watchdog_timeout(), argp); break; default: break; } return ret; } static int adm706_wdt_release(struct inode *inode, struct file *file) { int state = 1; if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { if (test_bit(WDT_ENABLED, &wdt_status)) { state = wdt_disable(); } } /* if the timer is not disbaled reload and notify that we are still * going down */ if (state != 0) { wdt_enable(); } clear_bit(WDT_IN_USE, &wdt_status); clear_bit(WDT_OK_TO_CLOSE, &wdt_status); printk(KERN_INFO "watchdog released, system is going to reboot ...\n"); return 0; } static const struct file_operations adm706_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = adm706_wdt_write, .unlocked_ioctl = adm706_wdt_ioctl, .open = adm706_wdt_open, .release = adm706_wdt_release, }; static struct miscdevice adm706_wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &adm706_wdt_fops, }; struct task_struct *p_creat_file; static void kick_wdt_fn(struct timer_list *timer) { static unsigned int count = 0; set_wdt_reg_val(count & WDT_HIGH_LEVEL); count++; mod_timer(timer, jiffies + msecs_to_jiffies(100)); // 100 定时器每次递加时间为100s } DEFINE_TIMER(kick_wdt_timer, kick_wdt_fn); /* 内核中通用喂狗函数,可以放置在内核任何需要喂狗的地方 */ void adm706_wdt_common(void) { static int val = 0; val = (val ? WDT_LOW_LEVEL : WDT_HIGH_LEVEL); if (wdt_timer_stop == 0) { set_wdt_reg_val(val); } } EXPORT_SYMBOL(adm706_wdt_common); static void adm706_wdt_init(void) { wdt_timer_stop = 0; printk("kernel start kick dog...\n"); add_timer(&kick_wdt_timer); mod_timer(&kick_wdt_timer, jiffies); } /* 注意:hi1230平台读写寄存器,通过WDG_WDI 喂外狗 */ static int adm706_wdt_probe(struct platform_device *pdev) { int ret; struct resource *res = NULL; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { printk("watchdog get res fail.\n"); return -ENXIO; } res = request_mem_region(res->start, resource_size(res), pdev->name); if (res == NULL) { printk("watchdog request mem fail.\n"); return -EBUSY; } g_wtd_reg_base_addr_mapped = (uintptr_t)ioremap(res->start, resource_size(res)); adm706_wdt_init(); ret = misc_register(&adm706_wdt_miscdev); if (ret == 0) { printk(KERN_INFO "adm706 watchdog timer: timeout 1.6 sec\n"); if (!nowayout) { printk("Watchdog can be stoped.\n"); } else { printk("Watchdog can not be stopped once started.\n"); } } return ret; } static int adm706_wdt_remove(struct platform_device *pdev) { int error = 0; misc_deregister(&adm706_wdt_miscdev); return error; } static const struct of_device_id adm706_wdt_match[] = { { .compatible = "analog,adm706", }, {}, }; MODULE_DEVICE_TABLE(of, adm706_wdt_match); static struct platform_driver adm706_wdt_driver = { .driver = { .name = "wdt-adm706", .owner = THIS_MODULE, .of_match_table = adm706_wdt_match, }, .probe = adm706_wdt_probe, .remove = adm706_wdt_remove, }; /* pcs may be needed to bring up other drivers */ static int __init adm706_wdt_init_driver(void) { return platform_driver_register(&adm706_wdt_driver); } subsys_initcall(adm706_wdt_init_driver); static void __exit adm706_wdt_exit_driver(void) { platform_driver_unregister(&adm706_wdt_driver); } module_exit(adm706_wdt_exit_driver); module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); MODULE_AUTHOR("Walter"); MODULE_DESCRIPTION("ADM706 watchdog timer driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 请帮我分析每一段代码的功能逻辑
08-15
speech_recognition.elf C:\WINDOWS\system32\cmd.exe /C "cd . && C:\Espressif\tools\xtensa-esp-elf\esp-14.2.0_20241119\xtensa-esp-elf\bin\xtensa-esp32s3-elf-g++.exe -mlongcalls -fno-builtin-memcpy -fno-builtin-memset -fno-builtin-bzero -fno-builtin-stpcpy -fno-builtin-strncpy -Wl,--cref -Wl,--defsym=IDF_TARGET_ESP32S3=0 -Wl,--Map=C:/TPC/IOT/IoT_Pad_MIC_Test/AI_Pad_Test/Src/build/speech_recognition.map -Wl,--no-warn-rwx-segments -Wl,--orphan-handling=warn -fno-rtti -fno-lto -Wl,--gc-sections -Wl,--warn-common -T esp32s3.peripherals.ld -T esp32s3.rom.ld -T esp32s3.rom.api.ld -T esp32s3.rom.bt_funcs.ld -T esp32s3.rom.libgcc.ld -T esp32s3.rom.wdt.ld -T esp32s3.rom.version.ld -T esp32s3.rom.newlib.ld -T memory.ld -T sections.ld @CMakeFiles\speech_recognition.elf.rsp -o speech_recognition.elf && cd ." C:/Espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld.exe: esp-idf/main/libmain.a(ui.c.obj):C:/TPC/IOT/IoT_Pad_MIC_Test/AI_Pad_Test/Src/main/ui/ui.c:45:(.data.actions+0x0): undefined reference to `action_gpio21_test_button' C:/Espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld.exe: esp-idf/main/libmain.a(ui.c.obj):(.data.actions+0x4): undefined reference to `action_gpio22_test_button' C:/Espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld.exe: esp-idf/main/libmain.a(ui.c.obj):(.data.actions+0x8): undefined reference to `action_iic_test_actions_button' C:/Espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld.exe: esp-idf/main/libmain.a(ui.c.obj):(.data.actions+0xc): undefined reference to `action_inv_native_action_button' C:/Espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/14.2.0/../../../../xtensa-esp-elf/bin/ld.exe: esp-idf/main/libmain.a(ui.c.obj):(.data.actions+0x10): undefined reference to `action_sd_card_test_button' collect2.exe: error: ld returned 1 exit status ninja: build stopped: subcommand failed. ninja failed with exit code 1, output of the command is in the C:\TPC\IOT\IoT_Pad_MIC_Test\AI_Pad_Test\Src\build\log\idf_py_stderr_output_20656 and C:\TPC\IOT\IoT_Pad_MIC_Test\AI_Pad_Test\Src\build\log\idf_py_stdout_output_20656
07-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值