中断使能

中断使能的情况下:中断产生---->中断标志位被mcu置1---->mcu暂停主程序去执行中断程序(别忘记清中断)—>返回主程序

不要陷入误区:
并不是说不使能串口接受中断就无法接收数据,只是为了在串口接收数据的时候防止其程序打扰串口数据的接收,所以跑到中断中去接收数据。
不使用串口接收中断的情况下,数据会到DR,然后你及时把DR的数据读出来,不然下次接收数据就会把上次数据覆盖。
控制好串口数据接收的那几个寄存器(SR和DR),不是用串口接收中断,也可以接受据。

使能中断却没有写对应的中断函数所带来的问题

编程时时刻谨记一点用不到的中断一定不要开,经验表明:使能中断却没有写对应的中断响应函数所带来的问题是不可知的(如跑飞各种奇怪现象)

中断标志位不清除的后果–知道它的原理就能推出它的后果

中断标志位不清除, 结果是完成中断处理程序后, 它就继续再进中断, 根本不会回到主程序。

响应中断条件是:中断使能和中断标志同时成立时.
一般来讲,响应中断后,有硬件清标志和软件清标志两种.(如果硬件不能清标志,说明书会说明).

单片机要靠查询中断标志来判断是否要进入中断,如果你不清除中断标志,本次中断退出,单片机又会检测到中断标志,因此重复进入中断。

中断挂起
如果中断发生时,正在处理同级或高优先级异常,或者被掩蔽,则中断不能立即得到响应,此时中断被悬起。悬挂意味着等待而不是舍去,当优先级高的或者同等级先发生的中断完成后,被挂起的中断才会执行。中断的悬起状态可以通过“中断设置悬起寄存器(SETPEND)”和“中断悬起清除寄存器(CLRPEND)”来读取,还可以写它们来手工悬起中断。

中断标志
当进入中断后,中断标志位会自动被置1,代表着“正在执行中断服务函数中”。当我们结束终端服务函数之前,一定要在函数中清除中断标志位。我们可以这样理解:中断标志位是满足中断条件的象征,当我们配置好中断发生的条件,一旦遇到中断标志位有效,就说明该执行中断服务函数了。如果我们不手动的清除中断标志位,那么系统会默认中断条件一直满足那就会一直执行中断服务函数跳不出来了。

中断

中断即打断,实至CPU再执行当前程序时,由于系统出现了某种需要处理的紧急情况,CPU暂停正在执行的程序,转而去执行另一段特殊程序来处理的出现的紧急事务,处理结束后CPU自动返回到原先暂停的程序中去继续执行,这种执行过程由于外界的的原因被中间打断的情况成为中断。
中断的作用:
中断使得计算机系统具备应对对处理突发事件的能力,提高了CPU的工作效率,如果没有中断系统,CPU就只能按照原来的程序编写的先后顺序,对各个外设进行查询和处理,即轮询工作方式,轮询方法貌似公平,但实际工作效率却很低,却不能及时响应紧急事件。

中断装置和中断处理程序统称为中断系统。

中断系统是计算机的重要组成部分。实时控制、故障自动处理、计算机与外围设备间的数据传送往往采用中断系统。中断系统的应用大大提高了计算机效率。

不同的计算机其硬件结构和软件指令是不完全相同的,因此,中断系统也是不相同的。计算机的中断系统能够加强CPU对多任务事件的处理能力。中断机制是现代计算机系统中的基础设施之一,它在系统中起着通信网络作用,以协调系统对各种外部事件的响应和处理。中断是实现多道程序设计的必要条件。 中断是CPU对系统发生的某个事件作出的一种反应。 引起中断的事件称为中断源。中断源向CPU提出处理的请求称为中断请求。发生中断时被打断程序的暂停点成为断点。CPU暂停现行程序而转为响应中断请求的过程称为中断响应。处理中断源的程序称为中断处理程序。CPU执行有关的中断处理程序称为中断处理。而返回断点的过程称为中断返回。中断的实现实行软件和硬件综合完成,硬件部分叫做硬件装置,软件部分成为软件处理程序

中断系统的功能

1)实现中断响应和中断返回
当CPU收到中断请求后,能根据具体情况决定是否响应中断,如果CPU没有更急、更重要的工作,则在执行完当前指令后响应这一中断请求。CPU中断响应过程如下:首先,将断点处的PC值(即下一条应执行指令的地址)推入堆栈保留下来,这称为保护断点,由硬件自动执行。然后,将有关的寄存器内容和标志位状态推入堆栈保留下来,这称为保护现场,由用户自己编程完成。保护断点和现场后即可执行中断服务程序,执行完毕,CPU由中断服务程序返回主程序,中断返回过程如下:首先恢复原保留寄存器的内容和标志位的状态,这称为恢复现场,由用户编程完成。然后,再加返回指令RETI,RETI指令的功能是恢复PC值,使CPU返回断点,这称为恢复断点。恢复现场和断点后,CPU将继续执行原主程序,中断响应过程到此为止。

2)实现优先权排队
通常,系统中有多个中断源,当有多个中断源同时发出中断请求时,要求计算机能确定哪个中断更紧迫,以便首先响应。为此,计算机给每个中断源规定了优先级别,称为优先权。这样,当多个中断源同时发出中断请求时,优先权高的中断能先被响应,只有优先权高的中断处理结束后才能响应优先权低的中断。计算机按中断源优先权高低逐次响应的过程称优先权排队,这个过程可通过硬件电路来实现,亦可通过软件查询来实现。

3)实现中断嵌套
当CPU响应某一中断时,若有优先权高的中断源发出中断请求,则CPU能中断正在进行的中断服务程序,并保留这个程序的断点(类似于子程序嵌套),响应高级中断,高级中断处理结束以后,再继续进行被中断的中断服务程序,这个过程称为中断嵌套。如果发出新的中断请求的中断源的优先权级别与正在处理的中断源同级或更低时,CPU不会响应这个中断请求,直至正在处理的中断服务程序执行完以后才能去处理新的中断请求。

中断、异常和系统调用

所谓中断是指CPU对系统发生的某个事件做出的一种反应,CPU暂停正在执行的程序,保留现场后自动地转去执行相应的处理程序,处理完该事件后再返回断点继续执行被“打断”的程序。

中断可分为三类:
第一类是由CPU外部引起的,称作中断,如I/O中断、时钟中断、控制台中断等。
第二类是来自CPU的内部事件或程序执行中的事件引起的过程,称作异常,如由于CPU本身故障(电源电压低于105V或频率在47~63Hz之外)、程序故障(非法操作码、地址越界、浮点溢出等)等引起的过程。
第三类由于在程序中使用了请求系统服务的系统调用而引发的过程,称作**“陷入”(trap,或者陷阱)**。前两类通常都称作中断,它们的产生往往是无意、被动的,而陷入是有意和主动的。

1.中断处理

中断处理一般分为中断响应和中断处理两个步骤。中断响应由硬件实施,中断处理主要由软件实施。

(1)中断响应

对中断请求的整个处理过程是由硬件和软件结合起来而形成的一套中断机构实施的。发生中断时,CPU暂停执行当前的程序,而转去处理中断。这个由硬件对中断请求作出反应的过程,称为中断响应。一般说来,中断响应顺序执行下述三步动作:

◆中止当前程序的执行;

◆保存原程序的断点信息(主要是程序计数器PC和程序状态寄存器PS的内容);

◆从中断控制器取出中断向量,转到相应的处理程序。

通常CPU在执行完一条指令后,立即检查有无中断请求,如果有,则立即做出响应。

当发生中断时,系统作出响应,不管它们是来自硬件(如来自时钟或者外部设备)、程序性中断(执行指令导致“软件中断”—Software Interrupts),或者来自意外事件(如访问页面不在内存)。

如果当前CPU的执行优先级低于中断的优先级,那么它就中止对当前程序下条指令的执行,接受该中断,并提升处理机的执行级别(一般与中断优先级相同),以便在CPU处理当前中断时,能屏蔽其它同级的或低级的中断,然后保存断点现场信息,通过取得的中断向量转到相应的中断处理程序的入口。

(2)中断处理

CPU从中断控制器取得中断向量,然后根据具体的中断向量从中断向量表IDT中找到相应的表项,该表项应是一个中断门。于是,CPU就根据中断门的设置而到达了该通道的总服务程序的入口。

核心对中断处理的顺序主要由以下动作完成:

◆保存正在运行进程的各寄存器的内容,把它们放入核心栈的新帧面中。

◆确定“中断源”或核查中断发生,识别中断的类型(如时钟中断或盘中断)和中断的设备号(如哪个磁盘引起的中断)。系统接到中断后,就从机器那里得到一个中断号,它是检索中断向量表的位移。中断向量因机器而异,但通常都包括相应中断处理程序入口地址和中断处理时处理机的状态字。

◆核心调用中断处理程序,对中断进行处理。

◆中断处理完成并返回。中断处理程序执行完以后,核心便执行与机器相关的特定指令序列,恢复中断时寄存器内容和执行核心栈退栈,进程回到用户态。如果设置了重调度标志,则在本进程返回到用户态时做进程调度。

2.系统调用

在Unix/Linux系统中,系统调用像普通C函数调用那样出现在C程序中。但是一般的函数调用序列并不能把进程的状态从用户态变为核心态,而系统调用却可以做到。

C语言编译程序利用一个预先确定的函数库(一般称为C库),其中有各系统调用的名字。C库中的函数都专门使用一条指令,把进程的运行状态改为核心态。Linux的系统调用是通过中断指令“INT 0x80”实现的。

每个系统调用都有惟一的号码,称作系统调用号。所有的系统调用都集中在系统调用入口表中统一管理。

系统调用入口表是一个函数指针数组,以系统调用号为下标在该数组中找到相应的函数指针,进而就能确定用户使用的是哪一个系统调用。不同系统中系统调用的个数是不同的,目前Linux系统中共定义了221个系统调用。

另外,系统调用表中还留有一些余项,可供用户自行添加。

当CPU执行到中断指令“INT 0x80”时,硬件就做出一系列响应,其动作与上述的中断响应相同。CPU穿过陷阱门,从用户空间进入系统空间。相应地,进程的上下文从用户堆栈切换到系统堆栈。

接着运行内核函数system_call()。首先,进一步保存各寄存器的内容;接着调用syscall_trace( ),以系统调用号为下标检索系统调用入口表sys_call_table,从中找到相应的函数;然后转去执行该函数,完成具体的服务。

执行完服务程序,核心检查是否发生错误,并作相应处理。如果本进程收到信号,则对信号作相应处理。最后进程从系统空间返回到用户空间。

上面两讲简要介绍了Linux内核的主要数据结构和相应的算法。Linux内核包含了丰富的内容,这里仅是其中的一点点,以求起到“抛砖引玉”的作用。

关于PendSV异常和SVC异常

SVC:系统服务异常。用户级想操作一些特权级的操作,是不可行的。假如修改底层寄存器的值是特权级操作,用户想修改底层的寄存器怎么办呢?方法就是用这个SVC 异常。OS会提供一些系统服务函数,用户调用这些服务函数,OS会发出SVC异常,从而进入异常服务函数里面, 再调用相关函数对寄存器进行 修改。如下图。

在这里插入图片描述
在这里插入图片描述

PendSv:可悬挂异常。如果当前没有更高优先级的异常或者中断需要执行,那么就执行pendsv的异常服务函数。 可以看出它有个特点,就是 缓期执行。cpu先执行比它高的服务函数,然后在执行它,

OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动 作。悬起 PendSV 的方法是:手工往 NVIC的 PendSV悬起寄存器中写 1。悬起后,如果优先级不够 高,则将缓期等待执行。

FreeRTOS就是利用了这个特性,来显示 任务切换的。请看下面systick异常中断服务函数的内容

void xPortSysTickHandler( void )
{
	vPortRaiseBASEPRI();
	{
		/* Increment the RTOS tick. */
		if( xTaskIncrementTick() != pdFALSE )
		{
			/* A context switch is required.  Context switching is performed in
			the PendSV interrupt.  Pend the PendSV interrupt. */
			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
		}
	}
	vPortClearBASEPRIFromISR();
}

vPortRaiseBASEPRI();设置basepri寄存器,开启中断屏蔽作用,这里是大于等于5的优先级异常和中断都将被屏蔽。

portNVIC_INT_CTRL_REG=portNVIC_PENDSVSET_BIT;//就是悬起PendSv。

然后清除中断屏蔽 中断位,退出systick服务函数。

FreeRTOS为什么要这样延后切换, 而不是直接进行任务切换呢?因为任务切换的时间 开销较大,这样会导致其他中断迟迟不能执行。

原文链接:https://blog.csdn.net/tangjienihaoma/article/details/81672180

在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐