0. linux版本

Linux version 5.4.31

1.设备树

usr_wtd {compatible = "user-watchdog";status = "okay";gpio = <&gpiof 3 GPIO_ACTIVE_HIGH>;pluse-width = <100>; /* 1ms */pluse-inverse = <1>;pluse-count = <3>;timeout-sec = <5>;};

2. 驱动 drivers/watchdog/usr_wtd.c

#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/kthread.h>
#include <dt-bindings/gpio/gpio.h>
#include <linux/jiffies.h>
#include <linux/delay.h>
#include <linux/timer.h>#include <linux/poll.h>/*
#include <linux/delay.h>  第一类延时函数原型是:(忙等)
void ndelay(unsigned long nsecs);
void udelay(unsigned long usecs);
void mdelay(unsigned long msecs);
说明:内核函数 ndelay, udelay, 以及 mdelay 对于短延时好用, 分别延后执行指定的纳秒数, 微秒数或者毫秒数. 它们涉及到的延时常常是最多几个毫秒。第二类延时函数原型是:(使进程进入休眠)
void msleep(unsigned int millisecs);
unsigned long msleep_interruptible(unsigned int millisecs);
void ssleep(unsigned int seconds)
*/
#define WATCHDOG_TAG "[wtd_tag]"
#define WATCHDOG_MAJOR 0
#define WATCHDOG_NAME "usr_wdt" //设备节点struct wtd_device_t {int gpio;int pluse_width;int pluse_count;int timeout_sec;int pluse_inverse;int status;struct timer_list timer;struct class *wtd_class;int major;
};static struct wtd_device_t watchdog_dev;static void feed_dog(struct wtd_device_t *dev)
{int i = 0;//printk(WATCHDOG_TAG"feed dog,count:%d,gpio:%d,width:%d\n",dev->pluse_count,dev->gpio,dev->pluse_width);for(i=0;i<dev->pluse_count;i++){gpio_direction_output(dev->gpio,dev->pluse_inverse);mdelay(dev->pluse_width);gpio_direction_output(dev->gpio,!dev->pluse_inverse);mdelay(dev->pluse_width);}gpio_direction_output(dev->gpio,dev->pluse_inverse);
}static void timer_function(struct timer_list *t)
{struct wtd_device_t *wtd = from_timer(wtd, t, timer);feed_dog(wtd);mod_timer(&wtd->timer, jiffies + wtd->timeout_sec * HZ);
} static int watchdog_pin_config(int gpio)
{int ret = 0;gpio_free(gpio);ret = gpio_request(gpio,"watchdog_pin");if(ret){printk(WATCHDOG_TAG"%s::request gpio[%d] failed\n",__FUNCTION__,gpio);return -1;}else{printk(WATCHDOG_TAG"%s::request gpio[%d] successfully\n",__FUNCTION__,gpio); }return 0;
}static int init_wtd_timer(struct wtd_device_t *dev)
{timer_setup(&dev->timer,timer_function,0);mod_timer(&dev->timer, jiffies + dev->timeout_sec * HZ);return 0 ;
}static int watchdog_open(struct inode* inode,struct file* file)
{return 0;
}static int watchdog_release(struct inode* inode ,struct file* file)
{return 0;
}#if 0
static int watchdog_ioctl(struct inode* inode, struct file* file,unsigned int cmd, unsigned long arg)
{return 0;
}
#endifstatic int watchdog_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
{return 0;
}static int watchdog_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{return 0;
}static struct  file_operations watchdog_fops =
{.owner = THIS_MODULE,.open  = watchdog_open,.release = watchdog_release,.write = watchdog_write,.read  = watchdog_read,
};static int user_wtd_probe(struct platform_device * pdev)
{struct device_node * node = pdev->dev.of_node;int ret;int num = 0;int gpio = 0;enum of_gpio_flags flags;struct wtd_device_t *dev = &watchdog_dev;if(!node)return -ENODEV;dev->major = register_chrdev(WATCHDOG_MAJOR,WATCHDOG_NAME,&watchdog_fops);if(dev->major <0){printk(WATCHDOG_TAG" register failed \n");return dev->major;}dev->wtd_class = class_create(THIS_MODULE,WATCHDOG_NAME);if(IS_ERR(dev->wtd_class)){printk(WATCHDOG_TAG " register class failed \n");return -1;}device_create(dev->wtd_class,NULL,MKDEV(dev->major,0),NULL,WATCHDOG_NAME);/* usr_wtd {compatible = "user-watchdog";status = "okay";gpio = <&gpioh 15 GPIO_ACTIVE_HIGH>;pluse-inverse = <1>;pluse-width = <1>; pluse-count = <2>;timeout-sec = <32>;};*/ret = of_property_read_u32(node, "pluse-inverse", &num);if (ret) {pr_err(WATCHDOG_TAG"pluse-inverse no found !!!\n");goto INIT_ERR_FREE;}printk("pluse-inverse:%d\n",num);dev->pluse_inverse = num;ret = of_property_read_u32(node, "pluse-width", &num);if (ret || !num) {pr_err(WATCHDOG_TAG"pluse-width no found !!!\n");goto INIT_ERR_FREE;}printk("pluse-width:%d\n",num);dev->pluse_width = num;ret = of_property_read_u32(node, "pluse-count", &num);if (ret || !num) {pr_err(WATCHDOG_TAG"pluse-count no found !!!\n");goto INIT_ERR_FREE;}printk("pluse-count:%d\n",num);dev->pluse_count = num;ret = of_property_read_u32(node, "timeout-sec", &num);if (ret || !num) {pr_err(WATCHDOG_TAG"timeout-sec no found !!!\n");goto INIT_ERR_FREE;}printk("timeout-sec:%d\n",num);dev->timeout_sec = num;gpio = of_get_named_gpio_flags(node, "gpio", 0,&flags);dev->gpio = gpio;ret = watchdog_pin_config(gpio);if (ret) {goto INIT_ERR_FREE;}init_wtd_timer(dev);dev_set_drvdata(&pdev->dev, dev);pr_info("init watchdog dev finish\n");return 0;INIT_ERR_FREE:pr_err("init watchdog dev err\n");return -1;
}static int user_wtd_remove(struct platform_device *pdev)
{struct wtd_device_t * dev = dev_get_drvdata(&pdev->dev);if(dev != NULL){del_timer(&dev->timer);unregister_chrdev(dev->major,WATCHDOG_NAME);device_destroy(dev->wtd_class,MKDEV(dev->major ,0));class_destroy(dev->wtd_class);}pr_info("exit user watchdog \n");return 0;
}#ifdef CONFIG_PM
static int user_wtd_suspend(struct device *dev)
{return 0;
}static int user_wtd_resume(struct device *dev)
{return 0;
}
#else
#define user_wtd_suspend NULL
#define user_wtd_resume NULL
#endifstatic const struct dev_pm_ops user_wtd_pm_ops = {.suspend = user_wtd_suspend,.resume = user_wtd_resume,
};static struct of_device_id user_wtd_of_match[] = {{ .compatible = "user-watchdog" },{},
};
MODULE_DEVICE_TABLE(of, user_wtd_of_match);static struct platform_driver user_wtd_driver = {.driver        = {.name   = "user-wtd",.owner  = THIS_MODULE,.pm  = &user_wtd_pm_ops,.of_match_table = of_match_ptr(user_wtd_of_match),},.probe     = user_wtd_probe,.remove       = user_wtd_remove,
};
module_platform_driver(user_wtd_driver);MODULE_DESCRIPTION("user watchdog driver");
MODULE_AUTHOR("zhengweiqing, 1548889230@qq.com");
MODULE_LICENSE("GPL");

3. drivers/watchdog/Makefile

末尾增加:

obj-m += usr_wtd.o

4. 编译

5. 使用

insmod usr_wtd.ko

6. 现象

usr_wtd {compatible = "user-watchdog";status = "okay";gpio = <&gpiof 3 GPIO_ACTIVE_HIGH>;pluse-width = <100>;pluse-inverse = <1>;pluse-count = <3>;timeout-sec = <5>;};

timeout-sec:周期,单位秒
pluse-inverse:脉冲是否反向
pluse-count:脉冲个数
pluse-width:脉冲宽度,单位毫秒

这里举例的是:每隔5秒有3个宽度为100毫秒的脉冲。

linux gpio喂狗驱动相关推荐

  1. linux下 gpio ma63xx_wdt.c驱动

    项目中需要实现watchdog功能,研究了下系统中的watchdog.硬件watchdog使用芯片max6371,看芯片资料,结合硬件设计,发现需要控制的信号有两个,是系统的GPIO,GPIO1是使能 ...

  2. Linux GPIO键盘驱动开发记录_OMAPL138

    Linux GPIO键盘驱动开发记录_OMAPL138 Linux基本配置完毕了,这几天开始着手Linux驱动的开发,从一个最简单的键盘驱动开始,逐步的了解开发驱动的过程有哪些.看了一下Linux3. ...

  3. 【全志T113-S3_100ask】15-2 linux系统gpio模拟spi驱动屏幕——ILI9341

    [全志T113-S3_100ask]15-2 linux系统gpio模拟spi驱动屏幕--ILI9341 背景 (一)查阅参考文档 (二)使能内核模块 (三)修改设备树 (四)测试 (五)后语 背景 ...

  4. linux设备驱动归纳总结(十一):简单的看门狗驱动

    http://blog.chinaunix.net/uid-25014876-id-112879.html 设备驱动的归纳已经差不多了,趁着知识点还没有遗忘,写点代码巩固一下,来个简单的看门狗驱动-- ...

  5. linux内核看门狗关闭方法,详解linux 看门狗驱动编写

    看门狗是linux驱动的一个重要环节.某些特殊的设备,有时候需要放在一些环境恶劣的地方,比如电信设备.但是,任何软件都不可能100%没有bug.如何保证软件在遇到严重bug.死机的时候也能正常运行呢, ...

  6. LINUX GPIO 基操之驱动篇

    LINUX GPIO 基操之驱动篇 GPIO 子系统操作GPIO GPIO子系统接口简介 单个GPIO GPIO数组 PINCTRL 子系统操作GPIO pinctrl 子系统相关接口 使用例子 pr ...

  7. GPIO模拟PWM驱动风扇Linux设备驱动

    前言 内核版本 linux5_10: GPIO产生PWM方波,控制风扇转速: 本驱动可在应用层 /sys/class/pwm/下生成文件接口,通过脚本进行配置: 本驱动可将该 PWM 设备树节点用于 ...

  8. Linux GPIO 驱动 (gpiolib)

    目录 1.简述 2.Gpiolib 相关数据结构分析 2.1 gpio_chip 结构 2.2 gpio_desc 结构 2.3 gpio_device 结构 3.Gpiolib 对接芯片底层 3.1 ...

  9. Linux看门狗驱动程序设计(三) 测试验证

    测试驱动之前需要执行make menuconfig,去掉内核自带看门狗驱动(位于Device Drivers -> Character devices -> Watchdog Timer ...

最新文章

  1. CocoaPods设置target支持的swift版本
  2. scala reduceLeft和reduceRight执行分析
  3. TensorFlow学习笔记(一)安装、配置、基本用法
  4. 如何把catia完全卸载干净_catia软件无法卸载怎么办?彻底删除catia等三维软件的方法...
  5. linux下tar压缩使用
  6. 在Linux上安装IDA的命令,Linux安装IDA神器
  7. 解决 CondaHTTPError: HTTP 404 NOT FOUND for url 和 InvalidVersionSpecError: Invalid version spec: =2.7
  8. 2018 大数据学习入门必备规划
  9. 填料吸收塔,填料教学实训,填料吸收实验系列QY-HGYL
  10. React+antd动态增加Table可编辑行
  11. questasim编译报error: Declarations must precede statements. Look for stray semicolons.
  12. biztalk 2006 事务补偿模型[翻译]
  13. liveness探测mysql_Kubernetes 服务中 Liveness 和 Readiness 探测
  14. dojo和ArcGIS
  15. 创客教育中常见的视觉识别摄像头介绍
  16. 《你拥有的最宝贵的财富是什么》作业
  17. 扑克牌顺子java_算法练习篇之:扑克牌顺子
  18. Linux命令——修改root密码
  19. 《技术立国》——日立的小平浪平传
  20. 理解WSDL,IDL

热门文章

  1. ASP.NET Core WEB部署:Kestrel
  2. LCD1602液晶显示模块学习笔记
  3. IT青年们如何突围?要接地气
  4. 按键精灵---句柄的介绍及获取
  5. 初学python心得1000字实训_数学教学1000字六年级心得大全
  6. 【05】制作鸿蒙版蜻蜓短视频系统-事件原理及完成点击,长按,双击等操作实现跳转-优雅草伊凡
  7. 小米4c信号显示无服务器,小米4c网速慢解决方法(小米4c卡顿严重)
  8. html腾讯视频组件,3.腾讯视频组件
  9. 11大Java开源中文分词器的使用方法和分词效果对比(转)
  10. java开心消消乐代码_Java小项目之:教你做开心消消乐!