/** 代码演示 - key_irq.c **/void do_gpioa_irq(void) { uart_puts("/n/r do_gpioa_irq /n/r"); GPIOA_DET |= (1<<28);}void key_irq_init(void) { GPIOA_INTENB &= ~(1<<28); // 先做中断源级屏蔽 //GPIO 配置 // 1、GPIO配置为输入 // 2、禁止内部上、下拉电阻 // 3、GPIO检测使能 // 4、GPIO检测下降沿事件 // 5、GPIO中断使能 // FUNC 0 // 输入口,禁止内部上下拉电阻 GPIOA_ALTFN1 &= ~(3<<(24)); GPIOA_OUTEN &= ~(1<<28); //清除检测标志位 GPIOA_DET |= (1<<28); //检测下降沿事件,使能检测 GPIOA_DETMODE1 = (GPIOA_DETMODE1 & ~(3<<24)) | (2<<24); GPIOA_DETMODEEX &= ~(1<<28); GPIOA_DETENB |= (1<<28); GPIOA_INTENB |= (1<<28); // 最后中断源级使能}/** ------------------------------------------------------ **/1.3 中断控制器 GIC - (省长)【特点】 1)中断源可以配置为group0或者group1; 2)group0中的中断可以配置为IRQ/FIQ的形式向目标处理器报告; 3)grout1中的中断只能以IRQ的形式向目标处理器报告;【支持4种类型的中断】 SGI * 16 :软件产生的中断信号,cpu和cpu之间的通信。 PPI * 6 :私有外围设备中断 PPI * 1 :私有内部设备中断 SPI * 128 :'共享的外部设备中断(按键就属于SPI)【中断状态】 inactive:非中断未决和中断进行。 pending:中断未决。中断已产生,等待cpu处理阶段。 active:中断进行。中断已产生,并正在执行相应的中断服务过程中。【中断被处理的模式】 1-N model / N-N model【中断优先级】了解【中断编号】interrupt IDs ID0~ID15:SGI ID16~ID31:PPI ID32~ID1019:SPI // 按键可用的编号在此范围内【中断源】---> P472. GPIOA中断对应的interrupt ID是 32 + 53 == 85【关于特殊功能寄存器的设置,分两部分】 distributor<分配器> + CPU interface<接口> = '中断控制器(GIC)' 1)以GICD_xxxx开头的寄存器,对distributor配置; 2)以GICC_xxxx开头的寄存器,对CPU interface配置。" GICD_CTRL // 归为group的中断信号是否可向interface GICD_CTRL - 0xc0009000 - [ 0 ] 0=屏蔽,1=使能 " GICD_IGROUPR // 决定中断归为group0还是group1 GICD_IGROUPR2 - 0xc0009088 - [ 21 ] 0=group0" GICD_ITARGETSR21 //配置中断产生后分配给那个核(cpu0,cou1...) GICD_ITARGETSR21 配置中断产生后分发给哪个核(cpu0 cpu1 ...cpu7) [15:8] 00000001 ID=85的中断发送到CPU0 GICD_ipRORITYR21 [15:8] 0x0a ID=85的中断优先级为10 GICD_ICPENDERR2 READ: 1, 中断产生了未得到处理 PENDING (未决/挂起) WRITE, 1 导致对应的bit 清0 GPIOA ID = 85 [21] 向其中写入1,将其清0 GICD_ISENABLER2 [21] 0/1 屏蔽/使能 ID=85的中断信号 GICC_CTRL [0], 0/1 禁止/使能上报group0组的中断信号给CPUn [1], 0/1 禁止/使能上报group1组的中断信号给CPUn [3], 0/1 group0的中断按照IRQ/FIQ方式上报 GICC_PMR 中断优先级阈值设置 优先级高于阈值的中断信号才有可能上报给CPU [7:0] 【对应的代码】interrupt.c int interrupt_init (void){ } 该函数在main.c1.4 ARM core设置 CPSR [I] 0,响应上报的IRQ信号 1,屏蔽上报的IRQ信号 start.s enable_interrupts该函数在main.c中被调用
2、异常的处理流程 增加start.s 而且调整shell.lds IRQ异常产生,硬件会自动做4件事 1)备份CPSR 到spsr_<irq> 2) 修改CPSR [4:0] 10010 [5] T=0 [6] F=1 [7] I=1 3) 保存返回地址到LR_<irq> LR_<irq> = PC -4 4) 给PC寄存器赋值 PC = vector_base + 0x18 = 0x48000000 + 0x18 start.s 1)异常向量表 b reset ldr ... ldr ... 2)reset: 重新设置异常向量表首地址 栈空间设置 bl main ( ) { 中断源 中断控制 arm初始化 //按键就出异常并且异常可以传递ARM CORE while(1) { } } 当有人按下key1键 ,IRQ异常报告给ARM CORE ARM CORE 1)备份cpsr 2)修改CPSR 3)保存返回地址到LR 4)PC = 0X48000018 软件代码执行 ldr pc, _irq irq: 保护现场 stmfd sp!, {r0-r12, lr} 执行按键处理动作 bl do_irq 恢复现场 ldmfd sp!, {r0-r12, r15}^ r15= lr ^: cpsr = spsr_<irq> do_irq() { /*确认哪个触发的IRQ*/ GPIOA28 interrupt id = 85 判断是否为GPIOA28触发的中断? { do_gpioa_irq() { /*重要的事:清除中断源的中断标志位*/ } 清除gpioa28在中断控制器中的pending位 } }练习: 梳理按键异常是如何产生的?流程 异常的软硬件响应过程? 能不能向其中再增加一个按键?
新闻热点
疑难解答