我有完全相同的问题,经过大量搜索后得出结论:答案取决于您的芯片以及您使用的操作系统如何配置该芯片。
因此,查看我最喜欢的芯片ARM Cortex-M3(其中中断是一种异常形式)的文档,在各个地方阅读:
操作模式
Cortex-M3支持特权和用户(非特权)执行。作为特权运行的代码具有完全访问权限,而作为用户执行的代码具有有限的访问权限。这些限制包括对指令使用的限制,例如MSR字段,基于系统设计的内存和外围设备的访问以及MPU配置所施加的限制。
处理器支持两种操作模式:线程模式和处理程序模式。线程模式在重置时输入,并通常在从异常返回时输入。在线程模式下,代码可以作为特权或非特权执行。
由于异常而进入处理程序模式。处理程序模式中的代码始终作为特权级别执行,因此核心将在发生异常时自动切换到特权模式。通过修改链接寄存器(R14)中的EXC_RETURN值,您可以在从异常返回时在特权线程模式和用户线程模式之间进行更改。您还可以通过使用MSR指令清除CONTROL [0]来从特权线程模式更改为用户线程模式。但是,您不能直接从非特权模式更改为特权模式,例如SVC。
主堆栈和进程堆栈
Cortex-M3支持两种不同的堆栈:主堆栈和进程堆栈。为了支持这一点,Cortex-M3有两个堆栈指针(R13)。其中一个根据使用的堆栈而被银行化。这意味着一次只能看到一个堆栈指针作为R13。但是,可以使用MRS和MSR指令访问两个堆栈指针。主堆栈在重置时使用,并且始终在处理程序模式下使用(进入异常处理程序时)。当处于线程模式时,进程堆栈指针仅作为当前堆栈指针可用。您可以通过两种方式之一选择在线程模式下使用哪个堆栈指针(主堆栈或进程堆栈),一种是使用EXC_RETURN值退出处理程序模式时,另一种是在线程模式中使用MSR指令写入CONTROL [1]。
当处理器发生异常时,除非异常是尾随链接或迟到的异常,否则处理器会将信息推送到当前堆栈上。此操作称为堆栈,并将八个数据字的结构称为堆栈帧。 ...
在堆栈后立即,堆栈指针指示堆栈帧中的最低地址。
来自书籍“ ARM Cortex-M3的权威指南”:
MSP也称为ARM文档中的SP_main,在上电后是默认的SP;内核代码和异常处理程序使用它。PSP或称为ARM文档中的SP_process,通常在具有嵌入式操作系统的系统中由线程进程使用。因为异常处理程序总是使用主堆栈指针,所以主堆栈内存应该包含足够的空间来容纳最大数量的嵌套中断。当异常发生时,寄存器R0-R3、R12、LR、PC和程序状态寄存器(PSR)被推入堆栈。如果正在运行的代码使用进程堆栈指针(PSP),则使用进程堆栈;如果正在运行的代码使用主堆栈指针(MSP),则使用主堆栈。之后,处理程序期间将始终使用主堆栈,因此所有嵌套中断都将使用主堆栈。
更新于2017年6月:我的先前答案是不正确的,我已经分析了Cortex处理器的FreeRTOS并重新编写了我的答案。实际上,Cortex-M3的标准FreeRTOS版本配置并使用MSP和PSP。当第一个任务运行时,它会修改MSP以指向向量表中指定的第一个地址(0x00000000),这通常是SRAM中的最后一个字。然后它触发一个系统调用,在系统调用异常处理程序中,它将PSP设置为下一个任务堆栈位置,然后修改异常LR值,以便“返回到线程模式并在返回时使用进程堆栈”。这意味着中断服务例程(又名异常处理程序)堆栈从向量表中指定的地址向下生长。您可以配置链接器和启动代码来定位异常处理程序堆栈在任何您喜欢的地方,确保您的堆或其他内存区域不重叠异常处理程序区域并确保该区域足够大。其他芯片和操作系统的答案可能完全不同!