搜索
bottom↓
回复: 3

LPCARM中断非典方法大全圣诞裸奔程序详解(更新)

[复制链接]

出0入0汤圆

发表于 2006-12-24 22:17:35 | 显示全部楼层 |阅读模式
/*----------------------------------------------------------------------------------

          LPCARM中断非典方法大全圣诞裸奔程序详解(更新)

雁塔菜农HotPower   2006.12.25 更新于菜地

----------------------------------------------------------------------------------*/

#include <LPC213xDEF.H>    //ARM菜鸟HotPower创建定义文件(最新为倒塌版)

/*---------------------------------------------------------------------------------

注意:

LPC213XDEF.H文件下载

可将LPC213XDEF.H拷贝到Keil\ARM\INC\PHILIPS目录下



点击下载本裸奔程序完整的工程压缩包

----------------------------------------------------------------------------------*/





void __swi(0) Enable_IRQ(void);

void __SWI_0            (void) {

int tmp;

  __asm

  {

    MRS tmp, SPSR

    BIC tmp, tmp, #0x80

    MSR SPSR_c, tmp

  }

}



void __swi(1) Disable_IRQ(void);

void __SWI_1             (void) {

int tmp;

  __asm

  {

    MRS tmp, SPSR

    ORR tmp, tmp, #0x80

    MSR SPSR_c, tmp

  }

}



void __swi(2) Enable_FIQ(void);

void __SWI_2            (void) {

int tmp;

  __asm

  {

    MRS tmp, SPSR

    BIC tmp, tmp, #0x40

    MSR SPSR_c, tmp

  }

}



void __swi(3) Disable_FIQ(void);

void __SWI_3             (void) {

int tmp;

  __asm

  {

    MRS tmp, SPSR

    ORR tmp, tmp, #0x40

    MSR SPSR_c, tmp

  }

}



void __swi(4) Enable_VIC(void);

void __SWI_4            (void) {

  VIC->Protection = 0;//开放对VIC的写入保护

}



/*-------------------------------------------------------------

  SWI中断和VICSoftInt软件中断的区别之处



  由于VIC->Protection可以在任何级别随意置'1',即关闭

对VIC的写入,故没必要构造Disable_VIC();

  以下函数SetVICProtection()只是说明SWI中断和VICSoftInt软件

中断的区别,即前者属于非屏蔽中断,且可带参数和返回值。

而后者和属于可屏蔽中断,与VIC中断一样,无参数和返回值。

但VICSoftInt软件中断有别于模块的VIC中断。它可自组中断,也可

模拟系统模块中断。

  两者都很灵活,但用途和方法有很大的差异。

SWI中断改进的注解见SWI.s和SWI_Table.s.否则不能正确开关FIQ/IRQ

--------------------------------------------------------------*/

unsigned int __swi(5) SetVICProtection(unsigned int val);

unsigned int __SWI_5                  (unsigned int val) {

  VIC->Protection = val;//VIC->Protection可以随意置'1',但清'0'必须在管理模式下

  return VIC->Protection;

}



extern void FIQ_EINT0 (void) __irq

{

  VIC->SoftIntClr = (1 << VICIntSel_EINT0);//增强安全性

  INTCON->EXT_INT = (1 << EINT0);    //清除INT0中断标志

  VIC->VectAddr = 0;

}



void IRQ_EINT1 (void) __irq

{

  VIC->SoftIntClr = (1 << VICIntSel_EINT1);;//增强安全性

  while(INTCON->EXT_INT & (1 << EINT1)) {//等待P0_3和P0_14都为高电平

    INTCON->EXT_INT = (1 << EINT1);//清除INT1中断标志(电平触发必须读后清除!!!)

  }

  VIC->VectAddr = 0;

}



void IRQ_SOFT (void) __irq

{

  VIC->SoftIntClr = (1 << VICIntSel_SoftInt22);//清除用户软件中断标志

  VIC->VectAddr = 0;

}



void IRQ_Default (void) __irq

{

  switch(VIC->IRQStatus) {

    case (1 << VICIntSel_EINT0)://拦截非法INT0中断

      INTCON->EXT_INT = (1 << EINT0);//清除非法INT0中断标志

      VIC->SoftIntClr = (1 << VICIntSel_EINT0);//清除非法INT0软件中断标志

      break;

    case (1 << VICIntSel_EINT1)://拦截非法INT1中断

      INTCON->EXT_INT = (1 << EINT1);//清除非法INT1中断标志

      VIC->SoftIntClr = (1 << VICIntSel_EINT1);//清除非法INT1软件中断标志

      break;

    case (1 << VICIntSel_EINT2)://拦截非法INT2中断

      INTCON->EXT_INT = (1 << EINT2);//清除非法INT2中断标志

      VIC->SoftIntClr = (1 << VICIntSel_EINT2);//清除非法INT2软件中断标志

      break;

    case (1 << VICIntSel_EINT3)://拦截非法INT3中断

      INTCON->EXT_INT = (1 << EINT3);//清除非法INT2中断标志

      VIC->SoftIntClr = (1 << VICIntSel_EINT3);//清除非法INT3软件中断标志

      break;

    case (1 << VICIntSel_SoftInt23)://拦截非法用户软件中断VICIntSel_SoftInt23

      VIC->SoftIntClr = (1 << VICIntSel_SoftInt23);//清除非法用户软件中断标志

      break;

    case (1 << VICIntSel_SoftInt24)://拦截非法用户软件中断VICIntSel_SoftInt24

      VIC->SoftIntClr = (1 << VICIntSel_SoftInt24);//清除非法用户软件中断标志

      break;

    case (1 << VICIntSel_SoftInt25)://拦截非法用户软件中断VICIntSel_SoftInt25

      VIC->SoftIntClr = (1 << VICIntSel_SoftInt25);//清除非法用户软件中断标志

      break;

    case (1 << VICIntSel_SoftInt26)://拦截非法用户软件中断VICIntSel_SoftInt26

      VIC->SoftIntClr = (1 << VICIntSel_SoftInt26);//清除非法用户软件中断标志

      break;

    default:

      VIC->SoftIntClr = 0xffffff;//清除所有非法用户软件中断标志

  }

  VIC->VectAddr = 0;

}



int main(void)

{

unsigned int i;



  Disable_IRQ();//关闭向量中断总开关

  Disable_FIQ();//关闭快速中断总开关



  VIC->IntEnable  = 0;//关闭全部中断

  VIC->SoftIntClr = 0xffffffff;//清除所有软中断标志

  VIC->IntSelect  = 0;//全部中断为IRQ中断或默认中断



  PINSEL->PIN_SEL0 = 0x00000000;//设置管脚连接GPIO

  PINSEL->PIN_SEL1 = 0x00000000;//设置管脚连接GPIO

  P0->IODIR        = 0x00000000;//设置P0口为输入

  P1->IODIR        = 0x00000000;//设置P1口为输入



  PINSEL->PIN_SEL0  |= (P0_1_EINT0 << P0_1_PINSEL);   //选择P0.1为INT0外部中断引脚

  PINSEL->PIN_SEL1  |= (P0_16_EINT0 << P0_16_PINSEL); //选择P0.16也可为INT0外部中断引脚



  PINSEL->PIN_SEL0  |= (P0_3_EINT1 << P0_3_PINSEL); //选择P0.3为INT1外部中断引脚

  PINSEL->PIN_SEL0  |= (P0_14_EINT1 << P0_14_PINSEL); //选择P0.14也可为INT1外部中断引脚



  INTCON->EXT_POLAR   = ~(1 << EXTPOLAR0); //INT0为低电平有效



  INTCON->EXT_POLAR  &= ~(1 << EXTPOLAR1); //INT1为低电平有效



  INTCON->EXT_MODE    = (1 << EXTMODE0);  //设置INT0为边沿触发



  INTCON->EXT_MODE   &= ~(1 << EXTMODE1); //设置INT1为电平触发





/*-------------------------------------------------------------------------------------------

              FIQ中断和IRQ中断的区别之处

FIQ中断和IRQ中断都属于可屏蔽中断,他们分别受CPSR的F和I位的控制。



前者不需对VIC->VectAddrs和VIC->VectCntls进行设置,但要想正确地

中断要做几步工作:

1. VIC->IntSelect   = (1 << VICIntSel_EINT0); //设置EINT0为FIQ中断

2. VIC->IntEnable  |= (1 << VICIntSel_EINT0); //使能EINT0中断

3. 建立FIQ中断函数FIQ_EINT0().

   注意要声明为外部的即extern void FIQ_EINT0 (void) __irq

4. 改写Startup.S的内容。(改写后的注解见Startup.S)



后者需对VIC->VectAddrs和VIC->VectCntls进行设置。方法:

1. VIC->IntSelect  &= ~(1 << VICIntSel_EINT1); //设置EINT1为IRQ中断

2. VIC->VectCntls[0] = VICIntSel_Enable | VICIntSel_EINT1;//设置外部中断1分配VIC最高优先级

   IRQ_EINT1;//设置中断服务程序地址见Startup_Table.S

   VIC->IntEnable  |= (1 << VICIntSel_EINT1); //使能EINT1中断

3. 建立IRQ中断函数IRQ_EINT1().

   注意要声明为内部的即void IRQ_EINT1 (void) __irq

4. 必须改写Startup.S的内容。

5. 当VIC中断向量地址未定义或超出VIC->VectAddrs[15]时,使用默认中断向量VIC->DefVectAddr

   向量(数组)向量与默认中断向量最大的不同在于每个向量中断都有1个中断地址,而默认中断向量

   只占用1个公共的中断地址但可包含多个中断源。故默认中断向量必须判别是某个具体的中断源。

   所以也可以认为默认中断向量是第17个中断向量。

   特别注意非典的默认中断向量内不是中断的地址而是序号16~31.

6. 非典与经典的最大不同在于前者的VIC->VectAddrs[x]内不是地址而是向量数组的序号。

   非典的中断向量地址需要在Startup_Table.s即FLASH内设置。

   而经典的中断向量地址需要在VIC->VectAddrs[x]或VIC->DefVectAddr即RAM内设置真正的中断向量地址。

--------------------------------------------------------------------------------------------*/



  VIC->IntSelect   = (1 << VICIntSel_EINT0); //设置EINT0为FIQ中断



  VIC->VectCntls[0] = VICIntSel_Enable | VICIntSel_EINT1;//设置外部中断1分配VIC最高优先级

;  VIC->VectAddrs[0] = (unsigned int)IRQ_EINT1;//设置中断服务程序地址

  VIC->IntEnable |= (1 << VICIntSel_EINT1);//使能外部中断1



  VIC->VectCntls[1] = VICIntSel_Enable | VICIntSel_SoftInt22;//设置用户软件中断

;  VIC->VectAddrs[1] = (unsigned int)IRQ_SOFT;//设置用户软件中断服务程序地址

  VIC->IntEnable |= (1 << VICIntSel_SoftInt22);//使能用户软件中断



  VIC->DefVectAddr = (unsigned int)31;//16~31都可//定义除VIC->VectAddrs[0]~VIC->VectAddrs[15]外的中断函数



  INTCON->EXT_INT = (1 << EINT0) //清除INT0中断标志

                  | (1 << EINT1) //清除INT1中断标志

                  | (1 << EINT2) //清除INT2中断标志

                  | (1 << EINT3);//清除INT3中断标志



  VIC->SoftIntClr = (1 << VICIntSel_EINT0) //清除EINT0软中断标志

                  | (1 << VICIntSel_EINT1) //清除EINT1软中断标志

                  | (1 << VICIntSel_EINT1) //清除EINT2软中断标志

                  | (1 << VICIntSel_EINT1);//清除EINT3软中断标志



  VIC->IntEnable  = (1 << VICIntSel_EINT0) //使能EINT0中断

                  | (1 << VICIntSel_EINT1);//使能EINT1中断



/*--------------------------------------------------------------------------

  下列循环是非典的精华所在,其思路请到菜地的[非典型LPCARM之攻防体系]里寻找。





  其他需要Startup_Hot.s支持,以配合非典的拦截工作。

---------------------------------------------------------------------------*/

  for (i = 0;i <= 15; i ++) {

    VIC->VectAddrs = i;//刷新向量地址寄存器VICVectAddr0~VICVectAddr15

  }





  VIC->Protection = 1;//关闭在用户级对VIC的一些写操作

  VIC->Protection = 0;//试图在用户级打开对VIC的一些写操作的保护

  Enable_FIQ();//开放快速中断总开关

  VIC->SoftInt = (1 << VICIntSel_EINT0);//软件模拟快速中断0(失败!!!)

  __nop();

  Enable_VIC();//等效为特权级的VIC->Protection = 0;

  VIC->SoftInt = (1 << VICIntSel_EINT0);//软件模拟快速中断0(成功!!!)

  __nop();



  VIC->SoftInt = (1 << VICIntSel_SoftInt22);//软件模拟用户软件中断(失败!!!)



  Enable_IRQ();//注意现在立即进入EINT1硬件中断(因为假定P0.3/P0.14都为高电平)

  VIC->SoftInt = (1 << VICIntSel_SoftInt22);//软件模拟用户软件中断(成功!!!)



  VIC->SoftInt = (1 << VICIntSel_EINT1);//软件模拟向量中断1(成功!!!)



  VIC->Protection = 1;//关闭在用户级对VIC的一些写操作

  VIC->Protection = 0;;//在用户级试图写'0'无效!!!应该用Enable_VIC();或SetVICProtection(0);

  while(i == 0) {//不会进入死循环

    __nop();

  }



  i = SetVICProtection(0);//进入特权级打开对VIC的一些写操作的保护



  VIC->IntEnable |= (1 << VICIntSel_SoftInt23);//使能非法用户软件中断

  VIC->IntEnable |= (1 << VICIntSel_SoftInt24);//使能非法用户软件中断

  VIC->IntEnable |= (1 << VICIntSel_SoftInt25);//使能非法用户软件中断

  VIC->IntEnable |= (1 << VICIntSel_SoftInt26);//使能非法用户软件中断



  Disable_IRQ();//关闭向量中断总开关

  PINSEL->PIN_SEL0  |= (P0_7_EINT2 << P0_7_PINSEL);   //选择P0.7为INT2外部中断引脚

  INTCON->EXT_POLAR  &= ~(1 << EXTPOLAR2); //INT2为低电平有效

  INTCON->EXT_MODE   |=  (1 << EXTMODE2); //设置INT2为边沿触发

//  INTCON->EXT_MODE   &= ~(1 << EXTMODE2); //设置INT2为电平触发

  VIC->IntEnable |= (1 << VICIntSel_EINT2);//使能非法外部中断2

/*----------------------------------------------------------------------------------------------

以下几句引发非法用户软件中断后VIC->VectAddr值为VIC->DefVectAddr,故程序飞入IRQ_Default()处执行。

-----------------------------------------------------------------------------------------------*/

  VIC->SoftInt = (1 << VICIntSel_SoftInt23);//软件模拟非法用户软件中断(程序飞)

  VIC->SoftInt = (1 << VICIntSel_SoftInt24);//软件模拟非法用户软件中断(程序飞)

  VIC->SoftInt = (1 << VICIntSel_SoftInt25);//软件模拟非法用户软件中断(程序飞)

  VIC->SoftInt = (1 << VICIntSel_SoftInt26);//软件模拟非法用户软件中断(程序飞)

  VIC->SoftInt = (1 << VICIntSel_EINT2);//软件模拟非法INT2软件中断(程序飞!!!)



  INTCON->EXT_INT = (1 << EINT2);//清除非法INT2中断标志

  VIC->SoftIntClr = (1 << VICIntSel_EINT2);//清除非法INT2软件中断标志



  Enable_IRQ();//开放向量中断总开关



  VIC->Protection = 1;//关闭在用户级对VIC的一些写操作,保护在用户级VIC不被以外改写

  while(i == 0) {//进入死循环

    __nop();

  }

}

出0入0汤圆

发表于 2006-12-27 12:42:17 | 显示全部楼层
把酷帖顶起!把酷帖顶齐!

出0入0汤圆

发表于 2007-8-16 13:58:45 | 显示全部楼层
LPC尿童,崇拜死了,菜农,谢谢!!!

出0入0汤圆

发表于 2011-4-19 09:04:16 | 显示全部楼层
感谢 LPC 中断
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-6 11:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表