驱动入门初识

1.操作系统对于驱动的好处:
更好的完成多任务并发
提供了内存管理机制
2.设备驱动的分类
字符设备:以串行顺序依次进行访问的设备,如触摸屏,磁带驱动器,鼠标等
块设备:以任意顺序进行访问的,以块为单位进行操作 如硬盘 软驱等 块设备比字符设备更复杂
网络设备
3.Linux内核主要是由进程调度(SCHED),内存管理(MM),虚拟文件系统(VFS),网络接口(NET)和进程通信(IPC)
在设备驱动编程中,当请求的资源不能得到满足时,驱动一般会调度其他进程执行,其对应的进程进入睡眠状态,直到他请求的资源被释放,才会被唤醒而进入就绪状态。其中启动内核线程的函数为:
int kernel_thread(int (*fn)(void *),void * arg, unsigned long flags);
一般情况Linux每个进程享有4GB的内存空间,0~3属于用户空间,3~4GB属于内核空间
ARM处理器有七种工作模式
用户模式(usr):大多数应用程序运行在用户模式下
快速中断模式(fiq):用于高速数据传输和通道处理
外部中断模式(irq):用于通用的中断处理
管理模式(svc)
数据访问终止模式(abt)
系统模式(sys)
未定义指令中止模式(und)
X86处理器包括四个不同的特权级,称为Ring0~Ring3下,可以执行特权级指令,对任何IO设备都有访问权等,而Ring3则有很多操作限制,但是在Linux系统中内核可以进行任何操作,而应用程序则被禁止对硬件的直接访问和对内存的未授权访问。
Linux系统只能通过系统调用和硬件中断完成从用户空间到内核空间的控制转移
4.内核的编译
安装modutils
安装module- init- tool
解压缩内核源代码,然后执行以下指令
ln –s linux-2.6.15.5 linux (将 Linux 符号连接映射到 linux-2.6.15.5)
执行make mrproper
配置内核:最常用的就是make menuconfig,然后会生成一个config配置文件(隐藏在顶层的makefile中),主要是记录了哪些部分被编译进内核,哪些部分被编译为内核模块
编译内核,并且将映像复制到相应的目录
make bzImage (生成使用 gzip 压缩的内核,生成文件位于 /usr/src/linux/arch/i386/boot 目录)
make modules modules_install (编译内核模块并安装到/lib/modules/2.6.15.5 目录)
cd /usr/src/linux
mv arch/i386/boot/bzImage /boot/bzImage2.6.15.5
mv System.map /boot/System.map-2.6.15.5
cd /boot
mv System.map oldSystem.map
ln –s System.map-2.6.15.5 System.map (创建相应的 System.map 符号链接)
针对更新前后版本的差异修改脚本和配置文件
Initrd bootloader初始化的内存盘
内核配置系统由以下三个部分组成
makefile
Kconfig
配置工具:Tcl/TK,Per
4.makefile
目标定义用来定义哪些内容要作为模块编译,哪些要编译并且连接进内核
文件模块的定义
目录的层次迭代

5.Kconfig
菜单入口,“config”:关键字定义新的配置选项,配置的选项属性包括类型,数据范围,输入提示,依赖关系,帮助信息以及认值等
菜单结构
6.x86上pc从上电/复位到运行Linux用户间的初始化进程的流程
当系统上电或复位时,cpu会将pc的指针赋值作为一个特定的地址0xFFFF0,并且执行该地址处的指令
BIOS运行时安装CMOS的设置定义的启动设备顺序来搜索处于活动状态,并且可以引导的设备
主引导加载程序查找并且加载次引导加载程序
次引导加载程序加载Linux内核和可选的初始RAM磁盘,将控制权交给Linux内核源代码
运行被加载的内核,并启动用户空间应用程序
7.GNU C和ANSI C
GNU C允许使用零长度数组,在定义变长对象的头结构的时候,这个特性非常有用
Case 范围
语句表达式
Typeof 的关键字
可变参数的宏
标号元素:在GNU C中,通过指定索引或着结构体成员名,允许初始化值以任意顺序出现。
当前函数
特殊属性声明
在声明的后面添加__attribute(属性说明)__
Aligned 属性用于变量,结构体和联合体的对界方式
Packed属性作用于变量和类型
内建函数,不属于库函数,以__builtin开始

8.Linux的文件操作
创建: int creat(const char *filename, mode_t mode); mode指定新建文件的存取权限,usmak代表了文件创建时需要去掉的一些存取权限 Int umask(int newmask);
打开
读写
定位
关闭
9.设备文件系统:udev取代了devfs
Udev完全时在用户态工作,在热插拔时,设备的详细信息会由内核输出到位于/sys 的sysfs文件系统
Linux应该在设备被发现的时候加载驱动模块,而不是他被访问的时候。
10.sysfs文件系统
Linux 2.6开始引入sysfs这个虚拟的文件系统,可以产生一个包括所有系统硬件的层级视图,与提供进程和状态信息的proc文件系统十分类
Syses的一个目的就是展示设备驱动模型中各组件的层次关系
11.kobject内核对象
这个截个图使得所有设备在底层都具有统一的接口,kobject提供了基本的对象管理能力,时构成Linux2.6设备模型的核心结构,每个在内核注册的kobject对象都对应于sysfs文件系统中的一个目录
和kobject不同的是,属性在sysfs中呈现为一个文件,而kobject则呈现为sysfs中的目录
12.kset内核对象的集合
Kobject通常通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合
每个kset必须属于某个subsystem
13.subsystem内核对象子系统
Subsystem是一系列kset的集合,他描述系统中某一类设备仔细听吧
一个挂接到同一subsystem的kset共享一个rwsem信号量,用于同步访问kset中的链表

14.Linux的设备模型组件
系统中的任何一个设备都在设备模型中都由一个device对象描述
15.udev的组成:以三个分割的子计划发展
Namedev
Libsysfs
Udev
Udev 适合内核空间,devfs适合用户空间
15.用Linux2.6中使用cdev结构体描述字符设备
cdev_init()函数用于初始化cdev的成员,并且建立cdev和file_operations之间的连接
cdev_alloc()函数用于动态申请一个cdev的内存
cdev_add()函数和cedv_del()函数分别向系统添加删除一个cdev,完成字符设备的注册和注销,在调用时cdev_add()函数向系统注册字符设备之前,应该首先调用register_chrdev_region()(已经知道设备号)或者alloc_chrdev_region()(不知道设备号)函数向系统申请设备号
16 file_operation结构体
llseek()函数用来修改一个文件的当前读写位置
mmap()函数将设备内存映射到进程的内存中(帧缓冲)
poll()函数一般用于询问设备是否可以非阻塞地立即读写
aio_read(),aio_write()异步读,异步写
17 Linux字符设备驱动的组成
字符设备驱动模块加载和卸载
字符设备驱动的file_operations,由于内核空间和用户空间不能互相访问需要借助于copy_from_user…
18 globalmem设备驱动
加载和卸载设备驱动
读写函数:主要是让设备结构体的mem[]数组和用户空间交互数据,并且随着访问的字节数变更返回用户文件读写的偏移位置
seek函数
ioctl函数
使用文件私有数据:将文件的私有数据private_data指向设备结构体
19.并发和竟态
对称多处理器(SMP,多cpu
解决竟态问题的途径时保证对共享资源的互斥访问
互斥机制:中断屏蔽,原子操作,自旋锁和信号量
中断屏蔽使得中断与进程之间的并发不在发生,而且由于Linux的内核的进程调度等操作都依赖中断来实现,内核抢占进程之间的并发也就得以避免了。但是擦和那个手机屏蔽中断很危险,常常与自旋锁联合使用。==》local_irq_disable, local_irq_enable
原子操作指的是在执行过程中不会被别的代码路径所中断的操作,使用原子变量最多只能被一个进程打开。
自旋锁是一种对临界资源进行互斥访问的典型手段,也是一种原子操作,所以在该操作完成之前其他执行单元不可能访问这个内存变量。有可能受到中断和底半部的影响。只有在占用锁时间极短的情况下使用自旋锁,而且也有可能死锁
定义自旋锁
初始化自旋锁
获得自旋锁
释放自旋锁
顺序锁
读写自旋锁 rwlock
读—-拷贝—-更新。RCU
信号量的使用,在未获得信号量的时候,进程不会原地打转而是进入休眠状态
定义信号量
初始化信号量
获得信号量
释放信号量
信号量用于同步,还有一种比信号量更好的同步机制完成量
信号量是进程级的代表进程来争夺资源的会发生上下文切换,当所要保护的临界区访问时间比较短的时候,用自旋锁非常方便;但是自旋锁的临界区千万不能包含可能引起阻塞的代码,如果需要中断或者软中断,只能选自旋锁。
20.Linux设备驱动的阻塞和非阻塞
等待队列来实现阻塞进程的唤醒
21.轮询操作
22.Linux设备驱动中的异步通知和异步IO
异步通知:一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,也可以叫做“信号驱动的异步I/O
阻塞I/O意味着一直等待设备可访问再访问,非阻塞I/O中使用poll()意味着查询设备是否可访问,而异步通知意味着设备通知自身可访问就可以了。
为了在用户空间能处理一个设备释放的信号,他必须完成以下三项工作
F_SetoWN IO控制命令设置设备文件的拥有者为本进程
F_SETEK IO控制命令设置设备文件支持FASYNC,即异步通知模式
通过signal()函数连接信号和信号处理函数
信号的释放
为了让设备支持异步通知机制,驱动程序中涉及以下三项工作
支持F_SetoWN命令
支持F_SETEL命令的处理
在设备资源可获得的时候,调用kill_fasync()函数激发相应的信号
23.异步IO
Linux系统中最常用的输入输出模型是同步IO,在这个模型中当请求发出之后,应用程序就会阻塞,直到请求满足为止
AIO基本思想就是允许进程发起很多I/O操作,而且不用阻塞或等待任何操作完成
24中断编程
申请和释放中断
1.申请IRQ:也就是要申请的硬件中断号
2.释放IRQ
使能和屏蔽中断
底半部机制
Linux系统实现底半部的机制主要有tasklet,工作队列和软中断、
tasklet也是基于软中断来实现的
中断共享
内核定时器,也是基于软中断实现的
内核延时
短延迟
长延迟
睡眠延迟
25 大多数嵌入式微控制器并不提供io空间,而仅存在内存空间,内存空间可以通过地址,指针来访问
内存管理单元MMU
提供虚拟地址和物理地址的映射,内存访问权限保护和Cache缓存控制等硬件支持
TLB:转换旁路缓存,是MMU的核心部件,是转换表的cache,因此也经常被称为“快表”
TTW:转换表漫游,需要通过对内存中转换表的访问来获得虚拟地址和物理地址的对应关系
26 DMA
DMA是一种无需cpu的参与就可以让外设和系统内存之间进行双向数据传输的硬件机制。
Cache被用作cpu针对内存的缓存,利用程序的空间局部性和时间局部性原理,达到较高的命中率就可以避免cpu每次都有点远与相对慢速的内存交互数据来提供数据的访问sulv
Cache数据和内存数据的不一致性(由DMA导致的),与主存中的数据一样则具有一致性。
基于DMA的硬件使用总线地址而非物理地址,总线地址是从设备角度上看到的内存地址,物理地址则是从cpu角度上看到的未经转换的内存地址(经过转换的为虚拟地址)
DMA映射包括两个方面的工作:分配一片DMA缓冲区;为这片缓冲区产生设备的可访问地址。
dma_alloc_coherent()申请一片DMA缓冲区,进行地址映射并且保证该缓冲区的cache的一致性,与之对应的释放函数是dma_free_coherent
SG映射属于流式DMA映射
申请资源—映射—访问—去映射—释放资源
27 触摸屏
触摸屏分为四种:电阻式,电容感应式,红外线式,表面声波式
ADC和触摸屏接口可工作于5种模式
普通转换模式
独立X/Y位置转换模式
自动X/Y位置转换模式
等待中断模式
待机模式

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...
win11本地账户怎么改名?win11很多操作都变了样,用户如果想要...