led驱动程序

news/2024/12/21 23:01:14/

led_drv.c文件如下:

#include <linux/module.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>#include "led_opr.h"#define LED_NUM 2/*① 确定主设备号,也可以让内核分配*/
static int major = 0;static struct class *led_class;struct led_operations *p_led_opr;
#define MIN(a , b)(a < b ? a : b)
/*③ 实现对应的 drv_open/drv_read/drv_write 等函数,填入 file_operations 结构体*/static  ssize_t led_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);return 0;
};//app调用此函数时采用write(fd, &val, 1) 取值val的一字节写入fd
static ssize_t	led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{	int err;char status;unsigned int minor = iminor(file_inode(file));//根据file结构体来得到次设备号printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);err = copy_from_user(&status, buf, 1);//buf里的数据copy到statusp_led_opr->ctl(minor,status);//根据status的值操作led//根据次设备号和status控制ledreturn 1;};
static 	int led_drv_open(struct inode *node, struct file *file)
{int minor = iminor(node);printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);//根据次设备号初始化ledp_led_opr->init(minor);return 0;
};
static 	int led_drv_close (struct inode *node, struct file *file)
{printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);return 0;
}
;
/*② 定义自己的 file_operations 结构体*/
static struct file_operations led_drv = {.owner	 = THIS_MODULE,.open    = led_drv_open,.read    = led_drv_read,.write   = led_drv_write,.release = led_drv_close,};//④ 把 file_operations 结构体告诉内核:register_chrdev、static int __init led_init(void)
{int err;int i;printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);major = register_chrdev(0, "led", &led_drv);led_class = class_create(THIS_MODULE, "led");//⑦ 其他完善:提供设备信息,自动创建设备节点:class_create, device_create*/err = PTR_ERR(led_class);if (IS_ERR(led_class)){printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);unregister_chrdev(major,"led");return -1;}for(i=0;i<LED_NUM;i++)device_create(led_class, NULL, MKDEV(major, i), NULL, "led%d",i); p_led_opr = get_board_led_opr();return 0;};//⑤ 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数
//⑥ 有入口函数就应该有出口函数:卸载驱动程序时,出口函数调用 unregister_chrdev
static void __exit led_exit(void)
{int i;for(i = 0; i < LED_NUM; i++)device_destroy(led_class,  MKDEV(major, i));printk("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__);device_destroy(led_class, MKDEV(major,0));class_destroy(led_class);unregister_chrdev(major,"led");
};module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

为了使同一个驱动程序可以操作不同的led,采用分层的思想,以下是led_opr.h文件

struct led_operations{int (*init)(int which);//初始化led,选择哪一个ledint (*ctl)(int which, char status);//控制led,选择哪一个led 亮1 灭0
};struct led_operations *get_board_led_opr(void);//调用此函数是为了让leddrv.c访问led_operation结构体

为了使此驱动程序使用于其他板子,以下是board_demo文件:

#include <linux/module.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include "led_opr.h"static int board_demo_led_init(int which)//初始化led,which哪一个led
{printk("%s %s line %d,led %d\n",__FILE__,__FUNCTION__,__LINE__,which);return 0;	}static int board_demo_led_ctl(int which,char status)//初始化led,which哪一个led
{printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");return 0;	}static struct led_operations board_demo_led_opr = {.init = board_demo_led_init,.ctl = board_demo_led_ctl,
};struct led_operations *get_board_led_opr(void)
{return &board_demo_led_opr;}

makefile文件如下:

KERN_DIR = /home/john/100ask_imx6ull-sdk/Linux-4.9.88all:make -C $(KERN_DIR) M=`pwd` modules $(CROSS_COMPILE)gcc -o ledtest ledtest.c clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderrm -f ledtest# 参考内核源码drivers/char/ipmi/Makefile
# 要想把a.c, b.c编译成ab.ko, 可以这样指定:
# ab-y := a.o b.o
# obj-m += ab.o# leddrv.c board_demo.c 编译成 100ask.ko
100ask_led-y := leddrv.o board_demo.o
obj-m	+= 100ask_led.o

http://www.ppmy.cn/news/364244.html

相关文章

Linux驱动_LED驱动

目录 一、地址映射 二、实验程序编写 1、注册驱动入口和出口函数 2、编写驱动入口和出口函数 3、驱动完整代码 4、应用完整代码 总结 一、地址映射 1、在裸机实验的时候操作LED等外设实际上是操作相应外设的寄存器。 2、linux下驱动开发最终要操作的也是寄存器&#…

RK系列LED驱动编程(简易)

一. 在主DTS&#xff08;系统主要调用的DTS&#xff09;里面添加节点&#xff08;注意不要添加到了别的节点里面&#xff09; 路径&#xff1a;/kernel/arch/arm64/boot/dts/rockchip&#xff08;一般是这个&#xff0c;有的在arm里&#xff09; lec_en { //节点名字随便写 …

驱动程序开发:新字符设备驱动之LED点灯

驱动程序开发&#xff1a;新字符设备驱动之LED点灯 newchrled.c /** 根据linux内核的程序查找所使用函数的对应头文件。*/ #include <linux/module.h> // MODULE_LICENSE&#xff0c;MODULE_AUTHOR #include <linux/init.h> // module_init&#xff0c;module_e…

Linux驱动开发 - LED驱动

驱动程序 #include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/gpio.h> …

Linux驱动_新LED驱动

一、新字符驱动原理 1、以前的字符驱动使用register_chedev注册字符设备&#xff0c;需要手动指定主设备号 2、新版字符型驱动有两种方式注册字符设备&#xff1a;alloc_chrdev_region(自动申请设备号&#xff09;和register_chrdev_region(手动申请主设备号)。两种申请方式的注…

一、LED驱动电路

该专栏笔记整理于哔哩哔哩up主 硬件工程师桥 &#xff0c;个人感觉up主视频质量还是很高的&#xff0c;对硬件感兴趣的小伙伴可以戳蓝字关注一波~ 文档中原理图部分&#xff08;不包含对原视频截图中涉及的原理图&#xff09;统一使用 立创EDA 进行绘制 同时&#xff0c;由于个…

linux设备驱动--LED驱动

linux设备驱动--LED驱动 最近正在学习设备驱动开发&#xff0c;因此打算写一个系列博客&#xff0c;即是对自己学习的一个总结&#xff0c;也是对自己的一个督促&#xff0c;有不对&#xff0c;不足&#xff0c;需要改正的地方还望大家指出&#xff0c;而且希望结识志同道合的朋…

【立创开源】RY3730-带充电的恒流驱动LED照明灯

如题所示&#xff0c;作者为了把手上的RY3730恒流驱动芯片和IP2312锂电池充电芯片用完&#xff0c;就做了这么一个板子&#xff0c;甚至顺便把之前打的亚克力板也用完了( 开源地址 RY3730-带充电的恒流驱动LED照明灯 - 嘉立创EDA开源硬件平台 嘉立创EDA开源硬件平台&#xff…