在嵌入式开发中,中断(Interrupt)是一种机制,可以使处理器暂停当前执行的任务,去处理一个紧急或高优先级的事件。中断机制能帮助嵌入式系统快速响应外部或内部的事件,提升实时性能和效率。
基本概念
中断是由硬件或软件事件触发的一种信号,用于打断处理器的当前流程,使其快速跳转到指定的 中断服务程序(ISR),以便处理特定事件。当 ISR 执行完毕,处理器会返回并继续执行被打断的任务。
中断的分类
中断大体可以分为以下几类:
- 外部中断:由外部硬件触发,例如按钮、传感器、计数器等。这类中断通常用于捕获外部事件。
- 内部中断:由处理器或外设内部事件触发,如定时器溢出、ADC 转换完成、串口数据接收等。
- 软件中断:通过软件指令触发的中断,用于实现特定的软件功能或系统调用。
中断的工作原理
中断的基本工作流程如下:
- 中断请求:中断源(如外设或软件)产生中断请求信号。
- 中断响应:处理器停止当前任务,并保存当前状态(如程序计数器和寄存器等)。
- 执行 ISR:处理器跳转到对应的中断服务程序,执行中断处理代码。
- 恢复执行:ISR 执行完成后,处理器恢复之前保存的状态,继续执行被打断的任务。
中断优先级和嵌套
在多中断系统中,中断的优先级决定了响应的先后顺序。中断的优先级可以进一步细分为不同的类型,以便更好地满足系统实时性和复杂性的需求。常见的中断优先级类型包括响应式优先级、抢占式优先级和自然优先级。
- 响应式优先级:响应式中断优先级指的是,中断的处理根据固定优先级顺序进行,不支持中断的嵌套或抢占;在多个中断发生时,优先响应高优先级的中断,直到 ISR 完成才响应下一个中断。
- 抢占式优先级:抢占式中断优先级允许高优先级中断打断低优先级中断的执行;
- 自然优先级:自然优先级是一种基于中断向量表的优先级机制,自然优先级实际上是中断向量表的序号,序号越小优先级越高。
无论是抢占优先级还是响应优先级,都是用数值表示的,数值越小,优先级越高。
中断向量表
中断向量表存储了各个中断服务程序的入口地址。每个中断源都有一个固定的入口地址。当发生中断时,处理器通过中断向量表找到相应 ISR 的地址并跳转执行。
中断服务程序(ISR)
中断服务程序用于处理中断事件的具体逻辑。设计 ISR 时需要注意以下几点:
- 简短高效:ISR 应该尽量简洁,避免长时间运行,减少对主程序的影响。
- 避免阻塞操作:ISR 中不适合使用延时、复杂计算或等待操作,以避免影响系统的实时性。
- 使用中断标志位:很多中断事件触发后会设置特定的标志位,ISR 中通常需要检查和清除标志位,以防止重复触发。
事件
事件是一种简化的触发机制,通常用于在不需要中断服务程序(ISR)的情况下唤醒处理器或触发某些外设的操作。事件不会打断当前的程序执行,也不会跳转到一个特定的中断服务程序。因此,事件的处理方式更加轻量,也没有优先级之分。
NVIC
NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)是 ARM Cortex-M 系列微控制器内核中的一个重要模块,负责管理和控制中断请求的响应和优先级处理。
优先级分组
优先级分组机制是一种在嵌入式系统中管理中断优先级的方式,它允许系统在中断的抢占优先级和子优先级(响应式优先级)之间进行分配,以更灵活地控制中断响应顺序。ARM Cortex-M 系列处理器通过嵌套向量中断控制器(NVIC)提供了优先级分组机制,使得在处理多种中断时可以实现更高的系统实时性和响应能力。
在 Cortex-M 架构中,中断优先级通过嵌套式向量型中断控制器(NVIC)进行配置;在 Cortex-M4 中使用 4 位来设置优先级;常见分组如下:
优先级分组 | 抢占优先级位数 | 子优先级位数 | 优先级分组类型描述 |
---|---|---|---|
0 | 4 | 0 | 全抢占优先级,没有子优先级 |
1 | 3 | 1 | 3 位抢占优先级,1 位子优先级 |
2 | 2 | 2 | 2 位抢占优先级,2 位子优先级 |
3 | 1 | 3 | 1 位抢占优先级,3 位子优先级 |
4 | 0 | 4 | 没有抢占优先级,全部为子优先级 |
举例:在 4 位抢占优先级、0 位子优先级的情况下,抢占优先级可以使用 0 到 15 之间的值进行设置;因为他占了四个字节。
回调函数
回调函数是一种将函数作为参数传递给另一个函数的编程技术。回调函数的作用是:允许一个函数在完成某些特定任务后,通过调用另一个“回调”函数来通知调用方任务完成,或执行特定的后续操作。
在中断处理中,我们不可以帮用户做决定,所以我们在中断中无法预知客户要做的事情是什么,这时候就可以使用回调函数;
中断
ARM Cortex-M 系列中断分为三类:
- 系统异常(System Exceptions):
- 内核自带的异常,例如复位(Reset)、不可屏蔽中断(NMI)、硬故障(Hard Fault)等。优先级较高,通常用于处理系统级的错误和状态。
- 外部中断(External Interrupts):
- 由外设(如 GPIO、UART、定时器等)产生的中断,通过 NVIC 进行管理。这些外部中断优先级由用户定义,响应外部事件,例如按钮按下、数据接收完成等。
- 软件中断(Software Interrupts):
- 由软件触发的中断,用于在代码中人为产生中断以实现特定功能,如任务调度或操作系统中的上下文切换。
EXTI(外部中断)
EXTI(External Interrupt/Event Controller,外部中断/事件控制器)主要作用是捕获外部中断/事件。
EXTI 负责检测和生成中断事件,而 NVIC 负责管理和调度中断的响应。
EXTI 的结构与工作流程:
- EXTI Line0~22:
- EXTI 控制器提供了多个外部中断线(Line0~Line22),这些线可以连接到外部设备或者 GPIO 引脚。
- 每一条 EXTI 线可以设置为边沿检测,即检测上升沿或下降沿的信号变化。
- 极性控制:
- 用于设置信号的触发极性。可以选择触发上升沿、下降沿,或者两者都触发。
- 极性控制模块通过设置不同的极性,控制边沿检测器检测信号变化的类型。
- 边沿检测:
- 边沿检测模块用于检测外部信号的变化。根据极性控制的设定,这里可以检测上升沿、下降沿,或者两者都检测。
- 当检测到符合设定的边沿信号时,将触发后续的中断或事件。
- 软件触发:
- 软件触发模块允许通过编程来触发 EXTI 中断,而不依赖外部信号。
- 通过软件触发,程序可以手动生成中断或事件,适用于某些特殊的控制场景。
- 中断屏蔽控制:
- 中断屏蔽控制模块用于控制 EXTI 信号是否生成中断。
- 当中断屏蔽控制允许时,检测到的边沿信号将触发中断信号并传输给 NVIC。
- 事件屏蔽控制:
- 事件屏蔽控制模块用于控制 EXTI 信号是否生成事件。
- 当事件屏蔽控制允许时,检测到的边沿信号将触发一个事件,用于系统内部的其他功能模块,如低功耗模式下的唤醒。
- 事件产生:
- 事件产生模块在满足边沿检测条件时产生事件。事件不同于中断,它不会直接引发 NVIC 的中断请求,而是用于系统的其他用途,比如唤醒单元等。
- 至 NVIC:
- 如果边沿检测模块检测到外部信号符合设定的条件,并且中断屏蔽控制允许,则通过 NVIC 触发中断服务程序。
- 至唤醒单元:
- 如果边沿检测满足条件且事件屏蔽控制允许,则可以触发事件产生,用于唤醒单元。
- 该功能主要在低功耗模式下使用,用于处理待机或睡眠模式下的唤醒需求。
中断和事件是独立控制的,可以通过配置相应的寄存器来独立启用或屏蔽中断和事件。
- 若只开启中断屏蔽而屏蔽事件,则只会产生中断,不会产生事件。
- 若只开启事件屏蔽而屏蔽中断,则只会产生事件,不会产生中断。
- 若同时开启中断和事件屏蔽,那么信号变化时会同时产生中断和事件。
EXTI 编号与触发源
NVIC
NVIC 是处理器核心中的一个模块,负责接收和管理中断请求。它可以将多个中断请求进行排序,按优先级分配中断,决定何时和以何种优先级响应中断。
中断向量表
示例流程
假设一个按键连接到 GPIO 引脚,用来触发 EXTI 中断,流程如下:
- EXTI 监测按键状态,检测到按键按下,生成一个中断请求并将其发送到 NVIC。
- NVIC 检查优先级:如果该中断优先级足够高,NVIC 将立即响应此请求,暂停其他任务。
- 执行中断服务程序:系统进入按键中断服务程序(ISR)进行处理,如记录按键状态或执行相应的功能。
- 清除中断标志:在 ISR 中处理完毕后,清除 EXTI 的中断标志,以便下一次按键按下时可以重新触发中断。
- 恢复正常运行:NVIC 将控制权交还给主程序或其他正在运行的任务。s
SYSCFG
SYSCFG(系统配置控制器)是 ARM Cortex-M 微控制器(如 STM32 系列)中的一个重要外设,负责配置系统的各种功能和引导外设的资源管理。
外部中断配置
- 引脚映射:SYSCFG 允许将外部 GPIO 引脚映射到 EXTI(外部中断)线。用户可以指定哪些引脚用于外部中断触发。
- 中断触发条件:支持设置中断触发条件(上升沿、下降沿、双边沿),以满足不同应用的需求。
MISC
MISC 是对嵌套向量中断控制器(NVIC)和系统定时器(SysTick)操作的软件包。
实现
功能:通过外部中断监听按钮按下和抬起的动作
硬件触发
1 | // GPIO 配置 |
步骤:
- GPIO 的配置
- 主要外部中断不在 GPIO的复用选项中,我们需要通过其他方式将 GPIO 映射到 EXIT。
- EXTI 配置
- GPIO 配置完成后,查看用户手册了解所使用的引脚属于那个中断源
- 使能 SYSCFG 外部时钟,将 GPIO 引脚映射到 EXTI
- 配置 NVIC
- 配置 EXIT,并使能
- 编写中断处理函数
- NVIC 所对应的中断处理函数要到启动文件(.s)文件中去找
- 在编写时候注意查看用户手册,了解我们所使用的的中断源是否需要手动清除;
软件触发
1 |
|
问题
一·、在使用 EXTI 与 NVIC 时为什么不需要显示的开启外部时钟
因为这两个模块的工作原理和时钟管理与外部时钟的启用无关。
EXTI 是用于处理外部硬件事件(如按键、传感器、外部信号等)触发的中断。它本质上是一个由外部事件触发的信号,依赖于微控制器的输入引脚(如 GPIO)上的状态变化。
NVIC 本身并不依赖于外部时钟。NVIC 只是处理从不同外设或外部事件(如 EXTI)发出的中断请求。它的作用是管理中断的优先级、响应时间以及是否允许中断等,所有这些操作都基于内部时钟(通常是系统时钟或 APB 时钟)。所以,NVIC 与外部时钟并无直接关系。
二、通过计数消抖这时间如何确定
以波特率为 115200 bps 为例,假设数据帧格式为1 位起始位 + 8 位数据位 + 1 位停止位,总共 10 位:
也就是说我们延时的时间比这个大就可以了;
三、exti_interrupt_flag_clear(EXTI_0);,可能会产生的bug
当凑巧我们按下的时候 EXTI0_IRQHandler 中的条件 cur_cnt - pre_cnt <= 100 为真时,函数会直接 return,而 在返回前没有清除 EXTI 的中断标志位。在这种情况下,该中断标志位依然保持为 1,因此后续也不会再触发相同的中断。
因此我们应该在进入中断后第一时间清除标志位;