一、什么是中断?

中断有两种,一种是CPU本身在执行程序的过程中产生的,一种是由CPU外部产生的。 cpu外部中断,就是通常所讲的“中断”(interrupt)。对于执行程序来说,这种“中断”的发生完全是异步的,因为不知道什么时候会发生。CPU对其的响应也完全是被动的, 可以通过“关中断”指令关闭对其的响应。 然而由软件产生的中断一般是由专设的指令,如X86中的“INT n”在程序中有意产生的, 是主动的,同步的。只要CPU执行一条INT指令,在开始执行下一条指令之前一定会进入中 断服务程序。这种主动的中断称为“陷阱”(trap)

从物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入中断控制器的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后,处理器会通知 OS 已经产生中断。这样,OS 就可以对这个中断进行适当的处理。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线(IRQ)。
中断可分为同步(synchronous)中断和异步(asynchronous)中断:

1. 同步中断是当指令执行时由 CPU 控制单元产生,之所以称为同步,是因为只有在一条指令执行完毕后 CPU 才会发出中断,而不是发生在代码指令执行期间,比如系统调用。

2. 异步中断是指由其他硬件设备依照 CPU 时钟信号随机产生,即意味着中断能够在指令之间发生,例如键盘中断。

二、什么是异常?

同步中断又称为异常(exception);异步中断则被称为中断(interrupt)。我们通常讲的中断指的都是异步中断,即cpu外部中断。
1.中断可分为可屏蔽中断(Maskable interrupt)和非屏蔽中断(Nomaskable interrupt)。
2.异常可分为故障(fault)、陷阱(trap)、终止(abort)三类。

这些类别之间的异同点如下:

类别             原因                   异步/同步                   返回行为
中断      来自I/O设备的信号          异步                 总是返回到下一条指令
陷阱      有意的异常                    同步                 总是返回到下一条指令
故障      潜在可恢复的错误           同步                 返回到当前指令
终止      不可恢复的错误              同步                 不会返回

三、中断处理过程

当中断产生时,处理器将按如下的顺序执行:
• 保存当前处理机状态信息
• 载入异常或中断处理函数到PC寄存器
• 把控制权转交给处理函数并开始执行
• 当处理函数执行完成时,恢复处理器状态信息
• 从异常或中断中返回到前一个程序执行点

中断使得CPU可以在事件发生时才予以处理,而不必让CPU连续不断地查询是否有相应的事件发生。通过两条特殊指令:关中断和开中断可以让处理器不响应或响应中断(在关闭中断期间,通常处理器会把新产生的中断挂起,当中断打开时立刻进行响应)。在执行中断服务例程的过程中,如果有更高优先级别的中断源触发中断,由于当前处于中断处理上下文环境中,根据不同的处理器构架可能有不同的处理方式:比如新的中断等待挂起直到当前中断处理离开后再行响应,但这在硬实时环境中不允许发生;或者新的高优先级中断打断当前中断处理过程,而去直接响应这个更高优先级的新中断源,这称为中断嵌套,而中断是否能够嵌套,一般由MCU处理器的中断机制决定,如stm32中只有新中断的抢占优先级比当前中断高时,才能打断当前中断进入新的中断服务函数。

在系统响应中断前,软件代码(或处理器)需要把当前线程的上下文保存下来(通常保存在当前线程的线程栈中),再调用中断服务例程进行中断响应、处理。在进行中断处理时(实质是调用用户的中断服务例程函数),中断处理函数中很可能会有自己的局部变量,这些都需要相应的栈空间来保存,所以中断响应依然需要一个栈空间来做为上下文运行中断处理函数。中断栈可以保存在打断的线程栈中,当从中断中退出时,返回相应的线程继续执行。中断栈也可以与打断线程栈完全分离开来,即每次进入中断时,在保存完被打断的线程上下文后,切换到新的中断栈中独立运行;在中断退出时,再做相应的上下文恢复。

使用独立中断栈相对来说更容易实现,并且对于线程栈使用情况也比较容易了解掌握(否则必须要为中断栈预留空间,如果系统支持中断嵌套,还需要考虑应该为嵌套中断预留多大的空间)。RT-Thread采用的方式是提供独立的中断栈,即中断发生时,中断的前期处理程序会将用户的栈指针更换到系统事先留出的中断栈空间中,等中断退出时再恢复用户的栈指针。这样中断就不会占用线程的栈空间,从而提高了内存空间的利用率,且随着任务的增加,这种减少内存占用的的效果也越明显。以stm32的cotex-M3/M4为例,cotex-M3/M4中拥有两个堆栈指针,然而它们是banked,因此任一时刻只能使用其中的一个:

主堆栈指针(MSP):复位后缺省使用的堆栈指针,用于操作系统内核,以及异常与中断处理。

进程堆栈指针(PSP):由用户的应用程序代码(如线程切换)使用。堆栈指针的最低两位永远是0,这意味着堆栈总是4 字节对齐的。

由此可以看出,在一个实际运行系统里有两大部分:一是操作系统和中断,一是用户应用程序。它们使用的资源是不一样的,从中断(线程调度时产生的中断)返回到用户应用程序线程时,系统使用的堆栈指针也从MSP变成PSP。

四、与操作系统相关的中断接口:在src/irq.c中

void rt_interrupt_enter(void);
void rt_interrupt_leave(void);
当整个系统被中断打断,进入中断处理函数时,OS需要知道当前已经进入到中断状态。
rt_interrupt_enter函数用于通知OS,当前已经进入了中断状态;rt_interrupt_leave函数用于通知OS,已经离开中断状态。通常来说,OS需要知道这样的运行状态,这样在中断服务例程中,如果调用了OS相关的调用,OS好及时调整相应的行为,例如进行任务切换时应该采取中断中任务切换的策略,而不是立即进行切换。但是如果中断服务例程很显然、很必然地不会去调用OS相关的函数,此时也可以不调用rt_interrupt_enter/leave函数。 rt_uint8_t rt_interrupt_get_nest(void);
获取当前中断嵌套计数值,大于0说明处于中断服务中,大于1说明存在中断嵌套

五、与MCU相关的中断接口:以stm32f4为例

关闭中断:在libcpu/arm/cotex-m4/context_rvds.S中用汇编语言实现
rt_base_t rt_hw_interrupt_disable(void);
函数返回中断前的系统中断状态。
当系统关闭了中断时,就意味着当前线程/代码不会被其他事件所打断(因为整个系统已经不再对外部事件响应),也就是当前线程不会被抢占(因为线程切换时用到了PendSV_Handler),除非这个线程主动让出处理器。 打开中断:在libcpu/arm/cotex-m4/context_rvds.S中用汇编语言实现
void rt_hw_interrupt_enable(rt_base_t level);
调用这个函数接口将恢复调用rt_hw_interrupt_disable前的中断状态,level是上一次关闭中断时返回的值。打开中断往往是和关闭中断成对使用的,用于恢复关闭中断前的状态。
注意:调用这个接口并不代表着肯定打开中断,而是恢复关闭中断前的状态,如果调用rt_hw_interrupt_disable()前是关中断状态,那么调用此函数后依然是关中断状态。

RT-thread内核之异常与中断的更多相关文章

  1. Linux内核--异常和中断的区别

          相信大家都知道非常著名的两个名词:异常和中断,不过,你真的理解这两个名词在说什么吗?它们之间有什么区别呢?       1.中断       大家都知道,当我们在敲击键盘的同时就会产生中断 ...

  2. Linux内核实现透视---硬中断

    Linux的中断处理是驱动中比较重要的一部分内容,要清楚具体的实现才能更好的理解而不是靠记住别人理解后总结的规律,所以今天就打算从从源码来学习一下Linux内核对于中断处理过程,设计中断子系统的初始化 ...

  3. 向linux内核中添加外部中断驱动模块

    本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...

  4. Java thread中对异常的处理策略

    转载:http://shmilyaw-hotmail-com.iteye.com/blog/1881302 前言 想讨论这个话题有一段时间了.记得几年前的时候去面试,有人就问过我一个类似的问题.就是j ...

  5. Linux内核设计笔记7——中断

    中断与中断处理 何为中断? 一种由设备发向处理器的电信号 中断不与处理器时钟同步,随时可以发生,内核随时可能因为中断到来而被打断. 每一个中断都有唯一一个数字标志,称之为中断线(IRQ) 异常是由软件 ...

  6. 鸿蒙内核源码分析(中断管理篇) | 江湖从此不再怕中断 | 百篇博客分析OpenHarmony源码 | v44.02

    百篇博客系列篇.本篇为: v44.xx 鸿蒙内核源码分析(中断管理篇) | 江湖从此不再怕中断 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪 ...

  7. 鸿蒙内核源码分析(中断概念篇) | 海公公的日常工作 | 百篇博客分析OpenHarmony源码 | v43.02

    百篇博客系列篇.本篇为: v43.xx 鸿蒙内核源码分析(中断概念篇) | 海公公的日常工作 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪里 ...

  8. 鸿蒙内核源码分析(中断切换篇) | 系统因中断活力四射 | 百篇博客分析OpenHarmony源码 | v42.02

    百篇博客系列篇.本篇为: v42.xx 鸿蒙内核源码分析(中断切换篇) | 系统因中断活力四射 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪 ...

  9. 浅析arm的异常、中断和arm工作模式的联系

    说到异常向量,会让人联想到中断向量.其实,中断是属于异常的子集的,也就是说中断其实是异常其中的一种. 回到异常向量,他其实是一张表格,每个格子里存放的是一个地址,或者是一个跳转命令,不管是哪个,其目的 ...

随机推荐

  1. [原创]用python实现系统状态监测和故障转移

    #coding: utf-8 import socket import select import time import os import threading def ser(): s = soc ...

  2. 实现动态的XML文件读写操作(依然带干货)

    前言 最近由于项目需求,需要读写操作XML文件,并且存储的XML文件格式会随着导入的数据不同而随时改变(当然导入的数据还是有一定约束的),这样我们要预先定义好XML文件的格式就不太现实了,如何实现不管 ...

  3. Redis系列六 Redis事务

    Redis事务 1.介绍 在Redis事务中可以一次执行多个命令,本质是一组命令的集合.一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞. 2.事务的作用 一个队列中, ...

  4. linux_fdisk命令详解,关于分区的详解

    这篇文章写的十分详细,特别的好 fdisk -l 可以列出所有的分区,包括没有挂上的分区和usb设备.我一般用这个来查找需要挂载的分区的位置,比如挂上u盘. 实例解说Linux中fdisk分区使用方法 ...

  5. == vs === in Javascript

    本文来自网易云社区 作者:魏文庆 如果你只想知道==与===的区别,请直接看总结,当然我更希望您能耐心看完全文.Javascript中用于相等比较的操作符有两个==和===.==我们通常称为" ...

  6. 追书神器API

    由于自己喜欢看小说,有的时候不方便手机看的时候希望在电脑上面看,但很多网站有广告啊,于是封装了套手机版的追书神器API 目前只做了搜索 详情 书评 换源 正文 调用方式: //搜索小说 var sea ...

  7. Spring学习记录-Java 11运行eureka-server报javax.xml.bind.JAXBContext not present错

    在pom.xml加入依赖就行 <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId&g ...

  8. InnoDB锁冲突案例演示(续)

      Preface       I've demontstrated several InnoDB locking cases in my previous blog.I'm gonna do the ...

  9. tomcat部署项目,80端口被占,解决方案

    第一个解决方案: 最大的可能:被System占了. 解决Windows Server 2008 System进程占用80端口 输入netstat -ano 可以看到80端口被PID4占用,于是打开任务 ...

  10. Linux命令应用大词典-第22章 GRUB

    22.1 grub-md5-crypt:使用MD5格式加密口令 22.2 grub-install:在设备上安装GRUB 22.3 grub:进入GRUB命令shell 22.4 grub-crypt ...