设备号:
主设备号:用于区分不同种类的设备。
次设备号:区分同一类型的多个设备。
驱动链表:管理所有设备的驱动。
**1.添加:**编写完驱动程序加载到内核。
1.1设备号。
1.2设备号。
1.3设备驱动函数(操作寄存器来驱动IO口)
**2.查找:**调用驱动程序,用户空间去open
驱动插入链表的顺序由设备号检索。
驱动代码基本框架:
加入static是由于linux内核源代码量庞大容易与其他指令重名,所以需要让这些指令只在当前文件有效
#include <linux/device.h> //class devise声明
#include <linux/uaccess.h> //copy_from_user 的头文件
#include <linux/types.h> //设备号 dev_t 类型声明
#include <asm/io.h> //ioremap iounmap的头文件
static struct class *pin4_class;
static struct device *pin4_class_dev;
static dev_t devno; //设备号
static int major =231; //主设备号
static int minor =0; //次设备号
static char *module_name="pin4"; //模块名
//led_open函数
static int pin4_open(struct inode *inode,struct file *file)
{
printk("pin4_open\n"); //内核的打印函数和printf类似
return 0;
}
//led_write函数
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{
printk90("pin4_write\n");
return 0;
}
static struct file_operations pin4_fops = {
.owner = THIS_MODULE,
.open = pin4_open,
.write = pin4_write,
};
int __init pin4_drv_init(void) //真实驱动入口
{
int ret;
devno = MKDEV(major,minor); //创建设备号
ret = register_chrdev(major, module_name,&pin4_fops); //注册驱动 告诉内核,把这个驱动加入到内核驱动的链表中
pin4_class=class_create(THIS_MODULE,"myfirstdemo"); //让代码在dev下自动生成设备(如果用手动生成设备较麻烦指令为:sudo mknod 名字 类型(通常为c字符串设备) 主设备号 次设备号)
pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name); //创建设备文件
return 0;
}
void __exit pin4_drv_exit(void)
{
device_destroy(pin4_class,devno); //销毁设备
class_destroy(pin4_class); //销毁类
unregister_chrdev(major, module_name); //卸载驱动
}
module_init(pin4_drv_init); //入口 内核加载该驱动时,这个宏会被调用
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");
在编译驱动代码前需要配置Linux内核源码中字符串设备里面的Makefile,添加obj-m +=pin4driver2.o. (驱动代码不一定非得放在对应的设备驱动文件夹下,可以任意放置,但是需要修改对应文件下加的makefile,使之变异之后生成对应的.ko文件)
路径:
源码树目录下的字符驱动设备路径。
添加配置
编译
使用内核编译指令进行编译(在内核源码的目录下进行编译):
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules
会生成pin4driver2.ko的文件。
使用交叉编译工具对上层代码进行编译:
上层代码:
编译上层代码:
复制上层代码和驱动到树莓派scp 文件 [email protected]:/home/pi
树莓派加载驱动代码:
sudo insmod pin4_drive2.ko 将驱动加载到驱动链表中去。
查看是否生成设备文件:ls /dev/pin4 -l
列出内核驱动模块:ls mod
删除驱动:sudo rmmod 加模块名不用加.ko后缀
还需要更改设备文件的类型:
sudo chmod 666 /dev/pin4
运行上层代码:
驱动代码中函数里面的printk是在内核中打印因此在命令界面没有打印,可以使用dmesg进行查看: