简介
1、字符设备是Linux驱动中最基本的一类设备驱动,字符设备就是一个个字节,按照字节流进行读写操作的设备。(例:按键,电池等,IIC,SPI,LCD)。这些设备的驱动就叫字符设备驱动。
在Linux下一切皆为文件,驱动加载成功以后会在“/dev”目录下生成一个相对应的设备节点(文件),应用程序通过对这个“/dev/xxx”的文件进行操作,这个xxx是具体的驱动文件名字。比如/dev/led,可以通过read来读取当前灯的状态(开或者关),write可以写数据,用来控制灯开或者关,open和close就是打开或者关闭这个led驱动
在 Linux 内核文件 include/linux/fs.h 中
有个叫做 file_operations 的结构体,此结构体就是 Linux 内核驱动操作函数集合(上面那几个函数都在里面)
2.字符设备驱动开发步骤
1、注册模块加载与卸载函数(也就是入口函数与出口函数)
module_init(xxx_init); //注册模块加载函数
2、 设置所使用的GPIO
获取设备节点
获取设备树中的gpio属性,得到设备编号
利用gpio子系统设备gpio口
3、注册字符设备驱动
创建设备号
进行一些初始化
创建出设备
4、注册模块卸载函数
module_exit(xxx_exit); //注册模块卸载函数
几个重要的结构体
1、设备结构体
内核用struct cdev结构体来描述一个字符设备,并通过struct kobj_map类型的散列表cdev_map来管理当前系统中的所有字符设备
struct gpioled_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev 字符设备结构体*/
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
int minor; /* 次设备号 */
struct device_node *nd; /* 设备节点 */
int led_gpio; /* led所使用的GPIO编号 */
};
//字符设备结构体
struct cdev {
struct kobject kobj;
struct module *owner;
const struct file_operations *ops;
struct list_head list;
dev_t dev;
unsigned int count;
};
2、设备操作结构体
应用层代码的write之后的函数会通过系统函数调用到设备操作结构体中的write函数
static struct file_operations gpioled_fops = {
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
read和write函数时,需要使用copy_to_user函数以及copy_from_user函数来进行数据访问,写入/读取成功函数返回0,失败则会返回未被拷贝的字节数。