您的当前位置:首页正文

笔记:IMX6ULL Mini板-新字符驱动

2024-11-29 来源:个人技术集锦

前面led用的都是register_chrdev 函数注册字符设备,unregister_chrdev 函数注销字符设备,驱动模块加载成功以后还需要手动使用 mknod 命令创建设备节点。

register_chrdev 和 unregister_chrdev 这两个函数是老版本驱动使用的函数,现在新的字符设备驱动已经不再使用这两个函数,而是使用 Linux 内核推荐的新字符设备驱动 API 函数。

先总结一下旧版本的字符驱动注册流程:

这四行不必多说,定义好入口xxx_init和出口xxx_exit

1、创建 static const struct file_operations 类型变量

2、对该结构体成员进行赋值 .owner .write .open .release主要是这四个

3、 创建主设备号,设备名字

4、register_chrdev()函数注册字符设备

 5、unregister_chrdev()注销设备

void unregister_chrdev(unsigned int major, const char *name);

 以上为旧版本内核驱动流程,现版本内核驱动改为用register_chrdev_region()和unregister_chrdev_region()进行申请和释放设备号,cdev_add()和cdev_del()进行添加和删除字符设备。

新字符驱动注册流程:

依旧一样

1、创建 static const struct file_operations 类型变量,用于各种字符设备的操作,和旧版本第一步一样

2、进来后先申请设备号,这里新字符驱动提供了自动申请设备号的功能,所以先判断是否已指定设备号,如果指定了设备号,那就直接用MKDEV()把主设备号和次设备号合并一个完整的设备号出来,然后调用register_chrdev_region()函数分配注册设备号;如果没有,那就用alloc_chrdev_region()动态地分配一段字符设备号

MAJOR和MINOR用于查看主设备号和次设备号 

int register_chrdev_region(dev_t from, unsigned int count, const char *name);

int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, const char *name);

#define MAJOR(dev)   (((dev) >> 20) & 0xfff)  // 提取主设备号
#define MINOR(dev)   ((dev) & 0xfffff)         // 提取次设备号
#define MKDEV(ma, mi) (((ma) << 20) | (mi))    // 创建设备号

3、创建struct cdev类型的变量,这个结构体有ops和dev,也就是字符设备文件操作函数集合和设备号,第一步定义的ops是用来初始化cdev的成员ops 

4、dev初始化,cdev_init()对cdev进行初始化,参数的*fops是第一步创建的ops 

void cdev_init(struct cdev *cdev, struct file_operations *fops);

5、 使用cdev_add()函数添加字符设备到linux内核中

int cdev_add(struct cdev *cdev, dev_t dev, unsigned count);

6、 调用unregister_chrdev_region()释放设备号之前需要先注销字符设备,用cdev_del()操作,随后调用unregister_chrdev_region()释放设备号

void cdev_del(struct cdev *cdev);

void unregister_chrdev_region(dev_t dev, unsigned count);

newchrled定义如下

通过上述的步骤篇幅对比,新版本的字符驱动步骤多了不少,也增加了一些复杂度,但是我们发现新版本的字符驱动把设备号和字符设备”隔离”了,这样也对其做了更明确的管理,更模块化了;那最大的不同还是增添了自动分配设备号的功能,开发者不再需要担心设备号冲突,内核可以自动分配设备号并管理,这样如果外设多起来,新版本可以更好的管理,更好的维护。

以上就是我在学习正点原子IMX6ULL Mini板的学习总结!!!发此博客以此勉励自己,砥砺前行

 

显示全文