cortex A7核按键中断实验
一、分析电路图
实验目的:完成板子三个按键操作
1.1 电路图IO口
KEY1------>PF9
KEY2------>PF7
KEY3------>PF8
1.2 工作原理
KEY1 ------> PF9 ------> 按键触发方式:下降沿触发
KEY2 ------> PF7 ------> 按键触发方式:下降沿触发
KEY3 ------> PF8 ------> 按键触发方式:下降沿触发
二、分析框图
2.1 分析框图
2.2 总结
1、通过以上框图分析可知,需要分析芯片手册RCC章节 / GPIO章节 / EXTI章节 / GIC章节
2、RCC章节 : 使能对应组控制器
3、GPIO章节 : 设置引脚为输入模式
4、EXTI章节 :配置引脚触发方式为下降沿触发
5、GIC章节 :按键如何管理中断号,判断哪一个按键按下
三、分析RCC章节
3.1 确定总线连接
3.2 确定基地址
3.3 分析RCC_MP_AHB4ENSETR寄存器
1.RCC_MP_AHB4ENSETR寄存器作用
设置对应组控制器使能
2.如何确定RCC_MP_AHB4ENSETR基地址
通过2.5.2章节 1)确定总线名称 2)确定对应组寄存器基地址
3.如何确定RCC_MP_AHB4ENSETR地址
RCC_MP_AHB4ENSETR地址 = 基地址 + 偏移地址 = 0x50000000 + 0xA28 = 0x50000A28
4.如何通过RCC_MP_AHB4ENSETR寄存器,设置GPIOF组控制器使能
RCC_MP_AHB4ENSETR[5] = 1 --------> 0x50000A28地址空间中第5位写1,保证其他位不变
四、分析GPIO章节
4.1 分析GPIOx_MODER寄存器
1.GPIOF_MODER寄存器作用
设置GPIO引脚模式
2.如何确定GPIOF_MODER基地址
通过2.5.2章节 1)确定总线名称 2)确定对应组寄存器基地址
3.如何确定GPIOF_MODER地址
GPIOF_MODER地址 = 基地址 + 偏移地址 = 0x50007000 + 0x00 = 0x50007000
4.如何通过GPIOF_MODER寄存器,设置PF9/PF7/PF8引脚为输入模式
key1: GPIOF_MODER[19:18] = 00 --------> 0x50007000地址空间中第[19:18]位写00,保证其他位不变
key2: GPIOF_MODER[15:14] = 00 --------> 0x50007000地址空间中第[15:14]位写00,保证其他位不变
key3: GPIOF_MODER[17:16] = 00 --------> 0x50007000地址空间中第[17:16]位写00,保证其他位不变
五、分析EXTI章节
5.1 介绍
5.2 框图
5.3 找出寄存器
5.4 EXTI选择寄存器介绍
5.5 分析EXTI_EXTICR3寄存器
1.EXTI_EXTICR3(EXTI external interrupt selection register 3)寄存器
寄存器全称:外部中断选择寄存器
作用:GPIO选择和哪一个EXTI组控制器进行连接
2.为什么有4个EXTI_EXTICRn寄存器
1) 通过EXTI选择寄存器介绍可知,一共有16个EXTI(EXTI0 ~ EXTI15)
2)通过以上选择寄存器分析可知,每8位管理一个EXTI,一个寄存器32位,所以最多管理4个EXTI
3)要想管理16个EXTI,所以需要4个这样的寄存器
3.如何配置KEY1/KEY2/KEY3与EXTI控制器进行连接
KEY1 -----> PF9 -----> EXTI9 -------> EXTI_EXTICR3[15:8] = 0x05
KEY2 -----> PF7 -----> EXTI7 -------> EXTI_EXTICR2[31:24] = 0x05
KEY3 -----> PF8 -----> EXTI8 -------> EXTI_EXTICR3[7:0] = 0x05
4.有没有什么公式可以计算操作的是哪个寄存器的哪几位
EXTI编号 / 4 = 商 … 余数
商 + 1:控制哪个寄存器
余数 * 8:操作8位中的最低位
KEY1 -----> PF9 -----> EXTI9 -------> 9 / 4 = 2 … 1 -------> EXTI_EXTICR3[15:8] = 0x05
KEY2 -----> PF7 -----> EXTI7 -------> 7 / 4 = 1 … 3 -------> EXTI_EXTICR2[31:24] = 0x05
KEY3 -----> PF8 -----> EXTI8 -------> 8 / 4 = 2 … 0 -------> EXTI_EXTICR3[7:0] = 0x05
5.6 分析EXTI_FTSR1寄存器
1.EXTI_FTSR1:EXTI falling trigger selection register
寄存器全称:EXTI下经验触发选择寄存器
作用:设置EXTI编号为下降沿触发
2.如何配置KEY1/KEY2/KEY3引脚为下降沿触发方式
KEY1 -----> PF9 -----> EXTI9 -------> EXTI_FTSR1[9] = 1 -------> 设置下降沿触发方式
KEY2 -----> PF7 -----> EXTI7 -------> EXTI_FTSR1[7] = 1 -------> 设置下降沿触发方式
KEY3 -----> PF8 -----> EXTI8 -------> EXTI_FTSR1[8] = 1 -------> 设置下降沿触发方式
5.7 分析EXTI_IMR1寄存器
1.EXTI_IMR1:EXTI CPU wakeup with interrupt mask register
寄存器全称:EXTI中断屏蔽寄存器
作用:设置EXTI信号是否转发到GIC层
2.如何配置KEY1/KEY2/KEY3引脚中断不屏蔽
KEY1 -----> PF9 -----> EXTI9 -------> EXTI_IMR1[9] = 1 -------> 设置中断不屏蔽,EXTI中断编号会被转发到GIC层
KEY2 -----> PF7 -----> EXTI7 -------> EXTI_IMR1[7] = 1 -------> 设置中断不屏蔽,EXTI中断编号会被转发到GIC层
KEY3 -----> PF8 -----> EXTI8 -------> EXTI_IMR1[8] = 1 -------> 设置中断不屏蔽,EXTI中断编号会被转发到GIC层
5.8 分析EXTI_FPR1寄存器
1.EXTI_FPR1:EXTI falling edge pending register
寄存器全称:EXTI下降沿触挂起寄存器
作用:清除EXTI层中断挂起标志
2.如何配置KEY1/KEY2/KEY3引脚清除EXTI层中断挂起标志
rc_w1:
读0:表示中断没有发生
读1:表示中断发生
写0:表示没有清除EXTI层中断挂起标志位
写1:表示清除EXTI层中断挂起标志位
KEY1 -----> PF9 -----> EXTI9 -------> EXTI_FPR1[9] = 1 -------> 清除EXTI层中断挂起标志位
KEY2 -----> PF7 -----> EXTI7 -------> EXTI_FPR1[7] = 1 -------> 清除EXTI层中断挂起标志位
KEY3 -----> PF8 -----> EXTI8 -------> EXTI_FPR1[8] = 1 -------> 清除EXTI层中断挂起标志位
六、中断整体框图
6.1 总结所以寄存器
EXTI章节总结:
1.中断选择寄存器 EXTI_EXTICR3
2.设置下降沿触发 EXTI_FTSR1
3.设置中断不屏蔽 EXTI_IMR1
4.清除EXTI层中断挂起标志位 EXTI_FPR1
GICD层
GICD interrupt set-enable register (GICD_ISENABLER0)
GICD interrupt priority register x (GICD_IPRIORITYRx)
GICD interrupt processor target register x (GICD_ITARGETSRx)
GICD control register (GICD_CTLR)
GICD interrupt clear-pending register x (GICD_ICPENDRx)
GICC input priority mask register (GICC_PMR)
GICC control register (GICC_CTLR)
GICC interrupt acknowledge register (GICC_IAR)
GICC end of interrupt register (GICC_EOIR)
6.2 框图
七、分析GICD章节
7.1 中断号如何管理
Software generated interrupts (SGI):软件产生中断 Interrupt ID:15-0
Private peripheral interrupts (PPI):私有外设中断,Interrupt ID:16-31
Shared peripheral interrupts (SPI):共享外设中断 Interrupt ID:32-287
GIC层一共管理288个中断号(0~287)
7.2 分析GICD_CTLR寄存器
1.GICD_CTLR:GICD control register
寄存器全称:GICD层控制寄存器
寄存器作用:使能对应组中断
2.使能GICD层组0中断:GICD_CTLR[0] = 1
7.3 分析GICD_ISENABLERx寄存器
GICD_ISENABLERx:GICD interrupt set-enable register
寄存器全称:中断设置使能寄存器
作用:接收EXTI层转发的中断信号
2.思考:
1)为什么GICD层一共有9个GICD_ISENABLERx(x = 0 ~ 8)寄存器
i)GICD_ISENABLERx这个寄存器一共32位,每一位管理一个中断号,一个寄存器最多管理32个中断号
ii)GIC层一共管理288个中断号(16个SGIS,16个PPIS,256个SPIS)
iii)所以需要 288 / 32 = 9 个GICD_ISENABLERx(x = 0 ~ 8)寄存器,才可以管理完成
2)如何确定KEY1/KEY2/KEY3中断号是多少?
通过21.3章节表117确定中断号
key1 -----> EXTI9 -----> 99
key2 -----> EXTI7 -----> 97
key3 -----> EXTI8 -----> 98
3.如何通过GICD_ISENABLERx寄存器设置KEY1/KEY2/KEY3使能
KEY1 -----> PF9 -----> EXTI9 -------> GICD_ISENABLER3[3] = 1 -------> 设置99号中断使能
KEY2 -----> PF7 -----> EXTI7 -------> GICD_ISENABLER3[1] = 1-------> 设置97号中断使能
KEY3 -----> PF8 -----> EXTI8 -------> GICD_ISENABLER3[2] = 1 -------> 设置98号中断使能
4.有什么公式可以直接计算出,操作哪个寄存器的哪一位?
中断号 / 32 = 商 … 余数
商:操作哪个寄存器
余数:操作寄存器的位数
KEY1 -----> PF9 -----> EXTI9 -------> 99 / 32 = 3…3 ------->GICD_ISENABLER3[3] = 1 -------> 设置99号中断使能
KEY2 -----> PF7 -----> EXTI7 -------> 97 / 32 = 3…1 ------->GICD_ISENABLER3[1] = 1-------> 设置97号中断使能
KEY3 -----> PF8 -----> EXTI8 -------> 98 / 32 = 3…2 ------->GICD_ISENABLER3[2] = 1 -------> 设置98号中断使能
7.4 分析GICD_IPRIORITYRx寄存器
1.GICD_IPRIORITYRx:GICD interrupt priority register
寄存器全名:GICD层中断优先级寄存器
作用:设置GICD层中断优先级
2. 为什么GICD层一共有72个GICD_IPRIORITYRx(x = 0 ~ 71)寄存器
i)GICD_IPRIORITYRx这个寄存器一共32位,每八位管理一个中断号,一个寄存器最多管理4个中断号
ii)GIC层一共管理288个中断号(16个SGIS,16个PPIS,256个SPIS)
iii)所以需要 288 / 4 = 72个GICD_IPRIORITYRx(x = 0 ~ 71)寄存器,才可以管理完成
3.思考:有什么公式可以直接计算出,操作哪个寄存器的哪一位?
中断号 / 4 = 商 … 余数
商:操作哪个寄存器
余数*8+3:操作寄存器的位数
3.何通过GICD_IPRIORITYRx寄存器设置KEY1/KEY2/KEY3对应的中断优先级
KEY1 -----> PF9 -----> EXTI9 -------> 99 / 4 = 24…3 ------->GICD_IPRIORITYR24[31:27] -------> 设置99号中断优先级
KEY2 -----> PF7 -----> EXTI7 -------> 97 / 4 = 24…1 ------->GICD_IPRIORITYR24[15:11] -------> 设置97号中断优先级
KEY3 -----> PF8 -----> EXTI8 -------> 98 / 4 = 24…2 ------->GICD_IPRIORITYR24[23:19] -------> 设置98号中断优先级
注意:中断的值越小,代表中断的优先级越高,设置中断优先级值的范围 0 ~ 2^5-1
7.5 分析GICD_ITARGETSRx寄存器
1.GICD_ITARGETSRx:GICD interrupt processor target register
寄存器全名:GICD层中断目标分配寄存器
作用:设置GICD层中断分配给哪个A7核,对于裸机开发中,只能给CPU0
2. 为什么GICD层一共有72个GICD_ITARGETSRx(x = 0 ~ 71)寄存器
i)GICD_ITARGETSRx这个寄存器一共32位,每八位管理一个中断号,一个寄存器最多管理4个中断号
ii)GIC层一共管理288个中断号(16个SGIS,16个PPIS,256个SPIS)
iii)所以需要 288 / 4 = 72个GICD_ITARGETSRx(x = 0 ~ 71)寄存器,才可以管理完成
3.思考:有什么公式可以直接计算出,操作哪个寄存器的哪一位?
中断号 / 4 = 商 … 余数
商:操作哪个寄存器
余数*8:操作寄存器的位数
4.何通过GICD_ITARGETSRx寄存器设置KEY1/KEY2/KEY3对应的中断分配给CPU0
KEY1 -----> PF9 -----> EXTI9 -------> 99 / 4 = 24…3 ------->GICD_ITARGETSR24[25:24] = 0bx1
KEY2 -----> PF7 -----> EXTI7 -------> 97 / 4 = 24…1 ------->GICD_ITARGETSR24[9:8] = 0bx1
KEY3 -----> PF8 -----> EXTI8 -------> 98 / 4 = 24…2 ------->GICD_ITARGETSR24[17:16] = 0bx1
5.这两位写什么样的值,分配给CPU0
0bx1:分配给CPU0 备注:x代表任意值
0b1x:分配给CPU1
0b11:分配给CPU1 和 CPU0
7.6 分析GICD_ICPENDRx寄存器
1.GICD_ICPENDRx:GICD interrupt clear-pending register
寄存器全称:中断清除挂起寄存器
作用:清除GICD层中断挂起标志位
2.思考:
1)为什么GICD层一共有9个GICD_ICPENDRx(x = 0 ~ 8)寄存器
i)GICD_ISENABLERx这个寄存器一共32位,每一位管理一个中断号,一个寄存器最多管理32个中断号
ii)GIC层一共管理288个中断号(16个SGIS,16个PPIS,256个SPIS)
iii)所以需要 288 / 32 = 9 个GICD_ICPENDRx(x = 0 ~ 8)寄存器,才可以管理完成
2)如何确定KEY1/KEY2/KEY3中断号是多少?
通过21.3章节表117确定中断号
key1 -----> EXTI9 -----> 99
key2 -----> EXTI7 -----> 97
key3 -----> EXTI8 -----> 98
3.有什么公式可以直接计算出,操作哪个寄存器的哪一位?
中断号 / 32 = 商 … 余数
商:操作哪个寄存器
余数:操作寄存器的位数
KEY1 -----> PF9 -----> EXTI9 -------> 99 / 32 = 3…3 ------->GICD_ICPENDR3[3]= 1------->清除99号中断对应GICD层中断挂起标志位
KEY2 -----> PF7 -----> EXTI7 -------> 97 / 32 = 3…1 ------->GICD_ICPENDR[1] = 1------->清除97号中断对应GICD层中断挂起标志位
KEY3 -----> PF8 -----> EXTI8 -------> 98 / 32 = 3…2 ------->GICD_ICPENDR[2] = 1 ------->清除98号中断对应GICD层中断挂起标志位
八、分析GICC章节
8.1 分析GICC_CTLR寄存器
1.GICC_PMR:GICC input priority mask register
GICC层中断优先级屏蔽寄存器
作用:设置GICC层中断优先级
2.如何设置GICC层中断优先级
GICC_PMR[7:3] = 中断优先级值
注意:GICD层中断优先级需要比GICC层中断优先级高,值越小代表优先级越高
8.2 分析GICC_PMR寄存器
1.GICC_PMR:GICC input priority mask register
GICC层中断优先级屏蔽寄存器
作用:设置GICC层中断优先级
2.如何设置GICC层中断优先级
GICC_PMR[7:3] = 中断优先级值
注意:GICD层中断优先级需要比GICC层中断优先级高,值越小代表优先级越高
8.3 分析GICC_IAR寄存器
GICC_IAR寄存器 作用:获取中断号
定义一个变量 = GICC_IAR[9:0]
8.4 分析GICC_EOIR寄存器
GICC_EOIR寄存器:清除中断号
GICC_EOIR[9:0]寄存器的值 = IAR[9:0]寄存器中获取的值
main.c
#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++);
}
#define EXTI7_INPUT_EVENT 7
#define EXTI8_INPUT_EVENT 8
#define EXTI9_INPUT_EVENT 9
#define GPIOGROUP 0x05
#define KEY1_ID 99
#define KEY2_ID 97
#define KEY3_ID 98
#define IPR_EXTI7 7
#define IPR_EXTI8 8
#define IPR_EXTI9 9
void led_init()
{
RCC->MP_AHB4ENSETR |= (0x1 << 4);
RCC->MP_AHB4ENSETR |= (0x1 << 5);
gpio_init_t init ={
.moder = OUTPUT,
.otyper = PP,
.ospeedr = LOW,
.pupdr = NO_PUPDR,
};
hal_gpio_init(GPIOE,&init,GPIO_PIN_10);
hal_gpio_init(GPIOE,&init,GPIO_PIN_8);
hal_gpio_init(GPIOF,&init,GPIO_PIN_10);
}
int main()
{
led_init();
key_gpio_rcc_init();
//KEY1
hal_exti_key_init(EXTI9_INPUT_EVENT,GPIOGROUP,Falling);
hal_gic_key_init(KEY1_ID,IPR_EXTI9);
//KEY2
hal_exti_key_init(EXTI7_INPUT_EVENT,GPIOGROUP,Falling);
hal_gic_key_init(KEY2_ID,IPR_EXTI7);
//KEY3
hal_exti_key_init(EXTI8_INPUT_EVENT,GPIOGROUP,Falling);
hal_gic_key_init(KEY3_ID,IPR_EXTI8);
while(1)
{
//当按键按下之后,触发irq异常源
//执行中断处理函数
}
return 0;
}
do_irq.c
#include "key.h"
extern void delay_ms(int ms);
extern void printf(const char *fmt, ...);
//按键按下之后,打印一句话
void do_irq(void)
{
unsigned int num;
//1.获取中断号 IAR[9:0]
num = GICC->IAR & 0x3ff;
//2.判断中断号
switch(num)
{
case 97: // KEY2 ---->LED2---->PF10
GPIOF->ODR ^= (0x1 << 10);
printf("key2 interrupt id = %d\n",num);
EXTI->FPR1 |= (0x1 << 7);
GICD->ICPENDR[3] |= (0x1 << 1);
break;
case 98: //KEY3 ---->LED1---->PE10
GPIOE->ODR ^= (0x1 << 10);
printf("key3 interrupt id = %d\n",num);
EXTI->FPR1 |= (0x1 << 8);
GICD->ICPENDR[3] |= (0x1 << 2);
break;
case 99: //KEY1 ---->LED3---->PE8
GPIOE->ODR ^= (0x1 << 8);
delay_ms(500);
printf("key1 interrupt id = %d\n",num);
//3.清除EXTI层中断挂起标志位 FPR1[9] = 1
EXTI->FPR1 |= (0x1 << 9);
//4.清除GICD层中断挂起标志位 ICPENDR[3] 第3位写1
GICD->ICPENDR[3] |= (0x1 << 3);
break;
}
//5.清除中断号EOIR
GICC->EOIR = num;
}
gpio.c
#include "gpio.h"
void hal_gpio_init(gpio_t* gpiox,gpio_init_t *init,unsigned int pin)
{
gpiox->MODER &= (~(0x3 << (pin * 2)));
gpiox->MODER |= (init->moder << (pin * 2));
gpiox->OTYPER &= (~(0x1 << pin));
gpiox->OTYPER |= (init->otyper << pin);
gpiox->OSPEEDR &= (~(0x3 << (pin * 2)));
gpiox->OSPEEDR |= (init->ospeedr << (pin * 2));
gpiox->PUPDR &= (~(0x3 << (pin * 2)));
gpiox->PUPDR |= (init->pupdr << (pin * 2));
}
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status)
{
if(status == OFF)
{
gpiox->ODR &= (~(0x1 << pin));
}
else
{
gpiox->ODR |= (0x1 << pin);
}
}
key.c
#include "key.h"
//GPIO章节和RCC章节初始化
void key_gpio_rcc_init()
{
//KEY1--->PF9
//KEY2--->PF7
//KEY3--->PF8
//1.设置GPIOF组使能 MP_AHB4ENSETR[5] = 1
RCC->MP_AHB4ENSETR |= (0x1 << 5);
//2.设置PF9为输入模式 MODER[19:18] = 00
GPIOF->MODER &= (~(0x3 << 18));
//3.设置PF7为输入模式 MODER[15:14] = 00
GPIOF->MODER &= (~(0x3 << 14));
//4.设置PF8为输入模式 MODER[17:16] = 00
GPIOF->MODER &= (~(0x3 << 16));
}
//EXTI章节初始化
void hal_exti_key_init(unsigned int input_event,
unsigned int gpiogroup,triger_t trigger)
{
//1.设置GPIO引脚和EXTI进行连接
switch(input_event / 4)
{
case 1:
EXTI->EXTICR2 &= (~(0xff << (input_event % 4 * 8)));
EXTI->EXTICR2 |= (gpiogroup << (input_event % 4 * 8));
break;
case 2:
EXTI->EXTICR3 &= (~(0xff << (input_event % 4 * 8)));
EXTI->EXTICR3 |= (gpiogroup << (input_event % 4 * 8));
break;
case 3:
break;
}
//2.设置中断触发方式
if(trigger == Falling)
{
//触发方式为下降沿触发
EXTI->FTSR1 |= (0x1 << input_event);
}
else
{
//触发方式为上升沿触发
EXTI->RTSR1 |= (0x1 << input_event);
}
//3.设置中断不屏蔽
EXTI->C1IMR1 |= (0x1 << input_event);
}
//GIC章节初始化
void hal_gic_key_init(unsigned int id,unsigned int ipr)
{
//1.设置GICD层中断使能寄存器
GICD->ISENABLER[id/32] &= (~(0x1 << (id % 32 )));
GICD->ISENABLER[id/32] |= (0x1 << (id % 32));
//2.设置GICD层中断优先级寄存器
GICD->IPRIORITYR[id/4] &= (~(0x1f << (id % 4 * 8 + 3)));
GICD->IPRIORITYR[id/4] |= (ipr << (id % 4 * 8 + 3));
//3.设置GICD层中断目标分配寄存器
GICD->ITARGETSR[id/4] &= (~(0x3 << (id % 4 * 8)));
GICD->ITARGETSR[id/4] |= (0x1 << (id % 4 * 8));
//4.设置GICD层中断全局控制器
GICD->CTRL |= (0x1 << 0);
//5.设置GICC层中断优先级寄存器
GICC->PMR |= (0x1f << 3);
//6.设置GICC层中断全局控制器
GICC->CTRL |= (0x1 << 0);
}
gpio.h
#ifndef __GPIO_H__
#define __GPIO_H__
typedef struct{
volatile unsigned int MODER;
volatile unsigned int OTYPER;
volatile unsigned int OSPEEDR;
volatile unsigned int PUPDR;
volatile unsigned int IDR;
volatile unsigned int ODR;
}gpio_t;
#define GPIOE ((gpio_t*)0x50006000)
#define GPIOF ((gpio_t*)0x50007000)
#define GPIO_PIN_0 0
#define GPIO_PIN_1 1
#define GPIO_PIN_2 2
#define GPIO_PIN_3 3
#define GPIO_PIN_4 4
#define GPIO_PIN_5 5
#define GPIO_PIN_6 6
#define GPIO_PIN_7 7
#define GPIO_PIN_8 8
#define GPIO_PIN_9 9
#define GPIO_PIN_10 10
#define GPIO_PIN_11 11
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_14 14
#define GPIO_PIN_15 15
typedef enum{
INPUT = 0,
OUTPUT,
ALT,
ANALOG,
}gpio_moder_t;
typedef enum{
PP = 0,
PDR,
}gpio_otyper;
typedef enum{
LOW = 0,
MED,
HIGH,
VERY_HIGH,
}gpio_ospeedr;
typedef enum{
NO_PUPDR = 0,
PU,
PD,
RESERVE,
}gpio_pupdr;
typedef enum{
OFF = 0,
ON,
}gpio_status_t;
typedef struct{
gpio_moder_t moder;
gpio_otyper otyper;
gpio_ospeedr ospeedr;
gpio_pupdr pupdr;
}gpio_init_t;
void hal_gpio_init(gpio_t* gpiox,gpio_init_t *init,unsigned int pin);
void hal_gpio_write(gpio_t* gpiox,unsigned int pin,gpio_status_t status);
#endif
key.h
#ifndef __KEY_H__
#define __KEY_H__
#include "stm32mp1xx_rcc.h"
#include "gpio.h"
#include "stm32mp1xx_exti.h"
#include "stm32mp1xx_gic.h"
typedef enum{
Rising = 0,
Falling,
}triger_t;
//GPIO章节和RCC章节初始化
void key_gpio_rcc_init();
//EXTI章节初始化
void hal_exti_key_init(unsigned int input_event,
unsigned int gpiogroup,triger_t trigger);
//GIC章节初始化
void hal_gic_key_init(unsigned int id,unsigned int ipr);
#endif
start.s
/*
* start.S
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* Exception vector table
*/
.text
.global _start
_start:
@ 异常向量表
b reset
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
_undefined_instruction:
.word undefined_instruction
_software_interrupt:
.word software_interrupt
_prefetch_abort:
.word prefetch_abort
_data_abort:
.word data_abort
_not_used:
.word not_used
_irq:
.word irq
_fiq:
.word fiq
/* The actual reset code */
reset:
@ 重新映射异常向量表的入口地址
/* Set Vector Base Address Register */
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1<<13)
mcr p15, 0, r0, c1, c0, 0
ldr r0,=0xc0008000
mcr p15,0,r0,c12,c0,0 @ Vector Base Address Register
/* Set the cpu to svc32 mode */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0xd3
msr cpsr, r0
/* Enable NEON/VFP unit */
mrc p15, #0, r1, c1, c0, #2
orr r1, r1, #(0xf << 20)
mcr p15, #0, r1, c1, c0, #2
mov r1, #0
mcr p15, #0, r1, c7, c5, #4
mov r0, #0x40000000
fmxr fpexc, r0
/* Cache init */
mrc p15, 0, r0, c0, c0, 0
and r1, r0, #0x00f00000
and r2, r0, #0x0000000f
orr r2, r2, r1, lsr #20-4
cmp r2, #0x30
mrceq p15, 0, r0, c1, c0, 1
orreq r0, r0, #0x6
mcreq p15, 0, r0, c1, c0, 1
/* Invalidate L1 I/D */
mov r0, #0
mcr p15, 0, r0, c8, c7, 0
mcr p15, 0, r0, c7, c5, 0
/* Disable mmu stuff and caches */
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000
bic r0, r0, #0x00000007
orr r0, r0, #0x00001000
orr r0, r0, #0x00000002
orr r0, r0, #0x00000800
mcr p15, 0, r0, c1, c0, 0
/* Initialize stacks */
@ 初始化各种模式下的占空间
init_stack:
ldr r0, stacktop /*get stack top pointer*/
/********svc mode stack********/
mov sp, r0
sub r0, #128*4 /*512 byte for irq mode of stack*/
/********irq mode stack********/
msr cpsr, #0xd2
mov sp, r0
sub r0, #128*4 /*512 byte for fiq mode of stack*/
/********fiq mode stack********/
msr cpsr, #0xd1
mov sp, r0
sub r0, #0
/********abort mode stack******/
msr cpsr, #0xd7
mov sp, r0
sub r0, #0
/********undefine mode stack**/
msr cpsr, #0xdb
mov sp, r0
sub r0, #0
/***sys mode and usr mode stack***/
msr cpsr, #0x10
mov sp, r0 /*1024 byte for user mode of stack*/
/******clear bss section********/
@ 清除BSS段
ldr r0, =__bss_start /* this is auto-relocated! */
ldr r1, =__bss_end__ /* this is auto-relocated! */
mov r2, #0x00000000 /* prepare zero to clear BSS */
clbss_l: cmp r0, r1 /* while not at end of BSS */
strlo r2, [r0] /* clear 32-bit BSS word */
addlo r0, r0, #4 /* move to next */
blo clbss_l
/* Call _main */
ldr pc, =main @ 汇编调用C 跳转到main.c文件的main函数中
/*
* Exception handlers
*/
.align 5 // 2的5次方,=32bit 也就是4字节对其
undefined_instruction:
b .
.align 5
software_interrupt:
b .
.align 5
prefetch_abort:
b .
.align 5
data_abort:
b .
.align 5
not_used:
b .
.align 5
.global irq
irq:
sub lr, lr, #4
stmfd sp!, {r0-r12, lr}
bl do_irq
ldmfd sp!, {r0-r12, pc}^
.align 5
.global fiq
fiq:
b .
stacktop: .word stack + 4 * 512
.data
stack: .space 4 * 512