和stm32一样,cortex-A7也具有中断向量表,不过不同的是cortex-A7的中断向量表中只有8个中断,虽然看上去比stm32的中断少了很多,但是其中的IRQ中断包含了所有的外部中断,所以只要外部中断一触发,就会进入IRQ中断中判断中断类型。 在cortex-A7中,GIC中断控制器用于管理中断,可以使能或者关闭中断,设置中断优先级。GIC将众多的中断源分为三类:SPI(共享中断)、PPI(私有中断)、SGI(软件中断)。为了区别这么多的中断源,需要给它们分配一个唯一的ID,这就是中断ID。每一个CPU最多支持1020个中断,将ID0-15分配给SGI,ID16-31分配给PPI,剩下的ID都归于SPI。(这里I.MU6U总共使用了128个中断ID,加上前面PPI和SGI的32个ID,一共为160个) GIC架构分为了两个逻辑块:Distributor和CPU Interface,也就是分发器端和CPU接口端。 CP15协处理器一般用于存储系统管理,中断中也会用到,CP15一共有16个32位寄存器,其访问寄存器通过MRC(读)和MCR(写)指令。指令的格式如下: .s文件的主要内容这里不具体放出来了,里面的重要内容主要是中断向量表的实现,在复位中断函数中,需要关闭I,D Cache和MMU,设置IRQ,SYS,SVC模式下的sp指针。接下来最重要的是IRQ中断服务函数,内部最重要的部分是读取CPU接口端的GICC_IAR寄存器的值,确定中断ID(这步决定了中断处理函数的具体操作),将这个中断ID函数参数带入到C语言中的中断处理函数system_irqhandler中,在system_irqhandler中断服务函数执行完成后,重新回来执行下一步,需要将对应ID值写入GICC_EOIR寄存器。 bsp_int这个文件中的主要结构体和函数内容如下: 这里的第一句使用的了typedef定义了一个新的变量名system_irq_handler_t,这里代表着指向中断服务函数的函数指针类型。 添加了描述中断触发类型的枚举gpio_interrupt_mode_t,并添加到了原来的gpio_pin_config_t结构体中。这样就能在总的GPIO初始化函数gpio_init中添加新编写的GPIO中断初始化函数gpio_intconfig实现函数的嵌套定义。除此之外,其他的时使能或禁止指定的IO中断函数gpio_enableint/gpio_disableint和清除中断标志位函数gpio_clearintflags。 GPIO中断初始化函数gpio_intconfig中通过pin_int_mode设置中断方式寄存其ICR1和ICR2,并且在之前就禁止寄存器EDGE_SEL,从而先禁止双边沿触发方式。初始化GPIO输入或输出及中断方式后,就可以通过置位IMR寄存器来开启GPIO中断(GPIO中断结束后,要对ISR寄存器写1清零中断标志)。 在修改和编写好start.s,按键驱动文件和中断驱动文件后,就可以编写最后的按键中断驱动函数了,这段代码比较简单 最后的main函数实现非常简单,while循环中只需要添加led灯闪烁的代码,按键驱动蜂鸣器直接通过中断实现,不再需要循环检测按键,代码更加高效。cortex-A7中断
一、cortex-A7中断系统
1、cortex-A7中断向量表
2、GIC中断控制器
①中断ID
②GIC逻辑分块
分发器端主要负责各个中断事件的分发问题,也就是中断事件应该分发到哪个CPU接口端上去。分发器收集所有的中断源,可以控制每个中断的优先级,它总是将优先级最高的中断事件发送到CPU接口段。
CPU接口段的作用就是连接分发器和CPU内核,作为其中的桥梁。
历程中的“core_ca7.h”中定义了GIC结构体,其中分发器端相关的的寄存器相对于GIC基地址偏移0x1000,CPU接口端相对于GIC基地址偏移0x2000。为了能精确访问两个逻辑块的寄存器,需要知道它们各自的基地址,所以就先需要获得GIC基地址,这就要用到CP15协处理器了。③CP15协处理器
cond:指令执行的条件码,如果忽略的话就表示无条件执行。
opc1:协处理器要执行的操作码。
Rt:ARM源寄存器,用于写入或者读出的数据寄存器。
CRn:CP15协处理器的目标寄存器。
CRm:协处理器中附加的目标寄存器或者源操作数寄存器,如果不需要附加信息就设置位C0,否则结果不可预测。
opc2:可选的协处理器特定操作码,当不需要的时候要设置为0.
指令中CRn、opc1、CRm和opc2通过不同的搭配,其得到的寄存器含义是不同的。
此实验中通过c1寄存器的SCTLR寄存器来关闭I,D Cache和MMU,通过c12寄存器的VBAR寄存器设置中断向量偏移,最后通过c15寄存器的CBAR寄存器获得GIC的基地址,这样就可以通过偏移获得分发器端和CPU接口端的寄存器基地址。二、代码实现
1、start.s文件的编写
2、bsp_int文件
/* 定义中断处理函数 */ typedef void (*system_irq_handler_t)(unsigned int gicciar, void *param); /* 中断处理函数结构体 */ typedef struct _sys_irq_handle { sys_irq_handler_t irqHandler; /* 中断处理函数 */ void *userParam; /* 中断处理函数的参数 */ }sys_irq_handle_t; /* 中断初始化函数 */ void int_init(void); /* 注册中断服务函数 */ void system_register_irqhandler(IRQn_type irq, system_irq_handler_t handler, void *userParam);
下面的int_init函数中初始化了GIC和中断处理函数表,并且设置了中断向量偏移(如果start.s中设置过,这里可以不设置)。
system_register_irqhandler函数主要用于中具体注册中断处理函数(这里再bsp_exit中用于注册GPIO1_IO18的中断处理函数)。
IRQ中断发生时,会执行bsp_int.c文件中的system_irqhandler函数,会传递中断ID并执行对应的中断服务函数。3、修改bsp_gpio文件
/* 描述中断触发类型 */ typedef enum gpio_interrupt_mode { kGPIO_NoIntmode = 0U; /* 无触发 */ kGPIO_IntLowLevel = 1U; /* 低电平触发 */ kGPIO_IntHighLevel = 2U; /* 高电平触发 */ kGPIO_IntRisingEdge = 3U, /* 上升沿触发 */ kGPIO_IntFallingEdge = 4U, /* 下降沿触发 */ kGPIO_IntRisingOrFallingEdge = 5U, /* 上升沿和下降沿都触发 */ }gpio_interrupt_mode_t; /* GPIO中断初始化函数 */ void gpio_intconfig(GPIO_Type *base, int pin, gpio_interrupt_mode_t pin_int_mode) { volatile uint32_t *icr; uint32_t icrShift; icrShift = pin; base->EDGE_SEL &= ~(1 << pin); /* 清零中断引脚的EDGE_SEL位,不是双边沿触发*/ if(pin < 16) /* 低16位 */ { icr = &(bass->ICR1); /* IO0~15为ICR1寄存器 */ icrShift -=16; } else { icr = &(bass->ICR2); /* IO16~31为ICR2寄存器 */ } switch(pin_int_mode) /* 触发模式设置 */ { case kGPIO_IntLowLevel: *icr &= ~(3 << (2*icrShift)); break; case kGPIO_IntHighLevel: *icr &= ~(3 << (2*icrShift)); *icr |= (1 << (2*icrShift)); break; case kGPIO_IntRisingEdge: *icr &= ~(3 << (2*icrShift)); *icr |= (2 << (2*icrShift)); break; case kGPIO_IntFallingEdge: *icr |= (3 << (2*icrShift)); break; case kGPIO_IntRisingOrFallingEdge: base->EDGE_SEL |= (1 << pin); break; default: break; } }
4、编写最终按键中断驱动函数
/* 初始化外部中断,也就是GPIO1_IO18 */ void exit_init(void) { /* GPIO初始化及中断方式设置结构体 */ gpio_pin_config_t key_config; /* 复用为GPIO1_IO18 */ IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0); IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080); /* GPIO初始化 */ key_config.direction = kGPIO_DigitalInput; key_config.interruptMode = kGPIO_IntFallingEdge; /* 下降沿中断触发模式 */ gpio_init(GPIO1, 18, &key_config); GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); /* 注册中断服务函数 */ system_register_irqhandler(GPIO1_Combined_16_31_IRQn, (system_irq_handler_t)gpio1_io18_irqhandler, NULL); /*使能中断*/ gpio_enableint(GPIO1, 18); } /*按键对应的中断处理函数*/ void gpio1_io18_irqhandler(unsigned int gicciar, void *param) { static unsigned char state = 0; delay(10); /* 在实际的开发中,禁止在中断服务函数中调用延时函数 */ if(gpio_pin_read(GPIO1, 18) == 0) { state = !state; beep_switch(state); } /* 清除中断标志位 */ gpio_clearintflags(GPIO1, 18); }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算