中断服务函数(ISR)
今天来学习记录下中断服务函数(ISR)。关于中断,其实大家或多或少都会了解过,那么,在笔试&面试中,关于中断服务子函数,我们又需要知道那些知识点?
1.中断服务函数4大注意点
1. 中断服务函数不能有返回值;
2. 中断服务函数不能传入参数;
3. 中断服务函数要短小精悍;
4. 中断服务函数中不能使用printf等glibc函数,会带来重入性和性能问题;
解析:首先,中断源连接到硬件,由硬件来触发产生中断,即:中断源提出中断申请,而中断申请一般由硬件电路产生,申请提出时间是随机的,因此中断的产生是随机的,也就是说,中断服务函数的调用是硬件级别的。当中断产生时,pc指针强制跳转到相应的中断服务函数入口执行中断服务函数。
1)关于返回值,需要进行入栈出栈操作。由于中断是随机的,且由硬件告知,并不是由某段代码调用,所以,如果有返回值那么返回值将返回给谁?显然,这是毫无意义的!也就是说,如果中断服务函数有返回值,返回时将返回值压入栈中后,那么何时出栈、如何出栈?
2)关于传入参数,这和返回值类似,也需要入栈出栈,那么什么时候入栈,谁给它传递参数?
3)至于ISR要短小精悍就更好理解了。假设存在一个中断,其中断产生的次数较为频繁,而它对应ISR耗时较长,那么对于中断的响应就会无限的延迟,从而会错过很多中断请求;
4)关于printf函数带来的重入性和性能问题,需要了解像printf这样的glibc函数,其采用的是缓冲机制,该缓冲区域是共享的,可以理解为全局变量。当某个中断发生时,向缓冲区中写入某些内容,而恰巧此时来了一个更高级的中断,它同样调用了printf函数,也向缓冲区中写入某些内容,此时,缓冲区中的内容就混乱了。
2.中断和调用子程序的那点破事
中断和子程序的调用有一定的相似性,但是这两者的区别却又很大,这里就来掀开窗帘,看看这两个到底在搞什么破事!
2.1联系
中断和调用子程序这两个过程中,都需要保护断点(即下一条指令的地址)、跳至相应的地方去执行相应的代码、保护现场、恢复现场、恢复断点(即返回主程序);
此外,两者都可以实现嵌套。
正在执行的子程序再调用另一个子程序、正在处理的中断程序又被另一个新的中断请求所中断
2.2区别
说白了他们俩的相似性基本上是因为过程相似,从本质上讲,他们俩完全不一样。根本区别主要集中在服务时间和服务对象上。
调用子程序是程序设计者事先安排的,也就是说调用子程序过程发生的时间是已知和固定的,即在主程序中调用指令执行时发生子程序的调用,调用指令的位置是已知和固定的;而中断如先前讲述的,它是随机的,由系统工作环境随机决定。
子程序为主程序提供服务,两者属于从属关系;而中断服务程序与主程序一般无关,不存在谁为谁提供服务的说法,即两者是平行的关系;
此外,还有一些其他的区别:
主程序调用子程序的过程完全属于软件处理过程,不需要专门的硬件电路;而中断的过程软硬结合,需要专门的硬件电路才能够完成中断处理的过程;
子程序嵌套可以实现若干级,嵌套的最多级数由计算机内存开辟的堆栈大小限制;而中断嵌套的级数主要由中断优先级级数来限制,一般优先级数不会很大
3.常见题型
中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展——让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf("/nArea = %f", area);
return area;
}
这段代码基本上把上面提到的4大注意点全都无视了…>_<
第一行,传入参数了;
第二行,在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算;
第三行,使用printf()函数带来的重入性和性能问题;
第四行,ISR中不能有返回值;
整体上,ISR应该是短小精悍的,所以在ISR中做浮点运算是不明智的;
<未完,持续更新中…>