深入了解异常处理

本文深入探讨了Cortex-M处理器的异常处理机制,包括C语言实现的异常处理、栈帧的构造、EXC_RETURN的使用,以及异常流程中的中断等待、优化策略等。异常处理涉及寄存器的保存与恢复,栈帧的大小根据处理器类型和浮点单元的存在与否而变化。异常进入时,EXC_RETURN保存在LR中,用于异常返回。异常流程中,处理器通过双字栈对齐、中断等待优化、末尾连锁、延迟到达、出栈抢占和惰性压栈等策略提高响应速度和效率。

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

一、简介

1.1 C实现的异常处理

对于cortex-m处理器,可以将异常处理或ISR实现为普通的C程序/函数,为了深入了解这种机制,我们先来看一下C函数在ARM架构上是如何工作的。

用ARM架构的C编译器遵循ARM的一个名为AAPCS的规范。根据这份标准,C函数可以修改R0R3、R12、R14(LR)以及PSR。若C函数需要使用R4R11,就应该将这些寄存器保存到栈空间中,并且在函数结束前将它们恢复,如下图所示:

R0~R3、R12、LR以及PSR被称作调用者保存寄存器,若在函数调用后还需要使用这些寄存器的数值,在进行调用前,调用子程序的程序代码需要将这些寄存器的内容保存到内存中(如栈)。函数调用后不需要使用的寄存器数值则不用保存。

R4~R11为调用者保存寄存器,被调用的子程序或函数需要确保这些寄存器在函数结束时不会发生变化(与进入函数时的数值一样)。这些寄存器的数值可能会在函数执行过程中变化,不过需要在函数退出前将它们恢复为初始值。

若cortex-m处理器具有浮点单元,则浮点单元中的寄存器也有类似的需求:

S0~S15为调用者保存寄存器。

S16~S31为被调用者保存寄存器。

一般来说,函数调用将R0R3作为输入参数,R0则用作返回结果。若返回值为64位,则R1也会用于返回结果。要使C函数可以用作异常处理,异常机制需要在异常入口处自动保存R0R3、R12、LR以及PSR,并在异常退出时将它们恢复,这些都要由处理器硬件控制。这样,当返回到被中断的程序时,所有寄存器的数值都会和进入中断时相同。另外,与普通的C函数调用不同,返回地址PC的数值并没有存在在LR中(异常机制在进入异常时将EXC_RETURN代码放入了LR中,该数值将会在异常返回时用到),因此,异常流程也需要将返回地址保存。这样对于CORTEX-M3或不具有浮点单元的CORTEX-M4处理器,需要在异常处理期间保存的寄存器共有8个。对于具有浮点单元的cortex-m4处理器,若用到了浮点单元,则异常机制还需要保存S0 ~ S15 及FPSCR。CONTROL寄存器中FPCA位表示这一操作的执行情况。

1.2 栈帧

​ 在异常入口处被压入栈空间的数据块为栈帧。对于cortex-M3或不具有浮点单元的cortex-m4处理器,栈帧都是8个字大小,对于具有浮点单元的cortex-m4,栈帧则可能是8或26个字。

AAPCS的另外一个要求为,栈指针的数值在函数入口和出口处应该是双字对齐的。因此,若在中断产生时栈帧未对齐到双字地址上,Cortex-m3和Cortex-m4处理器会自动插入一个字。这样可以保证栈指针位于异常处理的开始处。双字栈对齐特性是可编程的,若异常未完全符合AAPCS,则可以关闭该特性。

压栈的xPSR中的第9位表示栈指针的数值是否调整过。在下图中,栈指针为双字对齐的,因此就不会额外插入一个字,而且xPSR的第9位也为0。在双字栈对齐特性被关闭后,栈帧还是会保持这种方式的,只是栈指针的数值有可能未对齐到双字地址。

若使能了双字栈对齐特性&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值