【总结】中断

来源:互联网 发布:js中的保留字有哪些 编辑:程序博客网 时间:2024/04/29 04:49

Long long time ago...

 

中断出现以前,程序是顺序执行的,CPU按照预设的指令顺序(程序),顺序执行。不久,系统中除了CPU外,又增加了许多外部设备,像定时器啊,串口啊,这些外设IO的访问速度很慢,通常为毫秒级,而CPU指令执行速度是纳秒级,矛盾就这样产生了。。。

例如,CPU操作串口,把RAM中的数据通过串口设备发送出去,CPURAM中取一帧数据,发送给串口,然后就等待串口发送完成,其实是轮询(Poll)查看串口寄存器标志位,无法执行其他指令,浪费了大量CPU时间。

 

中断之后的故事

 

有了中断之后,CPU访问外设,就变得很“聪明”了,CPU向外设发送执行命令后,不再等待,立即返回,执行其他的指令,而外设接收到指令后,开始默默的干活。此时,CPU和外设是同时工作的,也就是异步方式。外设执行完相应工作后,会向CPU发送一个“中断”,中断CPU当前执行的指令,立即去响应该中断事件,即执行中断服务程序ISRInterrupt Service Routine),CPU执行完ISR后,从刚刚被中断的位置继续向下执行指令。

 

中断分类

 

从不同角度,可以有不同的分类方法。

 

内部中断和外部中断

根据中断的不同来源,可以分为内部中断和外部中断。

“内部”和“外部”都是相对CPU而言的。外设中断,都是外部中断;CPU执行中断指令(8086INT指令)属于内部中断。

 

软件中断和硬件中断

由外设产生的中断,叫做硬件中断。CPU执行指令产生的中断,叫做软件中断,如中断指令INT,异常指令(除数为0),非法指令,访问非法内存等。

 

向量中断和非向量中断

向量中断由硬件提供ISR入口地址,很多架构CPU提供中断向量表,用户只要实现中断向量表中对应的ISR即可;

非向量中断由软件提供ISR入口地址;

 

可屏蔽中断和非可屏蔽(NMI)中断

中断被屏蔽后,即使发生中断,CPU也不会做出任何响应。

通常都会有对应的Mask寄存器,对不同的中断,设置不同的屏蔽位。



中断优先级

 

不同的芯片,有不同的优先级规则。通常由芯片内部的优先级控制器(Priority controller)控制优先级的执行顺序。优先级越高,优先执行。

当正在执行中断服务程序时,又发生了中断,需要中断优先级去控制。有些时候,为了防止这种冲突,在执行某个中断服务程序时,先关闭所有中断,执行完ISR后,再开启所有中断。这种做法是否合适,是依赖你的系统的。


中断服务程序(ISR

 

中断是嵌入式系统中重要的组成部分,但是标准C中不包含中断。许多编译开发商在标准C上增加了

对中断的支持,提供新的关键字用于表示中断服务程序(ISR),类似于__interrupt,#program interrupt等。

当一个函数被定义为ISR的时候,编译器会自动为该函数增加中断服务程序所需要的中断现场入栈和出栈代码

 

ISR要求

1)不能返回值

2)不能像ISR传递参数

3ISR应尽可能的短小精悍

4printf函数会带来重入和性能问题,不能在ISR中使用


从产生中断,到CPU执行相应ISR的第一条语句,是需要消耗一定的时间的,因为中断要打断CPU正常的执行顺序,为了能够处理完中断后,继续正常执行,CPU需要保护现场,即保存PSWPC指针,通常为几个到十几个机器周期不等。当CPU正在执行RET指令时发生中断,需要更长保护现场时间。下面是7780k0R芯片中断时间9~14clock

 


 

 

实例分析

 

以瑞萨7780K0R系列芯片的优先级为例,对上述概念具体解释。7780K0R芯片是一款单片机级别的微控制器。

根据芯片手册,中断源定义如下:


 


 




由上表可知,7780K0R提供两类中断:可屏蔽中断和软中断(指令BRK),全部为向量中断。

42个中断源

外部中断13个,内部中断28个,只有IO管脚的几个中断为外部中断,像定时器,USART等都为内部中断;

0~40均为可屏蔽中断,另外提供软中断指令(BRK)以及四个Reset中断类型(软中断)

0~40个优先级,0优先级最高

4个配置种类,basic cnfiguration A~D,不同的类型,有不同的硬件结构,如,AB硬件结构






timer0的驱动程序如下


void timer0_isr(void)

{

//do something, like clearing some register

TDR00 = 0x3000;

}

 

void timer0_init(void)

{

/* Mask channel 0 interrupt */

TMMK00 = 1;

TMIF00 = 0;

 

/* 10ms */

TDR00 = 0x3000;

 

/* INTTM00 priority  */

TMPR000 = 0;

TMPR100 = 1;

}

 

void timer0_start(void)

{

//do something

}

 

void timer0_stop(void)

{

//do something

}


对于寄存器的配置,必须参考芯片的手册。


参考

中断相关的知识

ARM92410移植之ARM中断原理

嵌入式操作系统内核原理和开发

C语言嵌入式系统编程修炼之道

0 0