打印

中断嵌套的问题

[复制链接]
4772|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
想实习去|  楼主 | 2010-1-16 19:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
6019实验室| | 2010-1-16 19:09 | 只看该作者
我也问个问题:如果要实现中断嵌套该怎么做啊?

使用特权

评论回复
板凳
6019赵文| | 2010-1-16 19:11 | 只看该作者
您好:

当在定时器中断服务函数里的时候,系统IRQ中断是关闭的,此时不会响应任何IRQ中断。在中断里如果使用查询方式发送数据应该没有问题!

如果要做到中断嵌套,用户需要在中断服务程序中清除自己的中断源,关闭自己的中断优先级以及比自己低的优先级,然后打开内核的IRQ中断,清零VICVectAddr!

使用特权

评论回复
地板
gongtengxinyi| | 2010-1-16 19:11 | 只看该作者
ARM的中断管理体系和51系列微控制器的中断管理体系不太一样。熟悉51体系结构的用户需要特别
          注意这一点。ARM的中断不会自动嵌套,实现ARM微控制器的中断嵌套比较烦琐,我们不提倡中断
           嵌套。但不排除需要嵌套的应用,因而在启动代码中,有对中断嵌套的处理。模板中的文件IRQ.S
           用于处理中断嵌套,是以下中断处理方法的依据。用户要根据自己的应用更改此文件,只需要在文
           件末尾添加中断处理程序的句柄即可。
           中断嵌套的原则:低优先级的中断嵌套高优先级的中断。
           可嵌套中断服务程序编写方法:
               1、保存当前中断使能寄存器VICIntEnable的值;
               2、禁止当前中断和低优先级中断;
               3、清除中断逻辑,使VIC能够响应更高优先级的中断;
               4、中断处理服务程序;
               5、恢复保存的中断使能寄存器的值。
           声明需要嵌套的中断服务程序时,不能使用"__irq"关键字,而需要通过句柄的方式进行。

使用特权

评论回复
5
S3C2440| | 2010-1-16 19:12 | 只看该作者
说的不错,能不能举个例子啊?

使用特权

评论回复
6
亦正亦邪| | 2010-1-17 11:15 | 只看该作者
例子网上搜搜,很多呢

使用特权

评论回复
7
金鱼木鱼| | 2010-1-17 11:38 | 只看该作者
ls你能给个例子不?我搜不到!你帮个忙吧!

使用特权

评论回复
8
gongtengxinyi| | 2010-1-17 12:54 | 只看该作者
楼上的你不是搜不到是懒吧哈哈

使用特权

评论回复
9
gongtengxinyi| | 2010-1-17 12:56 | 只看该作者
(网上搜的,借用)例子如下:

/********************************************************************************************
* 文 件 名:VIC_Nesting.c
* 功 能:本实验演示中断嵌套现象。程序开启了两个中断:定时器0和外部中断0。定时器0使LED8~LED1
*           闪烁,而外部中断0取反蜂鸣器控制口。分配定时器0中断优先级高于外部中断0的优先级。设置
*           KEY1连接外部中断0。按住KEY1键后全速运行程序,看LED8~LED1能否闪烁,若闪烁,则说明中
*           断嵌套成功。需要在文件IRQ.S末尾添加句柄:
*           Timer0_Handler HANDLER IRQ_Timer0
*           Eint0_Handler   HANDLER IRQ_Eint0
* 说 明:用跳线帽短接KEY1,BEEP,74HC595_2相关跳线。
*
*在产生IRQ中断,进入服务程序之前,IRQ中断将自动禁止,而Fiq中断依然使能,故在IRQ中断下依然要响应Fiq中断。
*
*********************************************************************************************/
#include 'config.h'
#define    BEEPCON        ((uint32)0x01<<7)   // P0.7引脚控制蜂鸣器,低电平蜂鸣
#define    BEEP_ON()    IO0CLR=BEEPCON     // P0.7引脚输出低电平,蜂鸣器蜂鸣
#define    BEEP_OFF()     IO0SET=BEEPCON     // P0.7引脚输出高电平,蜂鸣器不蜂鸣
#define    SPI_CS       ((uint32)0x01<<20) // P1.20引脚模拟SPI的片选信号
#define    SPI_DATA    ((uint32)0x01<<22) // P0.22引脚模拟SPI的数据信号
#define    SPI_CLK        ((uint32)0x01<<25) // P1.25引脚模拟SPI的时钟信号
#define    H_SPI_CS()     IO1SET=SPI_CS    // SPI的片选信号置高
#define    L_SPI_CS()     IO1CLR=SPI_CS    // SPI的片选信号置低
#define    H_SPI_DATA() IO0SET=SPI_DATA // SPI的数据信号置高
#define    L_SPI_DATA() IO0CLR=SPI_DATA // SPI的数据信号置低
#define    H_SPI_CLK() IO1SET=SPI_CLK     // SPI的时钟信号置高
#define    L_SPI_CLK() IO1CLR=SPI_CLK     // SPI的时钟信号置低
void Timer0_Handler(void);
void Eint0_Handler(void);
uint8 data;
/********************************************************************************************
* 函数名称:SendDataTo74HC595()
* 功 能:向74HC595发送一字节数据
* 入口参数:data 要发送的数据
* 出口参数:无
* 注 意:发送数据时,高位先发送
*********************************************************************************************/
void SendDataTo74HC595(uint8 data)
{
   uint8 i;
  
   L_SPI_CS();                               // SPI_CS=0
   for(i=0;i<8;i++)                             // 发送8位数据(1个字节)
    {
   L_SPI_CLK();                         // SPI_CLK=0
   /* 设置SPI_DATA输出值 */
   if((data & 0x80)!=0)
      H_SPI_DATA();                      // SPI_DATA=1
   else
      L_SPI_DATA();                      // SPI_DATA=0
   data<<=1;                            // 将要发送的1字节数据左移一位
   H_SPI_CLK();                         // SPI_CLK=1
   }
   H_SPI_CS();                               // SPI_CS=1   
}
/********************************************************************************************
* 函数名称:IRQ_Timer0()
* 功 能:Timer0中断服务函数,LED8~LED1闪烁
* 入口参数:无
* 出口参数:无
*********************************************************************************************/
void IRQ_Timer0(void)
{
   uint32 bak;
  
   bak='VICIntEnable';                         // 备份当前VICIntEnable的值
   VICIntEnClr=(1<<4)|(1<<14);                // 禁止当前优先级中断及低优先级中断
   VICVectAddr='0x00';                         // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
  
   /* LED8~LED1闪烁 */
   if(data==0x00)
data='0xff';
   else
data='0x00';
   SendDataTo74HC595(data);
   T0IR=0x01;                                   // 清除Timer0中断标志
  
   VICIntEnable='bak';
}
/********************************************************************************************
* 函数名称:IRQ_Eint0()
* 功 能:外部中断0中断服务函数,取反蜂鸣器控制口,允许中断嵌套
* 入口参数:无
* 出口参数:无
*********************************************************************************************/
void IRQ_Eint0(void)
{
   uint32 bak;
  
   bak='VICIntEnable';                         // 备份当前VICIntEnable的值
   VICIntEnClr='1'<<14;                         // 禁止当前中断
   VICVectAddr='0x00';                         // 清除中断逻辑,以便VIC可以响应更高优先级IRQ中断
  
   IRQEnable();                               // 使能IRQ中断
  
   /* 取反蜂鸣器控制口 */
   if((IO0PIN & BEEPCON)==0)
BEEP_OFF();
   else
BEEP_ON();

   /* 等待外部中断信号恢复为高电平,清除EINT0中断标志*/
   while((EXTINT & 0x01)!=0)
   {
       EXTINT='0x01';
   }
   
   VICIntEnable='bak';
}

/********************************************************************************************
* 函数名称:main()
* 功 能:初始化定时器0,设置定时器0中断和外部中断0
*********************************************************************************************/
int main(void)
{
   PINSEL0&=~((uint32)0x03<<14);             // 将P0.7引脚选择为GPIO功能
   IO0DIR|=BEEPCON;                             // 设置P0.7为输出
   BEEP_OFF();                               // 蜂鸣器禁止蜂鸣
  
   PINSEL1&=~((uint32)0x03<<0);                 // 将P0.16引脚选择为EINT0功能
   PINSEL1|=0x00000001;
  
   PINSEL1&=~((uint32)0x03<<12);             // 设置P0.22引脚为GPIO
   PINSEL2&=~((uint32)0x01<<3);                 // 设置P1.20和P1.25引脚为GPIO
   IO0DIR|=SPI_DATA;                         // 设置P0.22,P1.20,P1.25引脚为输出
   IO1DIR|=(SPI_CS | SPI_CLK);
  
   /* Timer0初始化*/
   T0TC=0;                                      // 定时器设置为0
   T0PR=0;                                      // 时钟不分频
   T0MCR=0x03;                               // 设置T0MR0匹配后复位T0TC,并产生中断标志
   T0MR0=Fpclk/10;                            // 0,1秒定时
   T0TCR=0x01;                               // 启动定时器
  
   IRQEnable();                               // 使能IRQ中断
  
   data='0x00';
  
   /* 初始化Timer0、Eint0中断(使用向量IRQ)*/
   VICIntSelect='0x00000000';                   // 设置所有中断分配为IRQ中断
   VICVectCntl0=0x20 | 4;                       // 分配Timer0中断到向量中断0
   VICVectAddr0=(uint32)Timer0_Handler;       // 设置中断服务程序地址
   VICVectCntl1=0x20 | 14;                   // 分配EINT0中断到向量中断1
   VICVectAddr1=(uint32)Eint0_Handler;       // 设置中断服务程序地址
   T0IR=0x01;                                   // 清除Timer0中断标志
   EXTINT='0x01';                               // 清除EINT0中断标志
  
   VICIntEnable=(1<<4)|(1<<14);                 // 使能Timer0、EINT0中断
  
   while(1);                                  // 等待中断  
   return 0;
}

使用特权

评论回复
10
想实习去|  楼主 | 2010-2-24 17:12 | 只看该作者
知道了!呵呵!

使用特权

评论回复
11
huzixian| | 2010-3-11 23:21 | 只看该作者
在中断里面不要加用时太久的程序!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

500

帖子

1

粉丝