异常地址计算

文章详细介绍了微控制器在遇到不同类型的异常中断如HardFault、MemManageFault、BusFault、UsageFault时的处理机制。通过分析SCB系统控制寄存器和CFSR、HFSR等状态寄存器,以及异常返回值和栈内容,可以定位导致中断的具体原因,如非法指令、存储器访问错误或总线错误。此外,还提到了栈指针MSP和PSP的使用,以及异常返回时的寄存器入栈顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码造成进入异常中断

异常类型

Fault的原因

  1. 默认 只要HardFault,其他Fault需要手动打开
    使能Fault处理

这些Fault异常默认都是禁止的,所以都会上访成HardFault。可以通过系统处理控制和状态寄存器(SCB->SHCSR)来使能,将位16~位18置1就会使用这些Fault异常。

状态寄存器(SCB->SHCSR)
16MEMFAULTENA
17BUSFAULTENA
18USGFAULTENA
  1. (MemManage Fault)存储管理错误

MemManage错误由MPU配置定义的访问规则引发。例如,非特权的代码访问了只支持特权访问的存储器区域,向被MPU定义为只读的存储器位置进行写操作,试图从不可执行区域(XN)执行代码。这些访问可以是在指令执行,取指期间的数据访问或执行过程中的栈操作。

Memory Manage Fault(MFSR),地址:0xE000ED28
7MMARVALIDMMARVALID位为1,可以利用MemManage错误地址寄存器(SCB->MMFAR)确定引发错误的存储器地址。
6:5
4MSTKERR入栈访问不允许区域
3MUNSTKERR出栈访问不允许区域
2
1DACCVIOL不可访问区域读写数据,为1错误的代码可由栈帧中的PC定位
0IACCVIOL不可访问区域读指令,为1错误的代码可由栈帧中的PC定位
  1. 总线错误

Bus Fault是由存储器访问期间从处理器总线接口上收到的错误响应触发。包括取值,数据读写和栈操作。如果取指产生了总线错误,只有错误的位置进入执行阶段时才会触发总线错误。

总线错误分为精确的总线错误和不精确的总线错误两类。精确的总线错误是在存储器访问指令执行后错误异常立即产生。不精确的总线错误是因为处理器总线接口上存在写缓冲,存储器访问指令执行一段时间后才产生错误异常。有时候为了方便调试可以使用辅助控制寄存器中的DISDEFWBUF位禁止写缓冲。

SCB->CFSR中的第二字节是Bus Fault(BFSR),地址:0xE000ED29
7BFARVALIDBFAR寄存器有效(BFAR 保存总线故障地址)
4STKERR入栈错误
3UNSTKERR出栈错误
2IMPRECISERR不精确总线错误
1PRECISERR精确总线错误
0IBUSERR指令错误
  1. (Usage fault)用法错误

Usage fault可由多种情况引发。包括执行未定义的指令,非对齐操作,除零,非法指令(试图切换到ARM状态,执行协处理器指令),使用多重加载/存储指令时地址没对齐。

SCB->CFSR的高半字是 Usage Fault(UFSR),地址:0xE000ED2A
9DIVBYZERO企图执行除0的操作
8UNALIGNED企图执行非对齐访问
3NOCP企图执行协处理器指令
2INVPC无效异常返回码
1INVSTATE切换到ARM状态
0UNDEFINSTR为定义指令
4、(Hard fault)硬件错误错误
SCB->HFSR,地址:0xE000ED2C
---
31DEBUGEVT调试事件产生
30FORCED由bus memory Usage Fault升级的硬件错误
2~29--
1VECTBL取中断向量时出错
0--

异常代码定位

查看使用的哪个sp寄存器

当代码错误造成进入异常中断可通过查看cpu寄存器

R14 = 0XFFFFFFF9
异常返回值描述
0xFFFFFFF1返回Handler模式,异常返回使用MSP,返回后使用MSP合法异常
0xFFFFFFF9返回Thread 模式,异常返回使用MSP,使用MSP合法异常
0xFFFFFFFD返回Thread 模式,异常返回使用PSP,使用PSP合法异常
0xFFFFFFE1返回Handler 模式,异常返回使用MSP,使用MSP
0xFFFFFFE9返回Thread 模式,异常返回使用MSP,使用MSP
0xFFFFFFED返回Thread 模式,异常返回使用PSP,使用PSP

通过上表可以看到 异常返回值是0xFFFFFFF9,异常返回使用的MSP,表示异常代码的现场栈指针存放在MSP中

获取栈定地址

通过异常返回值知道使用的MSP
,
MSP = 0x2800AF10

获取栈内容

通过调试器memory窗口查看,sp栈顶地址的内容。

address      8      0  16     9 24    17 32    18
0x2800AF10	00000001  00FFFFFF 0000000E 00000001
0x2800AF20	00000001  10058BA5 10058BC4 2100F200

异常后寄存器入栈顺序

上一步我们找到了栈顶地址,并通过memory窗口查找到了栈内容,接下来了解Cortex-M 寄存器入栈顺序。
在这里插入图片描述

可以通过上图看到,入栈顺序,一次从上到下,出栈时反之;
左侧是开启浮点运算后 入栈顺序,可以看到先保存的浮点运算单元的寄存器,然后保存cpu的寄存器。
右侧是未开启浮点运算入栈顺序,保存cpu的寄存器。

				R0        R1      R2      R3
0x2800AF10	00000001  00FFFFFF 0000000E 00000001
			   R12       LR       PC      PSR
0x2800AF20	00000001  10058BA5 10058BC4 2100F200

通过对栈中的数据分析可以看到 导致进入异常中断的代码地址为 0X10058BC4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值