嵌入式硬件平台接口开发之中断接口

按键中断点亮熄灭led

硬件:Samsung Exynossoc

参考手册:SEC_Exynos4412 SCP_Users Manual_Ver.0.10.00_Preliminary

1. ARM中断的架构



cpu响应外设中断流程如下:

1) 每个cpu 响应外设中断有irq 和fiq,一般外设都是用的irq这根线

2) 中断源很多,但是通往cpu中断接口只有一根,所以需要一个设备来管理所有的中断源,该设备叫中断控制器,多核的称为GIC,单核 的称为VIC

3) 第一级中断控制器,比如GPX1 、GPX2只管理若干个中断源,会对中断源做初步的控制【中断使能屏蔽、触发方式、引脚滤波】

4) 中断信号就是由外设的发生中断信号的部件发出的,该电信号经过request line到达第一级中断控制器,通过第一级中断控制器,该信号就会到达GIC

5) GIC也会针对该中断源操作【使能屏蔽、优先级、发送到哪个cpu】,中断信号通过GIC就会到达cpu,

6)cpu收到中断信号之后硬件会自动进行arm处理器工作模式,然后跳到中断处理程序,执行中断程序。

7) 中断控制器如何标识这些中断源,soc设计的时候就已经给所有中断源编号称为HWinterrupt ID。

 

2. 按键中断初始化流程

1)找到按键中断对应的HW interruptID

2) 将按键连接的管脚GPX1设置成中断

3)设置中断的触发方式

4) 设置GPX1 的EXT_INT41_MASK这个寄存器 使能/屏蔽中断

5) 中断到达GIC,通过设置ICDISER 寄存器使能中断源

6) 通过设置ICDPTR寄存器决定该中断源送到哪个CPUinterface

7)使能GIC

还有两个需要做的是:

1)设置CPU的中断屏蔽级别,若屏蔽级别0xFF,表示所有的中断都处理

2) 中断信号到达cpu interface,通过ICCICR寄存器全局使能cpu

 

1)找到中断对应的HWinterrupt ID


 

2)将按键连接的管脚GPX1设置成中断。


 

3)设置中断的触发方式,首先找到GPX1对应的的设置中断的寄存器EXT_INT41CO,其他的相关的寄存器标注如下图所示:

 

4)使能中断

EXT_INT41_MASK


清除中断

EXT_INT41_PEND


 

5)在gic中使能中断源ICDISERn

57 /32    =    1  余   25       ICDISER1    25位



 

 

6)发送给具体的cpu

CPU interface57 / 4   =  14  余  1                ICDIPTR14        [15:8]



 

 

7)gic使能


 

还有两个要做的是:

1)设置CPU中断屏蔽级别

ICCPMR_CPU  


2)使能cpu

ICCICR_CPUn


 

 

3. 在中断程序中,清除相关中断,否则中断控制器会以为这个中断一直在发生。清除中断要做的有三是件事,一是找到中断号,二是清除相关中断标志位,三是告知cpu中断处理结束。

1)通过ICCIAR_CPUn寄存器获取中断号。

2)清除中断。GPX1对应的清中断寄存器为EXT_INT41_PEND


3)将中断号发给ICCEOIR_CPU寄存器,告知cpu,中断处理结束

 

利用按键中断点亮熄灭led示例代码如下:

S文件部分汇编代码:

    /****  irq_handler ****/

irq_handler:

 

    sub  lr,lr,#4 //修正返回地址,3级流水线

    stmfd sp!,{r0-r12,lr}//保存现场

    .weak do_irq         //

    mrs r0,cpsr

    bl  do_irq

    ldmfd sp!,{r0-r12,pc}^//恢复现场

 

C文件代码:



#include "exynos_4412.h"


static flag = 0;


void delay_ms(int num);
void led_init(void);
void led_on(void);
void led_off(void);
void  key_int_init(void);


void main()
{
key_int_init();
led_init();
led_off();
flag = 0;


while(1);
{}


}


void delay_ms(int num)
{
int i,j;


for(i=num;i>0;i--)
for(j=1000;j>0;j--)
;
}


void led_init(void)
{
GPX2.CON =  (GPX2.CON & (~(0xf<<28))) | (0x1<<28);
}


void led_on(void)
{
GPX2.DAT |= 0X1<<7;
}


void led_off(void)
{
GPX2.DAT = GPX2.DAT & (~(0X1<<7));
}


void do_irq(void)
{
int irq_num;
//读取需要处理的中断号,中断处理开始信号
//Penging状态--->Active状态
irq_num = CPU0.ICCIAR & 0x3ff;


switch(irq_num)
{
case 57:
if(flag ==0)
{
led_on();
flag =1;
}
else
{
led_off();
flag =0;
}
//清GPIO控制器中断挂起位
EXT_INT41_PEND |= 0x1<<1;


break;
}
//中断处理结束,写入处理的中断号,作为中断处理结束信号
//Active-->Inactive(Inactive and Pending)
CPU0.ICCEOIR = (CPU0.ICCEOIR&(~(0x3ff))) | irq_num;
}




void  key_int_init(void)
{
//设置管脚为接收中断方式
GPX1.CON = (GPX1.CON & (~(0XF<<4)))| (0XF<<4);


//设置中断触发方式为下降沿触发
EXT_INT41_CON = (EXT_INT41_CON &(~(0XF<<4)))|(0X2<<4);


//使能中断
EXT_INT41_MASK &= ~(0X1<<1);


//在GIC中,使能CPU0的SPI25/ID57,57 / 32 = 1 余 25
ICDISER.ICDISER1 |= 0X1<<25;


//设置将SPI25发送给CPU0处理,57 / 4 = 14 余 1
ICDIPTR.ICDIPTR14 = (ICDIPTR.ICDIPTR14&(~(0XFF<<8)))|(0X1<<8);


//GIC使能
ICDDCR = 1;
//设置CPU0中断屏蔽级别为0XFF,最低级,所有中断都处理
CPU0.ICCPMR = 255;
//全局使能CPU0
CPU0.ICCICR = 1;
}

 

 


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值