IMX6ULL嵌入式Linux驱动开发学习
以下内容是我在学习正点原子IMX6ULL
开发板alpha
中记录的笔记,部分摘录自正点原子IMX6ULL开发手册
。
一、新字符设备驱动原理(相比于上一篇笔记)
1 | int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) |
卸载驱动的时候,使用 unregister_chrdev_region
函数释放前面申请的设备号,原型如下:
1 | void unregister_chrdev_region(dev_t from, unsigned count) |
指定设备号
如果指定主设备号,使用
register_chrdev_region
函数来注册,原型如下:
1 | int register_chrdev_region(dev_t from, unsigned count, const char *name) |
一般是给定主设备号,然后使用 `MADEV` 构建完整的 `dev_t` ,一般次设备号选择`0`。
实际的驱动编写
需要考虑实际情况,因为在实际开发中会有两种情况:给定设备号和没有给定设备号。
字符设备注册
cdev
结构体表示字符设备,然后使用cdev_init
函数来初始化cdev
,原型
1 | cdev_init(struct cdev *cdev, const struct file_operations *fops) |
cdev_init
初始化完成 cdev
后,使用 cdev_add
添加到Linux内核,删除字符设备使用 cdev_del
。
二、自动创建设备节点
- linux内核在2.6版本中引入了
udev
机制,替换devfs
。udev
机制提供热插拔管理,可以在加载驱动的时候自动创建/dev/xxx
设备文件。 - 在使用busybox构建根文件系统的时候,busybox会创建一个
udev
的简化版本mdev
,所以在嵌入式linux中使用mdev
来实现设备节点文件的自动创建和删除。linux系统中的热插拔事件也由mdev
管理,在/etc/init.d/rsS
文件中如下语句。
1 | 11 echo /sbin/mdev > /proc/sys/kernel/hotplug |
创建设备节点
3.1. 创建设备类创建设备节点需要先使用
class_create()
函数创建类。1
2
3
4
5
6/* 创建类 */
newChrLed.class = class_create(THIS_MODULE, LED_NAME);
if (IS_ERR(newChrLed.class))
{
return PTR_ERR(newChrLed.class);
}3.2. 创建设备节点
使用
device_create()
函数来创建设备节点。1
2
3
4
5
6/* 创建设备节点 */
newChrLed.device = device_create(newChrLed.class, NULL, newChrLed.devid, NULL, LED_NAME);
if (IS_ERR(newChrLed.device))
{
return PTR_ERR(newChrLed.device);
}销毁设备节点和类
在驱动卸载的时候,需要对设备节点进行销毁。在驱动出口函数中使用如下代码进行销毁:
1
2
3
4
5/* 摧毁设备节点 */
device_destroy(newChrLed.class, newChrLed.devid);
/* 摧毁类 */
class_destroy(newChrLed.class);
因为创建设备节点是根据类来创建的,因此在销毁时,需要先销毁设备节点再销毁类。
三、文件私有数据
- 在
open
函数里设置filp->private_data
为设备变量。
1 | /* 设置私有数据 */ |
- 在其他的函数里,要访问设备的时候,直接读取私有数据
1 | struct newChrLed_dev *dev = filp->private_data; |
四、错误处理
在 xxx_init
加载驱动出现错误的时候,可以使用 goto
语句,对错误进行处理。比如:
1 | newChrLed.cdev.owner = THIS_MODULE; |
五、整体程序(开发中不使用这种方式)
1 |
|
六、测试应用程序
1 |
|
- 本文作者: 路痴的兔子
- 本文链接: https:/proudrabbit.gitee.io/IMX6ULL嵌入式Linux驱动学习笔记(四).html
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!