cortex-A7中断实验 --- STM32MP157

实验目的

1,实现KEY1/LEY2/KE3三个按键,中断触发打印一句话

2,实现KEY1/LEY2/KE3三个按键按下之后,灯的状态取反

一,异常源和异常模式

1,异常源:异常源引发处理器进入对应的异常模式

2,异常模式 === 异常源 === 

FIQ                         FIQ类型异常源

IRQ                        IRQ类型异常源

SVC                       reset(复位异常源)

                                swi(软中断指令)

ABORT                    data abort(取数据中止)

                                prefetch abort(取指令中止)

UNDEF                UNDEF未定义异常源

3,五种异常模式,对应7中异常源,根据不同的异常源,进入不同的异常模式,执行异常处理函数,异常源具有优先级,复位的优先级最高

二,异常处理流程

1,异常向量表

1:概念:异常向量表就是内存的一块寻址空间,共32个字节,分为8份,存放7中异常源,一份保留,地址是固定的,不可以随意修改。通过指定异常向量表的基地址和偏移地址,就可以找到相应的异常源,执行异常处理程序

2:为什么引入异常向量表:每个人编写的程序入口(函数名)不一致,但是可以通过地址指定异常处理异常程序的入口一致

 2,保存现场 (自动完成)

分为4大步,3小步:

1,保存CPSR寄存器中的值到SPSR_<MODE>寄存器中

2,修改CPSR寄存器的值

        1>修改CPSR寄存器中的T位(状态位),T=0,当前的状态为arm状态,指向arm指令集

        2>根据需要,禁止相应的 I / F中断位

        3>修改CPSR寄存器中第 [4:0] 位,为对应异常模式

3,保存函数的返回地址到LR寄存器中

4,修改PC指向异常向量表

3,恢复现场(手动完成)

分为两步

1,将LR寄存器中的值,恢复给PC

2,将SPER_<MODE>寄存器中的值,恢复给CPSR寄存器

4,软中断指令

指令码:SWI

指令格式:SWI 终端号(0 ~ 0xFFFFFF)

验证流程实例代码:

.text
.global _start
_start:
    @1.构建异常向量表
    b reset
    b undef_interrupt
    b software_interrupt
    b prefetch_dataabort
    b data_abort
    b .
    b irq
    b fiq

reset:
    @2.系统一上电,程序运行在SVC模式
        @1> 初始化SVC模式下,栈指针
    ldr sp,=0x40000800
    @3.从SVC模式切换到user模式
    msr cpsr,#0xD0
    @4.user模式下代码
        @1> 初始化user模式下,栈指针
    ldr sp,=0x40000700
    mov r0,#0x1
    mov r1,#0x2
    @4.执行软中断指令 ===> 保存现场(四大步三小步)
    swi 2
    add r0,r0,r1 @ r0 = 0x3
    b stop
    
    
undef_interrupt:
software_interrupt:
    @压栈保存现场    
    stmfd sp!,{r0-r12,lr}
    mov r0,#0x3
    mov r1,#0x4
    add r0,r0,r1 @ r0 = 0x7
    @出栈恢复现场    
    ldmfd sp!,{r0-r12,pc}^
    @^:将SPSR_<MODE>寄存器中的值,给到CPSR寄存器中
    
prefetch_dataabort:
data_abort:
irq:
fiq:
    
stop:
    b stop    
.end

三,分析电路图

中断触发方式:下降沿

网络编号 == 引脚号

KEY1 === PF9

KEY2 === PF7

KEY3 === PF8

1,分析框图

1,根据框图,需要分析RCC / GPIO / EXTI / GIC章节

2:RCC:使能GPIOF组寄存器(EXTI / GIC不属于核外寄存器,不需要使能,上电自动运行)

3:GPIO:设置引脚为输入模式

4:EXTI:设置中断触发方式(下降沿触发)

5:GIC:检测哪一个按键按下

中断触发流程:RCC使能 == GPIOF输入 == EXTI设置触发方式 == GIC检测按键 == A7核接收到中断信号,执行中断处理函数

四,分析RCC章节

1,确定总线连接

GPIO:AHB4

2,基地址

GICC === 0xA0022000

GICD === 0xA0021000

GPIOF === 0x50007000

EXTI === 0x5000D000

3,分析寄存器

1,分析RCC_MP_AHB4ENSETR寄存器

作用:使能GPIOF组寄存器

地址:0x50000000 + 0xA28 = 0x50000A28

伪代码:RCC_MP_AHB4ENSETR [5] = 1

五,分析GPIO章节

1,分析GPIOx_MODER寄存器

作用:设置GPIO引脚模式为输入模式(输入,输出,复用,模拟)

地址:0x50007000 + 0x00 = 0x50007000

伪代码:GPIOF_MODER [19:18] = 10 === KEY1

GPIOF_MODER [17:16] = 10 === KEY2

GPIOF_MODER [15:14] = 10 === KEY3

六,分析EXTI章节

1,概述

 2,内部框图

3,中断框图

 

3,分析寄存器

1,EXTI_EXTICRn寄存器(n=1~4)

EXTI external interrupt selection register === 外部中断选择寄存器

作用:设置GPIO引脚信号与EXTI进行连接 === 将外部按键信号经过GPIO控制器,转发到EXTI控制器

伪代码:EXTI_EXTICR3[15:8] = 0x05 ----> 设置KEY1按键与EXTI9进行连接

EXTI_EXTICR2[31:24] = 0x05 ----> 设置KEY2按键与EXTI7进行连接

EXTI_EXTICR3[7:0] = 0x05 ----> 设置KEY1按键与EXTI8进行连接

2,分析EXTI_FTSR1寄存器

作用:设置中断信号为下降沿触发方式

伪代码:EXTI_FTSR1[9] = 1 ----> 设置KEY1按键为下降沿触发方式

EXTI_FTSR1[7] = 1 ----> 设置KEY2按键为下降沿触发方式

EXTI_FTSR1[8] = 1 ----> 设置KEY3按键为下降沿触发方式

3,分析EXTI_IMR1寄存器

作用:设置中断不屏蔽 === EXTI层中断转发到GIC层

伪代码:EXTI_IMR1[9] = 1 ----> 设置KEY1按键中断不屏蔽

EXTI_IMR1[7] = 1 ----> 设置KEY2按键中断不屏蔽

EXTI_IMR1[8] = 1 ----> 设置KEY3按键中断不屏蔽

4,分析EXTI_FPR1寄存器

作用:清除EXTI层中断挂起标志位

rc_w1作用:读0:表示中断没有触发

读1:表示中断触发

写0:不清除EXTI层中断挂起标志位

写1:清除EXTI层中断挂起标志位

伪代码:EXTI_FPR1[9] = 1 ----> 清除key1按键EXTI层中断挂起标志位

EXTI_FPR1[7] = 1 ----> 清除key2按键EXTI层中断挂起标志位

EXTI_FPR11[8] = 1 ----> 清除key3按键EXTI层中断挂起标志位

七,分析GICD章节

1,中断号管理

SGI:Software generated interrupts ==> 软件产生中断(软中断)

PPI:Private peripheral interrupts ==> 私有外设中断

SPI:Shared peripheral interrupts ==> 共享外设中断

1,GIC层共有288个中断号(0 ~ 287)

2,16个PPIS(ID:16 ~ 31),16个SGIS(ID:0 ~ 15),256个SPIS(ID:32 ~ 287)

按键中断号: 97 === EXTI7

98 === EXTI8

99 === EXTI9

2,分析寄存器

1,GICD_CTLR寄存器

作用:设置GICD组0使能

伪代码:GICD_CTLR [0] = 1

2,分析GICD_ISENABLERx寄存器

作用:设置GICD层中断使能

伪代码:EXTI9 ----> 中断号99 ----> GICD_ISENABLER3[3] = 1

EXTI7 ----> 中断号97 ----> GICD_ISENABLER3[1] = 1

EXTI8 ----> 中断号98 ----> GICD_ISENABLER3[2] = 1

3,分析GICD_IPRIORITYRx寄存器

作用:设置GICD层中断优先级寄存器,GICD层优先级需要比GICC层优先级高,才能转发到GICC层(值的范围 0 ~ 2^5 -1,数字越小,优先级越高)

伪代码:中断号99 ---->GICD_IPRIORITYR24[31:27] = 0b00000

中断号97 ---->GICD_IPRIORITYR24[15:11] = 0b00000

中断号98 ---->GICD_IPRIORITYR24[23:19] = 0b00000 (值自定义)

4,GICD_ITARGETSRx寄存器

作用:设置GICD层中断目标分配给CPU0

0b00---不分配

0b01---分配给CPU0

0b10---分配给CPU1

0b11---分配给CPU0 和 CPU1

伪代码:GICD_ITARGETSR24[25:24] = 0b01

GICD_ITARGETSR24[9:8] = 0b01

GICD_ITARGETSR24[17:16] = 0b01

5,分析GICD_ICPENDRx寄存器

作用:清除GICD层中断挂起标志位

挂起:暂时被淘汰出内存

伪代码:中断号99 ----> GICD_ICPENDR3[3] = 1 ----> 清除key1按键GICD层中断挂起标志位

中断号97 -----> GICD_ICPENDR3[1] = 1 ----> 清除key2按键GICD层中断挂起标志位

中断号98  ----> GICD_ICPENDR3[2] = 1 ----> 清除key3按键GICD层中断挂起标志位

八,分析GICC章节

1,分析GICC_CTLR寄存器

作用:设置GICC层组0使能

伪代码:GICC_CTLR [0] = 1

2,分析GICC_PMR寄存器

作用:设置GICC层的优先级

伪代码:GICC_PMR [7:3] = 0b11111(自定义)

3,分析GICC_IAR寄存器

作用:获取中断号

伪代码: num = GICC_IAR

4,分析GICC_EOIR寄存器

作用:清除获取到的中断号

        GICC_EOIR = num

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值