1、cortex的异常和中断Cortex-M3 异常和中断-基于NXP LPC177x/8x分类:我的小问题集2013-04-10 08:261805人阅读评论(0)收藏举报目录(?)+0.前言本文想解决的问题有: 如何开启、关闭中断 如何开启、关闭异常 LPC177x/8x支持的中断优先级个数 复位后,异常/中断默认的优先级 如何设置异常/中断的优先级 什么是优先级组,如何设置优先级组,复位后的优先级组1. Cortex-M3的异常/中断屏蔽寄存器组注:只有在特权级下,才允许访问这3个寄存器。名 字功能描述PRIMASK只有单一比特的寄存器。置为1后,就关掉所有可屏蔽异常,只剩下NMI和硬Fau
2、lt可以响应。默认值是0,表示没有关闭中断。FAULTMASK只有单一比特的寄存器。置为1后,只有NMI可以响应。默认值为0,表示没有关异常。BASEPRI该寄存器最多有9位(由表达优先级的位数决定)。定义了被屏蔽优先级的阈值。当它被设置为某个值后,所有优先级号大于等于此值的中断都被关。若设置成0,则不关断任何中断,0为默认值。注:寄存器BASEPRI的有效位数受系统中表达优先级的位数影响,如果系统中只使用3个位来表达优先级,则BASEPRI有意义的值仅为0x00、0x20、0x40、0x60、0x80、0xA0、0xC0和0xE0使用MRS/MSR指令访问这三个寄存器,比如: MRS R0,
3、 BASEPRI ;读取BASEPRI到R0中 MSR BASEPRI, R0 ;将R0数据写入到BASEPRI中为了快速的开关中断,CM3还专门设置了一条CPS指令,有四种用法: CPSID I ;PRIMASK=1,关中断 CPSIE I ;PRIMASK=0,开中断 CPSID F ;FAULTMASK=1,关异常 CPSIE F ;FAULTMASK=0,开异常CMSIS-M3微控制器软件接口标准中的core_cm3.h给出了开关中断或异常的函数:1.1 开/关中断 1: /* 2: * brief Set the Priority Mask value 3: * 4: * param
4、 priMask PriMask 5: * 6: * Set the priority mask bit in the priority mask register 7: */ 8: static _INLINE void _set_PRIMASK(uint32_t priMask) 9: 10: register uint32_t _regPriMask _ASM(primask); 11: _regPriMask = (priMask); 12: 使用_set_PRIMASK(1)关闭中断;_setPRIMASK(0)开启中断。 一些说明:_INLINE是宏定义,对应_inline,这是k
5、eil编译器自定义关键字,表示这个函数是内联函数,但并不是强制性内联,编译器最终决定是否内联。 _ASM(“primask”): _ASM也是一个宏,对应_asm,这是keil编译器自定义关键字,关于这个关键字,有相当多的用法,可以在C中内嵌汇编语言、内嵌汇编函数、指定汇编标号以及本代码中的声明一个已命名寄存器变量。这里,已命名的寄存器是(primask),也就是说寄存器变量_regPriMask等同于编译器已命名的primask。语法为: register type var-name _asm(reg);keil编译器已命名的寄存器变量为:寄存器_asm修饰的字符串处理器APSRapsrAl
6、l processorsCPSRcpsrAll processorsBASEPRIbasepriCortex-M3, Cortex-M4BASEPRI_MAXbasepri_maxCortex-M3, Cortex-M4CONTROLcontrolCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4DSPdspCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4EAPSReapsrCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4EPSRepsrCortex-M0, Cortex-M1, Cort
7、ex-M3, Cortex-M4FAULTMASKfaultmaskCortex-M3, Cortex-M4IAPSRiapsrCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4IEPSRiepsrCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4IPSRipsrCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4MSPmspCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4PRIMASKprimaskCortex-M0, Cortex-M1, Cortex-M
8、3, Cortex-M4PSPpspCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4PSRpsrCortex-M0, Cortex-M1, Cortex-M3, Cortex-M4r0tor12r0tor12All processorsr14orlrr14orlrAll processorsr13orspr13orspAll processorsr15orpcr15orpcAll processorsSPSRspsrAll processors, apart from Cortex-M series processors.XPSRxpsrCortex-M0,
9、 Cortex-M1, Cortex-M3, Cortex-M41.2 开/关异常 1: /* 2: * brief Set the Fault Mask value 3: * 4: * param faultMask faultMask value 5: * 6: * Set the fault mask register 7: */ 8: static _INLINE void _set_FAULTMASK(uint32_t faultMask) 9: 10: register uint32_t _regFaultMask _ASM(faultmask); 11: _regFaultMas
10、k = (faultMask & 1); 12: 使用_set_FAULTMASK(1)来关闭中断和异常;使用_set_FAULTMASK(0)开启中断和异常.1.3 更精确的优先级屏蔽 1: /* 2: * brief Set the Base Priority value 3: * 4: * param basePri BasePriority 5: * 6: * Set the base priority register 7: */ 8: static _INLINE void _set_BASEPRI(uint32_t basePri) 9: 10: register uint32_
11、t _regBasePri _ASM(basepri); 11: _regBasePri = (basePri & 0xff); 12: 比如想屏蔽优先级不高于0x60的中断,则使用代码:_set_BASEPRI(0x60);如果想取消中断屏蔽,则使用_set_BASEPRI(0)即可。2.异常/中断和优先级 Cortex-M3的异常包括系统异常和外设中断,系统异常是Cortex-M3内核自带的一些异常,比如复位、总线Fault和SysTick等等(见表2-1),外设中断是指制造CPU的厂家加入的,比如串口、定时器中断等等(见表2-2)。注:关于异常和中断,想要分个清清楚楚实在有点困难。异常和
12、中断都可以“中断”正常执行的代码流,区别在于,异常是Cortex-M3内核产生的“中断”信号,而中断是Cortex-M3内核外部(片上外设或外部中断信号)产生的“中断”信号。希望你看懂了,有时候你心里明白,但要讲的清清楚楚着实难!表2-1:系统异常编号类型优先级简介0N/AN/A无1复位-3(最高)复位2NMI-2不可屏蔽中断(来自外部NMI输入脚)3硬Fault-1只要FAULTMASK没有置位,硬Fault服务例程会被强制执行4存储器管理Fault可编程MPU访问违例以及访问非法位置均可引发。企图在“非执行区”取址也会引发此Fault。5总线Fault可编程总线收到了错误响应,原因可以使预
13、取流产或数据流产,企图访问协处理器也会引发此Fault6用法Fault可编程由于程序错误导致的异常。通常是使用了一条无效指令,或者是非法的状态转换,例如尝试切换到ARM状态710保留保留保留11SVCall可编程执行系统服务调用指令(SVC)引发的异常12调试监视器可编程调试器(断点、数据观察点,或者是外部调试请求)13保留保留保留14PendSV可编程为系统设备而设的“可挂起请求”15SysTick可编程系统节拍时钟定时器(SysTick)表2-2:外设中断编号类型优先级简介16IRQ #0可编程外设中断#017IRQ #1可编程外设中断#1.可编程.255IRQ #239可编程外设中断#2
14、39注:表2-1和2-2中的“编号”有着特殊的意义,一是特殊功能寄存器IPSR中会记录当前正在服务的异常并给出了它的编号;二是优先级完全相同的多个异常同时挂起时,则先响应异常编号最小的那一个。 一个发生的异常如果不能被立即响应,就称它被“挂起”,值得一提的是,对于被挂起的中断/异常,中断/异常信号不必由其产生者保持,NVIC的挂起状态寄存器会来保持这个信号。所以哪怕后来挂起的中断源释放了中断请求信号,曾经的中断请求也不会丢失。 除了复位、NMI和硬Fault三个异常具有固定的优先级外,其它所有异常和中断的优先级都是可以编程的。这就涉及到优先级配置寄存器。Cortex-M3优先级配置寄存器共8位
15、,所以可以有256级的可编程优先级。但是大多数Cortex-M3芯片都会精简设计。 LPC177x/8x使用了优先级配置寄存器的5位,所以有32级可编程优先级。复位后,对于所有优先级可编程的异常,其优先级都被初始化为0(最高优先级)2.1 设置异常/中断的优先级2.1.1 系统异常优先级设置 SHPR1-SHPR3寄存器用于设置有可编程优先级的系统异常,可设置的优先级为0到31。SHPR1-SHPR3可按字节访问。为了提高软件效率,CMSIS简化了SCB寄存器的表述。在CMSIS中,字节数组SHP0 到SHP12对应于寄存器SHPR1至SHPR3。表2-3:SHPR1寄存器的位分配位名称功能3
16、1:24PRI_7保留23:16PRI_6系统处理程序6的优先级,用法Fault15:8PRI_5系统处理程序5的优先级,总线Fault7:0PRI_4系统处理程序4的优先级,存储器管理Fault表2-3:SHPR2寄存器的位分配位名称功能31:24PRI_11系统处理程序11的优先级,SVCall23:0-保留表2-4:SHPR3寄存器的位分配位名称功能31:24PRI_15系统处理程序15的优先级,SysTick 异常23:16PRI_14系统处理程序14的优先级,PendSV15:0-保留注:每个PRI_N域为8位宽,但是处理器仅实现每个域的位7:3,位2:0读取值为零并忽略写入值。2.
17、1.2 外设中断优先级设置 LPC177x/8x微处理器的中断优先寄存器IPR0IPR10用于设置外设中断优先级,控制41个外设中断。每个IPRx可以按字节访问,在CMSIS中,字节数组IP0 到IP40对应于寄存器IPR0IPR10。2.1.3 系统异常/外设中断优先级设置C代码 1: /* 2: * brief Set the priority for an interrupt 3: * 4: * param IRQn The number of the interrupt for set priority 5: * param priority The priority to set 6
18、: * 7: * Set the priority for the specified interrupt. The interrupt 8: * number can be positive to specify an external (device specific) 9: * interrupt, or negative to specify an internal (core) interrupt. 10: * 11: * Note: The priority cannot be set for every core interrupt. */ 12: static _INLINE
19、void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) 13: 14: if(IRQn SHP(uint32_t)(IRQn) & 0xF)-4 = (priority IP(uint32_t)(IRQn) = (priority AIRCR 10:8 PRIGROUP field. Only values from 0.7 are used. 9: * In case of a conflict between priority grouping and available 10: * priority bits (_NVIC_PRI
20、O_BITS) the smallest possible priority group is set. 11: */ 12: static _INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) 13: 14: uint32_t reg_value; 15: /* only values 0.7 are used */ 16: uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); 17: 18: reg_value = SCB-AIRCR; /* read old regis
21、ter configuration */ 19: /* clear bits to change */ 20: reg_value &= (SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); 21: /* Insert write key and priorty group */ 22: reg_value = (reg_value | 23: (0x5FA SCB_AIRCR_VECTKEY_Pos) | 24: (PriorityGroupTmp AIRCR = reg_value; 26: 其中,参数PriorityGroup为要设置的优先级分组(PRIGROUP)段的值,取值范围为07.由于操作AIRCR寄存器需要访问钥匙,所以要把0x05FA写入到该寄存器的bit31:16中,否则写入的值会被忽