《Linux设备驱动程序》(十六)-中断处理

《Linux设备驱动程序》(十六)-中断处理,第1张

设备与处理器之间的工作通常来说是异步,设备数据要传递给处理器通常来说有以下几种方法:轮询、等待和中断。

让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驱动识别设备的过程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9304244.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存