linux驱动开发详解
① 求教怎么学习linux内核驱动
1.首先要了解为什么要学习内核?下图已表明,如果要从事驱动开发或系统研究,就要学习内核。
2.内核的知识就像下面的绳结一样,一环扣一环,我们要解开它们,就必须要先找到线头也就是内核中的函数接口。初学阶段,我们一般不深入的研究内核代码,会使用内核的接口函数就不错了。
3.下面提供了如何学习这些内核函数的方法,就像解绳子一样
4.学习内核的四步法则,思维导图的设计尤为重要,这也是能否学习好内核的关键
5.语言基础也需要扎实,所以需要把C语言巩固巩固
② 什么是linux 平台驱动开发
在学习之前一直对驱动开发非常的陌生,感觉有点神秘。不知道驱动开发和普通的程序开发究竟有什么不同;它的基本框架又是什么样的;他的开发环境有什么特殊的地方;以及怎么写编写一个简单的字符设备驱动前编译加载,下面我就对这些问题一个一个的介绍。
一、驱动的基本框架
1. 那么究竟什么是驱动程序,它有什么用呢:
l 驱动是硬件设备与应用程序之间的一个中间软件层
l 它使得某个特定硬件能够响应一个定义良好的内部编程接口,同时完全隐蔽了设备的工作细节
l 用户通过一组与具体设备无关的标准化的调用来完成相应的操作
l 驱动程序的任务就是把这些标准化的系统调用映射到具体设备对于实际硬件的特定操作上
l 驱动程序是内核的一部分,可以使用中断、DMA等操作
l 驱动程序在用户态和内核态之间传递数据
2. Linux驱动的基本框架
3. Linux下设备驱动程序的一般可以分为以下三类
1) 字符设备
a) 所有能够象字节流一样访问的设备都通过字符设备来实现
b) 它们被映射为文件系统中的节点,通常在/dev/目录下面
c) 一般要包含open read write close等系统调用的实现
2) 块设备
d) 通常是指诸如磁盘、内存、Flash等可以容纳文件系统的存储设备。
e) 块设备也是通过文件系统来访问,与字符设备的区别是:内核管理数据的方式不同
f) 它允许象字符设备一样以字节流的方式来访问,也可一次传递任意多的字节。
3) 网络接口设备
g) 通常它指的是硬件设备,但有时也可能是一个软件设备(如回环接口loopback),它们由内核中网络子系统驱动,负责发送和接收数据包。
h) 它们的数据传送往往不是面向流的,因此很难将它们映射到一个文件系统的节点上。
二、怎么搭建一个驱动的开发环境
因为驱动是要编译进内核,在启动内核时就会驱动此硬件设备;或者编译生成一个.o文件, 当应用程序需要时再动态加载进内核空间运行。因此编译任何一个驱动程序都要链接到内核的源码树。所以搭建环境的第一步当然是建内核源码树
1. 怎么建内核源码树
a) 首先看你的系统有没有源码树,在你的/lib/ moles目录下会有内核信息,比如我当前的系统里有两个版本:
#ls /lib/ moles
2.6.15-rc7 2.6.21-1.3194.fc7
查看其源码位置:
## ll /lib/moles/2.6.15-rc7/build
lrwxrwxrwx 1 root root 27 2008-04-28 19:19 /lib/moles/2.6.15-rc7/build -> /root/xkli/linux-2.6.15-rc7
发现build是一个链接文件,其所对应的目录就是源码树的目录。但现在这里目标目录已经是无效的了。所以得自己重新下载
b)下载并编译源码树
有很多网站上可以下载,但官方网址是:
http://www.kernel.org/pub/linux/kernel/v2.6/
下载完后当然就是解压编译了
# tar –xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (配置内核各选项,如果没有配置就无法下一步编译,这里可以不要改任何东西)
#make
…
如果编译没有出错。那么恭喜你。你的开发环境已经搭建好了
三、了解驱动的基本知识
1. 设备号
1) 什么是设备号呢?我们进系统根据现有的设备来讲解就清楚了:
#ls -l /dev/
crwxrwxrwx 1 root root 1, 3 2009-05-11 16:36 null
crw------- 1 root root 4, 0 2009-05-11 16:35 systty
crw-rw-rw- 1 root tty 5, 0 2009-05-11 16:36 tty
crw-rw---- 1 root tty 4, 0 2009-05-11 16:35 tty0
在日期前面的两个数(如第一列就是1,3)就是表示的设备号,第一个是主设备号,第二个是从设备号
2) 设备号有什么用呢?
l 传统上, 主编号标识设备相连的驱动. 例如, /dev/null 和 /dev/zero 都由驱动 1 来管理, 而虚拟控制台和串口终端都由驱动 4 管理
l 次编号被内核用来决定引用哪个设备. 依据你的驱动是如何编写的自己区别
3) 设备号结构类型以及申请方式
l 在内核中, dev_t 类型(在 中定义)用来持有设备编号, 对于 2.6.0 内核, dev_t 是 32 位的量, 12 位用作主编号, 20 位用作次编号.
l 能获得一个 dev_t 的主或者次编号方式:
MAJOR(dev_t dev); //主要
MINOR(dev_t dev);//次要
l 但是如果你有主次编号, 需要将其转换为一个 dev_t, 使用: MKDEV(int major, int minor);
4) 怎么在程序中分配和释放设备号
在建立一个字符驱动时需要做的第一件事是获取一个或多个设备编号来使用. 可以达到此功能的函数有两个:
l 一个是你自己事先知道设备号的
register_chrdev_region, 在 中声明:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first 是你要分配的起始设备编号. first 的次编号部分常常是 0,count 是你请求的连续设备编号的总数. name 是应当连接到这个编号范围的设备的名子; 它会出现在 /proc/devices 和 sysfs 中.
l 第二个是动态动态分配设备编号
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
使用这个函数, dev 是一个只输出的参数, 它在函数成功完成时持有你的分配范围的第一个数. fisetminor 应当是请求的第一个要用的次编号; 它常常是 0. count 和 name 参数如同给 request_chrdev_region 的一样.
5) 设备编号的释放使用
不管你是采用哪些方式分配的设备号。使用之后肯定是要释放的,其方式如下:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2. 驱动程序的二个最重要数据结构
1) file_operation
倒如字符设备scull的一般定义如下:
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file_operation也称为设备驱动程序接口
定义在 , 是一个函数指针的集合. 每个打开文件(内部用一个 file 结构来代表)与它自身的函数集合相关连( 通过包含一个称为 f_op 的成员, 它指向一个 file_operations 结构). 这些操作大部分负责实现系统调用, 因此, 命名为 open, read, 等等
2) File
定义位于include/fs.h
struct file结构与驱动相关的成员
l mode_t f_mode 标识文件的读写权限
l loff_t f_pos 当前读写位置
l unsigned int_f_flag 文件标志,主要进行阻塞/非阻塞型操作时检查
l struct file_operation * f_op 文件操作的结构指针
l void * private_data 驱动程序一般将它指向已经分配的数据
l struct dentry* f_dentry 文件对应的目录项结构
3. 字符设备注册
1) 内核在内部使用类型 struct cdev 的结构来代表字符设备. 在内核调用你的设备操作前, 必须编写分配并注册一个或几个这些结构. 有 2 种方法来分配和初始化一个这些结构.
l 如果你想在运行时获得一个独立的 cdev 结构,可以这样使用:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
l 如果想将 cdev 结构嵌入一个你自己的设备特定的结构; 你应当初始化你已经分配的结构, 使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
2) 一旦 cdev 结构建立, 最后的步骤是把它告诉内核, 调用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
说明:dev 是 cdev 结构, num 是这个设备响应的第一个设备号, count 是应当关联到设备的设备号的数目. 常常 count 是 1, 但是有多个设备号对应于一个特定的设备的情形.
3) 为从系统去除一个字符设备, 调用:
void cdev_del(struct cdev *dev);
4. open 和 release
③ 《Linux设备驱动开发详解基于最新的Linux4.0内核》pdf下载在线阅读,求百度网盘云资源
《Linux设备驱动开发详解》(宋宝华)电子书网盘下载免费在线阅读
资源链接:
链接:https://pan..com/s/1ddjTHycqTk3yYQDr-raoKw
书名:Linux设备驱动开发详解
作者:宋宝华
豆瓣评分:6.5
出版社:机械工业出版社
出版年份:2015-8
页数:618
内容简介:
对于嵌入式工程师来说,进入更高阶段后,学习Linux设备驱动开发无疑就是职业生涯的一次“重生”。这是因为Linux设备驱动开发不仅仅涉及操作系统的转换,开发方式的转换,更重要的是思维上的转变。对于Linux这样一个复杂系统,如何从复杂的代码中抓住设备驱动开发的关键是任何一个Linux设备驱动开发者入门时需要面对的挑战。除了知识、工具之外,往往还需要思路上的指导。本书不但帮助Linux设备驱动开发的初学者厘清必要的概念,还从具体的实例、设备驱动开发的指导原则循序渐进地引导读者渐入学习佳境。为了让读者能够达到Linux设备驱动开发的至臻境界,作者更是从软件工程的角度抽象出设备驱动开发的一般思想。毫无疑问,本书将成为读者学习Linux设备驱动开发过程中的一座“灯塔”。
作者简介:
宋宝华,
Linux布道者,知名嵌入式系统专家,《Essential Linux Device Drivers》译者。作为最早从事Linux内核与设备驱动研究的专家之一,他在众多国内外知名企业开展Linux技术培训。他也是一位活跃的Linux开发者和深度实践者,为Linux官方内核贡献了大量的Linux源码并承担代码审核工作。至今已向Linux官方内核提交逾数万行代码和几百个补丁。他的《Linux设备驱动开发详解》系列书在嵌入式Linux开发者中有口皆碑,是众多Linux书籍中为数不多的畅销书。
④ 驱动开发必须使用开发板厂家提供的Linux源码吗
驱动开发环境
要进行linux驱动开发我们首先要有linux内核的源码树,并且这个linux内核的源码树要和开发板中的内核源码树要一直;
比如说我们开发板中用的是linux kernel内核版本为2.6.35.7,在我们ubuntu虚拟机上必须要有同样版本的源码树,
我们再编译好驱动的的时候,使用modinfo XXX命令会打印出一个版本号,这个版本号是与使用的源码树版本有关,如果开发板中源码树中版本与
modinfo的版本信息不一致使无法安装驱动的;
我们开发板必须设置好nfs挂载;这些在根文件系统一章有详细的介绍;
⑤ 《Linux设备驱动开发详解4.0》pdf下载在线阅读全文,求百度网盘云资源
《Linux设备驱动开发详解4.0》网络网盘pdf最新全集下载:
链接: https://pan..com/s/1wxaYK87l11FDur15aS6FTQ
简介:Linux设备驱动开发详解介绍了Linux设备驱动开发理论、框架与实例,详细说明了自旋锁、信号量、完成量、中断顶/底半部、定时器、内存和I/O映射以及异步通知、阻塞I/O、非阻塞I/O等Linux设备驱动理论,以及字符设备、块设备、tty设备、I2c设备、LCD设备、音频设备、USB设备、网络设备、PCI设备等Linux设备驱动架构中各个复杂数据结构和函数的关系,并讲解了Linux驱动开发的大量实例,使读者能够独立开发各类Linux设备驱动。
⑥ 嵌入式Linux设备驱动开发详解的目录
第1章嵌入式系统与驱动程序1
本章目标1
1.1嵌入式系统概述1
1.1.1嵌入式系统的概念1
1.1.2嵌入式系统的特点2
1.1.3嵌入式系统的体系结构2
1.2嵌入式处理器介绍4
1.2.1嵌入式处理器分类4
1.2.2ARM概述5
1.2.3ARM系列芯片简介5
1.3嵌入式操作系统介绍7
1.3.1主流嵌入式操作系统7
1.3.2嵌入式系统的发展状况8
1.3.3嵌入式Linux介绍8
1.3.4嵌入式系统开发环境的建立9
1.3.5嵌入式软件开发10
1.4嵌入式Linux驱动程序12
1.4.1嵌入式Linux的内核空间和用户空间12
1.4.2嵌入式Linux的文件系统12
1.4.3嵌入式Linux的设备管理14
1.4.4嵌入式Linux的驱动程序16
1.5知识索引20
1.6思考与练习21
第2章简单的字符设备驱动程序23
本章目标23
2.1嵌入式Linux字符设备的驱动程序结构23
2.1.1嵌入式Linux驱动程序常用的头文件24
2.1.2File_operations结构体24
2.1.3字符设备驱动程序的入口25
2.1.4驱动程序的设备注册26
2.2设备驱动程序中的具体问题27
2.2.1I/O端口28
2.2.2内存操作29
2.2.3中断处理29
2.3LED的驱动程序实例及测试30
2.3.1LED I/O端口设置30
2.3.2LED硬件电路设计32
2.3.3LED驱动程序设计33
2.3.4LED测试程序设计36
2.4嵌入式Linux中断处理驱动程序及测试37
2.4.1中断处理过程37
2.4.2中断向量表39
2.4.3中断的处理模式39
2.4.4中断的优先级40
2.4.5中断的嵌套40
2.4.6中断源的扩展40
2.4.7中断控制寄存器的设置41
2.5按键中断的驱动程序实例45
2.5.1按键中断的电路设计45
2.5.2按键中断的驱动程序设计45
2.6知识索引48
2.7思考与练习49
第3章数字显示驱动程序50
本章目标50
3.1数字显示器50
3.1.1数码管简介50
3.1.2数码管的分类51
3.1.3数码管显示原理51
3.2数码管显示电路的硬件设计52
3.2.1译码器的使用52
3.2.2数码管的驱动方式53
3.2.3串/并变换的译码设计55
3.3数码管驱动程序实例56
3.3.1驱动程序的初始化和卸载模块56
3.3.2文件操作结构模块57
3.3.3数码管的打开模块57
3.3.4数码管的读写模块58
3.3.5数码管的I/O控制模块58
3.3.6数码管的退出模块58
3.3.7驱动程序的模块加载和卸载59
3.4数码管显示电路测试程序设计60
3.4.1数码管测试设计60
3.4.2数码管测试程序60
3.4.3数码管测试效果61
3.5知识索引61
3.6思考与练习62
第4章键盘驱动程序63
本章目标63
4.1键盘接口概述63
4.1.1键盘的分类63
4.1.2键盘的防抖65
4.1.3键盘的扫描65
4.1.4键盘的缓冲算法67
4.2键盘的驱动设计实例67
4.2.1锁存器和缓冲器扩展键盘67
4.2.2锁存器和缓冲器的接口68
4.2.3锁存器和缓冲器扩展键盘驱动程序设计69
4.2.4锁存器和缓冲器扩展键盘测试程序设计71
4.3智能控制芯片HD7279扩展键盘72
4.3.1HD7279的电路设计72
4.3.2HD7279的指令介绍73
4.3.3HD7279的串行接口74
4.3.4HD7279的驱动程序设计75
4.3.5HD7279的测试程序设计84
4.4知识索引85
4.5思考与练习85
第5章A/D驱动程序86
本章目标86
5.1A/D转换的过程86
5.1.1采样和保持86
5.1.2量化和编码88
5.1.3ADC的分类89
5.2A/D转换器的基本原理89
5.2.1逐次逼近型A/D转换器89
5.2.2双积分型A/D转换器90
5.2.3V/F和F/V型转换器93
5.2.4其他A/D转换器95
5.3A/D转换器接口技术97
5.3.1ADC的主要参数及意义97
5.3.2ADC的电路选择方法98
5.3.3ADC实际应用中的问题99
5.4S3C2410 A/D转换驱动设计实例99
5.4.1S3C2410的A/D转换电路99
5.4.2S3C2410X的A/D转换控制寄存器100
5.4.3S3C2410X的A/D转换数据寄存器101
5.4.4S3C2410X中A/D转换驱动程序的设计102
5.4.5S3C2410X中A/D转换测试程序的设计105
5.5知识索引106
5.6思考与练习107
第6章D/A驱动程序108
本章目标108
6.1D/A的原理介绍108
6.1.1D/A转换的概念及基本原理108
6.1.2电子模拟开关109
6.1.3D/A转换器的基本结构110
6.1.4D/A转换的静态参数114
6.1.5D/A转换的动态参数115
6.2D/A转换的硬件电路设计116
6.2.1D/A转换的接口技术116
6.2.2D/A转换芯片介绍117
6.2.3D/A转换的电路设计118
6.3D/A转换器的驱动程序实例118
6.3.1D/A驱动程序中的宏定义118
6.3.2D/A的模块加载118
6.3.3D/A转换器的文件操作模块119
6.3.4D/A转换器的读写控制模块120
6.3.5D/A转换器的打开、退出模块120
6.4测试程序的设计120
6.4.1D/A测试程序中的宏定义121
6.4.2D/A测试程序的主函数121
6.4.3D/A测试程序中的功能函数122
6.4.4D/A测试程序中的功能打印函数123
6.4.5D/A测试程序中的波形生成函数123
6.4.6D/A测试程序的效果124
6.5知识索引125
6.6思考与练习125
第7章LCD驱动程序126
本章目标126
7.1LCD显示器概述126
7.1.1液晶126
7.1.2LCD显示屏的背光127
7.1.3LCD显示器的分类127
7.1.4LCD的显示原理127
7.1.5LCD的驱动方式130
7.1.6LCD的常用指标131
7.2LCD的显示接口131
7.2.1灰度STN的时序132
7.2.2彩色STN的时序133
7.2.3TFT的时序134
7.3嵌入式处理器的LCD控制器136
7.3.1LCD控制器136
7.3.2LCD控制器的设置137
7.3.3LCD的字符显示缓存139
7.4LCD的驱动程序设计140
7.4.1LCD驱动程序相关的宏定义140
7.4.2LCD驱动程序的底层操作函数142
7.4.3LCD驱动程序提供的API145
7.4.4LCD驱动程序的模块化加载151
7.4.5LCD的测试程序152
7.5基于Framebuffer的LCD驱动程序实例155
7.5.1Framebuffer概述155
7.5.2LCD的电路连接155
7.5.3Framebuffer设备驱动程序的结构156
7.5.4Framebuffer设备驱动程序的设计159
7.5.5Framebuffer设备测试程序的设计164
7.5.6嵌入式Linux常用的GUI166
7.6知识索引166
7.7思考与练习167
第8章触摸屏驱动程序168
本章目标168
8.1触摸屏概述168
8.2触摸屏的分类168
8.2.1电阻技术触摸屏168
8.2.2表面声波技术触摸屏169
8.2.3电容电感技术触摸屏170
8.2.4红外线技术触摸屏170
8.3触摸屏的特性171
8.3.1透明度和色彩失真171
8.3.2反光性171
8.3.3清晰度171
8.3.4漂移172
8.3.5检测和定位172
8.4触摸屏的硬件电路设计172
8.4.1电阻式触摸屏的电路原理172
8.4.2电阻式触摸屏原点的定位173
8.4.3电阻式触摸屏的电路连接174
8.5触摸屏的驱动程序实例176
8.5.1触摸屏接口的模式176
8.5.2A/D转换和触摸屏寄存器的设置177
8.5.3触摸屏的坐标179
8.5.4触摸屏的电路连接180
8.5.5触摸屏的驱动程序接口181
8.6测试程序的设计182
8.6.1触摸屏的数据定义183
8.6.2触摸屏的数据处理183
8.6.3触摸屏的运行测试185
8.7知识索引186
8.8思考与练习187
第9章CAN总线驱动程序188
本章目标188
9.1CAN总线接口设计188
9.1.1CAN总线概述188
9.1.2CAN的工作特点及主要优点189
9.1.3CAN总线的电气特征和MAC帧结构189
9.2嵌入式处理器上CAN总线接口的扩展190
9.2.1SJA1000简介190
9.2.2SJA1000扩展191
9.3SJA1000扩展CAN总线接口的设计192
9.3.1CAN 控制器SJA1000的操作模式192
9.3.2CAN控制器SJA1000的特征功能193
9.3.3CAN 控制器SJA1000的Basic CAN模式设置194
9.4SJA1000扩展CAN总线接口的通信196
9.4.1通过CAN总线建立通信的步骤196
9.4.2SJA1000的初始化196
9.4.3驱动程序的结构设计198
9.4.4驱动程序init、exit、open、close函数的实现200
9.4.5驱动程序read、write函数的实现201
9.4.6驱动程序interrupt、ioctl函数实现202
9.4.7测试程序的编写202
9.5驱动程序的加载204
9.6知识索引204
9.7思考与练习205
第10章IIC总线驱动程序206
本章目标206
10.1IIC总线概述206
10.1.1IIC总线介绍206
10.1.2IIC总线引入的原因206
10.1.3IIC总线的特点206
10.1.4IIC总线的基本结构207
10.1.5IIC总线的术语207
10.1.6IIC总线的工作208
10.1.7IIC总线的竞争仲裁209
10.1.8IIC总线的工作流程210
10.2嵌入式处理器的IIC接口211
10.2.1IIC总线控制寄存器212
10.2.2IIC总线控制/状态寄存器213
10.2.3IIC总线地址寄存器214
10.2.4IIC总线移位数据寄存器214
10.2.5S3C2410中与IIC对应的I/O端口215
10.3基于IIC的键盘芯片应用216
10.3.1ZLG7290的功能217
10.3.2ZLG7290的控制方式218
10.3.3ZLG7290的寄存器218
10.3.4ZLG7290的通信接口219
10.3.5ZLG7290的指令介绍219
10.4IIC总线驱动程序实例221
10.4.1ZLG7290的电路连接221
10.4.2ZLG7290的通信流程223
10.4.3ZLG7290驱动中变量的定义225
10.4.4ZLG7290驱动中实时时钟的改变226
10.4.5ZLG7290和IIC寄存器的初始化227
10.4.6ZLG7290驱动程序的模块化228
10.4.7ZLG7290的文件操作结构228
10.5IIC总线的测试程序230
10.6知识索引231
10.7思考与练习231
第11章音频总线驱动程序232
本章目标232
11.1音频总线接口概述232
11.1.1音频的采样精度233
11.1.2音频编码233
11.2IIS音频总线接口233
11.2.1IIS总线的物理连接233
11.2.2IIS的总线协议234
11.2.3IIS总线的硬件设计235
11.2.4IIS总线的寄存器236
11.3AC97音频总线接口239
11.4IIS总线的驱动程序设计240
11.4.1音频设备基础知识240
11.4.2音频设备文件241
11.4.3WAV声音文件243
11.4.4音频设备和驱动程序的通信243
11.4.5设备的初始化和加载244
11.4.6DMA的操作和宏定义246
11.4.7audio设备文件的操作248
11.4.8mixer设备文件的操作260
11.5音频驱动程序的测试262
11.6知识索引262
11.7思考与练习263
第12章IDE接口驱动程序264
本章目标264
12.1IDE接口概述264
12.1.1硬盘知识介绍264
12.1.2IDE接口标准267
12.1.3IDE接口的传输模式269
12.1.4IDE接口寄存器269
12.2IDE接口驱动程序的移植271
12.2.1嵌入式Linux下IDE驱动程序接口271
12.2.2嵌入式Linux下IDE驱动程序272
12.2.3IDE硬盘的读/写操作274
12.3IDE驱动程序测试282
12.3.1磁盘文件系统简介283
12.3.2IDE分区测试283
12.4知识索引285
12.5思考与练习285
第13章闪存芯片的驱动程序286
本章目标286
13.1闪存芯片概述286
13.1.1闪存芯片的物理特性286
13.1.2嵌入式文件系统概述289
13.1.3MTD体系介绍289
13.1.4Flash专有名词291
13.2NAND Flash291
13.2.1NAND Flash的结构291
13.2.2NAND Flash的操作292
13.2.3NAND Flash控制器294
13.2.4NAND Flash的时序296
13.2.5NAND Flash的驱动程序实例297
13.3NOR Flash301
13.3.1NOR Flash的结构301
13.3.2NOR Flash的操作302
13.3.3NOR Flash的驱动程序实例303
13.4基于闪存的文件系统307
13.5知识索引309
13.6思考与练习310
第14章USB 设备驱动程序311
本章目标311
14.1USB接口概述311
14.1.1USB系统311
14.1.2USB的电气特性312
14.1.3USB总线的拓扑结构313
14.1.4USB的通信协议313
14.2嵌入式系统中USB的使用315
14.2.1OHCI概述315
14.2.2Host接口硬件设计316
14.3嵌入式系统中USB设备的驱动程序设计316
14.3.1
⑦ linux驱动开发insmod hello.ko失败
你好,记得当初也被这个问题困惑了,kernel mole 的insmod 的时候是需要版本验证的(也可以使用方法绕过版本验证)。你可以看看他到底是怎么个版本验证法,加深你的学习。
现在看看你的问题,你下载的kerne 是2.30.4的,在make的时候kernel_dir 指定也是这个。那编译出来的mole 肯定也是也是2.30.4的版本了,然后你想把这个mole insmod 到的你pc linux 系统,那就肯定不行了。
1. 你可以用的linux系统内核来编译你的hello 模块。
2. 先写个makefile:
obj-m:= hello.o
3. 然后 make -C /lib/moles/$(shell uname -r )/build M=`pwd` moles
4.编译好了再insmode. 就能成功了。但是还要看的printk 的等级了,可能你还需要dmesg才能看道你的模块的操作
5. 然后你可以把上面的过程集成道一个makefile里,直接在当前目录make 就好了。
提醒下,假如你是用自己的系统作这些实验,要当心点,有的mole可能会让你的系统出现oops。
所以建议你安装个虚拟机玩,或者真正要学的话,直接买个板子最好了。
最后看你下载了linux 2.30.4?是不是应该是2.6.30.4? 然后你的开发板是也是这个kernel?假如你是用板子,你现在可以把刚编好的模块,push 到板子,在insmod就好了。
⑧ 如何系统的学习Linux驱动开发
在学习之前一直对驱动开发非常的陌生,感觉有点神秘。不知道驱动开发和普通的程序开发究竟有什么不同;它的基本框架又是什么样的;他的开发环境有什么特殊的地方;以及怎么写编写一个简单的字符设备驱动前编译加载,下面我就对这些问题一个一个的介绍。
一、驱动的基本框架
1.那么究竟什么是驱动程序,它有什么用呢:
l驱动是硬件设备与应用程序之间的一个中间软件层
l它使得某个特定硬件能够响应一个定义良好的内部编程接口,同时完全隐蔽了设备的工作细节
l用户通过一组与具体设备无关的标准化的调用来完成相应的操作
l驱动程序的任务就是把这些标准化的系统调用映射到具体设备对于实际硬件的特定操作上
l驱动程序是内核的一部分,可以使用中断、DMA等操作
l驱动程序在用户态和内核态之间传递数据
2.Linux驱动的基本框架
3.Linux下设备驱动程序的一般可以分为以下三类
1)字符设备
a)所有能够象字节流一样访问的设备都通过字符设备来实现
b)它们被映射为文件系统中的节点,通常在/dev/目录下面
c)一般要包含open read write close等系统调用的实现
2)块设备
d)通常是指诸如磁盘、内存、Flash等可以容纳文件系统的存储设备。
e)块设备也是通过文件系统来访问,与字符设备的区别是:内核管理数据的方式不同
f)它允许象字符设备一样以字节流的方式来访问,也可一次传递任意多的字节。
3)网络接口设备
g)通常它指的是硬件设备,但有时也可能是一个软件设备(如回环接口loopback),它们由内核中网络子系统驱动,负责发送和接收数据包。
h)它们的数据传送往往不是面向流的,因此很难将它们映射到一个文件系统的节点上。
二、怎么搭建一个驱动的开发环境
因为驱动是要编译进内核,在启动内核时就会驱动此硬件设备;或者编译生成一个.o文件,当应用程序需要时再动态加载进内核空间运行。因此编译任何一个驱动程序都要链接到内核的源码树。所以搭建环境的第一步当然是建内核源码树
1.怎么建内核源码树
a)首先看你的系统有没有源码树,在你的/lib/ moles目录下会有内核信息,比如我当前的系统里有两个版本:
#ls /lib/ moles
2.6.15-rc72.6.21-1.3194.fc7
查看其源码位置:
## ll /lib/moles/2.6.15-rc7/build
lrwxrwxrwx 1 root root 27 2008-04-28 19:19 /lib/moles/2.6.15-rc7/build -> /root/xkli/linux-2.6.15-rc7
发现build是一个链接文件,其所对应的目录就是源码树的目录。但现在这里目标目录已经是无效的了。所以得自己重新下载
b)下载并编译源码树
有很多网站上可以下载,但官方网址是:
http://www.kernel.org/pub/linux/kernel/v2.6/
下载完后当然就是解压编译了
# tar –xzvf linux-2.6.16.54.tar.gz
#cd linux-2.6.16.54
## make menuconfig (配置内核各选项,如果没有配置就无法下一步编译,这里可以不要改任何东西)
#make
…
如果编译没有出错。那么恭喜你。你的开发环境已经搭建好了
三、了解驱动的基本知识
1.设备号
1)什么是设备号呢?我们进系统根据现有的设备来讲解就清楚了:
#ls -l /dev/
crwxrwxrwx 1 root root1,3 2009-05-11 16:36 null
crw------- 1 root root4,0 2009-05-11 16:35 systty
crw-rw-rw- 1 root tty5,0 2009-05-11 16:36 tty
crw-rw---- 1 root tty4,0 2009-05-11 16:35 tty0
在日期前面的两个数(如第一列就是1,3)就是表示的设备号,第一个是主设备号,第二个是从设备号
2)设备号有什么用呢?
l传统上,主编号标识设备相连的驱动.例如, /dev/null和/dev/zero都由驱动1来管理,而虚拟控制台和串口终端都由驱动4管理
l次编号被内核用来决定引用哪个设备.依据你的驱动是如何编写的自己区别
3)设备号结构类型以及申请方式
l在内核中, dev_t类型(在中定义)用来持有设备编号,对于2.6.0内核, dev_t是32位的量, 12位用作主编号, 20位用作次编号.
l能获得一个dev_t的主或者次编号方式:
MAJOR(dev_t dev); //主要
MINOR(dev_t dev);//次要
l但是如果你有主次编号,需要将其转换为一个dev_t,使用: MKDEV(int major, int minor);
4)怎么在程序中分配和释放设备号
在建立一个字符驱动时需要做的第一件事是获取一个或多个设备编号来使用.可以达到此功能的函数有两个:
l一个是你自己事先知道设备号的
register_chrdev_region,在中声明:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
first是你要分配的起始设备编号. first的次编号部分常常是0,count是你请求的连续设备编号的总数. name是应当连接到这个编号范围的设备的名子;它会出现在/proc/devices和sysfs中.
l第二个是动态动态分配设备编号
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
使用这个函数, dev是一个只输出的参数,它在函数成功完成时持有你的分配范围的第一个数. fisetminor应当是请求的第一个要用的次编号;它常常是0. count和name参数如同给request_chrdev_region的一样.
5)设备编号的释放使用
不管你是采用哪些方式分配的设备号。使用之后肯定是要释放的,其方式如下:
void unregister_chrdev_region(dev_t first, unsigned int count);
6)
2.驱动程序的二个最重要数据结构
1)file_operation
倒如字符设备scull的一般定义如下:
struct file_operations scull_fops = {
.owner = THIS_MODULE,
.llseek = scull_llseek,
.read = scull_read,
.write = scull_write,
.ioctl = scull_ioctl,
.open = scull_open,
.release = scull_release,
};
file_operation也称为设备驱动程序接口
定义在,是一个函数指针的集合.每个打开文件(内部用一个file结构来代表)与它自身的函数集合相关连(通过包含一个称为f_op的成员,它指向一个file_operations结构).这些操作大部分负责实现系统调用,因此,命名为open, read,等等
2)File
定义位于include/fs.h
struct file结构与驱动相关的成员
lmode_t f_mode标识文件的读写权限
lloff_t f_pos当前读写位置
lunsigned int_f_flag文件标志,主要进行阻塞/非阻塞型操作时检查
lstruct file_operation * f_op文件操作的结构指针
lvoid * private_data驱动程序一般将它指向已经分配的数据
lstruct dentry* f_dentry文件对应的目录项结构
3.字符设备注册
1)内核在内部使用类型struct cdev的结构来代表字符设备.在内核调用你的设备操作前,必须编写分配并注册一个或几个这些结构.有2种方法来分配和初始化一个这些结构.
l如果你想在运行时获得一个独立的cdev结构,可以这样使用:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;
l如果想将cdev结构嵌入一个你自己的设备特定的结构;你应当初始化你已经分配的结构,使用:
void cdev_init(struct cdev *cdev, struct file_operations *fops);
2)一旦cdev结构建立,最后的步骤是把它告诉内核,调用:
int cdev_add(struct cdev *dev, dev_t num, unsigned int count);
说明:dev是cdev结构, num是这个设备响应的第一个设备号, count是应当关联到设备的设备号的数目.常常count是1,但是有多个设备号对应于一个特定的设备的情形.
3)为从系统去除一个字符设备,调用:
void cdev_del(struct cdev *dev);
4.open和release
⑨ linux驱动开发 主要要开发哪些驱动
您好:做嵌入式应用的话一般的编程就可以了。那么嵌入式驱动开发与内核开发的话就需要学习多个方面的知识。我就把这方面的要求给你交流一下:
(一家之言啊,自己多年从事嵌入式开发的一点感悟)
嵌入式驱动开发需要了解的知识大概有以下几类:
1 嵌入式操作系统驱动框架。每一个操作系统都有自己的构架,应该了解驱动在整个系统中的具体位置与构建驱动程序的主要事项
2 总线知识,比如PCI、USB总线。
3 芯片知识。驱动其实就是对设备上一些寄存器的配置、CPU与设备本身的通讯以及对不同命令的处理
4 要做好驱动,必须对所使用的CPU体系结构有一个比较深刻的认识
5 C++基本用不上,主要是C和汇编。
6 做驱动最好要懂内核调试(比如说linux)
⑩ 怎么学linux内核驱动
怎么学linux内核驱动?1. 分享Linux内核学习和驱动开发的经验。
内核学习
Linux 内核功能越来越完善,如果没有充裕的时间,深入内核并不是很现实。所以建议先读一本内核的书,
第一遍是读,会读的很迷糊;之后反省一下,然后再浏览一下;可以想象一个 OS 是如何运行的,这样可以不
陷入 Linux 内核的细节;最后可以深入自己感兴趣或者需要的那一子系统
推荐 《Linux Kernel Development》
即便是子系统,也是很庞大的。一个省力的方式是网上搜一些相关的文章,便于快速了解这个子系统的运作;
然后结合代码,形成自己的认知,最后做一下总结。如果仅仅是快速了解某一子系统的运作,可以参考一些早期
代码的注解书籍,再深入的时候看看最新的代码实现
对内核的认知是一个反复的过程,一开始并不完善,可能需要反复纠正。不要陷入这种纠错中;而是以后继续
使用和学习过程中,发现了没有弄清楚的地方再深入,毕竟 Linux 内核是不断变化的
还有一个很好的方式是,从系统调用入手,现在这方面的数据不少,而且对系统调用的语义都有讲解,这样可以
间接了解 Linux 系统的一些概念。对系统调用熟悉了,可以根据系统调用的执行过程,来大体了解内核的一个
运作过程;但是跟踪系统调用的时候要注意抓主线,现在内核系统很复杂,一些 code path 上可能会涉及多个
子系统,可以从名字上猜测它们是干什么的,不需要深入,否则会发现精力完全被分散掉了
学习 Linux 内核,一个很重要的是抽象的能力,所谓的抽象这里仅仅是指分清接口和接口的实现。因为 Linux
内核子系统很多,有很多子系统相互渗透,这样 code path 看上去很复杂。阅读代码的时候,为了排除干扰,
需要分清哪些是自己需要看的,哪些是其它子系统的接口,对于其它子系统的接口,先当作它们功能完善不会
出问题好了,这样可以关注重点;打个比方,一个应用程序的代码可能量很大,比如一个 apache 项目,它
包含很多组件,有时候阅读代码的时候会看到不同组件的 API,深入看相关组件实现并不现实,这时候分清主次
对于代码的阅读就很有帮助了,总不能看到了 malloc 就要先把它的实现弄清楚吧,系统调用多者呢