arm 裸机编程 外部中断篇

GIC

即 Generic Interrupt Controller 通用中断控制器,是支持和管理系统中断的集中式资源。
提供:

  1. 从硬件(外围)启用、禁用和生成处理器中断
  2. 产生软件中断
  3. 中断屏蔽和优先级

支持三种中断:

  1. 软件生成中断(SGI)
  2. 专用外设中断(PPI):特定于单个处理器的外围中断
  3. 共享外设中断(SPI):这是可以将其分发给任何处理器组合的外围中断

触发方式:

  1. 边沿触发
  2. 电平触发

设置外部中断的过程

  1. 查询原理图,查找外部中断的引脚以及其对应的外部中断引脚
  2. 将对应GPIO的功能设置为中断,并获得该引脚所对应的外部中断寄存器(例:EXT_INT41,不知道名字暂时这样叫)
  3. 设置GPIO外部中断触发方式
  4. 使能GPIO外部中断
  5. 通过GPIO的中断功能查找中断号
  6. 在GIC中使能中断号对应的中断
  7. 在GIC中设置中断优先级
  8. 设置中断处理核心
  9. 打开GIC中断总开关
  10. 设置对应核新的掩码
  11. 打开对应中断核心开关

代码(汇编初始化部分)

.text
.global _start
_start:
	b reset
	nop
	nop
	nop
	nop
	nop
	b irq_handle
	nop
	
reset:
	@通过协处理器指令将中断向量表设置到0x40008000位置
	ldr r0, =0x40008000
	mcr p15, 0, r0, c12, c0, 0
	
	@模式切换,切换到irq模式
	mrs r0, cpsr
	bic r0, #0x1f
	orr r0, #0x12
	msr cpsr, r0
	
	@设置irq模式下的栈
	ldr lr, =irq_end
	
	@切换到user模式
	mrs r0, cpsr
	bic r0, #0x9f	@使能中断,将cpser中的7位置0开启中断
	orr r0, #0x10
	msr cpsr, r0
	
	@设置svc模式下的栈
	ldr lr, =svc_end
	
	@跳转到主函数
	b mian
	
irq_handle:
	@设置lr
	@硬件中断会打断当前正在执行的指令,所以在中断处理函数结束时,需要重新执行被打断的指令。
	sub lr, #4
	
	@入栈
	stmfd sp!, {r0-r12, lr}
	
	@跳转中断处理函数处执行
	bl do_irq
	
	@出栈
	ldmfd sp!, {r0-r2, pc}^
	
.data
	svc_start:
		.space(128)
	svc_end:
	
	irq_start:
		.space(128)
	irq_end:

.end

代码(C语言功能实现以及中断处理部分)

//GPX1控制寄存器
#define GPX1CON			(*(volatile unsigned int *)0x11000C20)
//EXT_INT41控制寄存器
#define EXT_INT41CON	(*(volatile unsigned int *)0x11000E04)
//EXT_INT41屏蔽寄存器
#define EXT_INT41_MASK	(*(volatile unsigned int *)0x11000F04)
//中断设置使能寄存器
#define ICDISER1_CPU0	(*(volatile unsigned int *)0x10490104)
//优先级寄存器
#define ICSIPR14_CPU0	(*(volatile unsigned int *)0x10490438)
//处理器目标寄存器
#define ICDIPTR14_CPU0	(*(volatile unsigned int *)0x10490838)
//分配器控制寄存器
#define ICDDCR			(*(volatile unsigned int *)0x10490000)
//中断优先级屏蔽寄存器
#deifne ICCPMR_CPU0		(*(volatile unsigned int *)0x10480004)
//CPU接口控制寄存器 CPU interface control register
#define ICCICR_CPU0		(*(volatile unsigned int *)0x10480000)

//中断应答寄存器
#define ICCIAR_CPU0		(*(volatile unsigned int *)0x1048000c)
//中断等待清除寄存器
#define ICDICPR1_CPU0	(*(volatile unsigned int *)0x10490284)
//外部中断EXT INT41待处理寄存器
#define EXT_INT41_PEND	(*(volatile unsigned int *)0x11000f44)
//中断结束寄存器
#define ICCEOIR_CPU0	(*(volatile unsigned int *)0x10480010)

void KyeInit()
{
	GPX1CON = GPX1CON | 0xf << 4;
	EXT_INT41CON = EXT_INT41CON & ~(0x7) | 0x2 << 4;
	EXT_INT41_MASK = EXT_INT41_MASK & ~(0x1 << 1);
	ICDISER1_CPU0 = ICDISER1_CPU0 | ( 0x1 << (57-32) );
	ICSIPR14_CPU0 = ICSIPR14_CPU0 & ~(0xff << 8) | 12 << 8;
	ICDIPTR14_CPU0 = ICDIPTR14_CPU0 & ~(0xff << 8) | 0x1 << 8;
	ICDDCR = 1;
	ICCPMR_CPU0 = 0xff;
	ICCICR_CPU0 = 1;
}

void do_irq()
{
	//获取中断号
	int number = ICCIAR_CPU0 & 0x3ff;
	switch(number)
	{
		case 57:
		{
			/*此处添加中断处理代码*/
			
			//清除中断
			ICDICPR1_CPU0 = ICDICPR1_CPU0 | ( 0x1 << (57-32) );
			EXT_INT41_PEND = EXT_INT41_PEND | 0x1 << 1; 
			break;
		}
	}
	ICCEOIR_CPU0 = ICCEOIR_CPU0 &~ (0x3FF) | iNumber;
}

int mian()
{
	KeyInit();
	while(1);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值