目录
说明:此博客为我自己对正点原子提供的资料学习的记录,内容大部分来源于正点原子资料,大家也可以去下载正点原子的官方资料学习,内容丰富。侵权删。
1.字符设备驱动简介
字符设备是Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、IIC、SPI,LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。在详细的学习字符设备驱动架构之前,我们先来简单的了解一下Linux 下的应用程序是如何调用驱动程序的,Linux 应用程序对驱动程序的调用如下图 所示:
其中关于 C库以及如何通过系统调用 “陷入 到内核空间这个我们不用去管,我们重点关注的是应用程序和具体的驱动,应用程序使用到的函数在具体驱动程序中都有与之对应的函数,比如应用程序中调用了 open这个函数,那么在驱动程序中也得有一个名为 open的函数。每一个系统调用,在驱动中都有与之对应的一个驱动函数,在 Linux内核文件 include/linux/fs.h中有个叫做 file_operations的结构体,此结构体就是 Linux内核驱动操作函数集合,内容如下所示:
2.字符设备驱动开发步骤
2.1驱动模块的加载和卸载
module_init(xxx_init); //注册模块加载函数
module_exit(xxx_exit); //注册模块卸载函数
module_init函数用来向 Linux内核注册一个模块加载函数,参数 xxx_init就是需要注册的具体函数,当使用“ insmod”命令加载驱动的时候 xxx_init这个函数就会被调 用。 module_exit()函数用来向 Linux内核注册一个模块卸载函数,参数 xxx_exit就是需要注册的具体函数,当使用“ rmmod”命令卸载具体驱动的时候 xxx_exit函数就会被调用。所以一般在xxx_init函数里进行一些驱动的初始化工作,在xxx_exit里面就需要对驱动程序的卸载做一些回收工作。
2.2字符设备注册与注销
static inline int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
static inline void unregister_chrdev(unsigned int major, const char *name)
register_chrdev函数用于注册字符设备,此函数共有三个参数:
major:主设备号,linux每个设备都有一个设备号,设备号分为主设备号和次设备号。
name:设备名字,指向一串字符串。
fops:结构体file_operations类型指针。
unregister_chrdev函数用那个与注销字符设备,此函数共有两个参数:
major:要注销的设备对应的主设备号。
name:要注销的设备对应的设备名。
2.3实现设备的具体操作函数
对具体设备驱动功能实现需要分析其需求,也就是构造file_operation结构体,对file_operations结构体成员进行实例化。
假设实现一个chttest驱动,打开open和关闭close是最基本的要求,几乎所有设备都得提供打开和关闭的功能,因此我们要实现file_operations结构体中的open和release两个函数。
假设chrtest这个设备控制着一段缓冲区,应用程序需要哦通过read和write这两个函数来对缓冲区的进行读写操作,那么我们也得实现file_operations结构体中的read和write两个函数。
假设基本需求就这些,那么驱动框架如下:
/*1、实现file_operations结构体中的open、release、read、write函数*/
static int chrtest_open(struct inode *inode,struct file *filp)
{
//具体内容根据具体需求实现
return 0;
}
//从设备读取数据
static ssize_t chrtest_read(struct file *filp,char __user *buf,size_t cnt,loff_t * offt)
{
//具体内容根据具体需求实现
return 0;
}
//向设备写入数据
static ssize_t chrtest_write(struct file *filp,const char __user *buf,
size_t cnt,loff_t *offt)
{
//具体内容根据具体需求实现
return 0;
}
//关闭和释放设备
static int chrtest_release(struct inode *indoe,struct file *filp)
{
//具体内容根据具体需求实现
return 0;
}
//初始化file_operations结构体
static struct file_operations test_fops=(void)
{