首页 > 编程知识 正文

irq和fiq中断,eplan闪退重启

时间:2023-05-06 11:20:47 阅读:134680 作者:1050

irq中断键k2或k3会发生irq中断

回忆异常的处理流程:

5种异常模式7种异常源

0号地址有异常向量。 每个异常源都有一个固定地址,它是跳转指令,用于跳转到相应的异常处理函数

发生异常时,会发生什么呢?

ARM core将自动执行以下操作:

将cpsr的值复制到spsr并将返回值复制到lr (将pc的值分配给lr,但bl将pc-4的值分配给lr ) )将处理器的状态设置为ARM状态,将处理器的工作模式手动设置为相应的异常模式

需要:

申请对应的堆栈空间入站保存字段出站恢复字段(包括lr值还原到pc,将spsr值复制到cpsr )

irq和fiq有什么区别?

1.irq为普通低优先级中断,fiq为高优先级中断,fiq可以中断irq,irq无法中断irq,只能按顺序处理

2.fiq响应速度5个专用寄存器位于中断向量表末尾,可以直接写入中断处理函数优先级高

例)基于k2的irq键中断

1 .查看原理图

引脚: GPX1_1外部中断: xeint9(9号外部中断源) ) ) ) ) ) ) )引脚: GPX1_1外部中断: xeint9(9号外部中断源) )

2 .查看芯片手册

中断进入cpu,最终处理(中断处理函数被调用)的是过五关斩六将,必须打开各自的门才能进入

按键会发生中断----gpio控制器必须对中断启用--GIC控制器的各个部分必须对中断启用---CPU0必须对中断启用

写代码需要什么?

设定GPIO引脚功能的GPIO控制器对中断使能GIC控制器对中断使能及分发工作完成(cpu选择) cpu接口对中断使能中断处理相关代码

ustify;">

当中断产生后,会先进入GPIO控制器,所以首先需要在GPIO控制器中对中断进行使能,接下来会进入到GIC,第一步需要GIC对中断进行使能,第二步,需要选择哪个接口来处理中断(分发),第三步,进行分发使能,同意这样选择,第四步,接口使能,第五步,设置优先级的门槛,优先级的取值范围是0-255,数字越大,优先级越小,所以一般就设置为255,允许所有优先级的中断通过

GIC可以产生三种类型的中断:

SGI:软件产生的中断

PPI:私有中断  只能由某一个cpu处理

SPI:共享中断  可以由cpu0-cpu3的任何一个处理   k2产生的中断

SGI、PPI、SPI一共有160个,每个中断都有自己的ID号,ID号是0-159

其中:SGI  16个  0-15

  PPI  16个  0-15

  SPI  128个  0-127

我们之后在使用的使用的时候,有些地方用的是SPI内部的0-127这个编号,有些地方又只能使用0-159这个编号

经过查找:k2(EINT9)的id号是57,SPI port no是25

 

一共有160个中断源,而一个寄存器只有32位,一个寄存器的位对应一个中断源,那也得5个寄存器才能表示完这个多中断源,经过查找,我们k2产生的中断对应的寄存器是ICDISER1,我们想让cpu0处理,所以寄存器的名字叫ICDISER1_CPU0

注意:

1.如果要使用绝对地址,链接地址和运行地址必须一样,所以我们需要改变链接地址为0x40008000,但是我们要使用的绝对地址是0,当中断产生时,cpu会去真正的0地址找中断向量表,而此时我们自己写的中断向量表在0x40008000这个地址,所以需要告诉cpu,将0x40008000这个地址作为0地址来使用

2、当中断产生时,GIC和GPIO控制器会自动设置这个中断对应的标志位,表示这个中断还没有被处理,让这个中断处于一个悬而未决的状态,所以当我们的中断被处理完之后,记得把中断标志位清除掉,否则cpu就会认为这个中断还没有被处理

在前几天点亮led灯、看门狗,及uart通信的文件基础下,添加irq.c文件、irq.h文件,及修改start.s汇编文件,map.lds链接脚本文件和makrfile工程文件 irq.c文件: #include "irq.h"#include "uart.h"#include "led.h"void irq_init(){/*********GPIO*****************///设置GPX1_1引脚的功能为外部中断GPX1CON = GPX1CON | 0XF << 4;//设置中断触发方式为下降沿触发EXT_INT41_CON = EXT_INT41_CON & ~(0xf << 4) | 0x2 << 4;//在GPIO控制器中使能中断EXT_INT41_MASK &= ~(0x1 << 1);/*********GIC******************///使能GICICDISER1_CPU0 |= 0X1 << 25;//分发ICDIPTR14_CPU0 = ICDIPTR14_CPU0 & ~(0XFF << 8) | 0X1 << 8;//分发使能ICDDCR = 1;//接口使能ICCICR_CPU0 = 1;//设置优先级门槛ICCPMR_CPU0 = 255;}void do_irq(){//得到当前中断的id号int intId = ICCIAR_CPU0 & 0x3ff;//不同的中断进行不同的处理switch(intId){case 57:uart_putc('k');uart_putc('2');//清GPIO中的中断标志位EXT_INT41_PEND |= 0X1 << 1;//清GIC中的中断标志位ICDICPR1_CPU0 |= 0x1 << 25;break;default:uart_putc('e');}//告诉CPU0,中断处理完了ICCEOIR_CPU0 = ICCEOIR_CPU0 & ~0X3FF | intId;} irq.h文件: #ifndef _IRQ_H_#define _IRQ_H_//#define GPX1CON *((volatile unsigned int *)0x11000C20)//在led灯的文件代码中该寄存器已被使用#define EXT_INT41_CON *((volatile unsigned int *)0x11000E04)#define EXT_INT41_MASK *((volatile unsigned int *)0x11000f04)#define ICDISER1_CPU0 *((volatile unsigned int *)0x10490104)#define ICDIPTR14_CPU0 *((volatile unsigned int *)0x10490838)#define ICDDCR *((volatile unsigned int *)0x10490000)#define ICCICR_CPU0 *((volatile unsigned int *)0x10480000)#define ICCPMR_CPU0 *((volatile unsigned int *)0x10480004)#define ICCIAR_CPU0 *((volatile unsigned int *)0x1048000C)#define EXT_INT41_PEND *((volatile unsigned int *)0x11000F44)#define ICDICPR1_CPU0 *((volatile unsigned int *)0x10490284)#define ICCEOIR_CPU0 *((volatile unsigned int *)0x10480010)void irq_init();void do_irq();#endif start.s汇编文件: .global _start_start:.text@异常向量表b reset @resetnop @undefnopnop @prefetch abortnop @data abortnop @reservedb irq_handler @irqnop @fiqirq_handler:@入栈保存现场sub lr,#4stmfd sp!, {r0-r12, lr}bl do_irqirq_handler_end:@出栈恢复现场ldmfd sp!, {r0-r12, pc}^ reset: @告诉cpu,把0x40008000当成0地址ldr r0, =0x40008000mcr p15,0,r0,c12,c0,0@切换到irq模式mrs r0, cpsrbic r0, #0x1forr r0, #0x12@使能irq中断bic r0, #0x80msr cpsr, r0@给irq模式的sp赋值ldr sp,=stack_irq_top @切换到user模式mrs r0, cpsrbic r0, #0x1forr r0, #0x10msr cpsr, r0@给user模式的sp赋值ldr sp,=stack_user_topb main.datastack_user:.space 1024stack_user_top:stack_irq:.space 100stack_irq_top:.end

map.lds链接脚本文件:

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)SECTIONS{. = 0x40008000; @要使用绝对地址,链接地址和运行地址必须一样. = ALIGN(4);.text :{*(.text)} . = ALIGN(4); .data : { *(.data) } . = ALIGN(4); .bss : { *(.bss) }} makefile工程文件: CROSS = arm-none-linux-gnueabi-CC=$(CROSS)gccLD=$(CROSS)ldOBJCOPY=$(CROSS)objcopyall:$(CC) -g -c -o main.o main.c $(CC) -g -c -o irq.o irq.c $(CC) -g -c -o led.o led.c $(CC) -g -c -o start.o start.s $(CC) -g -c -o wdt.o wdt.c $(CC) -g -c -o pwm.o pwm.c $(CC) -g -c -o uart.o uart.c $(LD) start.o led.o uart.o irq.o main.o wdt.o pwm.o -Tmap.lds -o led.elf$(OBJCOPY) -O binary -S led.elf led.bin$(CROSS)objdump -D led.elf > led.dis clean:rm -f *.o *.elf *.bin *.dis

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。