嵌入式系统中断
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
器的相应位置位
嵌入式系统中断
异常及非屏蔽中断
异常就是CPU内部出现的中断,即在CPU 执行特定指令时出现的非法情况。
非屏蔽 中断就是 计算机内部硬件出错 时引起的异常情况
Intel把非屏蔽中断作为一种异常来处理 在CPU执行一个 异常处理程序时,就不
再为其他异 常或可屏蔽中断请求服务
嵌入式系统中断
嵌入式系统中断
中断的相关数据结构
(3) 定义在include/linux/ interrupt.h中的struct irqaction数据结构包含 了内核接收到特定IRQ之后应采取的操作,其成员如下:
handler:是一指向某个函数的指针。该函数就是所在结构对相应中 断的处理函数。
flags:取值只有SA_INTERRUPT(中断可嵌套), SA_SAMPLE_RANDOM(这个中断是源于物理随机性的),和 SA_SHIRQ(这个IRQ和其它struct irqaction共享)。
中断与异常
嵌入式系统中断
主要内容
中断的基本知识 中断描述符表的初始化 中断处理 中断的下半部处理机制 中断的应用-时钟中断
嵌入式系统中断
中断的基本概念
硬中断的概念
硬中断即和硬件相关的中断也就是通常意义上的“中断处理程序”,它是直 接处理由硬件发过来的中断信号的。
中断执行的过程
当某个设备发出中断请求时,CPU停止正在执行的指令, 转而跳到包括 中断处理代码或者包括指 向中断处理代码的转移指令所在的内存区域。 这些代码一般在CP U的中断方式下运 行。就回去自己驱动的设备上去看 看设备的状态寄存器以了 解发生了什么事情,并进行相应的操作。当中 断处理完毕以后,CPU将恢复到以前的状态,继续执行中断处理前正在 执行的指令。
指向irqaction描述符链表的下一个元素中断线共享的数据结构28初始化idt表之后必须通过requestirq函数将相应的中断服务例程挂入中断请求队列即对其进行注册在关闭设备时必须通过调用freeirq函数释放所申请的中断请求号注册中断服务例程?intrequestirqunsignedintirqvoidhandlerintvoidstructptregsunsignedlongirqflagsconstchardevnamevoiddevid29cpu从中断控制器的一个端口取得中断向量i根据i从中断描述符表idt中找到相应的中断从中断门获得中断处理程序的入口地址调用doirq对所接收的中断进行应答并禁止这条中断线调用handleirqevent来运行对应的中断服务例程中断处理程序的执行30当处理所有外设中断请求的函数doirq执行时内核栈顶包含的就是doirq的返回地址这个地址指向retfromintr从中断返回时cpu要调用恢复中断现场的宏restoreall彻底从中断返回
异常及非 屏蔽中断 :
CPU内部中断或计算机内部硬件出错 引起的异 常
中断描述符表 : 描述 中断的相关信息
中断的 相 关汇 编指令 :
嵌入式系统中断
中断向量-中断源的类型
中断 向量: 每个中 断源都被分配一个8位无符号整数作为 类型码,即中断向量
中断的种类: 中断:
外部 可屏蔽中断 外部非 屏蔽中断
嵌入式系统中断
中断的相关数据结构
图 3.4 Linux 的中断处理数据结构
嵌入式系统中断
中断的相关数据结构
在 i386 系统中,Linux 启动时要设置系统的中断描述符表 IDT。IDT 中包含各个中断(以及异常,诸如浮点运算溢 出)的服务程序地址,中断服务程序地址由 Linux 提供。 每个设备驱动程序可以在图 3.4 所示的结构(irq_action) 中注册自己的中断及中断处理程序地址。Linux 的中断服 务程序根据 irq_action 中的注册信息调用相应的设备驱 动程序的中断处理程序。和硬件相关的中断处理代码隐藏 在中断服务程序中,这样,设备驱动程序的中断处理程序 可在不同平台之间 方便移植。一般来说,CPU 在处理中 断时,首先要在堆栈中保存与 CPU 指令执行相关的寄存 器(例如指令计数 寄存器),然后调用中断服务程序, 中断服务程序结束时 再恢复这些寄存器。
与硬中断相关数据结构主要有三个, 三者关系如图3.5所示。
嵌入式系统中断
3.2.2 中断的相关数据结构
图3.5 与硬中断相关的几个数据结构的关系
嵌入式系统中断
中断的相关数据结构
(1) 定义在/arch/i386/Kernel/irq.h中的struct hw_interrupt_type数据结 构,它是一个抽象的中 断控制器。这包含一系列的指向函数的指针, 这些函数处理控制器 特有的操作:
由于0-31号中断向量已被Intel保留,就剩下32-255共224个中断向量 可用。在Linux中,这224个中断向量除了0x80 (SYSCALL_VECTOR) 用作系统调用总入口之外,其它都用在外部硬件中断源(包括可编程 中断控制器8259A的15个irq)上。实际上,当没有定义 CONFIG_X86_IO_APIC时,其它223(除0x80外)个中断向量,只利用 了从32号开始的15个,其它208个空着未用。这些中断服务程序入口 的设置将在下面详细说明。
中断的相关数据结构
从数据结 构入手,应该说 是分析操作系统源码最常用的 和最主要的方法。因为操 作系统的几 大功能部件,如进 程管理、 设备管 理、内存 管理等, 都可以通过对其相 应的数据结 构的分析来弄懂 其实现机制。 很好的掌握 这种方法, 对分析Linux内核大有帮助。
中断向量在保护模式下的实现机制是中断描述符表 (Interrupt Descriptor Table, IDT),中断描述符表的结构如 图3.4所示。中断描述符 表即中断向量表相当于一个数组, 包含256个中断描述符,每个中断描述符8位,对应硬件提 供的256个中断服务 例程的入口,即256个中断向量。 IDT的位置由idtr确定,idtr是个48位的寄存器,高32位是 IDT的基址,低16位为IDT的界限(通常为2k=256*8)。
struct hw_interrupt_type {
const char * typename;
void (*startup)(unsigned int irq);
void (*shutdown)(unsigned int irq);
void (*handle)(unsigned int irq, struct pt_regs * regs);
mask:在x86或者体系结构无关的代码中不会使用(除非将其设置为 0);只有在SPARC64的移植版本中要跟踪有关软盘的信息时才会使 用它。
name:产生中断的硬件设备的名字。因为不止一个硬件可以共享一 个IRQ。
dev_id:标识硬件类型的一个唯一的ID。Linux支持的所有硬件设备 的每一种类型,都有一个由制造厂商定义的在此成员中记录的设备ID。
为方便处理,Linux为每条中断线设 置了一个 中断请求队列
中断服务例程 与中断处理程序 中断线共享的数据结构 注册中断服务例程
嵌入式系统中断
中断服务例程与中断处理程序
中断服务例程(Interrupt Service Routine ):每个中断请求都有自己 单独的中断服务例程
中断处理程序:共享同一条中断线 的所有中断请求有一个总的中断处 理程序
next:如果IRQ是共享的,那么这就是指向队列中下一个struct irqaction结构的指针。通常情况下,IRQ不是共享的,因此这个成员 就为空。
嵌入式系统中断
中断的相关数据结构
struct irqaction { void (*handler)(int, void *, struct pt_regs *); unsigned long flags; unsigned long mask; const char *name; void *dev_id; struct irqaction *next; };
嵌入式系统中断
中断的相关数据结构
irq_desc是irq_desc_t 类型 的数组。对于每一个IRQ都有一个数组入 口,即数组把每一个IRQ映射 到和它相关的处理程序和irq_desc_t中 的其它信息。
typedef struct { unsigned int status; // IRQ status - IRQ_INPROGRESS, IRQ_DISABLED struct hw_interrupt_type *handler; // handle/enable/disable functions struct irqaction *action; // IRQ action list unsigned int depth; // Disable depth for nested irq disables } irq_desc_t;
status:一个整数。代表IRQ的状态:IRQ是否被禁止了,有关IRQ的 设备当前是否正被自动检测,等等。
handler:指向hw_interrupt_type的指针。 action:指向irqaction结构组成的队列的头。正常情况下每个IRQ只有
一个操作,因此链接列表的正常长度是1(或者0)。但是,如果IRQ 被两个或者多个设备所共享,那么这个队列中就有多个操作。 depth:irq_desc_t的当前用户的个数。主要是用来保证在中断处理过 程中IRQ不会被禁止。
嵌入式系统中断
中断的流程如图
i8259.c负责对外部中断的支持。8259芯片负责接收外部设备——如定时器、键盘、声卡等——的 中断,两块8259共支持16个中断
嵌入式系统中断
嵌入式系统中断
Linux 中断处理特色
分 为上半部和下半部执行 上 半部屏蔽所有中断 下 半部允许中断,执行几乎所有中断
typename:控制器的名字。
startup:允许从给定 的控制器的IRQ所产生的事件。
shutdown:禁止从给 定的控制器的IRQ所产生的事件。
handle:根据提供 给该函数的IRQ,处理唯一的中断。
enable和disable:这两个函数基本上和start结构
irq_action 实际是一个数组,其中包含指向 irqaction 的指针,每个数 组元素分别定义一个 IRQ。Linux 内核提供相应的操作函数,设备驱 动程序可调用这些操作函数设置相应的中断处理函数。一般在系统启 动时,由各个设备驱动程序通过如下途径获取相关的设备 IRQ 并设置 对应的 irq_action 数组元素所指向的 irqaction 结构。
在对下一条指令执行前,CPU先要判 断在执行当前指令的过程中是否发生 了中断或异常。
如果发生了一个中断或异常,那么 CPU将做以下事情 :
嵌入式系统中断
中断和异常处理中CPU的工作
确定所发生中断或异常的向量i(在0~255之间) 通过IDTR寄存器找到IDT表,读取IDT表第i项(或叫第i个
门) 分“段”级、“门”级两步进行有效性检查
检查是否发生了特权级的变化
中断处理程序堆 栈
堆
栈
SS
增
ESP
长
EFLAGS
方 向
CS EIP
中断发生前 夕的SS:ESP
返回地址
ERROR CODE
错误码
EFLAGS CS EIP ERROR CODE
嵌入式系统中断
中断请求队列的建立
由于硬件 条件的限制,很多硬件设 备共享一条中断线
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
};
嵌入式系统中断
中断的相关数据结构
(2) 定义在/arch/i386/Kernel/irq.h中的另外一个数据结构是irq_desc_t, 它具有如下成员:
异常:不 使用中断控制器,不能被屏蔽
故障 陷阱
嵌入式系统中断
外设可屏蔽中断
Intel x86通过两片中断控制器8259A来 响应15个外中断源,每个8259A可管 理8个中断源。
外部设备拥有相应权限时 ,可以向 特定的中断线发送中断请求信号
外部I/O请求的屏蔽:
从CPU的角度, 清除eflag的中断标志位 从中断控制器的角度,将中断屏蔽寄存
嵌入式系统中断
中断处理
中断和异常的 硬件处理 :
从硬件的角 度看CPU如何处理中断和异常
中断请求队列 的建立:
方便外设共 享中断线
中断处理程序的执行 从中断返回:
调用恢复中断现场的宏RESTORE_ALL,彻底从 中断返回
嵌入式系统中断
中断和异常的硬件处理
当CPU执行了当前指令之后,CS和 EIP这对寄存器中所包含的内容就是 下一条将要执行指令的虚地址。
嵌入式系统中断
中断常识
中断控 制的主要优点:
CPU只 有在I/O需要服务时才响应
外部中断: 外部 设备所发出的I/O请求
内部 中断:
也称之为“异常”,是为解决机器运 行时所出现的某些随机事件及编程方 便而出现的
嵌入式系统中断
中断向量 :
中 断源的编号
外设可屏蔽中断:
屏蔽外 部I/O请求
嵌入式系统中断
异常及非屏蔽中断
异常就是CPU内部出现的中断,即在CPU 执行特定指令时出现的非法情况。
非屏蔽 中断就是 计算机内部硬件出错 时引起的异常情况
Intel把非屏蔽中断作为一种异常来处理 在CPU执行一个 异常处理程序时,就不
再为其他异 常或可屏蔽中断请求服务
嵌入式系统中断
嵌入式系统中断
中断的相关数据结构
(3) 定义在include/linux/ interrupt.h中的struct irqaction数据结构包含 了内核接收到特定IRQ之后应采取的操作,其成员如下:
handler:是一指向某个函数的指针。该函数就是所在结构对相应中 断的处理函数。
flags:取值只有SA_INTERRUPT(中断可嵌套), SA_SAMPLE_RANDOM(这个中断是源于物理随机性的),和 SA_SHIRQ(这个IRQ和其它struct irqaction共享)。
中断与异常
嵌入式系统中断
主要内容
中断的基本知识 中断描述符表的初始化 中断处理 中断的下半部处理机制 中断的应用-时钟中断
嵌入式系统中断
中断的基本概念
硬中断的概念
硬中断即和硬件相关的中断也就是通常意义上的“中断处理程序”,它是直 接处理由硬件发过来的中断信号的。
中断执行的过程
当某个设备发出中断请求时,CPU停止正在执行的指令, 转而跳到包括 中断处理代码或者包括指 向中断处理代码的转移指令所在的内存区域。 这些代码一般在CP U的中断方式下运 行。就回去自己驱动的设备上去看 看设备的状态寄存器以了 解发生了什么事情,并进行相应的操作。当中 断处理完毕以后,CPU将恢复到以前的状态,继续执行中断处理前正在 执行的指令。
指向irqaction描述符链表的下一个元素中断线共享的数据结构28初始化idt表之后必须通过requestirq函数将相应的中断服务例程挂入中断请求队列即对其进行注册在关闭设备时必须通过调用freeirq函数释放所申请的中断请求号注册中断服务例程?intrequestirqunsignedintirqvoidhandlerintvoidstructptregsunsignedlongirqflagsconstchardevnamevoiddevid29cpu从中断控制器的一个端口取得中断向量i根据i从中断描述符表idt中找到相应的中断从中断门获得中断处理程序的入口地址调用doirq对所接收的中断进行应答并禁止这条中断线调用handleirqevent来运行对应的中断服务例程中断处理程序的执行30当处理所有外设中断请求的函数doirq执行时内核栈顶包含的就是doirq的返回地址这个地址指向retfromintr从中断返回时cpu要调用恢复中断现场的宏restoreall彻底从中断返回
异常及非 屏蔽中断 :
CPU内部中断或计算机内部硬件出错 引起的异 常
中断描述符表 : 描述 中断的相关信息
中断的 相 关汇 编指令 :
嵌入式系统中断
中断向量-中断源的类型
中断 向量: 每个中 断源都被分配一个8位无符号整数作为 类型码,即中断向量
中断的种类: 中断:
外部 可屏蔽中断 外部非 屏蔽中断
嵌入式系统中断
中断的相关数据结构
图 3.4 Linux 的中断处理数据结构
嵌入式系统中断
中断的相关数据结构
在 i386 系统中,Linux 启动时要设置系统的中断描述符表 IDT。IDT 中包含各个中断(以及异常,诸如浮点运算溢 出)的服务程序地址,中断服务程序地址由 Linux 提供。 每个设备驱动程序可以在图 3.4 所示的结构(irq_action) 中注册自己的中断及中断处理程序地址。Linux 的中断服 务程序根据 irq_action 中的注册信息调用相应的设备驱 动程序的中断处理程序。和硬件相关的中断处理代码隐藏 在中断服务程序中,这样,设备驱动程序的中断处理程序 可在不同平台之间 方便移植。一般来说,CPU 在处理中 断时,首先要在堆栈中保存与 CPU 指令执行相关的寄存 器(例如指令计数 寄存器),然后调用中断服务程序, 中断服务程序结束时 再恢复这些寄存器。
与硬中断相关数据结构主要有三个, 三者关系如图3.5所示。
嵌入式系统中断
3.2.2 中断的相关数据结构
图3.5 与硬中断相关的几个数据结构的关系
嵌入式系统中断
中断的相关数据结构
(1) 定义在/arch/i386/Kernel/irq.h中的struct hw_interrupt_type数据结 构,它是一个抽象的中 断控制器。这包含一系列的指向函数的指针, 这些函数处理控制器 特有的操作:
由于0-31号中断向量已被Intel保留,就剩下32-255共224个中断向量 可用。在Linux中,这224个中断向量除了0x80 (SYSCALL_VECTOR) 用作系统调用总入口之外,其它都用在外部硬件中断源(包括可编程 中断控制器8259A的15个irq)上。实际上,当没有定义 CONFIG_X86_IO_APIC时,其它223(除0x80外)个中断向量,只利用 了从32号开始的15个,其它208个空着未用。这些中断服务程序入口 的设置将在下面详细说明。
中断的相关数据结构
从数据结 构入手,应该说 是分析操作系统源码最常用的 和最主要的方法。因为操 作系统的几 大功能部件,如进 程管理、 设备管 理、内存 管理等, 都可以通过对其相 应的数据结 构的分析来弄懂 其实现机制。 很好的掌握 这种方法, 对分析Linux内核大有帮助。
中断向量在保护模式下的实现机制是中断描述符表 (Interrupt Descriptor Table, IDT),中断描述符表的结构如 图3.4所示。中断描述符 表即中断向量表相当于一个数组, 包含256个中断描述符,每个中断描述符8位,对应硬件提 供的256个中断服务 例程的入口,即256个中断向量。 IDT的位置由idtr确定,idtr是个48位的寄存器,高32位是 IDT的基址,低16位为IDT的界限(通常为2k=256*8)。
struct hw_interrupt_type {
const char * typename;
void (*startup)(unsigned int irq);
void (*shutdown)(unsigned int irq);
void (*handle)(unsigned int irq, struct pt_regs * regs);
mask:在x86或者体系结构无关的代码中不会使用(除非将其设置为 0);只有在SPARC64的移植版本中要跟踪有关软盘的信息时才会使 用它。
name:产生中断的硬件设备的名字。因为不止一个硬件可以共享一 个IRQ。
dev_id:标识硬件类型的一个唯一的ID。Linux支持的所有硬件设备 的每一种类型,都有一个由制造厂商定义的在此成员中记录的设备ID。
为方便处理,Linux为每条中断线设 置了一个 中断请求队列
中断服务例程 与中断处理程序 中断线共享的数据结构 注册中断服务例程
嵌入式系统中断
中断服务例程与中断处理程序
中断服务例程(Interrupt Service Routine ):每个中断请求都有自己 单独的中断服务例程
中断处理程序:共享同一条中断线 的所有中断请求有一个总的中断处 理程序
next:如果IRQ是共享的,那么这就是指向队列中下一个struct irqaction结构的指针。通常情况下,IRQ不是共享的,因此这个成员 就为空。
嵌入式系统中断
中断的相关数据结构
struct irqaction { void (*handler)(int, void *, struct pt_regs *); unsigned long flags; unsigned long mask; const char *name; void *dev_id; struct irqaction *next; };
嵌入式系统中断
中断的相关数据结构
irq_desc是irq_desc_t 类型 的数组。对于每一个IRQ都有一个数组入 口,即数组把每一个IRQ映射 到和它相关的处理程序和irq_desc_t中 的其它信息。
typedef struct { unsigned int status; // IRQ status - IRQ_INPROGRESS, IRQ_DISABLED struct hw_interrupt_type *handler; // handle/enable/disable functions struct irqaction *action; // IRQ action list unsigned int depth; // Disable depth for nested irq disables } irq_desc_t;
status:一个整数。代表IRQ的状态:IRQ是否被禁止了,有关IRQ的 设备当前是否正被自动检测,等等。
handler:指向hw_interrupt_type的指针。 action:指向irqaction结构组成的队列的头。正常情况下每个IRQ只有
一个操作,因此链接列表的正常长度是1(或者0)。但是,如果IRQ 被两个或者多个设备所共享,那么这个队列中就有多个操作。 depth:irq_desc_t的当前用户的个数。主要是用来保证在中断处理过 程中IRQ不会被禁止。
嵌入式系统中断
中断的流程如图
i8259.c负责对外部中断的支持。8259芯片负责接收外部设备——如定时器、键盘、声卡等——的 中断,两块8259共支持16个中断
嵌入式系统中断
嵌入式系统中断
Linux 中断处理特色
分 为上半部和下半部执行 上 半部屏蔽所有中断 下 半部允许中断,执行几乎所有中断
typename:控制器的名字。
startup:允许从给定 的控制器的IRQ所产生的事件。
shutdown:禁止从给 定的控制器的IRQ所产生的事件。
handle:根据提供 给该函数的IRQ,处理唯一的中断。
enable和disable:这两个函数基本上和start结构
irq_action 实际是一个数组,其中包含指向 irqaction 的指针,每个数 组元素分别定义一个 IRQ。Linux 内核提供相应的操作函数,设备驱 动程序可调用这些操作函数设置相应的中断处理函数。一般在系统启 动时,由各个设备驱动程序通过如下途径获取相关的设备 IRQ 并设置 对应的 irq_action 数组元素所指向的 irqaction 结构。
在对下一条指令执行前,CPU先要判 断在执行当前指令的过程中是否发生 了中断或异常。
如果发生了一个中断或异常,那么 CPU将做以下事情 :
嵌入式系统中断
中断和异常处理中CPU的工作
确定所发生中断或异常的向量i(在0~255之间) 通过IDTR寄存器找到IDT表,读取IDT表第i项(或叫第i个
门) 分“段”级、“门”级两步进行有效性检查
检查是否发生了特权级的变化
中断处理程序堆 栈
堆
栈
SS
增
ESP
长
EFLAGS
方 向
CS EIP
中断发生前 夕的SS:ESP
返回地址
ERROR CODE
错误码
EFLAGS CS EIP ERROR CODE
嵌入式系统中断
中断请求队列的建立
由于硬件 条件的限制,很多硬件设 备共享一条中断线
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
};
嵌入式系统中断
中断的相关数据结构
(2) 定义在/arch/i386/Kernel/irq.h中的另外一个数据结构是irq_desc_t, 它具有如下成员:
异常:不 使用中断控制器,不能被屏蔽
故障 陷阱
嵌入式系统中断
外设可屏蔽中断
Intel x86通过两片中断控制器8259A来 响应15个外中断源,每个8259A可管 理8个中断源。
外部设备拥有相应权限时 ,可以向 特定的中断线发送中断请求信号
外部I/O请求的屏蔽:
从CPU的角度, 清除eflag的中断标志位 从中断控制器的角度,将中断屏蔽寄存
嵌入式系统中断
中断处理
中断和异常的 硬件处理 :
从硬件的角 度看CPU如何处理中断和异常
中断请求队列 的建立:
方便外设共 享中断线
中断处理程序的执行 从中断返回:
调用恢复中断现场的宏RESTORE_ALL,彻底从 中断返回
嵌入式系统中断
中断和异常的硬件处理
当CPU执行了当前指令之后,CS和 EIP这对寄存器中所包含的内容就是 下一条将要执行指令的虚地址。
嵌入式系统中断
中断常识
中断控 制的主要优点:
CPU只 有在I/O需要服务时才响应
外部中断: 外部 设备所发出的I/O请求
内部 中断:
也称之为“异常”,是为解决机器运 行时所出现的某些随机事件及编程方 便而出现的
嵌入式系统中断
中断向量 :
中 断源的编号
外设可屏蔽中断:
屏蔽外 部I/O请求