LINUX设备驱动开发详解----第一篇随笔

1,软件的设计宗旨呢,是高内聚,低耦合。其意思是一个驱动程序里面,尽量是自己把事情都干完,别跟其他模块或驱动牵扯太多。不然出问题的时候,就不好排查,当然这样也利于移植,只要搞清楚了驱动程序里面的代码,那换个平台,也变得轻松。

2,驱动是沟通硬件和应用的桥梁。无操作系统下的驱动一般是由一个h文件和c文件组成。h文件里面是一些结构体的定义以及提供给外部调用的函数声明,c文件就是这些函数的具体实现。无操作系统的软件结构是这样的:一个无限循环里,对设备中断的检测或轮询,并处理。    应用工程师在写代码的时候,直接面对的就是驱动接口。

3,带操作系统的驱动。ok,我们会发现,带操作系统的情况下,驱动变得复杂了,不仅要完成对硬件的操作,还要与内核对接,融入内核。干啥呢?为啥搞麻烦了呢?记住了,上帝是公平的,在驱动这边麻烦点,添加了各种设备注册等函数,就是为了在应用上的便利。使得应用看待驱动都是一个样。比如:不管你是I2C,SPI或是简单的GPIO驱动,它fopen /dev/xxx,都是打开了这个驱动,write就是往里面写东西。

4,驱动的分类:

  字符设备指那些必须以串行顺序依次进行访问的设备。

  块设备可以用任意顺序进行访问,为什么?经过了系统的快速缓冲。

  网络设备面向数据包的接收和发送设计,没有对应的文件系统节点。

  另一种分类方式:I2C驱动,USB驱动,PCI驱动。这些驱动可以纳入到上面三种方式,但是其应用复杂且广泛,因此linux系统给他们定义了独特的驱动体系结构。(比如:专属于I2C的一些注册,读写等方式)
5, 中央处理器架构:冯诺依曼和哈佛。冯诺依曼是将程序指令和数据存储器合并在一起的存储器,其程序指令和数据的宽度相同。哈佛结构将程序指令和数据分开存储,指令和数据的宽度可以有不同的数据宽度。
   从指令集角度来讲,可分为精简指令集(RISC)和复杂指令集(CISC)。精简指令强调尽可能的减少指令集,指令单周期执行,但是目标代码会更大。而复杂指令集强调的是指令的能力,其指令复杂,指令周期长,相应的目标代码减少。
6, NOR Flash的特点是可以芯片内执行(XIP, eXecute In Place),程序可以直接在NOR 内运行。而Nand Flash和CPU的接口必须由相应的控制电路进行转换,当然也可以通过地址线或GPIO产生Nand Flash接口的信号。NAND Flash以块方式进行访问,不支持芯片内执行。
  RAM存储在电容器中,所以掉电后,电容漏电数据丢失。
7,USB提供四种传输方式:控制传输、同步传输、中断传输以及批量传输。
  以太网隔离变压器的作用:信号传输,阻抗匹配,波形修复,抑制信号杂波和高电压隔离。
8,Linux内核的组成部分:1)进程调度;申请资源得不到满足时,休眠,然后等待资源释放后唤醒。2)内存管理;控制多个进程安全的共享主内存区域,完成为每个进程进行虚拟内存到物理内存的转换。3)虚拟文件;4)网络接口;5)进程间通信
9,container_of(ptr, type, member)   ptr是具体的指针,type是一个结构体,member是结构体里面的形参的名字。它的作用就是知道了type结构体里面member的指针是ptr,然后获取该type结构体的指针。
10,copy_to_user, copy_from_user实现内核空间和用户空间数据的交互:

   copy_to_user在每次拷贝时需要检测指针的合法性,也就是用户空间的指针所指向的地址的确是一段该进程本身的地址,而不是指向了不属于它的地方,而且每次都会拷贝一次数据,频繁访问内存,由于虚拟地址连续,物理地址不一定会连续,从而造成CPU的CACHE频繁失效,从而使速度降低。

  在read和write的系统函数中,注意return的值,一般是传递的字节数。

11,Linux驱动的分析方法是点面结合,将对函数和数据结构的理解放在整体架构的背景之中。

原文地址:https://www.cnblogs.com/cyc2009/p/4123263.html