dragonnk 发表于 2014-1-8 10:58:14

S3C6410裸机中断编程

本帖最后由 dragonnk 于 2014-5-16 20:38 编辑

S3C6410中断编程相对比较简单,相关中断寄存器需提前设置好,下面一一讲解我编写中断程序的过程,不对之处还请斧正。
       1、ARM处理器执行中断时会自动进入IRQ或FIQ模式,因此需要提前设置好该模式下的椎栈指针SP。开机启动芯片进入SVC安全模式,因此可以直接通过改变CPSR值进入IRQ或FIQ模式,并设置CP15寄存器使中断向量地址由VIC决定。参考汇编代码:
          LDR sp,=0x0C0003FC /*SVC模式堆栈*/         
          MRS r0,cpsr
          BIC r0,r0,#0x02
          MSR CPSR,r0   /*进入FIQ模式*/
          LDR sp,=0x0C0001FC /*FIQ模式堆栈*/
          ADD r0,r0,#0x01
          MSR cpsr,r0   /*进入IRQ模式*/
      LDR sp,=0x0c000FFC /*IRQ模式堆栈*/
      ADD r0,r0,#0x01      
       MSR cpsr,r0   /*返回SVC模式*/

      MRC p15,0,r0,c1,c0,0
      ORR r0,r0,#0x01000000
      MCR p15,0,r0,c1,c0,0/*中断向量由VIC接口决定*/
   2、配置和使能中断。写VICXINTSELECT确定相关中断是IRQ还是FIQ中断;将中断函数地址写入对应中断向量地址寄存器;置VICXINTENABLE中相应中断位为1使能中断(当然还要清除CPSR中的I或F位,不列举代码了)。以下是我写的配置并使能中断的一个函数,编写好中断函数后调用配置函数即可使能中断:
void set_interrupt(unsigned int VEC_NUM,unsigned int IF,void (*fun)())
{   //设置并使能中断,中断号0~63,IF为0为IRQ中断,否则为FIQ中断
unsigned int *p;
if(IF>0)
IF=1;
if(VEC_NUM>63)
return;
if(VEC_NUM<32)
{
VIC0INTSELECT|=(IF<<VEC_NUM);
p=(unsigned int*)(0x71200100+4*VEC_NUM );
*p=(unsigned int)fun;
VIC0INTENABLE|=(1<<VEC_NUM);
}
else
{   
VEC_NUM=VEC_NUM-32;
VIC1INTSELECT|=(IF<<VEC_NUM);
p=(unsigned int*)(0x71300100+4*VEC_NUM);
*p=(unsigned int)fun;
VIC1INTENABLE|=(1<<VEC_NUM);
}
}   
3、编写中断函数。
      GCC中中断函数的声明:
   void isr () __attribute__ ((interrupt ("IRQ")));//isr为函数名,自己随便写(写入上面配置函数中的最后一个参数),interrupt后面的说明符可为: IRQ, FIQ, SWI, ABORT 和UNDEF,定义可不用加后面的属性说明。如:
   void __attribute__ ((interrupt ("IRQ"))) isr()
      {
          //处理程序代码
         
         VICXADDRESS=0;  (注:好像是两个ADDRESS寄存器都要写入0)
      }
       注意中断函数最后要写VICXADDRESS清除当前中断。

飞凌-路飞 发表于 2014-1-23 08:59:55

谢谢楼主的无私分享!!!
页: [1]
查看完整版本: S3C6410裸机中断编程