头文件:
#ifndef __HEAD_H__
#define __HEAD_H__#define LED_ON _IOW('l', 1,int)
#define LED_OFF _IOW('l', 0,int)
#endif
c文件
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "head.h"
int main(int argc, char const *argv[])
{char buf[20] = "";int a, b;int fd = open("/dev/myled0", O_RDWR);if (fd < 0){printf("打开设备文件失败\n");return -1;}while (1){printf("请输入要实现的功能 1(关灯) 0(开灯):");scanf("%d", &a);switch (a){case 0:ioctl(fd, LED_ON);break;case 1:ioctl(fd, LED_OFF);break;}}close(fd);return 0;
}
驱动文件:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/timer.h>
#include "head.h"
int major;
char kbuf[20] = "";
struct class *cls;
struct device *dev;
struct device_node *dnode;
unsigned int gpionu1;
unsigned int gpionu2;
unsigned int gpionu3;
struct timer_list mytimer;
//int ret;
int mycdev_open(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
//自定义点灯函数
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch (cmd){case LED_ON:gpio_set_value(gpionu1, 1);gpio_set_value(gpionu2, 1);gpio_set_value(gpionu3, 1);break;case LED_OFF:gpio_set_value(gpionu1, 0);gpio_set_value(gpionu2, 0);gpio_set_value(gpionu3, 0);break;}return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);return 0;
}
// 定义操作方法结构体变量并赋值
struct file_operations fops = {.open = mycdev_open,.unlocked_ioctl = mycdev_ioctl,.release = mycdev_close,
};
//定时器处理函数
void mytimer_function(struct timer_list *timer)
{//打印一次hello worldprinkt("hellow world\n");//再次启用定时器mod_timer(timer,jiffies+(5*HZ));
}
static int __init mycdev_init(void)
{// 字符驱动设备注册major = register_chrdev(0, "myled", &fops);if (major < 0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功:major=%d\n", major);// 向上提交目录cls = class_create(THIS_MODULE, "myled");if (IS_ERR(cls)){printk("向上提交目录失败\n");return -PTR_ERR(cls);}printk("向上提交目录成功\n");// 向上提交三个设备节点信息int i;for (i = 0; i < 3; i++){dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);if (IS_ERR(dev)){printk("向上提交设备节点失败\n");return -PTR_ERR(dev);}}printk("向上提交设备节点成功\n");// 解析设备树节点信息dnode = of_find_node_by_path("/myled");if (dnode == NULL){printk("解析设备树节点失败\n");return -ENXIO;}printk("解析设备树节点成功\n");// 获取LED1 GPIO编号gpionu1 = of_get_named_gpio(dnode, "led1-gpio", 0);if (gpionu1 < 0){printk("获取LED1GPIO编号失败\n");return -ENXIO;}// 获取LED2 GPIO编号gpionu2 = of_get_named_gpio(dnode, "led2-gpio", 0);if (gpionu2 < 0){printk("获取LED2GPIO编号失败\n");return -ENXIO;}// 获取LED3 GPIO编号gpionu3 = of_get_named_gpio(dnode, "led3-gpio", 0);if (gpionu3 < 0){printk("获取LED3GPIO编号失败\n");return -ENXIO;}// 申请LED1 GPIO编号int ret = gpio_request(gpionu1, NULL);if (ret){printk("申请LED1 GPIO编号失败");return -ENXIO;}printk("申请LED1 GPIO编号成功:%d\n", gpionu1);// 申请LED2 GPIO编号ret = gpio_request(gpionu2, NULL);if (ret){printk("申请LED2 GPIO编号失败");return -ENXIO;}printk("申请LED2 GPIO编号成功:%d\n", gpionu2);// 申请LED3 GPIO编号ret = gpio_request(gpionu3, NULL);if (ret){printk("申请LED3 GPIO编号失败");return -ENXIO;}printk("申请LED3 GPIO编号成功:%d\n", gpionu3);// 设置LED1 GPIO输出ret = gpio_direction_output(gpionu1, 0);if (ret){printk("LEd1 GPIO输出设置失败\n");return -1;}// 设置LED2 GPIO输出ret = gpio_direction_output(gpionu2, 0);if (ret){printk("LEd2 GPIO输出设置失败\n");return -1;}// 设置LED3 GPIO输出ret = gpio_direction_output(gpionu3, 0);if (ret){printk("LEd3 GPIO输出设置失败\n");return -1;}//初始化定时器对象timer_setup(&mytimer,mytimer_function,0);mytimer.expires=jiffies+(5*HZ);//定时5s//注册定时器add_timer(&mytimer);return 0;
}
static void __exit mycdev_exit(void)
{// 设置灯灭gpio_set_value(gpionu1, 0);gpio_set_value(gpionu2, 0);gpio_set_value(gpionu3, 0);//注销定时器del_timer(&mytimer);// 释放GPIO编号gpio_free(gpionu1);gpio_free(gpionu2);gpio_free(gpionu3);// 销毁设备节点信息int i;for (i = 0; i < 3; i++){device_destroy(cls, MKDEV(major, i));}// 销毁目录class_destroy(cls);// 注销字符设备驱动unregister_chrdev(major, "myled");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");