赞
踩
一般中断定义为打断CPU指令正常执行顺序的事件。
在芯片中,打断CPU执行顺序的事件,有两种情况:
1)硬件中断(硬件事件)
在CPU指令周期的任何时刻都有可能发生的。
"异步中断" ===>中断
2)软中断(系统错误)
在执行某条指令时,产生的一种编程错误/系统错误,也需要打断CPU的执行顺序,去做错误处理。
“异步中断” ===>异常
cortex M4处理器有两种工作模式
1.线程模式(thread mode)
正常模式
2.处理模式(handler mode)
异常模式/中断模式
注:当CPU的INTR引脚收到一个信号。CPU就会自动切换到处理模式,去执行相应的中断服务程序(中断处理函数),处理完毕后,再回到线程模式下。
CPU如何知道具体是哪个中断产生了?
xPSR[8:0]:程序状态寄存器的最低位是用来表示 IPSR 中断程序状态寄存器,其作用就是用来保存当前产生的那个中断的中断编号
NVIC在管理和维护中断通道时,给每个中断请求线一个唯一的编号,当某个中断产生后,NVIC会将该中断的编号存入到 IPSR中,并向CPU的INTR已经发起中断请求,来打断CPU的正常执行,迫使CPU进入 处理模式
CPU在进入处理模式后,通过IPSR获取到中断编号,也就知道是哪个中断产生了!!!
CPU如何知道该中断对应的服务程序是哪个?
CPU预先定义一个数组,当遇到某个中断,就可以到那个地址去执行,这个数组就是“中断向量表" ===> 保存在启动文件中。
中断向量表:本质其实就是一个中断处理函数指针数组,数组中每个元素就是一个函数指针,指向一个个的中断服务程序,并且在中断向量表这个数组中,数组元素下标就是中断号
也就是说 中断向量表实际上就是记录了各个中断处理函数的入口地址(函数名)
这个向量表本身保存在哪个地方呢?cortex M4约定保存在存储器0x0000 0000的那个地方,然后地址位0处一般是存储引导代码。它通常是FLASH或者ROM器件,所以NVIC中有一个寄存器,称为"向量偏移地址存储器0xE000_ED08)",通过修改它的值就能定位向量表。
NVIC向外设硬件、GPIO端口提供 硬件中断信号的输入通道,也向CPU提供系统异常信号的输入通道,并且会给每个通道一个唯一的编号,称为 中断编号,共 8bits 即 M3/M4总共有 256个中断通道,其中:
240个可屏蔽中断
1个不可屏蔽中断
1个滴答定时器中断
多个系统异常
图一
图二
STM32F4xx中提供 23个外部中断输入通道 EXTI0 ~ EXTI22,其中ETXI0~EXTI15分配给GPIO
GPIO端口线经过SYSCFG(数据选择器)后分为16个中断线,这16个中断线再通过EXTI(外部中断控制器)与NVIC连接
当同时发生多个中断请求时,CUP不需要判断哪个先执行,NVCI会对其进行优先级排序,最后选择优先级最高的中断请求传达到CPU,CPU则执行相应的中断服务程序即可(NVIC相当于医院的叫号系统,CPU相当于医生)
① 使能时钟(GPIO时钟、SYSCFG时钟)
【注:EXTI时钟一直开着,不用使能; NVIC为内核外设,而RCC只管内核外的外设,所以也不需要使能】
由上面框图可知中断源的配置分为3步:
① 配置GPIO端口
输入模式
GPIO端口线x
上下拉电阻
② 配置数据选择器SYSCFG
选择某个GPIO分组的具体哪个引脚作为中断口线
③ 配置EXTI外部中断控制器
选择外部中断线
中断模式/事件模式
触发边沿
① 配置优先级分组
② 配置NVIC
中断请求线
抢占优先级
响应优先级
使能
配置PA0为外部中断0
//外部中断配置 void Exti_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; EXTI_InitTypeDef EXTI_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; //1.使能时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); //SYSCFG时钟 //2.中断源配置 //2.1配置GPIO GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; //输入模式 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; //第0口线 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; //无上下拉 GPIO_Init(GPIOA, &GPIO_InitStruct); //PA0 //2.2配置选择器SYSCFG SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); //选择PA0作为EXTI0 //2.3配置外部中断控制器EXTI EXTI_InitStruct.EXTI_Line = EXTI_Line0; //外部中断线选择 EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //外部中断模式 EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; //上升沿触发 EXTI_Init(&EXTI_InitStruct); //3.配置嵌套中断向量控制器NVIC //3.1配置优先级分组 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //抢占优先级与响应优先级各占2bit //3.2配置NVIC NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; //中断请求线 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; //响应优先级 NVIC_Init(&NVIC_InitStruct); } //中断处理函数(位置任意) void EXTI0_IRQHandler(void) { //先判断中断标志位 if(EXTI_GetITStatus(EXTI_Line0) == SET) { //中断处理 //硬件置位,软件清除!!! EXTI_ClearITPendingBit(EXTI_Line0); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。