M0/M3的异常和中断

1. Cortex-M3的异常/中断屏蔽寄存器组

注:只有在特权级下,才允许访问这3个寄存器。

 

 

 

名 字

功能描述

PRIMASK

只有单一比特的寄存器。置为1后,就关掉所有可屏蔽异常,只剩下NMI和硬Fault可以响应。默认值是0,表示没有关闭中断。

FAULTMASK

只有单一比特的寄存器。置为1后,只有NMI可以响应。默认值为0,表示没有关异常。

 

BASEPRI

该寄存器最多有9位(由表达优先级的位数决定)。定义了被屏蔽优先级的阈值。当它被设置为某个值后,所有优先级号大于等于此值的中断都被关。若设置成0,则不关断任何中断,0为默认值。

注:寄存器BASEPRI的有效位数受系统中表达优先级的位数影响,如果系统中只使用3个位来表达优先级,则BASEPRI有意义的值仅为0x00、0x20、0x40、0x60、0x80、0xA0、0xC0和0xE0

使用MRS/MSR指令访问这三个寄存器,比如:

  MRS    R0, 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  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,这是keil编译器自定义关键字,表示这个函数是内联函数,但并不是强制性内联,编译器最终决定是否内联。

       __ASM(“primask”): __ASM也是一个宏,对应__asm,这是keil编译器自定义关键字,关于这个关键字,有相当多的用法,可以在C中内嵌汇编语言、内嵌汇编函数、指定汇编标号以及本代码中的声明一个已命名寄存器变量。这里,已命名的寄存器是("primask"),也就是说寄存器变量__regPriMask等同于编译器已命名的primask。语法为:

        register type var-name __asm(reg);

keil编译器已命名的寄存器变量为:

 

 

 

寄存器

__asm修饰的字符串

处理器

APSR

"apsr"

All processors

CPSR

"cpsr"

All processors

BASEPRI

"basepri"

Cortex-M3, Cortex-M4

BASEPRI_MAX

"basepri_max"

Cortex-M3, Cortex-M4

CONTROL

"control"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

DSP

"dsp"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

EAPSR

"eapsr"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

EPSR

"epsr"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

FAULTMASK

"faultmask"

Cortex-M3, Cortex-M4

IAPSR

"iapsr"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

IEPSR

"iepsr"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

IPSR

"ipsr"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

MSP

"msp"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

PRIMASK

"primask"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

PSP

"psp"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

PSR

"psr"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

r0 to r12

"r0" to "r12"

All processors

r14 or lr

"r14" or "lr"

All processors

r13 or sp

"r13" or "sp"

All processors

r15 or pc

"r15" or "pc"

All processors

SPSR

"spsr"

All processors, apart from Cortex-M series processors.

XPSR

"xpsr"

Cortex-M0, Cortex-M1, Cortex-M3, Cortex-M4

1.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:   __regFaultMask = (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_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)。

注:关于异常和中断,想要分个清清楚楚实在有点困难。异常和中断都可以“中断”正常执行的代码流,区别在于,异常是Cortex-M3内核产生的“中断”信号,而中断是Cortex-M3内核外部(片上外设或外部中断信号)产生的“中断”信号。希望你看懂了,有时候你心里明白,但要讲的清清楚楚着实难!

表2-1:系统异常

 

 

 

编号

类型

优先级

简介

0

N/A

N/A

1

复位

-3(最高)

复位

2

NMI

-2

不可屏蔽中断(来自外部NMI输入脚)

3

硬Fault

-1

只要FAULTMASK没有置位,硬Fault服务例程会被强制执行

4

存储器管理Fault

可编程

MPU访问违例以及访问非法位置均可引发。企图在“非执行区”取址也会引发此Fault。

5

总线Fault

可编程

总线收到了错误响应,原因可以使预取流产或数据流产,企图访问协处理器也会引发此Fault

6

用法Fault

可编程

由于程序错误导致的异常。通常是使用了一条无效指令,或者是非法的状态转换,例如尝试切换到ARM状态

7~10

保留

保留

保留

11

SVCall

可编程

执行系统服务调用指令(SVC)引发的异常

12

调试监视器

可编程

调试器(断点、数据观察点,或者是外部调试请求)

13

保留

保留

保留

14

PendSV

可编程

为系统设备而设的“可挂起请求”

15

SysTick

可编程

系统节拍时钟定时器(SysTick)

表2-2:外设中断

编号类型优先级简介
16

IRQ #0

可编程

外设中断#0

17

IRQ #1

可编程

外设中断#1

...

...

可编程

...

255

IRQ #239

可编程

外设中断#239

注:表2-1和2-2中的“编号”有着特殊的意义,一是特殊功能寄存器IPSR中会记录当前正在服务的异常并给出了它的编号;二是优先级完全相同的多个异常同时挂起时,则先响应异常编号最小的那一个。

        一个发生的异常如果不能被立即响应,就称它被“挂起”,值得一提的是,对于被挂起的中断/异常,中断/异常信号不必由其产生者保持,NVIC的挂起状态寄存器会来保持这个信号。所以哪怕后来挂起的中断源释放了中断请求信号,曾经的中断请求也不会丢失。

        除了复位、NMI和硬Fault三个异常具有固定的优先级外,其它所有异常和中断的优先级都是可以编程的。这就涉及到优先级配置寄存器。Cortex-M3优先级配置寄存器共8位,所以可以有256级的可编程优先级。但是大多数Cortex-M3芯片都会精简设计。

        LPC177x/8x使用了优先级配置寄存器的5位,所以有32级可编程优先级。复位后,对于所有优先级可编程的异常,其优先级都被初始化为0(最高优先级)

2.1 设置异常/中断的优先级

2.1.1 系统异常优先级设置

        SHPR1-SHPR3寄存器用于设置有可编程优先级的系统异常,可设置的优先级为0到31。SHPR1-SHPR3可按字节访问。为了提高软件效率,CMSIS简化了SCB寄存器的表述。在CMSIS中,字节数组SHP[0] 到SHP[12]对应于寄存器SHPR1至SHPR3。

表2-3:SHPR1寄存器的位分配

名称

功能

[31:24]

PRI_7

保留

[23:16]

PRI_6

系统处理程序6的优先级,用法Fault

[15:8]

PRI_5

系统处理程序5的优先级,总线Fault

[7:0]

PRI_4

系统处理程序4的优先级,存储器管理Fault

表2-3:SHPR2寄存器的位分配

名称

功能

[31:24]

PRI_11

系统处理程序11的优先级,SVCall

[23:0]

-

保留

表2-4:SHPR3寄存器的位分配

名称

功能

[31:24]

PRI_15

系统处理程序15的优先级,SysTick 异常

[23:16]

PRI_14

系统处理程序14的优先级,PendSV

[15:0]

-

保留

注:每个PRI_N域为8位宽,但是处理器仅实现每个域的位[7:3],位[2:0]读取值为零并忽略写入值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值