设备与处理器之间的工作通常来说是异步,设备数据要传递给处理器通常来说有以下几种方法:轮询、等待和中断。
让CPU进行轮询等待总是不能让人满意,所以通常都采用中断的形式,让设备来通知CPU读取数据。
26内核的函数参数与现在的参数有所区别,这里都主要介绍概念,具体实现方法需要结合具体的内核版本。
request_irq函数申请中断,返回0表示申请成功,其他返回值表示申请失败,其具体参数解释如下:
flags 掩码可以使用以下几个:
快速和慢速处理例程 :现代内核中基本没有这两个概念了,使用SA_INTERRUPT位后,当中断被执行时,当前处理器的其他中断都将被禁止。通常不要使用SA_INTERRUPT标志位,除非自己明确知道会发生什么。
共享中断 :使用共享中断时,一方面要使用SA_SHIRQ位,另一个是request_irq中的dev_id必须是唯一的,不能为NULL。这个限制的原因是:内核为每个中断维护了一个共享处理例程的列表,例程中的dev_id各不相同,就像设备签名。如果dev_id相同,在卸载的时候引起混淆(卸载了另一个中断),当中断到达时会产生内核OOP消息。
共享中断需要满足以下一个条件才能申请成功:
当不需要使用该中断时,需要使用free_irq释放中断。
通常我们会在模块加载的时候申请安装中断处理例程,但书中建议:在设备第一次打开的时候安装,在设备最后一次关闭的时候卸载。
如果要查看中断触发的次数,可以查看 /proc/interrupts 和 /proc/stat。
书中讲述了如何自动检测中断号,在嵌入式开发中通常都是查看原理图和datasheet来直接确定。
自动检测的原理如下:驱动程序通知设备产生中断,然后查看哪些中断信号线被触发了。Linux提供了以下方法来进行探测:
探测工作耗时较长,建议在模块加载的时候做。
中断处理函数和普通函数其实差不多,唯一的区别是其运行的中断上下文中,在这个上下文中有以下注意事项:
中断处理函数典型用法如下:
中断处理函数的参数和返回值含义如下:
返回值主要有两个:IRQ_NONE和IRQ_HANDLED。
对于中断我们是可以进行开启和关闭的,Linux中提供了以下函数 *** 作单个中断的开关:
该方法可以在所有处理器上禁止或启用中断。
需要注意的是:
如果要关闭当前处理器上所有的中断,则可以调用以下方法:
local_irq_save 会将中断状态保持到flags中,然后禁用处理器上的中断;如果明确知道中断没有在其他地方被禁用,则可以使用local_irq_disable,否则请使用local_irq_save。
locat_irq_restore 会根据上面获取到flags来恢复中断;local_irq_enable 会无条件打开所有中断。
在中断中需要做一些工作,如果工作内容太多,必然导致中断处理所需的时间过长;而中断处理又要求能够尽快完成,这样才不会影响正常的系统调度,这两个之间就产生了矛盾。
现在很多 *** 作系统将中断分为两个部分来处理上面的矛盾:顶半部和底半部。
顶半部就是我们用request_irq来注册的中断处理函数,这个函数要求能够尽快结束,同时在其中调度底半部,让底半部在之后来进行后续的耗时工作。
顶半部就不再说明了,就是上面的中断处理函数,只是要求能够尽快处理完成并返回,不要处理耗时工作。
底半部通常使用tasklet或者工作队列来实现。
tasklet的特点和注意事项:
工作队列的特点和注意事项:
以装载和卸载模块为例:
1、首先输入代码
#include <linux/inith>
#include <linux/moduleh>
2、然后输入下方的代码:
static int my_init(void)
{
return 0;
}
static void my_exit(void)
3、然后在输入下方的代码:
{
return;
}
module_init(my_init);
module_exit(my_exit);这样就完成了。
驱动程序识别设备时,有以下两种方法:
(1)驱动程序本身带有设备的信息,比如开始地址、中断号等:加载驱动程序时,就可以根据这些信息来识别设备。
(2)驱动程序本身没有设备的信息,但是内核中已经(或以后)根据其他方式确定了很多设备的信息;加载驱动程序时,将驱动程序与这些设备逐个比较,确定两者是否匹配(match)。如果驱动程序与某个设备匹配,就可以通过该驱动程序 *** 作这个设备了。内核常使用第二种方法来识别设备,这可以将各种设备集中在-一个文件中管理,当开发板的配置改变时,便于修改代码。在内核文件include/linux/platform _deviceh 中,定义了两个数据结构来表示这些设备和驱动程序: platform_ device 结构用来描述设备的名称、ID、所占用的资源(比如内存地址/大小、中断号)等; platform_ driver 结构用来描述各种 *** 作函数, 比如枚举函数、移除设备函数、驱动的名称等。内核启动后,首先构造链表将描述设备的platform_device结构组织起来,得到一一个设备的列表:当加载某个驱动程序的platform_ driver 结构时,使用一些匹配函数来检查驱动程序能否支持这些设备,常用的检查方法很简单:比较驱动程序和设备的名称。
Linux内核API文档可以在官方网站上找到。Linux内核API文档包括内核函数、数据类型、宏定义等内容,可以在Linux官方网站的文档页面中找到。这些文档通常包含了针对不同内核版本的API接口,可以帮助开发人员编写和调试Linux内核驱动程序。另外,也可以通过阅读相关的书籍和网络教程来学习和理解Linux驱动开发的相关知识和技术。
linux的驱动一般有两种格式,分别为:tar和rpm格式。
rpm安装步骤:
1.将驱动程序文件bcm5700-srcrpm复制到一个临时目录中,并在此目录中运行以下命令:
rpm –ivh bcm5700-srcrpm
2.运行以下命令切换到驱动目录中:
cd /usr/src/redhat/SPECS/
3.此目录中会生成一个名字为bcm5700spec的文件,运行以下命令对驱动程序进行编译:
rpmbuild –bb bcm5700spec (对4xx版本的RPM适用)或 rpm -bb bcm5700spec
4.运行以下命令切换到RPM目录中:
cd /usr/src/redhat/RPMS/i386/
5.运行以下命令安装驱动程序:
rpm –ivh bcm5700-i386rpm (对于Red Hat 72, 73, 21AS和其他包含老版本驱动的系统需要使用--force的参数,强制用新的驱动替换系统自带的老版本驱动)
6.运行以下命令加载驱动模块:
insmod bcm5700
7.运行kudzu命令,系统会自动搜索到硬件,进行配置即可。
或者重新启动系统,启动过程中系统会自动找到硬件,进行相应配置即可。
tar格式安装步骤:
1 将驱动程序压缩文件bcm5700-targz复制到一个临时目录中,并使用以下命令解压缩:
tar xvzf bcm5700-targz
2.构建驱动程序为运行内核可加载模块
cd bcm5700-/src
make
3.加载测试
insmod bcm5700
4.加载驱动程序
make install
5.重新启动系统,启动过程中找到硬件,进行相应配置。
或者直接运行kudzu命令,系统会自动搜索到硬件,进行配置即可。
一、查看网卡型号和机器位数
1、查看网卡型号
linux系统下通过以下命令,可以查看当前的网卡驱动信息;
[box color="white" icon="none"]
[root@localhost zhangy]# lspci |grep -i eth
03:000 Ethernet controller: Realtek Semiconductor Co, Ltd RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 06)
[/box]
2、查看机器位数
驱动程序是要区分系统是32位系统还是64位系统的, 所以通过以下linux命令,就可以知道 *** 作系统的位数了;
[box color="white" icon="none"]
[root@localhost ~]# uname -a
Linux localhostlocaldomain 2618-308131el5PAE #1 SMP Tue Aug 21 17:50:26 EDT 2012 i686 i686 i386 GNU/Linux
[/box]
下载前先看一下你的网卡驱动,如果是最新的就不用在重新装了。
[box color="white" icon="none"]
[root@localhost zhangy]# ethtool -i eth0
driver: r8169
version: 23LK-1-NAPI
firmware-version:
bus-info: 0000:03:000
[/box]
RTL8111/8168B就是网卡的型号,这样你可以网卡的型号来找一下网卡驱动的官方网站,然后下载最新的网卡驱动,驱动分64位和32位的,i386,i686是32位的机器,x86_64表示是64位的机器,不要选错驱动了。
二、下载驱动,并安装
1、解压
[box color="white" icon="none"]
[root@localhost download]# tar jxvf r8168-803200tarbz2
[/box]
2、安装
[box color="white" icon="none"]
[root@localhost r8168-803200]# make && make install
[/box]
如果报以下错误
make -C /lib/modules/2618-30882el5PAE/build SUBDIRS=/home/zhangy/r8168-803200/src INSTALL_MOD_DIR=kernel/drivers/net modules_install
make: /lib/modules/2618-30882el5PAE/build: 没有那个文件或目录。 停止。
make: [install] 错误 2
说明你kernel源码没有安装。安装kernel源码
[box color="white" icon="none"]
[root@localhost r8168-803200]# yum install kernel-xen kernel-xen-devel kernel \
> kernel-PAE kernel-PAE-devel kernel-devel kernel-headers
[/box]
安装完以后,一定要重启机器。不然下面 *** 作就过不去了,会报FATAL: Module r8168 not found
[box color="white" icon="none"]
[root@localhost r8168-803200]# depmod -a
[root@localhost r8168-803200]# modprobe r8168
[/box]
编辑配置文件/etc/modprobecof,如果以前没有添加alias eth0 r8168,如果已经有了修改一下成alias eth0 r8168。
查一下驱动是不是加载了,如果有以下内容说明驱动安装成功了。
[box color="white" icon="none"]
[root@localhost r8168-803200]# lsmod |grep r8168
r8168 231132 0
[/box]
必须重新启动一下机器,用ethtool查看驱动才会改变,不然还是老样子。下面是新的驱动。
[box color="white" icon="none"]
[root@localhost ~]# ethtool -i eth0
driver: r8168
version: 803200-NAPI
firmware-version:
bus-info: 0000:02:000
[/box]
在24内核中,加载驱动命令为:insmod ,删除模块为:rmmod;
在26以上内核中,除了insmod与rmmod外,加载命令还有modprobe;
insmod与modprobe不同之处:
insmod 绝对路径/××o,而modprobe ××即可,不用加ko或o后缀,也不用加路径;最重要的一点是:modprobe同时会加载当前模块所依赖的其它模块;
lsmod查看当前加载到内核中的所有驱动模块,同时提供其它一些信息,比如其它模块是否在使用另一个模块。
以上就是关于《Linux设备驱动程序》(十六)-中断处理全部的内容,包括:《Linux设备驱动程序》(十六)-中断处理、如何编写Linux 驱动程序、嵌入式linux驱动识别设备的过程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)