一、中断简介
1.1 中断介绍
中断:单片机执行主程序时,由于某个事件的原因,暂停主程序的执行,调用相应的中断处理程序处理该事件(中断服务函数,ISR:Interrupt service routine),处理完毕后再自动继续执行主程序的过程
CPU跳到固定地址去执行代码,这个固定地址通常被称为中断向量,这个跳转时硬件实现的
中断处理过程包含中断请求、中断响应、中断服务及中断返回四个步骤:
中断请求:中断源向CPU发出中断请求
中断响应:CPU允许中断,主程序或中断服务程序暂停,进入中断服务程序(ISR)
中断服务:执行中断服务程序的过程
中断返回:中断服务程序执行完毕后回到主程序或者次级别中断服务程序的过程
1.2 中断延迟处理
中断能打断任何优先级的任务的运行,因此中断一般用于处理比较紧急的事件,ISR执行的要快,否则:
(1)其他低优先级的中断无法被处理:实时性无法保证
(2)用户任务无法被执行:系统显得很卡顿
如果中断非常耗时间,那就需要分为两部分做:
(1)只做简单处理,例如标记该事件,然后触发某个任务
(2)任务:处理复杂且耗时的操作
在使用 FreeRTOS 系统时,ISR和任务之间进行通信一般使用消息队列、信号量、任务通知(只可以发送)或事件标志组等,将标志发给处理任务, 任务做具体处理
具体流程:
t1:任务1运行,任务2阻塞
t2:发生中断,该中断的ISR函数被执行,任务1被打断
ISR函数要尽快能快速地运行,它做一些必要的操作(比如清除中断),然后唤醒任务2
t3:在创建任务时设置任务2的优先级比任务1高(这取决于设计者),所以ISR返回后,运行的是 任务2,它要完成中断的处理。任务2就被称为"deferred processing task",中断的延迟处理任务。
t4:任务2处理完中断后,进入阻塞态以等待下一个中断,任务1重新运行
通过中断机制,在外设不需要 CPU 介入时,CPU 可以执行其他任务,而当外设需要 CPU 时通过产生中断信号使 CPU 立即停止当前任务转而来响应中断请求。这样可以使 CPU 避免把大量时间耗费在等待、查询外设状态的操作上,因此将大大提高系统实时性以及执行效率。
1.3 中断优先级分组
ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级,但STM32,只用了中断优先级配置寄存器的高4位 [7 : 4],所以STM32提供了最大16级的中断优先等级
其中,STM32的中断分为抢占优先级和响应优先级、
抢占优先级:抢占优先级高的中断可以打断正在执行但抢占优先级低的中断
响应优先级:当同时发生具有相同抢占优先级的两个中断时,子优先级数值小的优先执行
注意:中断优先级数值越小,优先级越高
对于FreeRTOS而言:
(1)低于configMAX_SYSCALL_INTERRUPT_PRIORITY优先级的中断里才允许调用FreeRTOS 的API函数
(2)由于高优先级中断可以抢占低优先级中断,但如果存在子优先级,对于正在运行的中断(抢占优先级相同),子优先级高的中断无法打断正在运行的中断,对于全部设置为抢占式优先级,很容易区分中断优先级。为了方便FreeRTOS管理,分组方式建议
使用分组4:NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 ),全部设置为抢占优先级
(3)中断优先级数值越小越优先,任务优先级数值越大越优先
二、中断相关寄存器
2.1 中断优先级配置寄存器(配置PendSV:上下文切换、Systick:任务调度,中断优先级)
三个系统中断优先级配置寄存器(32位),分别为 SHPR1、 SHPR2、 SHPR3
SHPRx是一个 32 位的寄存器,只能通过字节访问,每 8 位控制着一个内核外设的中断优先级的配置。位 7:4 这高四位有效,所以可编程为 0 ~ 15
SHPR1寄存器地址:0xE000ED18
SHPR2寄存器地址:0xE000ED1C
SHPR3寄存器地址:0xE000ED20
下图所示,每个寄存器为8位,4个寄存器组成一个优先级寄存器SHPR
在FreeRTOS中,port.c文件中定义
(1)SHPR3寄存器的地址(包括PendSV、Systick)
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_PENDSV_PRI ( ( ( uint32_t )
configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t )
configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
(2)在FreeRTOSConfig.h中定义了配置内核中断优先级:255(0xFF:1111 1111)即最低优先级,Cortex-M3只需关注高四位即可
#define configKERNEL_INTERRUPT_PRIORITY 255
所以(1)中的下面两句是将PendSV、 Systick优先级寄存器(8位)全设为1,除此之外,其余位均为0
(3) 由于SHPR3为32位寄存器,所以要按位或配置PendSV、Systick优先级寄存器,不改变其他寄存器的值,将其设置为最低优先级
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
※ 注:每开启任务调度器,FreeRTOS将PendSV和SysTick设置最低优先级,保证系统任务切换不会阻塞系统其他中断的响应(中断可以打断任务,但任务不可以打断中断)
2.2 中断屏蔽寄存器
三个中断屏蔽寄存器,分别为 PRIMASK、 FAULTMASK 和BASEPRI
1:关中断,0开中断
名称 | 描述 |
PRIMASK | 只有1位 1:关闭所有可屏蔽的中断,只剩下NMI和硬fault可以响应 0:不关闭中断(默认值) |
FAULTMASK | 只有1位 1:关闭所有中断,只剩下NMI可以响应 0:不关闭中断(默认值) |
BASEPRI | 最多9位,由表达优先级的位数决定,定义了被屏蔽优先级的阈值 设置某值:所有优先级数值大于等于此值的中断(即 |