696|4

219

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

《原子Linux驱动开发》阅读观点篇 [复制链接]

在Linux设备驱动模型中,字符设备驱动确实是最基本和最常见的一类设备驱动。字符设备是以字节流的方式进行数据读写的设备,通常没有复杂的寻址方式,也不支持随机访问。

字符设备驱动的主要特点包括:

  1. 字节流访问:字符设备是以字节为单位进行读写的,每次读写操作都是按照字节流进行的。

  2. 顺序访问:对字符设备的读写操作是有顺序的,通常不支持随机访问。

  3. 设备文件:在Linux中,每个字符设备都会在/dev目录下有一个对应的设备文件,通过这个设备文件,用户空间程序可以访问设备。

  4. 文件操作:字符设备驱动通过实现一系列的文件操作接口(open(), read(), write(), close()等)来与用户空间进行交互。

下面正式开始,从第一字符设备驱动开始:

 

在Linux系统中,字符设备驱动通过创建位于/dev目录下的设备文件来提供对硬件的访问。这些设备文件通常具有特定的命名规则,/dev/xxx,其中xxx是具体的驱动文件名字,它代表了某个特定的字符设备。

应用程序通过打开、读取、写入和关闭这些设备文件来与硬件进行交互。这些操作在应用程序中通常使用标准的文件I/O函数(如open(), read(), write(), close()等)来完成。当应用程序对这些设备文件进行操作时,Linux内核会将这些操作转发给相应的字符设备驱动。

字符设备驱动会实现一系列的文件操作函数,这些函数定义了如何对硬件进行具体的操作。当应用程序调用write()函数向设备文件写入数据时,内核会调用字符设备驱动中实现的write文件操作函数,该函数会负责将数据发送给硬件。同样地,当应用程序调用read()函数从设备文件读取数据时,内核会调用字符设备驱动中实现的read文件操作函数,该函数会从硬件中读取数据并返回给应用程序。

 

点灯我是最喜欢的了,因为从开始学就是点灯,到最后的结束或者调试都可以用灯来进行判断,所以我特意贴了点灯篇。

 

  

 

 

 

Linux驱动开发涉及到对硬件的直接操作,包括配置硬件寄存器,而这些操作通常是通过内存映射来完成的。下面我会对您的描述进行一些补充和解释。

地址映射在Linux驱动开发中的作用

在Linux系统中,内核空间和用户空间是隔离的,每个进程都有自己独立的虚拟地址空间。为了访问物理硬件,如GPIO端口,驱动程序需要在内核空间中进行操作。然而,直接操作物理地址是不安全的,因此Linux使用了虚拟地址来替代物理地址。

MMU(内存管理单元)负责将虚拟地址转换为物理地址。在Linux内核启动时,它会初始化MMU并设置一系列的内存映射,包括将物理内存映射到虚拟地址空间,以及将特定的硬件设备地址映射到内核的虚拟地址空间。

Linux驱动中的地址映射

在编写Linux驱动时,对于需要直接访问的硬件寄存器,驱动程序通常会使用ioremap()函数(或其替代函数,如devm_ioremap_resource())来获取一个指向这些寄存器的虚拟地址。一旦获得了这个虚拟地址,驱动程序就可以像操作普通内存一样来操作这些寄存器了。

例如,如果您要操作一个连接到GPIO端口的LED灯,您可能需要找到该GPIO端口的基地址,并使用ioremap()将其映射到内核的虚拟地址空间。然后,您就可以通过这个虚拟地址来读写GPIO寄存器,从而控制LED灯的开关状态。

注意事项

  1. 权限:只有内核空间的代码才有权限直接访问硬件。用户空间的程序不能直接访问硬件寄存器,它们需要通过系统调用来请求内核空间的驱动程序来完成这些操作。
  2. 平台依赖性:不同的处理器和硬件平台可能有不同的内存映射方式和寄存器布局。因此,在编写驱动程序时,需要仔细查阅相关的硬件文档,以确保正确地配置和访问硬件寄存器。
  3. 资源管理:使用ioremap()获取的虚拟地址在驱动卸载时需要使用iounmap()释放,以避免内存泄漏和其他潜在问题。

 

这个我也贴上来,因为之前一直不知道含义是什么,看到这里时就突然清楚了。

 

 

cdev_del函数:

 

使用的是基于 cdev 的现代字符设备驱动接口,应该在驱动卸载时调用 cdev_del() 来删除字符设备,并调用 unregister_chrdev_region() 来释放设备号范围。这两个函数合起来的功能相当于旧式接口中的 unregister_chrdev() 函数。这样做可以确保你的驱动在卸载时能够正确地清理其分配的资源。

 

cdev_del()

cdev_del() 函数用于从内核中删除一个字符设备结构体(struct cdev)。当你使用 cdev_init() 或 cdev_alloc() 初始化或分配一个字符设备结构体,并且使用 cdev_add() 将其添加到系统中后,在驱动卸载时,你需要调用 cdev_del() 来从系统中移除它。

 

 

 

 

创建和删除类

在Linux中,class是一个用于组织和管理设备节点的结构体,定义在include/linux/device.h头文件中。每个class都对应一个设备类别,例如“tty”对应终端设备,“sound”对应声音设备等。

class_create()

class_create()函数用于创建一个新的class。它的原型通常如下:

  • owner:通常是THIS_MODULE宏,表示这个类属于当前加载的模块。
  • name:类的名称,通常与设备类型相关。

class_create()返回一个指向新创建的class结构体的指针。如果创建成功,这个指针可以用于后续的设备创建操作。

class_destroy()

当驱动卸载时,需要调用class_destroy()来删除之前创建的类:

  • cls:要删除的类的指针。

调用class_destroy()会释放与类相关的资源,并删除该类。

创建设备节点

创建了类之后,还需要在类下创建具体的设备节点,这样用户空间程序才能通过/dev目录下的设备文件与内核驱动进行交互。

device_create()

device_create()函数用于在指定的类下创建一个新的设备:

  • class:设备所属的类。
  • parent:设备的父设备,通常为NULL。
  • devt:设备的设备号,通常由MKDEV()宏生成。
  • drvdata:传递给设备的私有数据,通常为NULL。
  • fmt:设备名称的格式字符串,以及后续的变参。

这个函数返回一个指向新创建设备的device结构体的指针。如果创建成功,这个设备会在/dev目录下生成一个对应的设备文件。

 

 

 

 

最新回复

RTOS,Real-Time OS,不过Linux应该不是实时的吧? 没有玩过RTOS,这个有现成的系统了解一下吗?   详情 回复 发表于 2024-3-27 14:41
点赞 关注

回复
举报

6960

帖子

11

TA的资源

版主

沙发
 

MMU(内存管理单元)负责将虚拟地址转换为物理地址。在Linux内核启动时,它会初始化MMU并设置一系列的内存映射,包括将物理内存映射到虚拟地址空间,以及将特定的硬件设备地址映射到内核的虚拟地址空间。

这个东西就是跟MCU最大的差别吧。

点评

RTOS是不是就和linux好像     详情 回复 发表于 2024-3-22 09:05
 
 

回复

6450

帖子

10

TA的资源

版主

板凳
 
lugl4313820 发表于 2024-3-21 21:47 MMU(内存管理单元)负责将虚拟地址转换为物理地址。在Linux内核启动时,它会初始化MMU并设置一系列的内存 ...

RTOS是不是就和linux好像   

 
个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 
 

回复

7608

帖子

18

TA的资源

五彩晶圆(高级)

4
 

cdev_del 哪个版本的内核?好像有点老了哦?

 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

1364

帖子

1

TA的资源

五彩晶圆(初级)

5
 

RTOS,Real-Time OS,不过Linux应该不是实时的吧?

没有玩过RTOS,这个有现成的系统了解一下吗?

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表