cortex A7核按键中断实验

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



实验现象

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AST2600 SoC 包含两个主要的处理器心:一个 Cortex-A7 内和一个 Cortex-M3 内。这两个内之间可以通过 AMBA AXI4 接口进行通信。在 Cortex-M3 内中,可以通过 NVIC(Nested Vector Interrupt Controller)设置和管理中断。以下是在 AST2600 中设置 Cortex-M3 内间通信中断的基本步骤: 1. 配置 AMBA AXI4 接口:在 Cortex-A7 内中,需要配置 AMBA AXI4 接口,以便与 Cortex-M3 内进行通信。这包括设置 AXI4 接口的基址、大小和属性等参数。 2. 配置 Cortex-M3 中断:在 Cortex-M3 内中,需要使用 NVIC 设置和管理中断。可以使用 CMSIS(Cortex Microcontroller Software Interface Standard)库中提供的 NVIC API 来设置中断优先级、使能中断等。 3. 设置中断处理程序:在 Cortex-M3 内中,需要编写中断处理程序来处理接收到的中断。可以使用标准的 C 或汇编语言编写中断处理程序,并将其链接到正确的中断向量表中。 4. 触发中断:在 Cortex-A7 内中,可以通过向 AXI4 接口发送中断请求来触发中断。当 Cortex-M3 内接收到中断请求后,将跳转到相应的中断处理程序中执行。 需要注意的是,上述步骤仅提供了一般的框架,具体的实现方式可能会因系统架构和应用场景而异。在实际应用中,可能需要进一步优化中断处理程序的性能和可靠性,并考虑调试和故障排除等方面的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值