一.异常处理流程
1.异常处理流程
(1)保存现场(CPU自动完成)
将CPSR中状态保存到SPSR_<MODE>中
将CPSR寄存器的状态位T,改为ARM状态
根据需要,进制IRQ,FIQ中断,修改CPSR中I/F位
修改CPSR寄存器中的模式位[4:0],切换到对应的异常模式
将函数返回值地址保存到LR_<MODE>中,
修改PC指针指向异常向量表
(2)恢复现场(手动完成)
恢复SPSR_<MODE>寄存器中的值到CPSR中
恢复LR_<MODE>寄存器中的值。给到对应的PC
二.中断实现框图
三.中断流程
GPIO组先到EXTI中中断选择寄存器,选择对应中断对应的EXTI寄存器,在进行检验触发事件(选择下降沿触发或上升沿触发,按键中断属于下降沿触发),再设置中断屏蔽寄存器,设置为不屏蔽中断,之后进入GICD层,GICD层管理着288个中断号,先通过中断设置寄存器给对应中断号位置使能,之后设置中断优先级,GICD层的中断优先级需要比GICC层的中断优先级高,(值越小,优先级越高),之后通过中断目标选择寄存器选择CPU,并进入GICC层.GICC在GICC层中也需要设置中断优先级,并通过捕获中断号寄存器获取中断号,清除中断号寄存器清除中断号
四.分析芯片手册
RCC:使能GPIO
GPIO:设置GPIO_MODER为输入模式
EXTI:
设置中断对应的EXTI寄存器
设置触发中断方式为下降沿触发
设置中断屏蔽寄存器为不屏蔽中断
利用中断标志位清除中断
GIC:
GICD:
使能GICD层
设置对应中断号位置使能
设置中断优先级
利用中断目标选择寄存器选择CPU
利用GICD层中断挂起标志位进行清除中断
GICC:
使能GICC层
设置中断优先级屏蔽寄存器
利用捕获中断寄存器获取中断号
利用清除中断寄存器清除中断号
五.代码
key.c
#include "../include/key.h"
#include "../common/include/stm32mp1xx_gpio.h"
#include "../common/include/stm32mp1xx_exti.h"
#include "../common/include/stm32mp1xx_gic.h"
#include "../common/include/stm32mp1xx_rcc.h"
/*
* key1-----PF9
*
* key2-----PF7
*
* key3-----PF8
*/
//uart4初始化
void rcc_init()
{
RCC->MP_AHB4ENSETR|=(0x1<<5);
}
void gpio_init(){
GPIOF->MODER&=(~(0x3<<18)); //设置key1为输入模式
GPIOF->MODER&=(~(0x3<<14));//设置key2为输入模式
GPIOF->MODER&=(~(0x3<<16));//设置key3为输入模式
}
void exti_init(){
//EXTICRn初始化
EXTI->EXTICR3&=(~(0xff<<8));
EXTI->EXTICR3|=(0x05<<8); //key1
EXTI->EXTICR2&=(~(0xff<<24));
EXTI->EXTICR2|=(0x05<<24); //key2
EXTI->EXTICR3&=(~(0xff));
EXTI->EXTICR3|=(0x05);
//EXTIFTSR1初始化
EXTI->FTSR1|=(0x1<<9);
EXTI->FTSR1|=(0x1<<7);
EXTI->FTSR1|=(0x1<<8);
//EXTI_IMR1
EXTI->C1IMR1|=(0x1<<9);
EXTI->C1IMR1|=(0x1<<7);
EXTI->C1IMR1|=(0x1<<8);
}
void gicd_init(){
GICD->CTRL|=0x1; //使能GICD
GICD->ISENABLER[3]|=0x1<<3; //中断设置使能
GICD->ISENABLER[3]|=0x1<<1;
GICD->ISENABLER[3]|=0x1<<2;
GICD->IPRIORITYR[24]|=(0x1<<27); //中断优先级
GICD->IPRIORITYR[24]|=(0x1<<11);
GICD->IPRIORITYR[24]|=(0x1<<19);
GICD->ITARGETSR[24]&=(~(0x3<<24)); //中断目标分配
GICD->ITARGETSR[24]|=(0x1<<24);
GICD->ITARGETSR[24]&=(~(0x3<<8));
GICD->ITARGETSR[24]|=(0x1<<8);
GICD->ITARGETSR[24]&=(~(0x3<<16));
GICD->ITARGETSR[24]|=(0x1<<16);
}
void gicc_init(){
GICC->CTRL|=0x1;
GICC->PMR|=0x9<<3;
}
do_irq
#include "../include/key.h"
#include "../common/include/stm32mp1xx_gpio.h"
#include "../common/include/stm32mp1xx_exti.h"
#include "../common/include/stm32mp1xx_gic.h"
#include "../common/include/stm32mp1xx_rcc.h"
extern void printf(const char *fmt, ...);
extern void delay_ms(int ms);
unsigned int i = 0;
void do_irq(void)
{
unsigned int num;
num=GICC->IAR&0x3ff;
if(num==97){
delay_ms(500);
printf("key2############\n");
EXTI->FPR1|=(0x1<<7);
GICD->ICPENDR[3]|=0x1<<1;
}else if(num==98){
delay_ms(500);
printf("key3############\n");
EXTI->FPR1|=(0x1<<8);
GICD->ICPENDR[3]|=0x1<<2;
}else if(num==99){
delay_ms(500);
printf("key1############\n");
EXTI->FPR1|=(0x1<<9);
GICD->ICPENDR[3]|=0x1<<3;
}
//清除中断号
GICC->EOIR&=(~(0x3ff));
GICC->EOIR|=num;
}
#include "./include/key.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
int i,j;
for(i = 0; i < ms;i++)
for (j = 0; j < 1800; j++);
}
void init()
{
rcc_init();
gpio_init();
exti_init();
gicd_init();
gicc_init();
}
int main()
{
init();
while(1)
{
}
return 0;
}