下面按IAR Embedded Workbench for Arm里最常见的Cortex-M工程来写。IAR官方文档明确说明,Cortex-M的中断函数进入和返回方式与普通函数一致,不使用__irq、__fiq这类关键字;同时,异常名和默认向量代码由cstartup_M.c或cstartup_M.s提供。也就是说,IAR里的中断配置,核心不是“给函数加特殊修饰”,而是把启动文件、向量表、链接地址和NVIC设置对齐。
一、IAR ARM中断怎么配置
先把中断入口接对,再去谈优先级,不然程序能编过,但中断未必能真正进来。IAR文档说明,向量表应保持__vector_table这个名字,因为C-SPY会靠这个符号定位向量表;默认异常处理函数是weak符号,你自己只要用同名函数定义新的处理函数,就会覆盖默认实现。
1、先用器件头文件里的IRQn_Type对齐中断号
CMSIS设备头文件会定义IRQn_Type,负数是内核异常,非负数是外设中断;这份枚举本来就是给启动文件和NVIC配置对齐用的。中断号如果和头文件不一致,后面即使函数名写对,向量位置也可能错。
2、处理函数先按启动文件里的名字覆盖
像NMI_Handler、HardFault_Handler、SysTick_Handler这些名字,IAR已经在cstartup_M.c或cstartup_M.s里定义为weak符号。你在工程里直接写同名函数即可覆盖默认处理;如果还要加入额外外设中断项,就应复制并修改cstartup_M.c或cstartup_M.s,把新入口补进向量表。
3、把向量表和启动代码放到正确地址
IAR的链接文档给过明确示例,启动代码和向量表通常要放在ROM起始处,或者直接放到地址0x0;同时,启动代码和初始向量表应位于非易失存储器。工程里最该核对的就是icf链接文件有没有把相应section放到起始区域。
4、优先级和使能尽量走CMSIS接口
CMSIS提供了NVIC_EnableIRQ、NVIC_SetPriority、NVIC_SetPriorityGrouping这些接口,设备头文件还会给出__NVIC_PRIO_BITS。实际项目里,优先级最好不要自己手算移位后直接写寄存器,先用CMSIS接口把基础配置做稳,后面核对也更直接。
5、如果有Bootloader或RAM重定位,再补一层VTOR
Arm文档说明,SCB->VTOR用来指定向量表基址;复位后,处理器会从VTOR当前值对应的位置取初始栈顶和Reset向量。所以只要你的应用不是直接从默认地址启动,就一定要把VTOR一并核对。
二、IAR ARM向量表与优先级怎么核对
真正排错时,最好别只看代码,要从“表”和“寄存器”两头同时核。Arm文档说明,向量表里先放初始MSP,再放各异常和中断入口地址;而IAR文档又要求这个表保持__vector_table符号名。也就是说,核对时要同时看启动文件中的表项顺序,以及运行时VTOR、优先级寄存器和分组寄存器的实际值。
1、先核向量表顺序是不是和IRQn_Type一致
CMSIS设备头文件要求IRQn_Type反映启动文件中的向量扩展顺序,所以最先要查的是startup文件里外设中断项有没有漏、有没有排错位。尤其是自己改过cstartup_M.c或cstartup_M.s的项目,这一步最容易出问题。
2、再核VTOR当前指向的到底是不是这张表
如果链接文件把表放在Flash起始区,但程序运行时又把VTOR改到了别处,那么真正生效的是VTOR指向的那张表,不是你在源码里看到的那张。核对时要把链接地址、下载后的内存内容和SCB->VTOR三者对上。
3、优先级先看位宽,再看数值
__NVIC_PRIO_BITS由设备头文件定义,表示芯片实际实现了多少个优先级位。Arm还特别说明,优先级位实现于优先级寄存器的高位,未实现位写入会被忽略;如果直接向NVIC的优先级寄存器写值,就必须按这个高位对齐规则理解结果。
4、分组不要只看SetPriority,要把PRIGROUP读出来
NVIC_SetPriorityGrouping和NVIC_GetPriorityGrouping对应的是AIRCR的PRIGROUP字段,它决定了“抢占优先级”和“子优先级”怎么分。很多项目表面上优先级数字没问题,实际却是分组改过导致抢占关系和预期不一致,所以核对时一定要把PRIGROUP一起读出来。
5、最稳的做法是用Encode和Decode反推一次
CMSIS提供NVIC_EncodePriority和NVIC_DecodePriority,专门把PriorityGroup、抢占优先级和子优先级互相换算。如果现场已经有人手工写过优先级,最省事的核对方式不是重新心算,而是把当前PriorityGroup和优先级值丢进Decode看实际拆分结果。
三、IAR ARM中断排查时最容易漏的地方
很多中断问题不是“没开中断”,而是表、地址、分组和数值有一处没对齐。把下面几项连起来看,排查会快很多。相关依据都能在IAR和Arm的官方资料里对上。
1、函数名对了,但没进正确向量槽
这通常是startup文件改过、IRQn顺序不一致,或者自定义中断没有真正补进向量表。
2、源码里的表是对的,但运行时VTOR指到了别处
这类问题最常见于Bootloader、双镜像和RAM向量表场景。
3、数值写成了对的“逻辑优先级”,却错在寄存器位对齐
尤其是直接写IPR的项目,最容易忽略“实现位在高位”这一点。
4、优先级值本身没错,但PRIGROUP改了
一旦分组变化,抢占关系和子优先级关系都会跟着变,不能只盯NVIC_SetPriority的参数。
总结
IAR ARM中断怎么配置,按Cortex-M口径看,关键就是四步:处理函数用正确名字覆盖weak默认入口,向量表保持__vector_table,链接文件把启动代码和向量表放到正确地址,再用CMSIS接口完成使能和优先级设置。IAR ARM向量表与优先级怎么核对,最实用的顺序则是先核startup文件和IRQn_Type,再核SCB->VTOR,接着核__NVIC_PRIO_BITS和PRIGROUP,最后用NVIC_DecodePriority把当前优先级实际拆分结果反推一遍。这样查下来,绝大多数“中断不进”或“优先级不对”的问题都能比较快定位。