Cortex-M4的系统控制模块SCB
系统控制模块(System Control Block, SCB)提供了系统实现信息,系统控制接口, 也包含了配置、控制、报告系统异常的功能。 该模块的寄存器被映射到了系统控制空间(System Control Space, SCS)中了。
1. ACTLR
默认情况下该寄存器为Cortex-m4提供了最优的性能,一般是不需要更改的。 但是,我们也可以在Privileged的权限下关闭一些功能。
- DISMCYCINT:
关闭Multi-Cycle Interruptions。当该位为'1'时,将不允许中断多周期的装载和保存数据指令。 这样将增加中断响应时间,因为必须在LDM或者STM执行结束后才能进入中断响应函数。 - DISDEFWBUF:
关闭写缓存:这将导致所有的BusFaults都是precise BusFaults。 但是会影响性能,因为在所有写数据到内存的操作完成之前是不能执行其它指令的。 - DISFOLD:
关闭IT指令的folding功能。在一些情况下,处理器可以在执行IT指令的时候, 执行一个IT块的第一条指令。这种特性被称为IT folding。 它可以提高系统的性能,但是它会产生一种jitter in looping的现象(什么鬼,没见到过)。 如果一定要避免这种现象,就要将该位置'1',关闭它。
此外还有DISFPCA和DISOOFP,干什么用的也还没弄明白。
2. CPUID
CPUID包含了处理器的版本号等实现信息。是一个只读的寄存器。
- Revision:
Cortex-M4内核版本号的p部分。 ARM的补丁版本号是rnpn的形式,其中r为大版本号标志,p为小版本号标志,n为具体的版本号。 Cortex-M4最新的版本是r0p1,所以该字段的值为1。 - PartNo:
处理器的part number,为0xC4,标志着Cortex-M4。 - Constant:
就是一个常数,为0xF,似乎没有什么意思。 - Variant:
Cortex-M4内核版本号的r部分,为0x0。 - Implementer:
0x41标志着ARM。
3. ICSR
中断控制和状态寄存器,提供了NMI的置位标志和PendSV、SysTick的置位和清除位。 同时还记录了正在执行和将要执行的中断编号,也标志了是否有中断被抢断了。 需要注意的是,对该寄存器进行写操作时不能同时对PENDST(SV)CLR和PENDST(SV)SET写1, 系统的运行情况将不可知。
- VECTACTIVE:
正在处理的异常编号。在使用CMSIS的中断编号时,需要将该值减去16, 原因参见Cortex-M4的异常和中断系统。 - RETTOBASE:
标志着中断服务函数退出后是否返回到base level。 当该位为'0'时不返回,意味着有优先级更低的中断服务被抢断了。 - VECTPENDING:
将要被处理的中断。它记录了当前所产生的中断中优先级最高的那个的中断编号, 作为下一个被处理的中断。受到BASEPRI和FAULTMASK的影响,但与PRIMASK无关。 - ISRPENDING:
标志着除了NMI和FAULT之外的中断是否产生。 - PENDSTCLR:
清除计时器SysTick的中断标志。该位只写,读的话值未知。 - PENDSTSET:
置位计时器SysTick的中断标志。 向该位写0没有影响,写1则标志SysTick中断。对该位的读标志着SysTick是否中断。 - PENDSVCLR:
清除PendSV的中断标志。 - PENDSVSET:
PendSV的中断标志。 - NMIPENDSET:
标志着NMI产生。
4. VTOR
中断向量表偏移地址寄存器。中断向量表是128个word对齐的,也就是说它的低9位都是0。 对该寄存器的设置将修改中断向量表的起始地址。 而该寄存器的第29位标志了中断向量表是在SRAM中还是代码段中,有时也称该位为TBLBASE位。
5. AIRCR
应用中断和复位控制寄存器,提供了中断的优先级分组控制,记录了数据的大小端存储方式, 以及系统的复位控制。为了安全,对该寄存器的写操作必须保证VECTKEY字段写入0x5FA, 否则将忽略该写操作。
- VECTRESET:
保留做DEBUG用,到底有啥用还不清楚。读操作返回0,如果对该位进行写操作,一定要写0, 否则效果未知。 - VECTCLRACTIVE:
与VECTRESET一样保留做DEBUG用。读操作返回0,如果对该位进行写操作,一定要写0, 否则效果未知。 - SYSRESETREQ:
请求系统重启除Debug外的所有主要外设。 - PRIGROUP:
中断分组控制,申明了PRI_n中group priority和subpriority的为划分:如下表 1 中断优先级分组
PRIGROUP
[2:0]Interrupt priority level value, PRI_N[7:4] Number of Binary point Group priority bits Subpriority bits Group priorities Subpriorities 0b0xx 0bxxxx [7:4] None 16 None 0b100 0bxxx.y [7:5] [4] 8 2 0b101 0bxx.yy [7:6] [5:4] 4 4 0b110 0bx.yyy [7] [6:4] 2 8 0b111 0byyyy None [7:4] None 16 在PRI_n中用x表示group priority的位,y表示subpriority的位 - ENDIANS:数据大小端存储,为0表示小端存储。
- VECTKEY:对该寄存器的写访问,必须保证对该字段写0x5FA,否则将忽略。对该字段的读操作将总是返回0xFA05。
6. SCR
系统控制寄存器,控制着系统进入和退出低电压状态的方式和特征。
- SLEEPONEXIT:
为0时,当中断服务函数处理完后返回到Thread模式时,系统将不休眠。 为1时,从中断服务函数返回时系统将进入sleep或者deep sleep状态。 - SLEEPDEEP:
控制着处理器进入低电压状态时是sleep模式还是deep sleep模式。为0时是sleep模式。 - SEVEONPEND:
为0时只有使能的中断才能唤醒系统,为1时所有的中断都可以唤醒系统。
7. CCR
配置和控制寄存器,控制着进入Thread模式的方式和特性,也用于使能非对齐访问和除零的异常trap。
- NONBASETHRDENA:
该位置1时,任何时候都可以通过控制EXC_RETURN的值返回到Thread模式。 为0时,则只有当没有异常需要处理时才可以返回到Thread模式。 - USERSETMPEND:
决定unprivileged软件是否可以访问STIR寄存器。 - UNLIGN_TRP:
使能unligned访问的trap。如果该位置1,那么当产生unligned访问时将产生一个usage fault。 无论该位是否置1,非对齐的LDM, STM, LDRD, STRD指令都会触发fault异常。 - DIV_0_TRP:
使能除零trap。当该位为0时,除零的结果是0。 - BFHFNMIGN:
为0时,由于读写内存产生的bus fault将产生一个lock-up。 为1时,处理优先级为-1和-2的中断,既SysTick和PendSV中断时,将忽略由于load和store指令产生的bus fault。 - STKALIGN:
配置进入中断服务时栈空间对齐方式。在进入中断时处理器用PSR的第9位标记栈对齐方式, 中断返回时将根据这一位装载正确的栈空间对齐方式。为0时,4字节对齐;为1时,8字节对齐。
8. SHPR
系统异常服务优先级寄存器,System Handler Priority Registers。 一共有三个这样的寄存器,标记为SHPR1,SHPR2,SHPR3,它们可以按字节访问。 SHPR1用于配置memory management fault(PRI_4), bus fault(PRI_5)和Usage fault(PRI_6); SHPR2用于配置SVCall(PRI_11);SHPR3则用于配置PendSV(PRI_14)和SysTick(PRI_15)。 虽然每一个PRI_n都有8位,但低4位是只读的,只有高4位可以用来配置。
9. SHCSR
系统异常服务控制和状态寄存器,System Handler Control and State Regester。 该寄存器用于激活系统异常服务,使能fault异常中断,记录系统异常中断触发事件。
如果关闭了系统异常服务,而且产生了fault异常中断,则会触发hard fault异常事件。
10. CFSR
可配置错误异常状态寄存器,Configurable Fault State Register。 该寄存器实际上可以拆分为MEMFSR,BFSR,UFSR三个子寄存器,它们可以被单独访问。
MEMFSR对应CFSR[7:0],可以通过地址0xE000ED28直接访问,涉及的位定义如下:
- IACCVIOL:
标志着处理器尝试从一段非执行内存中获取指令。 - DACCVIOL:
标志着处理器尝试从一段没有相应权限的内存中读取或者写入数据。 - MUNSTKERR:
标志着处理器从异常中断中退出时没有正确处理栈指针。 - MSTKERR:
标志着处理器进入异常中断时没有正确处理栈指针。 - MLSPERR:
标志着处理器在floating-point lazy状态下产生的内存错误。 - MMARVALID:
标志着Memory Management Fault Address Register(MMAR)中记录了一个异常地址。
BFSR对应CFSR[15:8],可以通过地址0xE000ED29直接访问,我们也可以通过0xE000ED28半字访问MEMFSR和BFSR。涉及的位定义如下:
- IBUSERR:
指令总线错误,处理器在prefetch一条指令时就会检测指令中线错误,但只有在issue指令时才将该位置‘1’。 - PRECISERR:
Precise data bus error。在处理器将该位置‘1’的同时,也会把错误地址写入BFAR中。 - IMPRECISERR:
Imprecise data bus error。当处理器将该位置‘1’时,不会写BFAR。 - UNSTKERR:
因为退出中断时没有恢复栈空间导致的各种各样的总线错误。 - STKERR:
因为进入中断时没有恢复栈空间导致的各种各样的总线错误。 - LSPERR:
处理器在floating-point lazy状态下产生的总线错误。 - BFARVALID:
标志着Bus Fault Address Register(BFAR)中记录了一个总线异常地址。
UFSR对应CFSR[31:16],可以通过地址0xE000ED2A直接访问,涉及的位定义如下:
- UNDEFINERR:
处理器尝试执行一个未定义的指令。 - INVSTATE:
处理器尝试非法地访问EPSR。 - INVPC:
处理器尝试非法地装载数据到PC寄存器中。 - NOCP:
处理器尝试访问不支持的协处理器Co-Processor。 - UNALIGNED:
处理器访问未对齐的地址。 - DIVBYZERO:
除零。
11. HFSR
硬件错误状态寄存器。该寄存器是可读的,对该寄存器写1将清除对应位。
- VECTTBL:
向量表错误。 - FORCED:
由其它fault导致的硬件错误,当该位置‘1’时,需要检查其它错误状态寄存器以确定事件来源。 - DEBUG_VT:
保留Debug用,对该位必须写‘0’,否则将可能产生以外的现象。
12. MMAR
当MMFSR中的MMARVALID置位时,该寄存器将记录出错的地址。
13. BFAR
当BFSR中的BFARVALID置位时,该寄存器将记录出错的地址。
14. AFSR
其它错误寄存器,Auxilliary Fault State Register。由具体的处理器实现定义。