#define TIMER_NAME “timer”
#define TIMER_COUNT 1
#define TIMEROFF 0 /* 关灯 */
#define TIMERON 1 /* 开灯 */
#define CLOSE_CMD _IO(0xEF,1) //关闭命令
#define OPEN_CMD _IO(0xEF,2) //打开命令
#define SETPRIOD_CMD _IO(0xEF,3) //设置周期
struct timer_dev {
struct cdev cdev;
struct class \*class;/\*类:为了自动创建节点\*/
struct device \*device;/\*设备:为了自动创建节点\*/
dev\_t devid; //设备号
int major; //主设备号
int minor; //次设备号
struct device\_node \*nd; //设备节点
int led_gpio;
/\*定义设备结构体\*/
struct timer\_list timer;
int timerperiod; /\*定时器ms\*/
};
struct timer_dev timerdev; //TIMER设备
static int timer_open(struct inode *inode,struct file *filp)
{
filp->private_data = &timerdev;
return 0;
}
static ssize_t timer_write(struct file *filp, const char __user *buf,size_t cnt, loff_t *offt)
{
//struct timer_dev *dev = (struct timer_dev *)filp->private_data;
return 0;
}
static int timer_release(struct inode *inode,struct file *filp)
{
//struct timer_dev *dev = (struct timer_dev *)filp->private_data;
return 0;
}
long timer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct timer_dev *dev = (struct timer_dev *)filp->private_data;
int value = 0;
int ret = 0;
switch (cmd)
{
case CLOSE_CMD:
del\_timer\_sync(&dev->timer);
break;
case OPEN_CMD:
mod\_timer(&dev->timer,jiffies + msecs\_to\_jiffies(500));
break;
case SETPRIOD_CMD:
ret = copy\_from\_user(&value,(int \*)arg,sizeof(int));
if (ret < 0)
{
return -EFAULT;
}
dev->timerperiod = value;
mod\_timer(&dev->timer,jiffies + msecs\_to\_jiffies(dev->timerperiod));
break;
}
return 0;
}
static struct file_operations timer_fops = {
.owner = THIS_MODULE,
.write = timer_write,
.open = timer_open,
.release = timer_release,
.unlocked_ioctl = timer_ioctl,
};
static void timer_func(unsigned long arg)
{
struct timer_dev *dev = (struct timer_dev *)arg;
static int sta = 1;
sta = !sta;
gpio\_set\_value(dev->led_gpio,sta);
//重新开启定时器
mod\_timer(&dev->timer,jiffies + msecs\_to\_jiffies(dev->timerperiod));
}
/*初始化LED*/
int led_init(struct timer_dev *dev)
{
int ret = 0;
dev->nd = of\_find\_node\_by\_path("/gpioled");
if (dev->nd == NULL)
{
ret = -EINVAL;
goto fail_fd;
}
dev->led_gpio = of\_get\_named\_gpio(dev->nd,"led-goios",0);
if (dev->led_gpio < 0)
{
ret = -EINVAL;
goto fail_gpio;
}
ret = gpio\_request(dev->led_gpio,"led");
if(ret){
ret = -EBUSY;
printk("gpio\_request fail\r\n");
goto fail_request;
}
ret = gpio\_direction\_output(dev->led_gpio,1); //默认关灯
if (ret < 0)
{
ret = -EINVAL;
goto fail_gpioset;
}
return 0;
fail_gpioset:
fail_request:
gpio_free(dev->led_gpio);
fail_gpio:
fail_fd:
return ret;
}
static int __init timer_init(void)
{
int ret = 0;
/\*注册字符设备\*/
timerdev.major = 0;
if (timerdev.major){
timerdev.devid = MKDEV(timerdev.major,0);//设备号
ret = register\_chrdev\_region(timerdev.devid,TIMER_COUNT,TIMER_NAME);
} else{
ret = alloc\_chrdev\_region(&timerdev.devid,0,TIMER_COUNT,TIMER_NAME);
timerdev.major = MAJOR(timerdev.devid);
timerdev.minor = MINOR(timerdev.devid);
}printk("led major = %d led minor = %d \r\n",timerdev.major,timerdev.minor);
if (ret < 0){
goto faile_devid;
}
/\*2、添加字符设备\*/
timerdev.cdev.owner = THIS_MODULE;
cdev\_init(&timerdev.cdev,&timer_fops);
ret = cdev\_add(&timerdev.cdev,timerdev.devid,TIMER_COUNT);
if(ret<0){
goto fail_cdev;
}
/\*3、创建设备类\*/
timerdev.class = class\_create(THIS_MODULE,TIMER_NAME);
if(IS\_ERR(timerdev.class)){
ret = PTR\_ERR(timerdev.class);
printk("can't class\_create \r\n");
goto fail_class;
}
/\*4、创建设备节点\*/
timerdev.device = device\_create(timerdev.class,NULL,timerdev.devid,NULL,TIMER_NAME);
if(IS\_ERR(timerdev.device)){
ret = PTR\_ERR(timerdev.device);
printk("can't device\_create \r\n");
goto fail_device;
}
/\*5、初始化led\*/
ret = led\_init(&timerdev);
if (ret < 0)
{
ret = -EINVAL;
goto fail_init;
}
/\*6、定时器初始化\*/
init\_timer(&timerdev.timer);
timerdev.timerperiod = 500;
timerdev.timer.expires = jiffies + msecs\_to\_jiffies(timerdev.timerperiod);
timerdev.timer.function = timer_func;
timerdev.timer.data = (unsigned long)&timerdev;
add\_timer(&timerdev.timer); /\*添加到系统\*/
return 0;
fail_init:
fail_device:
class_destroy(timerdev.class);
fail_class:
cdev_del(&timerdev.cdev);
fail_cdev:
unregister_chrdev_region(timerdev.devid,TIMER_COUNT);
faile_devid:
return ret;
}
static void __exit timer_exit(void)
{
/\* 关灯 \*/
gpio\_set\_value(timerdev.led_gpio,1);
/\*删除定时器\*/
del\_timer(&timerdev.timer);
/\*删除设备\*/
cdev\_del(&timerdev.cdev);
/\*释放设备号\*/
unregister\_chrdev\_region(timerdev.devid,TIMER_COUNT);
/\*摧毁设备\*/
device\_destroy(timerdev.class,timerdev.devid);
/\*释放类\*/
class\_destroy(timerdev.class);
/\*释放IO\*/
gpio\_free(timerdev.led_gpio);
}
//模块加载函数
module_init(timer_init);
//模块卸载
module_exit(timer_exit);
MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“qhy”);
#### 应用编程
应用使用ioctl函数。unlocked\_ioctl和compat\_ioctl。
![在这里插入图片描述](https://img-blog.csdnimg.cn/02b8270ce06a4588b014fb7e8b4a6d7e.png)
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
/**
* 1 表示向驱动读取数据
*
* 2 表示向驱动写入数据
*
*/
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!
片转存中…(img-4tSRcQid-1715757414301)]
[外链图片转存中…(img-QhGUm7A8-1715757414301)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!