Stm32笔记-NVIC中断向量控制
NIVC中断控制的寄存器(组)是位于cortex-M3内核中的,所以平时可能较少接触所以在这里补充一个笔记。
参考资料主要是《cortex-M3中文参考手册》
1.一些与内核有关的名词
-
在内核中,所有的中断都可以称为 ”异常“ : ”异常“ 定义如下: -
”挂起“:即一个异常不能被立即响应时的状态,(我理解为 ”立flag“)定义如下: 注意:功能上是与FreeRTOS中的挂起任务列表相同,但挂起任务列表与其没有关系(时使用链表实现的) -
向量表:实际上是处理例程(我理解成是中断服务函数内容)的入口地址组成的表单。 -
一些缩写的自我猜测:
-
NMI: Not Mask Interrupt 不可屏蔽中断; 永远不会被屏蔽的中断,可用于发生紧急情况时使用; -
PendSV :Pendable request for System Serve 系统可挂起请求; FreeRtos中用于任务的切换,参考手册中也提及使用PendSV进行任务切换(需将其设为任务优先级最低),可以免去OS切换任务时检查是否有中断发生. -
MSP:主栈指针,异常(中断/中断嵌套)调度时使用; PSP:进程栈指针,任务调度时使用。
2. 异常清单:
1)系统异常及外部异常清单:
Cortex-M3共有256级中断,前16个系统中断中前4个不可变程,其余均可编程;
240个外部中断( 这里的外部是相对于Cortex_M3内核来说的,不等同于STM32的外部中断(是前者的很小一部分) )均可编程。( 如野火所说STM32的NVIC是cortex-M3NVIC的一个子集 )
stm32对这个中断清单的分配如下图:
(详情见stm32参考手册中断与事件章节)
(可以看到外部中断只占很小一部分而已,而且,stm32f103也只支持(使用256中前)60种中断(16级)而已)
3.寄存器组(族)
NVIC的寄存器数量比较多,以寄存器组(族)方式出现。而且除了自身的寄存器,还有一些其他的寄存器也于NVIC功能相关。
1)NVIC寄存器组:
NVIC 的这些寄 存器都是写 1 有效的,写 0 是无效的。
-
ISER[8]: SET ENAs族(8个32位,Interrupt Set-Enale Registers): 0xE000_E100-0xE000_E11C 对应位写一,使能240个外部中断对应的 外部中断 (还是相对于cortex-M3来说的,下面均是如此). -
ICER[8]: CLR ENAs族(8个32位,Interrupt Clear-Enale Registers): 0xE000_E180-0xE000_E19C 对应位写一,失能240个外部中断对应的 外部中断 (还是相对于cortex-M3来说的). -
ISPR[8]:SETPENDs族(8个32位,Interrupt Set-Pending Registers) 0xE000_E200 – 0xE000_E21C,写一挂起对应的 外部中断 。 -
ICPR[8]:CLRPENDs族(8个32位,Interrupt Clear-Pending Registers) 0xE000_E280 – 0xE000_E29C,写一解挂对应的 外部中断 。
-
IABR[8]:ACTIVE族,Interrupt Active Bit Registers(8*32位), 类似于状态标志位,当240个外部中断处于活动状态时,其被置1,否则为0,为只读寄存器。 -
IP[240] Interrupt Priority Registers,优先级族寄存器,共240个*8位,分别决定美个外部异常的优先级(8位中,高X位表示抢占优先级,低X位表示响应优先级,取决于优先级分组AIRCR的PRIGROUP三位),如下图:
- AIRCR;优先级分组寄存器,见上图。
2)与NVIC相关的寄存器:
以下几个寄存器常使用汇编指令访问。
-
PRIMASK 优先级屏蔽寄存器,使除NMI和硬fault外的所有异常失能。 -
FAULTMASK fault异常掩蔽寄存器,使除NMI外的所有异常失能。 cortex-M3中NMI是绝对不可能被屏蔽的。在STM32中将其与时钟树中的CSS相连,用于补救时钟故障的情况。 -
BASEPRI 只会屏蔽优先级的数字比它大的寄存器(所以对于系统的4个不可编程是没有影响的,优先级为负数)。 FreeRTOS中就是通过设置BSASEPRI的值来进出临界段。
3.库函数使用
库函数的使用相当简单,而且普遍:
- 初始化中断优先级分组(通常在主函数中进行分组,且只分一次,后来程序不会改动):
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
-
在每个需要使用中断向量的地方,对该中断向量初始化: 初始化结构体如下: typedef struct
{
uint8_t NVIC_IRQChannel;
uint8_t NVIC_IRQChannelPreemptionPriority;
uint8_t NVIC_IRQChannelSubPriority;
FunctionalState NVIC_IRQChannelCmd;
} NVIC_InitTypeDef;
NVIC_Init(&NVIC_InitStructure);
-
注意:因为在stm32的启动文件 startup_stm32f10x_hd.s 中有中断服务函数的弱定义,(为了初始化向量表),如果我们中断服务函数的函数名写错的话,那中断执行时就会跳转到启动文件中,而里面的函数是个什么都不做的死循环,系统也不会err提示。所以中断服务函数的名称一定要写对。
|