S3C6410裸机中断终于搞定了,不需要汇编 ,使用VIC

时间:2021-04-21 12:20:47

经过几天的努力,期间遇到很多的麻烦,终于搞定了S3C6410裸机中断,测试使用的是外部中断0组的PN0,定时器使用的是定时器0.

 

之前一直很郁闷的是网上的一些S3C6410使用的中断都是像51单片机那样的固定中断向量入口,这种方式不仅需要汇编支持,而且效率相当的低下,既然S3C6410自带有中断处理协处理器VIC,那么我还是建议使用VIC来管理中断.

 

下面这段话摘自网上,不知道是谁写的,但是要谢谢他,让我搞清楚了如何使用裸机中断.

///////////////////////////////////////////////////////////////////////////////

为了向下兼容,6410保留了2410的软件中断跳转方式,在三星的文档里被称为SystemBUS模式,默认的,而其特有的VIC Port模式则要手动开启,启动代码:

 

mrc p15,0,r0,c1,c0,0

orrr0,r0,#(1<<24)

mcr p15,0,r0,c1,c0,0

 

将其加到启动文件的main函数入口点之前即可开始VICPort模式,在这个模式下,中断的使用简单了不少,比如说我要用某个按键来实现外部中断,则相应的过程如下:

 

初始化中断向量控制器:

 

      填充 rVICxINTENCLEAR ,清空VICxINTSELECT和VICxADDR,这步嘛没什么可说的,就是一个简单的重置工作。

 

配置按键对应的GPIO脚为中断模式:

 

     GPxxCON 每一个脚的配置占此寄存器的2位,其中中断配置为10b,将对应的两位位设为10b即可使用中断功能。

 

开启中断:

 

  将VICxINTENABLE对应位置一即可开启对应的中断,比如要开启11号中断,就将此寄存器第11位置一,注意此寄存器是32位的,x=0的时候开启0-31号中断,x=1时开启剩下的中断。

 

设置外部中断类型:

 

   操作EINxCONy,中断分组对应的寄存器可以在三星的手册里查到,每两个中断占用寄存器的三位,换句话说,寄存器每三位控制两个中断的触发方式,其中中断号小的偶数的两倍对应起始位,中断号大的奇数的两倍对应结束位,例如EINT11、10,对应寄存器的[22:20]三位,这三位怎么配手册上有详细描述,不废话。

 

装载中断伺服程序:

 

/////////////////////////////////////////////////////////////////////////

void led_init(void)

{

GPIOM->CON        =0x1111;

GPIOM->DAT        =0;

}

 

void Delay(u32 n)

{

u32i;

while(n--)

{

for(i= 0;i < 2000000;i ++);

}

}

 

void __irqIRQ_Exception(void)

{

EINT0PEND= 1;//写1清除中断标志

GPIOM->DAT^= BIT2;

ClearInterrupt(INT_EINT0);//中断结束

}

 

void Key_Init(void)

{

//PN0

GPION->CON= 2;//外部中断模式

EINT0CON0= 0x2;

EINT0PEND= 0xffffffff;

EINT0MASK&= ~(BIT0);//取消中断屏蔽

Set_IsrAddr(INT_EINT0,(u32)IRQ_Exception);        //设置中断矢量入口

Set_IntEnable(INT_EINT0,Enable);

}

 

 

void __irqIsr_Timer0(void)

{

TINT_CSTAT|= BIT5;//清除中断标志

GPIOM->DAT^= 1 << 3;

ClearInterrupt(INT_TIMER0);//中断结束

}

 

 

voidTIMER0_Init(void)

{

TCFG0=65;        //定时器0预分频65+1,由PCLK=66提供时钟,66分频产生1MHz的定时器时钟

TCON= BIT3;//定时器0自动更新使能

TCNTB0 = 200000;//重装值,200ms

TINT_CSTAT|= BIT5;//清除中断标志

TINT_CSTAT= 1;//使能定时器0中断

Set_IsrAddr(INT_TIMER0,(u32)Isr_Timer0);        //设置中断矢量入口

Set_IntEnable(INT_TIMER0,Enable);//使能定时器0全局中断

//以下操作启动定时器0

TCON|= BIT1;//手动更新

TCON&= ~BIT1;//结束手动更新

TCON|= BIT0;//启动定时器0

 

}

 

 

 

//主函数

void main(void)

{

u8i;

 

led_init();

Key_Init();

TIMER0_Init();

while(1)

{

for(i= 0;i < 2;i ++)

{

GPIOM->DAT^= 1 << i;

Delay(10);

}

}

}


//把下面的汇编加入到启动文件中,主要用来打开CPU中断和初始化VIC

;VIC Port模式,开启后就可以不用汇编使用中断,使用VIC控制中断
mrc p15,0,r0,c1,c0,0
orr r0,r0,#(1<<24)
mcr p15,0,r0,c1,c0,0

;允许中断,开启CPU总中断
MRS R0, CPSR         ;将CPSR保存至R0寄存器中
BIC R0, R0, #0x80    ;R0 = R0 & ~0x80,清除中断位
MSR CPSR_c, R0       ;将R0写回CPSR状态寄存

 

 

以上就是相关的代码,因为大家的寄存器宏定义不同,因此名字可能不同,因为我写了注释的,大家可以对着文档,设置相应的寄存器就可以了,如果需要可以找我,邮箱:cp1300@139.com

 

由于我也是刚学裸机操作,希望大家多多指导.