摘要:
USB urb (USB request block)内核使用2.6.29.4 USB 设备驱动代码通过urb和所有的 USB 设备通讯。urb用 struct urb 结构描述(include/linux/usb.h )。 urb以一种异步的方式同一个特定USB设备的特定端点发送或接受数据。一个 USB 设备驱动可根据驱动的需要,分配多个 urb 给一个端点或重用单个 urb 给多个不同的端点。设备中的每个端点都处理一个 urb 队列, 所以多个 urb 可在队列清空之前被发送到相同的端点。 一个 urb 的典型生命循环如下: (1)被创建; (2)被分配给一个特定 USB 设备的特定端点; 阅读全文
摘要:
内核使用2.6.29.4 USB设备其实很复杂,但是Linux内核提供了一个称为USB core的子系统来处理了大部分的复杂工作,所以这里所描述的是驱动程序和USB core之间的接口。 在USB设备组织结构中,从上到下分为设备(device)、配置(config)、接口(interface)和端点(endpoint)四个层次。 对于这四个层次的简单描述如下: 设备通常具有一个或多个的配置 配置经常具有一个或多个的接口 接口通常具有一个或多个的设置 接口没有或具有一个以上的端点 设备 很明显,地代表了一个插入的USB设备,在内核使用数据结构 struct usb_device来描述整个USB设 阅读全文
摘要:
从此文档开始,内核使用2.6.29.4 很久没有写《LDD3》的学习笔记了,趁着做项目的机会,学习一下USB的驱动程序,并写学习笔记。 。 如果刚开始接触USB,会感觉无从下手,这种感觉就像我第一次接触嵌入式Linux一样。所以要对USB的硬件原理、数据传输和在USB电缆上传输的数据格式有一定的了解。所以推荐一篇《实用USB术语详解》。再去CEPARK ( China Electronics Park ) 电子园看完上面的经典教程和基础知识。看了上面的文章,您会对USB有一定的认识(如果你再写一个简单的在51上的USB固件就更好了),在学习USB的Linux驱动您就会觉得很轻松了。 如果您想要 阅读全文
摘要:
热插拔 有 2 个不同角度来看待热插拔: 从内核角度看,热插拔是在硬件、内核和内核驱动之间的交互。 从用户角度看,热插拔是内核和用户空间之间,通过调用用户空间程序(如hotplug、udev 和 mdev)的交互。 当需要通知用户内核发生了某种热插拔事件时,内核才调用这个用户空间程序。 现在的计算机系统,要求 Linux 内核能够在硬件从系统中增删时,可靠稳定地运行。这就对设备驱动作者增加了压力,因为在他们必须处理一个毫无征兆地突然出现或消失的设备。热插拔工具 当用户向系统添加或删除设备时,内核会产生一个热插拔事件,并在 /proc/sys/kernel/hotplug 文件里查找处理设备连接 阅读全文
摘要:
通过一个设备在内核中生命周期的各个阶段,可以更好地理解Linux设备模型。我将通过分析lddbus和sculld的源码来了解Linux设备模型中各环节的整合。《LDD3》中的(PCI总线)各环节的整合这部分内容作为参考资料,因为嵌入式Linux比较少用到PCI总线。看这部分内容一定要先熟悉一下 lddbus 和 sculld 的源码。一、lddbus模块:添加总线、导出总线设备和设备驱动的注册函数。lddbus子系统声明了一个bus_type结构,称为ldd_bus_type 。源码是在编译时初始化了这个结构体,源码:/* * And the bus type. */struct bus_ty 阅读全文
摘要:
文章的例子和实验使用《LDD3》所配的lddbus模块(稍作修改)。提示:在学习这部分内容是一定要分析所有介绍的源代码,知道他们与上一部分内容(kobject、kset、attribute等等)的关系,最好要分析一个实际的“flatform device”设备,不然会只学到表象,到后面会不知所云的。总线总线是处理器和一个或多个设备之间的通道,在设备模型中, 所有的设备都通过总线相连, 甚至是内部的虚拟"platform"总线。总线可以相互插入。设备模型展示了总线和它们所控制的设备之间的实际连接。 在 Linux 设备模型中, 总线由 bus_type 结构表示, 定义在 & 阅读全文
摘要:
以《LDD3》的说法:Linux设备模型这部分内容可以认为是高级教材,对于多数程序作者来说是不必要的。但是我个人认为:对于一个嵌入式Linux的底层程序员来说,这部分内容是很重要的。以我学习的ARM9为例,有很多总线(如SPI、IIC、IIS等等)在Linux下已经被编写成了子系统,无需自己写驱动;而这些总线又不像PCI、USB等在《LDD3》上有教程,有时还要自己研究它的子系统构架,甚至要自己添加一个新的总线类型。对于这方面的学习,我推荐几个网页,这些也是我这部分文章的参考资料:(1)《 Linux那些事儿 之 我是Sysfs》来源于复旦和交大三个牛人的Linux技术博客:网址: http: 阅读全文
摘要:
可以让设备在产生某个事件时通知处理器的方法就是中断。一个“中断”仅是一个信号,当硬件需要获得处理器对它的关注时,就可以发送这个信号。 Linux 处理中断的方式非常类似在用户空间处理信号的方式。 大多数情况下,一个驱动只需要为它的设备的中断注册一个处理例程,并当中断到来时进行正确的处理。本质上来讲,中断处理例程和其他的代码并行运行。因此,它们不可避免地引起并发问题,并竞争数据结构和硬件。 透彻地理解并发控制技术对中断来讲非常重要。 安装中断处理例程内核维护了一个中断信号线的注册表,类似于 I/O 端口的注册表。模块在使用中断前要先请求一个中断通道(或者 IRQ中断请求),并在使用后释放它。所用 阅读全文
摘要:
度量时间差时钟中断由系统定时硬件以周期性的间隔产生,这个间隔由内核根据 HZ 值来设定,HZ 是一个体系依赖的值,在 <linux/param.h>中定义或该文件包含的某个子平台相关文件中。作为通用的规则,即便如果知道 HZ 的值,在编程时应当不依赖这个特定值,而始终使用HZ。对于当前版本,我们应完全信任内核开发者,他们已经选择了最适合的HZ值,最好保持 HZ 的默认值。 对用户空间,内核HZ几乎完全隐藏,用户 HZ 始终扩展为 100。当用户空间程序包含 param.h,且每个报告给用户空间的计数器都做了相应转换。对用户来说确切的 HZ 值只能通过 /proc/interrupt 阅读全文
摘要:
在学习有关I/O总线的内容时,最好先看看相关的知识:从PC总线到ARM的内部总线I/O 端口和 I/O 内存每种外设都是通过读写寄存器来进行控制。 在硬件层,内存区和 I/O 区域没有概念上的区别: 它们都是通过向在地址总线和控制总线发出电平信号来进行访问,再通过数据总线读写数据。因为外设要与I\O总线匹配,而大部分流行的 I/O 总线是基于个人计算机模型(主要是 x86 家族:它为读和写 I/O 端口提供了独立的线路和特殊的 CPU 指令),所以即便那些没有单独I/O 端口地址空间的处理器,在访问外设时也要模拟成读写I\O端口。这一功能通常由外围芯片组(PC 中的南北桥)或 CPU 中的附加 阅读全文
摘要:
内核为设备驱动提供了一个统一的内存管理接口,所以模块无需涉及分段和分页等问题。 我已经在第一个scull模块中使用了 kmalloc 和 kfree 来分配和释放内存空间。 kmalloc 函数内幕kmalloc 是一个功能强大且高速(除非被阻塞)的工具,所分配到的内存在物理内存中连续且保持原有的数据(不清零)。原型:#include <linux/slab.h>void *kmalloc(size_t size, int flags); size 参数内核管理系统的物理内存,物理内存只能按页面进行分配。kmalloc 和典型的用户空间 malloc 在实际上有很大的差别,内核使用 阅读全文
摘要:
由于前面的学习中有用到 第十一章 内核数据结构类型 的知识,所以我先看了。要点如下:将linux 移植到新的体系结构时,开发者遇到的若干问题都与不正确的数据类型有关。坚持使用严格的数据类型和使用 -Wall -Wstrict-prototypes 进行编译可能避免大部分的 bug。内核数据使用的数据类型主要分为 3 个类型: 标准 C 语言类型、确定大小的类型和特定内核对象的类型。 标准 C 语言类型当需要“一个2字节填充符”或“用一个4字节字串来代表某个东西”,就不能使用标准C语言类型,因为在不同的体系结构,C 语言的数据类型所占的空间大小不同。后面的datasize 程序实验展示了用户空间 阅读全文
摘要:
提供访问控制对于一个设备节点来的可靠性来说有时是至关重要的。这部分的内容只是在open和release方法上做些修改,增加一些检查机制既可。 独享设备最生硬的访问控制方式是只允许一个设备一次被一个进程打开(独享),这是一个设备驱动最简单的访问控制。实现十分简单,具体的代码看实验源码吧!模块程序链接:scullsingle.tar.gz模块测试程序链接:scullsingle-test.tar.gzARM9实验板的实验现象是:[Tekkaman2440@SBC2440V4]#cd /lib/modules/[Tekkaman2440@SBC2440V4]#insmod scullsingle.k 阅读全文
摘要:
这一部分主要讨论:如果驱动程序无法立即满足请求,该如何响应?(65865346)一、休眠进程被置为休眠,意味着它被标识为处于一个特殊的状态并且从调度器的运行队列中移走。这个进程将不被在任何 CPU 上调度,即将不会运行。 直到发生某些事情改变了那个状态。安全地进入休眠的两条规则:(1) 永远不要在原子上下文中进入休眠,即当驱动在持有一个自旋锁、seqlock或者 RCU 锁时不能睡眠;关闭中断也不能睡眠。持有一个信号量时休眠是合法的,但你应当仔细查看代码:如果代码在持有一个信号量时睡眠,任何其他的等待这个信号量的线程也会休眠。因此发生在持有信号量时的休眠必须短暂,而且决不能阻塞那个将最终唤醒你 阅读全文
摘要:
今天进入《Linux设备驱动程序(第3版)》第六章高级字符驱动程序操作的学习。 一、ioctl 大部分设备除了读写能力,还可进行超出简单的数据传输之外的操作,所以设备驱动也必须具备进行各种硬件控制操作的能力. 这些操作常常通过 ioctl 方法来支持,它有和用户空间版本不同的原型:int (*ioctl) (struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg);需要注意的是:不管可选的参数arg是否由用户给定为一个整数或一个指针,它都以一个unsigned long的形式传递。如果调用程序不传递a 阅读全文