///代码系 3.x
//移到 5.x
//1/定时器 改为 setup
//2/模块初始化 少probe 参数
//3/gpio.h sys_config.h 5.x 没有
//4/timer list function 3.x unsigned long
5.x timer list
//#define DEBUG
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/platform_devi
#include <linux/gpio.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/sys_config.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
#include <linux/timer.h>
//声明内核定时器队列
struct timer_list mytimer;
//定时器句柄控制
static void timeout_handle(unsigned long arg);
//狗释放操作……
static void wdt_release(struct device *dev)
{
}
//平台驱动接口名称
static struct platform_device wdt_dev = {
.name = "hw_wdt",
.id = 1,
.dev = {
.release = wdt_release,
},
};
//启用标志位
static int enable = 1;//驱动加载时,默认开启喂狗功能,待应用层打开时
struct platform_driver wdt_drv = {
.probe = wdt_probe,
.remove = wdt_remove,
.driver = {
.name = "hw_wdt",
},
};
#define HW_WDI_PIN 34//喂狗引脚号,根据具体硬件原理图修改
static int wdt_open(struct inode *inode, struct file *file)
{
enable = 0;//关闭定时器喂狗功能
gpio_direction_output(HW_WDI_PIN,0);
return 0;
}
static unsigned int wdt_status=0x00;//记录引脚状态,每调用一次write时进行"非"操作一次
static ssize_t wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
wdt_status = !wdt_status;
__gpio_set_value(HW_WDI_PIN,wdt_status);
return 0;
}
static void timeout_handle(unsigned long arg)
{
static unsigned int flag=0;
//printk("feed the hw_wdt\n");
if(enable == 1){
//定时器软中断仅触发一次,故需要周期中断的情况下,需每次重新设置超时时间
mytimer.expires = jiffies + (1*HZ);
add_timer(&mytimer);
}
flag = !flag;
__gpio_set_value(HW_WDI_PIN,flag);
}
static struct file_operations wdt_fops={
.owner = THIS_MODULE,
.open = wdt_open,
.write = wdt_write,
};
static int major=0;
static struct class *drv_class;
static int wdt_probe(struct platform_device *pdev)
{
printk("hw_wdt enter probe\n");
init_timer(&mytimer);
mytimer.expires = jiffies + (1*HZ);
mytimer.data = 5;
mytimer.function = timeout_handle;
add_timer(&mytimer);
//
major = register_chrdev(0,"hw_wdt",&wdt_fops);
drv_class = class_create(THIS_MODULE,"hw_wdt");
device_create(drv_class,NULL,MKDEV(major,0),NULL,"hw_watchdog");
return 0;
}
static int wdt_remove(struct platform_device *pdev)
{
printk("enter remove\n");
device_destroy(drv_class,MKDEV(major,0));
class_destroy(drv_class);
unregister_chrdev(major,"hw_wdt");
del_timer(&mytimer);
return 0;
}
static int wdt_drv_init(void)
{
platform_driver_register(&wdt_drv);
return 0;
}
static void wdt_drv_exit(void)
{
platform_driver_unregister(&wdt_drv);
}
module_init(wdt_drv_init);
module_exit(wdt_drv_exit);
MODULE_LICENSE("GPL");