第一章:设备驱动概述:
1.1 操作系统的用处:
有了操作系统之后,设备驱动反而变得复杂,那要操作系统干什么?
首先,一个复杂的软件系统需要处理多个并发的任务,没有操作系统,想完成多任务并发是很困难的。
其次,操作系统给我们提供内存管理机制。一个典型的例子是,对于多数含 MMU 的处理器而言, Windows 、 Linux 等操作系统可以让每个进程都独立地访问 4GB 的内存空 间。简而言之,操作系统通过给设备驱动制造麻烦来达到给上层应用提供便利的目的。如果设备驱动都按照操作系统给出的独立于设备的接口而设计,应用程序将可使用统一的系统调用接口来访问各种设备。对于类UNIX的VxWorks、Linux等操作系统而言,应用程序通过write()、read()等函数读写文件就可以访问各种字符设备和块设备,而不用管设备的具体类型和工作方式,是非常方便的
1.2 Linux 将存储器和外设分为3个基础大类:
l 字符设备;
l 块设备;
l 网络设备。
字符设备指那些必须以串行顺序依次进行访问的设备,如触摸屏、磁带驱动器、鼠标等。块设备可以用任意顺序进行访问,以块为单位进行操作,如硬盘、软驱等。字符设备不经过系统的快速缓冲,而块设备经过系统的快速缓冲。但是,字符设备和块设备并没有明显的界限,如Flash设备符合块设备的特点,但是我们仍然可以把它作为一个字符设备来访问。
字符设备和块设备的驱动设计呈现出很大的差异,但是对于用户而言,他们都使用文件系统的操作接口 open()、close()、read()、write()等函数进行访问。
在 Linux 系统中,网络设备面向数据包的接收和发送而设计,它并不对应于文件系统的节点。内核与网络设备的通信和内核与字符设备、块设备的通信方式完全不同。
另外,TTY 驱动、I2C驱动、USB驱动、PCI驱动、LCD驱动等本身大体可归纳入3个基础大类,但是对于这些复杂的设备,Linux系统还定义了独特的驱动体系结构。
1.3 Linux 设备驱动与整个软硬件系统的关系
应用程序可以使用 Linux的系统调用接口编程,也可以使用C库函数,出于代码可移植性的考虑,后者更值得推荐。C库函数本身也通过系统调用接口而实现,如C库函数中的fopen()、fwrite()、fread()、fclose()分别会调用操作系统API的open()、write()、read()、close()函数
1.4 编写Linux设备驱动的技术基础
Linux 设备驱动的学习是一项浩大的工程,读者需要首先掌握以下基础。
l 编写Linux设备驱动要求工程师具有良好的硬件基础,懂得SRAM、Flash、SDRAM、磁盘的读写方式,UART、I2C、USB等设备的接口,轮询、中断、DMA的原理,PCI总线的工作方式以及CPU的内存管理单元(MMU)等。
l 编写Linux设备驱动要求工程师具有良好的C语言基础,能灵活地运用C语言的结构体、指针、函数指针及内存动态申请和释放等。
l 编写Linux设备驱动要求工程师具有一定的Linux内核基础,虽然并不要求工程师对内核各个部分有深入的研究,但至少要了解设备驱动与内核的接口,尤其是对于块设备、网络设备、Flash设备、串口设备等复杂设备。
l 编写Linux设备驱动要求工程师具有良好的多任务并发控制和同步的基础,因为在设备驱动中会大量使用自旋锁、互斥、信号量、等待队列等并发与同步机制。
本书对以上内容都进行了详细的讲解,以使读者快速掌握编写 Linux 设备驱动的基础。
1.5.1 处理器
1.5.2 存储器
存储器可分为只读储存器(ROM)、闪存(Flash)、随机存取存储器(RAM)、光介质存储器和磁介质存储器。 ROM 还可再细分为不可编程ROM、可编程 ROM(PROM)、可擦除可编程ROM(EPROM)和电可擦除可编程ROM(E2PROM),E2PROM完全可以用软件来擦写,已经非常方便了。 目前 ROM 有被 Flash 替代的趋势,NOR(或非)和NAND(与非)是市场上两种主要的Flash 闪存技术。Intel公司于 1988 年首先开发出NOR Flash,彻底改变了原先由EPROM 和 E2PROM一统天下的局面。紧接着,1989 年,东芝公司开发出 NANDFlash,每比特的成本被大大降低。 NOR Flash 和 CPU 的接口属于典型的类 SRAM接口(如图 2.5 所示),不需要增加额外的控制电路。NOR Flash的特点是可芯片内执行(XIP,eXecute In Place),程序可以直接在NOR 内运行。而 NAND Flash 和 CPU的接口必须由相应的控制电路进行转换,当然也可以通过地址线或 GPIO产生 NAND Flash 接口的信号。NAND Flash 以块方式进行访问,不支持芯片内执行 .
一个 NAND Flash 的接口主要包含如下信号。
l I/O 总线:地址、指令和数据通过这组总线传输,一般为8 位或 16位。
l 芯片启动(Chip Enable,CE#):如果没有检测到CE#信号,那么,NAND器件就保持待机模式,不对任何控制信号做出响应。
l 写使能(Write Enable,WE#):WE#负责将数据、地址或指令写入 NAND之中。
l 读使能(Read Enable,RE#):RE#允许数据输出。
l 指令锁存使能(Command Latch Enable,CLE): 当CLE 为高时,在 WE#信号的上升沿,指令将被锁存到 NAND 指令寄存器中。
l 地址锁存使能(Address Latch Enable,ALE):当ALE 为高时,在 WE#信号的上升沿,地址将被锁存到 NAND 地址寄存器中。 l 就绪/忙(Ready/Busy,R/B#):如果NAND 器件忙,R/B#信号将变低。该信号是漏极开路,需要采用上拉电阻。 NAND Flash 与NOR Flash 相比容量大、价格低;NAND Flash中每个块的最大擦写次数是 100 万次,而 NOR 的擦写次数是10 万次;NAND Flash的擦除、编程速度远超过 NOR Flash Flash 的编程原理都是只能将1 写为 0,而不能将0 写为 1。所以在Flash 编程之前,必须将对应的块擦除,而擦除的过程就是把所有位都写为1 的过程,块内的所有字节变为 0xFF . 以上所述的各种 ROM、Flash和磁介质存储器都属于非易失性存储器(NVM),掉电信息不会丢失,而RAM 则与此相反。 RAM 也可再分为静态RAM(SRAM)和动态RAM(DRAM)。DRAM以电荷形式进行存储,数据存储在电容器中。由于电容器会由于漏电而导致电荷丢失,因而DRAM器件需要定期被刷新。SRAM 是静态的,只要供电它就会保持一个值,SRAM没有刷新周期。每个SRAM 存储单元由 6 个晶体管组成,而 DRAM存储单元由 1 个晶体管和1 个电容器组成。 通常所说的 SDRAM、DDR SDRAM皆属于 DRAM 的范畴,它们采用与CPU 外存控制器同步的时钟工作(注意,不是CPU 的工作频率)。与 SDRAM 相比,DDRSDRAM同时利用了时钟脉冲的上升沿和下降沿传输数据,因此在时钟频率不变的情况下,数据传输频率加倍。此外,还存在使用RSL(Rambus发信电平)技术的 RDRAM(Rambus DRAM)和Direct RDRAM。
针对许多特定场合的应用,嵌入式系统中往往还使用了一些特定类型的 针对许多特定场合的应用,嵌入式系统中往往还使用了一些特定类型的 RAM。
1.5.3 接口与总线
1 串口 2 I2C总线 3 USB 4 以太网接口 5 ISA总线 6 PCI 和 cPCI
1.6 硬件时序分析
对驱动工程师或硬件工程师而言,时序分析的意思是让芯片之间的访问满足芯片手册中时序图信号有效的先后顺序、采样建立时间(setup time)和保持时间(hold time)的要求,在电路板工作不正常的时候,准确地定位时序方面的问题。 建立时间是指在触发器的时钟信号边沿到来以前,数据已经保持稳定不变的时间,如果建立时间不够,数据将不能在这个时钟边沿被正确采样;保持时间是指在触发器的时钟信号边沿到来以后,数据还需稳定不变的时间,如果保持时间不够,数据同样不能被正确采样。