韦东山第12课-字符设备驱动框架、led驱动
来源:互联网 发布:防止域名被腾讯报毒 编辑:程序博客网 时间:2024/05/16 01:21
1 first_drv驱动函数
first_drv.c:
#include <linux/types.h>#include <linux/errno.h>#include <linux/miscdevice.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/fcntl.h>#include <linux/mc146818rtc.h>#include <linux/netdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/system.h>#include <linux/delay.h>static int first_drv_open(struct inode *inode, struct file *file){ printk("first_drv_open \n"); return 0; }static ssize_t first_drv_open(struct file *file, const char __user *buf, size_t count, loff_t *ppos);{ printk("first_drv_write \n"); return 0; }static const struct file_operations first_drv_fops = {.owner = THIS_MODULE,/* owner */.write = first_drv_write,/* write */.open =first_drv_open,/* open */};static int __init first_drv_init(void){register_chrdev(111,"first_drv",&first_drv_fops);//registe dev;rell kernel/* 这是有对比空缺的设备号填写的,也可以用int major=register_chrdev(0,"first_drv",&first_drv_fops); //填0表示自动分配设备号*/ //主设备号,名字,file_operatins结构体 }static void __exit first_drv_exit(void){ unregister_device(111,"first_drv");//卸载函数 //主设备号,设备名}module_init(first_drv_init);module_exit(first_drv_exit);MODULE_LICENSE("GPL");MODULE_ALIAS_CHARDEV_MAJOR(IBM_FS3270_MAJOR);
Makefile:
KERN_DIR = /home/book/workspace/jz2440/systems/linux-2.6.22.6all: make -C $(KERN_DIR) M='pwd' modulesclean:make -C $(KERN_DIR) M='pwd' module cleanrm -rf modules.orderobj-m += first_drv.o
加载驱动:
cat /proc/devices //查看驱动
insmod SHT21.ko
//装置驱动 调用module_init(first_drv_init);
rmmod first_drv //卸载驱动调用module_exit(first_drv_init);
lsmod //查看内核中已经加载了哪些模块
mknod /dev/led c 111 0 // 创建设备文件
2 自动创建设备文件
int major=register_chrdev(0,"first_drv",&first_drv_fops); //填0表示自动分配设备号
udev机制,我们就是mdev,
cd /sys/ 目录下有系统设备的信息
mdev根据系统信息创建设备节点。
在驱动注册函数中加入如下代码:
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
在驱动卸载函数中加入如下代码:
class_device_unregister(firstdrv_class_dev);class_destroy(firstdrv_class);
这个时候驱动加载进去就会自动创建设备文件。
问:为什么可以自动创建呢:
答:驱动程序通过这两个函数,给内核提供了系统信息。一加载就会有文件生成 /sys/class/firstdrv/xyz/dev mdev根据这些信息创建设备。
问:为什么mdev机制可以根据/sys目录文件的改变生成文件呢?
答:/etc/init.d/rcS 中有“echo /sbin/mdev > /proc/sys/kernel/hotplug” 表示支持热插拔:有驱动加载,就调用mdev
我的系统竟然不支持热插拔,
1 构建根文件系统时busybox 配置为支持hotplug
2 /etc/init.d/rcS 中加入“echo /sbin/mdev > /proc/sys/kernel/hotplug”等
程序框架:
//first_drv.c:
udev机制,我们就是mdev,
cd /sys/ 目录下有系统设备的信息
mdev根据系统信息创建设备节点。
在驱动注册函数中加入如下代码:
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
在驱动卸载函数中加入如下代码:
class_device_unregister(firstdrv_class_dev);class_destroy(firstdrv_class);
这个时候驱动加载进去就会自动创建设备文件。
问:为什么可以自动创建呢:
答:驱动程序通过这两个函数,给内核提供了系统信息。一加载就会有文件生成 /sys/class/firstdrv/xyz/dev mdev根据这些信息创建设备。
问:为什么mdev机制可以根据/sys目录文件的改变生成文件呢?
答:/etc/init.d/rcS 中有“echo /sbin/mdev > /proc/sys/kernel/hotplug” 表示支持热插拔:有驱动加载,就调用mdev
我的系统竟然不支持热插拔,
1 构建根文件系统时busybox 配置为支持hotplug
2 /etc/init.d/rcS 中加入“echo /sbin/mdev > /proc/sys/kernel/hotplug”等
程序框架:
//first_drv.c:
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>static struct class *firstdrv_class;static struct class_device*firstdrv_class_dev;static int first_drv_open(struct inode *inode, struct file *file){printk("first_drv_open\n");/* 配置GPF4,5,6为输出 */return 0;}static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){printk("first_drv_write\n");return 0;}static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = first_drv_open, .write= first_drv_write, };int major;static int __init first_drv_init(void){ major=register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核 // (主设备号,驱动名字(cat /proc/devices中显示),file_operations类)firstdrv_class = class_create(THIS_MODULE, "firstdrv"); //(THIS_MODULE,驱动名字)firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */ //(firstdrv_class类,父类,驱动号:MKDEV(主号,次号)),struct device *device,mdev要创建的设备名称)return 0;}static void first_drv_exit(void){unregister_chrdev(major, "first_drv"); // 卸载class_device_unregister(firstdrv_class_dev);class_destroy(firstdrv_class);}module_init(first_drv_init);module_exit(first_drv_exit);MODULE_LICENSE("GPL");
3 led驱动
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/arch/regs-gpio.h>#include <asm/hardware.h>static struct class *firstdrv_class;static struct class_device*firstdrv_class_dev;volatile unsigned long *gpfcon = NULL;volatile unsigned long *gpfdat = NULL;static int first_drv_open(struct inode *inode, struct file *file){ *gpfcon &= ~((3<<4*2)|(3<<5*2)|(3<<6*2)); *gpfcon |= ((1<<4*2)|(1<<5*2)|(1<<6*2)); // *gpfdat=((1<<4)|(1<<5)|(1<<6)); //printk("first_drv_open\n");/* 配置GPF4,5,6为输出 */return 0;}static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos){ int val; copy_from_user(&val,buf,count); if(val==1) { //电灯 *gpfdat &=~((1<<4)|(1<<5)|(1<<6)); } else { //down *gpfdat |=((1<<4)|(1<<5)|(1<<6)); } //printk("first_drv_write\n");return 0;}static struct file_operations first_drv_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = first_drv_open, .write= first_drv_write, };int major;static int __init first_drv_init(void){ major=register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核firstdrv_class = class_create(THIS_MODULE, "firstdrv");firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);gpfdat = gpfcon + 1;return 0;}static void first_drv_exit(void){unregister_chrdev(major, "first_drv"); // 卸载class_device_unregister(firstdrv_class_dev);class_destroy(firstdrv_class);//iounmap(gpfcon);}module_init(first_drv_init);module_exit(first_drv_exit);MODULE_LICENSE("GPL");
4 copy_from_user
copy_from_user
static inline int copy_from_user(void *to, const void __user *from, int n)
例子:.ko/first_drv_write:copy_from_user(&val, buf, count); //从buf考值到val中
测试程序用write写数据到驱动first_drv_write
copy_to_user
static inline int copy_to_user(void __user *to, const void *from, int n)
例子:.ko/second_drv_read:copy_to_user(buf, key_vals, sizeof(key_vals)); //将key_cals的值考入buf中
seconddrvtest.c:read(fd, key_vals, sizeof(key_vals));
4 测试函数
firstdrvtest.cfirstdrvtest.c: //通过操作文件/dev/led 使用驱动,open write与驱动中的对应
昨天编译一直不能用是因为用的gcc 编译的 应该用arm-linux-gcc -o firstdrvtest firstdrvtest.c
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>/* firstdrvtest on * firstdrvtest off */int main(int argc, char **argv){int fd;int val = 1;fd = open("/dev/xxx", O_RDWR);if (fd < 0){printf("can't open!\n");}if (argc != 2){printf("Usage :\n");printf("%s <on|off>\n", argv[0]);return 0;}if (strcmp(argv[1], "on") == 0){val = 1;}else{val = 0;}write(fd, &val, 4);return 0;}
阅读全文
1 0
- 韦东山第12课-字符设备驱动框架、led驱动
- 韦东山第12课-字符设备驱动、按键查询、copy_to_user
- 韦东山第12课-字符设备、中断方式查询驱动
- LED字符设备驱动
- led字符设备驱动
- 字符设备驱动---Led
- 字符设备驱动-LED驱动
- 字符设备驱动第十五课-----LED点灯
- 字符设备驱动之LED
- 字符设备驱动点亮led
- 字符设备驱动----LED驱动程序
- Linux 字符设备驱动 LED
- 字符设备驱动--LED驱动程序
- 韦东山第12.6节-字符驱动之异步通知
- Linux字符设备驱动之LED驱动
- linux字符设备驱动-LED驱动
- 第一篇 字符设备驱动程序之LED流水灯驱动
- 字符设备驱动框架
- Springboot启动后只能本地访问,无法通过外部IP访问
- 关于emoji表情在Qt(详细利用代码晚点分享)
- php返回json数据中文显示的问题
- JS追加文件下载
- eclipse下进行ndk开发步骤
- 韦东山第12课-字符设备驱动框架、led驱动
- 【上云须知】全面了解阿里云能为你做什么
- Ericsson Ridea从入门到精通(四)
- 最长公共上升子序列内n^4~n^2
- 微信小程序 页面跳转传参详解
- Linux学习:安装Linux虚拟机
- Android界面编程——Android高级组件
- layim的websocket消息撤回功能实现
- 常见的几种RuntimeException