原创 ARM中断嵌套

2012-8-10 13:42 3618 19 28 分类: 消费电子

作者:下家山(请尊重原创,转载请注明:上海索漫科技培训教材http://www.xiajiashan.com )

我们这里以LPC2136为例。

         Lpc2136中有22个中断源,中断控制器提供了16个向量IRQ控制器,分别可以设置16个中断优先级!

         其实,要真正体现中断优先级(当低优先级中断服务程序正在执行时,高优先级中断事件到来了,先执行高优先级中断服务程序代码,即高优先级中断会中断低优先级中断服务程序),必须实现中断嵌套!

         很多裸奔的arm7或者arm9产品,并没有做中断嵌套,这种产品存在着隐患,而这种隐患常让工程师(开发或维护)无法解释!所以,就出现了,客户把有问题的产品拿到原厂,原厂却说在他哪里是好的,并且当场测试却怎么也测试不出来!

==================================================

假设,我们这里有两个外部中断

EINT1==KEY1===P0.3和EINT3===KEY3====P0.30

而且,我们这里EINT3的中断优先级高于EINT1

当EINT1正在执行的时候,EINT3来了,按照惯例,EINT1会停下来,去执行EINT3的中断,等EINT3的中断服务程序执行完毕,再回头执行EINT1的服务程序。如果我们不用中断嵌套,事情并非如此。

下面是实验代码:

#define KEY1  1<<3

#define KEY3  1<<30

#define LED1  1<<16

#define EINT1_NUM  15

#define EINT3_NUM  17

#define P03_FUN_EINT1  3<<6

#define P030_FUN_EINT3  2<<28

#define EINT1_ENABLE  1<<15

#define EINT3_ENABLE  1<<17

 

/******************************************

【By 下家山 Q群 75303301        上海松江文汇路928号258室    松江大学城

上海索漫科技  http://www.xiajiashan.com  专注嵌入式(ARM7,Cortex-M0,Cortex-M3,ARM9,linux)培训】***********/

void __irq IRQ_Eint3(void)

{  

while(1)

{

                IO0SET = BEEPCON;

}

EXTINT = 1<<3; // 清除EINT3中断标志,

VICVectAddr=0x00;                         // 清除中断逻辑,

}

/*===============================================*/

void __irq IRQ_Eint1(void)

         

while(1){

                 IO1CLR = LED1;

}

EXTINT = 1<<1; // 清除EINT3中断标志,

VICVectAddr=0x00;                         // 清除中断逻辑

}

/*************************************************************/

void Init_EXT(void)

{

PINSEL0 = P03_FUN_EINT1 | P030_FUN_EINT3; // 设置管脚连接,P0.3设置为EINT1, P0.30设置为EINT3

EXTMODE  |=  1<<3; // 设置EINT3中断为边沿触发模式

EXTPOLAR  &=  ~(1<<3);// 设置EINT3中断为上升沿触发模式

EXTMODE  |=  1<<1; // 设置EINT1中断为边沿触发模式

EXTPOLAR  &=  ~(1<<1);// 设置EINT1中断为上升沿触发模式

EXTINT  =  0xF;

 

VICIntSelect = 0x00; // 所有中断通道设置为IRQ中断

 

VICVectAddr0 = (uint32)IRQ_Eint3; // 设置中断服务程序地址向量

VICVectCntl0 =  0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)

VICVectAddr1 = (uint32)IRQ_Eint1; // 设置中断服务程序地址向量

VICVectCntl1 = 0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)

VICIntEnable  =  EINT1_ENABLE  |  EINT3_ENABLE; // 使能EINT1&EINT3中断,EINT3在Bit17,EINT1在bit15上

}

=======================================================================================

By 下家山 Q群 75303301        上海松江文汇路928号258室    松江大学城   

上海索漫科技  http://www.xiajiashan.com  专注嵌入式(ARM7,Cortex-M0,Cortex-M3,ARM9,linux)培训 /*************************************/

void BEEFON(void)

{

IO0SET =BEEPCON;

}

/*************************************/

void BEEFOFF(void)

{

IO0CLR =BEEPCON;

}

/*************************************/

void init_system()

{

 IO0CLR = BEEPCON;

IO0DIR = BEEPCON;

IO1SET =  LED1;

IO1DIR = LED1 ;

}

/*************************************/

int main (void)

{

init_system();

Init_EINT();

while(1);

return 0;

}

上述程序执行结果是,我们先按下KEY1,LED1会亮,当我们再按下KEY3时,蜂鸣器并不会响。

=========================================================================================================================================================改成中断嵌套=======================================================================================================================================================================

#define KEY1  1<<3

#define KEY3  1<<30

#define LED1  1<<16

#define EINT1_NUM  15

#define EINT3_NUM  17

#define P03_FUN_EINT1  3<<6

#define P030_FUN_EINT3  2<<28

#define EINT1_ENABLE  1<<15

#define EINT3_ENABLE  1<<17

 

/*************************************/

__inline void enable_IRQ(void)

{

  int tmp;

  __asm

  {

    MRS tmp, CPSR

    BIC tmp, tmp, #0x80

    MSR CPSR_c, tmp

  }

}

/*************************************/

/*****************************************************/

void __irq IRQ_Eint3(void)

{  

    uint32 vic_enable_bak;

    vic_enable_bak = VICIntEnable;

    VICIntEnClr = (EINT3_ENABLE) | (EINT1_ENABLE); //清除自己及比自己优先级更低的中断,以便更高优先级中断响应

                   VICVectAddr=0x00;                         // 清除中断逻辑,

while(1)

{

                IO0SET = BEEPCON;

}

EXTINT = 1<<3; // 清除EINT3中断标志,

VICIntEnable =   vic_enable_bak;//恢复中断

}

=======================================================================================

By 下家山 Q群 75303301        上海松江文汇路928号258室    松江大学城   

上海索漫科技  http://www.xiajiashan.com  专注嵌入式(ARM7,Cortex-M0,Cortex-M3,ARM9,linux)培训 /*===============================================*/

void __irq IRQ_Eint1(void)

   uint32 vic_enable_bak;

   vic_enable_bak = VICIntEnable;

   VICIntEnClr =  EINT1_ENABLE;//清除自己以便更高优先级中断响应

   VICVectAddr=0x00;     // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断

 

    enable_IRQ();

while(1){//一般不会在中断服务程序里面做死循环,但为了更好说明问题使然。

                 IO1CLR = LED1;

}

EXTINT = 1<<1; // 清除EINT3中断标志,

VICIntEnable =   vic_enable_bak; //恢复中断

}

/*************************************************************/

void Init_EXT(void)

{

PINSEL0 = P03_FUN_EINT1 | P030_FUN_EINT3; // 设置管脚连接,P0.3设置为EINT1, P0.30设置为EINT3

EXTMODE  |=  1<<3; // 设置EINT3中断为边沿触发模式

EXTPOLAR  &=  ~(1<<3);// 设置EINT3中断为上升沿触发模式

EXTMODE  |=  1<<1; // 设置EINT1中断为边沿触发模式

EXTPOLAR  &=  ~(1<<1);// 设置EINT1中断为上升沿触发模式

EXTINT  =  0xF;

 

VICIntSelect = 0x00; // 所有中断通道设置为IRQ中断

 

VICVectAddr0 = (uint32)IRQ_Eint3; // 设置中断服务程序地址向量

VICVectCntl0 =  0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)

VICVectAddr1 = (uint32)IRQ_Eint1; // 设置中断服务程序地址向量

VICVectCntl1 = 0x20 | EINT1_NUM; // 定时器中断通道分配最高优先级(向量控制器)

VICIntEnable  =  EINT1_ENABLE  |  EINT3_ENABLE; // 使能EINT1&EINT3中断,EINT3在Bit17,EINT1在bit15上

}

/*************************************/

void BEEFON(void)

{

IO0SET =BEEPCON;

}

/*************************************/

void BEEFOFF(void)

{

IO0CLR =BEEPCON;

}

/*************************************/

void init_system()

{

 IO0CLR = BEEPCON;

IO0DIR = BEEPCON;

IO1SET =  LED1;

IO1DIR = LED1 ;

}

/*************************************/

int main (void)

{

init_system();

Init_EINT();

while(1);

return 0;

}

上述程序执行结果是,我们先按下KEY1,LED1会亮,当我们再按下KEY3时,即使EINT1中断进入了死循环,因为正确设置了中断嵌套,EINT3可以中断EINT1的服务程序运行自己的中断服务程序,蜂鸣器会响。

 写于上海松江

作者:下家山(请尊重原创, 转载请注明)  http://www.xiajiashan.com,有什么问题可与我联系:ximenpiaoxue4016@sina.com

文章评论9条评论)

登录后参与讨论

用户1454308 2016-3-25 11:51

Good

用户1678053 2016-3-25 09:07

看看

franky_kin_226593135 2016-3-25 08:59

thank you very much

自做自受 2012-11-13 21:05

是啊,现在有很多,太多太多可以利用的闲置和废弃的电子消费品,比如笔记本电脑、手机等等,整机或部件都可以再利用,尤其是适用于DIY,博主有何高见和应用实例,欢迎介绍介绍。

用户1602177 2012-10-11 15:49

博主的修行现在是什么状态呢?更新一下吧~~

用户1663059 2012-10-6 19:42

so good

allen_zhan_752827529 2012-2-13 18:25

随意说说, 其实我更担心中断嵌套, 会造成未知的bug产生, 因为系统处理逻辑开始复杂化, 要考虑的任务更多了. 当然可能有很多系统不得不这样做...想想看, 中断的中断, 听听就头大``` 不过无论如何, 这样的讨论是非常有益的.

用户1075677 2011-10-24 10:51

不錯的經驗分享; 頂!

用户1624253 2011-10-21 10:51

不错,谢谢楼主分享

用户1625603 2011-10-18 18:22

多谢楼主 分享经验
相关推荐阅读
用户1037328 2016-04-17 17:59
好的理论可以避免犯错——读《丈量世界》有感!
     《丈量世界》,早就因为仰慕高斯而想看这本书      1.殊途同归      这本书写的是高斯和洪堡两个人,为什么要把这两个人放在一起写呢?因为高斯是一个宅男,不喜欢什么旅游,考察!他觉得...
用户1037328 2016-04-05 09:10
叛逆在爱因斯坦性格中的重要性(一)
叛逆在爱因斯坦性格中的重要性(一) 《爱因斯坦传》读书笔记      昨天晚上,读完了2016年书单的第二部书,《爱因斯坦传》。我想梳理一下自己读这本书的收获,或者说感悟!在读这...
用户1037328 2016-04-05 09:09
叛逆在爱因斯坦性格中的重要性(二)
叛逆在爱因斯坦性格中的重要性(二) 《爱因斯坦传》读书笔记                                四  叛逆性 在爱因斯坦的同时期科学家中,我想比他IQ...
用户1037328 2014-07-09 19:55
RTEMS系统时钟原理
作者,下家山(转载请注明作者及出处,请尊重原创)   专注嵌入式(ARM7,Cortex-M0,Cortex-M3,ARM9,linux)培训 一:从应用看原理      每个...
用户1037328 2014-07-09 19:47
RTEMS在S3C2410上的移植(一)
作者:下家山(转载,请注明) 1:RTEMS开发环境建立 1.1开发环境建立前的准备工作 因为RTEMS开发环境主要用的是GNU的工具链,所以需要一台装有Linux的HOST. 1.2...
用户1037328 2014-07-09 19:45
深入浅出学Makefile<三,如何自动生成Makefile>
(请尊重原创,转载请注明,作者:下家山) 五: 运行make编译得到可执行文件 root@parson-desktop:/home/parson/tmp/automk# make gcc ...
我要评论
9
19
关闭 站长推荐上一条 /2 下一条