精华内容
下载资源
问答
  • 中断服务子程序

    千次阅读 2018-05-16 17:55:42
    中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准...下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_...

    中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。

    具代表事实是,产生了一个新的关键字 __interrupt。

    下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。


    __interrupt double compute_area (double radius) 
    {
        double area = PI * radius * radius;
        printf(“\nArea = %f”, area);
        return area;
    }


    这个函数有太多的错误了,以至让人不知从何说起了:

    1)  ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。

    2)  ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。

    3)  在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。

    此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。

    4) 与第三点一脉相承,printf经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

     

    不能在中断服务程序中执行类似操作的原因是运算时间太长,不能在中段中作复杂的工作,你可以在中断服务程序中置一个标志位.然后在主程序中查询此位,判断是否执行计算子程序.当然这样做会在中断产生与实际的中断响应之间产生一定的延迟,如果你的系统对时间不太敏感还好,如果非常敏感可以考虑采用rtos。否则。。。多加几句对中断标志位的判断语句。。。。

    在主程序中监测是否被置位来决定子程序是否执行.可能存在以下问题,就是,中断返回后要执行几个耗时比较长的子程序才能执行判断标志位的语句,这样,可能会有太长的时间间隔.如果你在几个耗时比较长的子程序之间加上一句判断语句,就会减小中断产生与中断响应之间的时间延迟.

     中断活动的全过程大致为:

    1、中断请求:中断事件一旦发生或者中断条件一旦构成,中断源提交“申请报告”,与请求CPU暂时放下目前的工作而转为中断源作为专项服务

    2、中断屏蔽:虽然中断源提交了“申请报告”,但是,是否得到CPU的响应,还要取决于“申请报告”是否能够通过2道或者3道“关卡”(中断屏蔽)送达CPU(相应的中断屏蔽位等于1,为关卡放行;反之相应的中断屏蔽位等于0,为关卡禁止通行);

    3、中断响应:如果一路放行,则CPU响应中断后,将被打断的工作断点记录下来(把断点地址保护到堆栈),挂起“不再受理其他申请报告牌”(清除全局中断标志位GIE=0),跳转到中断服务子程序

    4、保护现场:在处理新任务时可能破坏原有的工作现场,所以需要对工作现场和工作环境进行适当保护;

    5、调查中断源:检查“申请报告”是由哪个中断源提交的,以便作出有针对性的服务;

    6、中断处理:开始对查明的中断源进行有针对性的中断服务;

    7、清除标志:在处理完毕相应的任务之后,需要进行撤消登记(清除中断标志),以避免造成重复响应;

    8、恢复现场:恢复前面曾经被保护起来的工作现场,以便继续执行被中断的工作;

    9、中断返回:将被打断的工作断点找回来(从堆栈中恢复断点地址),并摘下“不再受理其他申请报告牌”(GIE=1),继续执行原先被打断的工作


    展开全文
  •  中断服务子程序设计的任务 中断服务子程序设计的基本任务有下列4条: (1)设置中断允许控制寄存器IE,允许相应的中断请求源中断。 (2)设置中断优先级寄存器IP,确定并分配所使用的中断源的优先级。 (3)若是外部...
  • 汇编程序 有关一个响铃程序(中断服务子程序)使用中断服务子程序
  • 中断服务子程序 ISR

    千次阅读 2017-06-06 16:28:36
    中断是嵌入式系统中重要的组成部分,这导致了很多...下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius)  {  

    中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。

    具代表事实是,产生了一个新的关键字 __interrupt。

    下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。


    __interrupt double compute_area (double radius) 
    {
        double area = PI * radius * radius;
        printf("\nArea = %f", area);
        return area;
    }


    这个函数有太多的错误了,以至让人不知从何说起了:

    1)  ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。

    2)  ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。

    3)  在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。

    此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。

    4) 与第三点一脉相承,printf经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

     

    不能在中断服务程序中执行类似操作的原因是运算时间太长,不能在中段中作复杂的工作,你可以在中断服务程序中置一个标志位.然后在主程序中查询此位,判断是否执行计算子程序.当然这样做会在中断产生与实际的中断响应之间产生一定的延迟,如果你的系统对时间不太敏感还好,如果非常敏感可以考虑采用rtos。否则。。。多加几句对中断标志位的判断语句。。。。

    在主程序中监测是否被置位来决定子程序是否执行.可能存在以下问题,就是,中断返回后要执行几个耗时比较长的子程序才能执行判断标志位的语句,这样,可能会有太长的时间间隔.如果你在几个耗时比较长的子程序之间加上一句判断语句,就会减小中断产生与中断响应之间的时间延迟.

     中断活动的全过程大致为:

    1、中断请求:中断事件一旦发生或者中断条件一旦构成,中断源提交“申请报告”,与请求CPU暂时放下目前的工作而转为中断源作为专项服务

    2、中断屏蔽:虽然中断源提交了“申请报告”,但是,是否得到CPU的响应,还要取决于“申请报告”是否能够通过2道或者3道“关卡”(中断屏蔽)送达CPU(相应的中断屏蔽位等于1,为关卡放行;反之相应的中断屏蔽位等于0,为关卡禁止通行);

    3、中断响应:如果一路放行,则CPU响应中断后,将被打断的工作断点记录下来(把断点地址保护到堆栈),挂起“不再受理其他申请报告牌”(清除全局中断标志位GIE=0),跳转到中断服务子程序

    4、保护现场:在处理新任务时可能破坏原有的工作现场,所以需要对工作现场和工作环境进行适当保护;

    5、调查中断源:检查“申请报告”是由哪个中断源提交的,以便作出有针对性的服务;

    6、中断处理:开始对查明的中断源进行有针对性的中断服务;

    7、清除标志:在处理完毕相应的任务之后,需要进行撤消登记(清除中断标志),以避免造成重复响应;

    8、恢复现场:恢复前面曾经被保护起来的工作现场,以便继续执行被中断的工作;

    9、中断返回:将被打断的工作断点找回来(从堆栈中恢复断点地址),并摘下“不再受理其他申请报告牌”(GIE=1),继续执行原先被打断的工作

    展开全文
  • 中断服务子程序(ISR)

    千次阅读 2018-09-11 20:33:36
    中断是嵌入式系统中重要的组成部分,这导致...下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius)  { double are...

    中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展-让标准C支持中断。其代表事实是,产生了一个新的关键字 __interrupt(51即如此)。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

    __interrupt double compute_area (double radius) 
    
    {
    
    double area = PI * radius * radius;
    
    printf("/nArea = %f", area);
    
    return area;
    
    }

    这个函数有太多的错误了,以至让人不知从何说起了(前提是非操作系统下的中断服务函数):

    1)ISR 不能返回一个值(都应该为void类型)。如果你不懂这个,那么你不会被雇用的。

    2)ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。

    3)在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额外的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的另外中断服务程序是运行在内核态的(linux),内核通常是不支持浮点运算的

    展开全文
  • 中断服务子程序是如何被执行的 ?

    千次阅读 2020-05-25 00:07:18
    笔者在 《程序是如何在 CPU 中运行的(二)》中从 PC 指针寄存器的角度分析了一级函数调用和二级函数调用执行的过程,那么中断服务子程序又是如何被执行的呢?两者的相同点和不同点是什么呢?该篇文章笔者将详细地阐述...

    前言

    笔者在 《程序是如何在 CPU 中运行的(二)》中从 PC 指针寄存器的角度分析了一级函数调用和二级函数调用执行的过程,那么中断服务子程序又是如何被执行的呢?两者的相同点和不同点是什么呢?该篇文章笔者将详细地阐述这个概念。

    中断的概念

    当 CPU 正在处理某件事情的时候,外部发生的某一事件请求 CPU 迅速去处理,于是,CPU 暂时中止当前的工作,转去处理所发生的事件。中断服务处理完该事件以后,再回到原来被中止的地方,继续原来的工作,这样的过程称之为中断,示意图如下:
    中断执行示意图

    中断响应及处理过程

    回顾函数调用的过程,子程序由主程序进行调用,从而完成执行。但是中断服务子程序并没有被主程序进行调用,中断服务子程序的执行是通过中断请求完成的,也就是说中断服务子程序可以发生在主程序执行的随意位置,那现在就面临一个问题了,如果当CPU 正在执行函数调用的子程序的内容的时候产生了一个中断请求,那么这个时候 CPU 将暂停执行函数调用的子程序的内容,转而去执行中断服务子程序的内容,如果不进行额外的处理,那么函数调用的子程序的相关数据将丢失,因此在执行中断服务子程序之前,CPU 必须要保存发生中断的那个地方的相关信息,这个操作用专业的术语来讲就是保护现场,保护现场之后,CPU 将执行中断服务子程序的内容,执行完中断服务子程序的内容之后,CPU 要回到刚刚暂停的地方继续执行,另外在返回之前,CPU 还要进行恢复现场,恢复现场之后,就可以返回到暂停的地方继续执行了,下面是整个过程的示意图:
    中断响应示意图
    通过上述示意图我们也可以看到在返回地址这个地方,中断服务子程序和函数调用子程序的返回地址所遵循的原理是一样的,函数调用子程序的返回地址是函数调用指令的下一条指令的地址,而在上述示意图中的 N 和 N+1 的含义也是类似的,当 CPU 执行到第 N 条指令的时候,CPU 接收到了一个中断请求,在执行完第 N 条指令之后,转而去执行中断服务子程序的内容,然后中断服务子程序的返回地址对应的是第 N+1 条指令的地址。

    中断的堆栈占用

    在刚刚所述的内容中,说到 CPU 在执行中断服务子程序的内容之前,需要保护现场,那保护现场这个操作具体是怎么实现的呢?这个时候,就要用到我们的堆栈了。在这里拿 ARM Cortex M3 举例,在响应中断时所做的第一个操作就是保护现场,它会依次把 xPSR,PC,LR,R12以及 R3-R0 由硬件自动压入适当的堆栈中,注意,这里是自动压入堆栈,也就是说如果我们看对应的汇编代码是看不到这部分压栈操作的。另外,我们知道对于 ARM Cortex M3 的堆栈来说,它存在两个,一个是主堆栈指针(MSP),一个是线程堆栈指针(PSP),其中主堆栈指针是复位后默认使用的堆栈指针,用于操作系统内核和中断处理程序,线程堆栈指针(PSP)是由用户的应用程序代码所使用。那么在执行现场保护时将相关寄存器的值压入堆栈,应该使用哪个堆栈指针呢?这也是存在一个原则的,如果在响应中断时,当前的代码正在使用线程堆栈指针(PSP),那么将使用线程堆栈指针(PSP)进行压栈,否则将使用主堆栈指针(MSP)。另外在 CPU 进入中断服务子程序之后,所涉及的堆栈操作所使用的堆栈一直是主堆栈指针(MSP)。为了更直观的展示这个过程,下图是发生中断请求后,堆栈的变化示意图:
    中断堆栈调用示意图
    通过上图我们可以很清楚地看到在响应中断时产生的保护现场操作,堆栈明显增长了,而在执行完中断服务子程序的内容之后,又将执行恢复现场的操作,这个时候堆栈的内容又减少了。
    为了更清楚地展示压入堆栈寄存器的操作,笔者在这里也给出上述图中堆栈粉色部分的详细内容,图片如下:
    保护现场堆栈内容
    上述就是保护现场时所压入堆栈的相关寄存器,另外还需注意的一点是当所涉及的中断服务子程序逻辑比较复杂的时候,就需要更多的寄存器了,这个时候就需要用到 R4-R11 了,但是这部分寄存器是不能进行自动压栈的,也就是说如果在中断服务子程序中使用到这部分寄存器的时候就需要进行手动压栈,那么这部分的压栈操作在汇编层面就能看到了。

    中断向量表

    在上述所阐述的内容中,我们知道了中断会在主程序的任意发生中断请求,从而执行中断服务子程序的内容,也阐述了在执行中断服务子程序的内容之前需要进行保护现场的操作,以及执行完中断服务子程序的内容之后需要进行恢复现场。现在我们再来思考,在 CPU 中,中断源不止一种,可以是按键按下所触发的一个外部中断,也可能是在使用串行通信时,收到数据所触发的一个中断,亦或者在 CPU 中定义的一个定时中断由于设置的时间到了而触发的定时中断,这个时候,就浮现一个问题了,要如何将这一个一个的中断源与其各自的中断服务子程序所一一对应起来呢?换句更为通俗的话来讲就是当 CPU 接收到一个中断信号时,CPU 将如何找到对应的中断服务子程序进行执行呢?这个时候,就需要中断向量表了,下面是中断向量表的特点:

    • 中断向量表在 CPU 中是一段连续的存储空间
    • 中断向量表在 CPU 复位后有默认的起始地址
    • 每一个中断在中断向量表中都有对应的表项,该表项的值为该中断源对应的中断服务程序的地址
    • 由程序代码确定中断向量表中的每个表项

    上述特点说中断向量表都存在默认的起始地址,在这里依旧拿 ARM Cortex M3 内核来看,它的中断向量表默认的起始地址是从地址 0x0000 0000 开始的,如下图所示:
    中断向量表
    当然这只是一部分,并不是全部的表项。有了中断向量表之后,那么当 CPU 接收到中断请求的时候,就会根据这个中断请求的信号去查这个表,从而查找到其所对应的中断服务子程序的地址,然后将这个地址赋值给 PC 指针寄存器就,那么 CPU 就可以完成中断服务子程序的执行了,对于 PC 指针寄存器不是太清楚地朋友可以看笔者的这篇文章 《程序是如何在 CPU 中运行的(二)》

    中断服务函数的写法

    中断服务函数的写法不同的 CPU 有各自不同的写法,对于 ARM Cortex M3 的 CPU 来说,因为其内核的特点,在执行完中断服务函数后的返回指令与普通函数调用的返回指令是一样的,因此中断服务函数的写法与 C 语言中普通函数的定义没有区别,比如下面是 STM32F103 的一个外部中断的服务函数

    void EXTI0_IRQHandler(void)
    {
    	/* 确保是否产生了中断 */
    	if(EXTI_GetITStatus(EXTI_Line0) != RESET) 
    	{	
    		/*用户代码*/
    		/*清除中断标志位*/
    		EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);     
    	}  
    }
    

    通过上述的代码我们可以看到中断服务函数的另一个特点,就是它的返回值和形参都为 void ,这也是由原因的,因为中断服务函数本来就不是由主程序进行调用的,既然中断服务函数不会被其他函数所调用,那么其返回值和形参自然是 void 了。
    上述说到是因为 ARM Cortex M3 的 CPU 在处理中断服务函数的返回地址时用的指令和普通函数调用时的返回地址的指令一致,所以才能够使中断服务函数的写法与普通 C 语言函数没有差异,下面举一个 51 单片机的定时器中断服务函数的例子:

    void InterruptTimer0() interrupt 1
    {
        /*省略*/
    }
    

    上述的这个中断服务函数, InterruptTimer0可以任意起,但是括号后面的是有严格规定的,为了 51 单片机能够进行中断处理,C51 编译器对函数进行了扩展,增加了一个扩展关键字interrupt,从而让 CPU 知道这个是一个中断服务函数。

    中断的嵌套

    C 语言函数能够进行嵌套调用,同样的中断服务函数也能够进行嵌套,同样的用一张图来表明中断的嵌套:
    中断嵌套示意图
    可以看到中断的嵌套也是在消耗堆栈的,和使用函数嵌套调用一个道理,这里需要注意的是中断是存在优先级的,如果发生了一个比当前执行的中断优先级低的中断请求,那么新产生的中断请求会等待正在执行的中断执行完成之后才开始响应新的中断,如果产生的中断的优先级比当前的优先级要高,那么也就会像上图所示一样进行执行。另外需要注意的是,中断的优先级是有限的,也就是说中断嵌套的层数是有限的,如果再考虑堆栈溢出的话,那么中断嵌套的层数还和堆栈的大小有关。

    总结

    上述就是关于中断的相关内容,简单地叙述了中断是如何响应的,如何执行保护现场和恢复现场的操作,CPU 如何根据中断向量表找到对应的中断服务函数,以及中断的嵌套,这就是这次分享的全部内容啦~

    展开全文
  • 请看下面的程序(一个中断服务子程序ISR),请指出这段代码的错误。)[中国台湾某著名CPU生产公司2005年面试题] 答案:(1)ISR不能返回一个值。如果你不懂这个,那么是不会被雇用的。(2)ISR不能传递参数。...
  • 嵌入式 中断服务子程序注意事情

    千次阅读 2014-09-23 17:16:45
    中断是嵌入式系统中重要的组成部分,这导致了很多...下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius)  {  
  • 中断服务子程序(ISR)

    千次阅读 2014-06-08 18:30:25
    中断是嵌入式系统中重要的组成部分,这导致了很多...下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius)  {  
  • 中断是嵌入式系统中重要的组成部分,这...下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius) { double area = P
  • 嵌入式系统中断服务子程序(ISR)

    千次阅读 2013-04-12 13:33:41
    中断是嵌入式系统中重要的组成部分,这...下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。 __interrupt double compute_area (double radius) { double area = P
  • 串口中断服务程序及相关寄存器设置,相关的说明见程序注释
  • 微机原理中关于中断服务的机器代码,适用于8051的单片机,别的单片机没有试过。
  • 中断服务子程序是不是就是驱动程序? 进程向CPU发出中断请求-》保存CPU环境-》转到中断服务子程序 这里的中断服务子程序是驱动程序吗?还是中断服务子程序会调用驱动程序?求大神?
  • ISR 中断服务子程序的几个特点

    千次阅读 2014-02-14 12:53:12
    中断是嵌入式系统中重要组成部分,很多编译器开发商都让标准c支持中断,并引入关键字_interrupt.但是 ISR不能有返回值;ISR不能传递参数;ISR应该是短而高效的,在ISR中做浮点运算是不明智的;ISR中不应该有...
  • 我现在接触的3份J1939的代码例程中,有一份是使用POLL模式,而最近的两份代码则是使用的中断模式。虽然,大概的功能已经分析过了,但是中断ISR还是没有看过究竟是如何用的。而这部分应该是这份代码在不同平台上移植...
  • __interruptdoublecompute_area(doubleradius) { doublearea=PI*radius*radius; printf("\nArea=%f",area); returnarea; } 答:这个函数有如下的错误: 1) ISR不能返回一个值。...3)在许多的处理器/编译...
  • 中断服务程序与普通子程序有什么根本的区别? 答:中断服务程序是随机发生的,结束后要返回断点。普通子程序是安排好的,没有断点。
  • 1.实现子程序和中断服务子程序的设计 2.编写子程序设置40H中断为自定义中断服务子程序 3.编写中断服务子程序实现AX=AX+BX 4.编写主程序调用子程序和中断

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,135
精华内容 454
关键字:

中断服务子程序