ISR(中断服务例程)有单独的堆栈吗



当使用RTOS(例如FreeRTOS)时,我们为每个线程都有单独的堆栈空间。那么ISR(中断服务例程)呢?它们在内存中有单独的堆栈吗?或者这是可配置的?

如果他们没有存储ISR中声明的局部变量的堆栈?

我也有同样的问题,经过大量的搜索,我得出了这样的结论:答案取决于你的芯片以及你使用的操作系统如何配置该芯片。

因此,看看我最喜欢的芯片之一ARM Cortex-M3(中断是一种例外形式),不同位置的文档如下:

操作模式

Cortex-M3支持特权和用户(非特权)执行。以特权身份运行的代码具有完全访问权限,而以特权身份执行的代码用户的访问权限有限。限制包括限制关于指令使用,如MSR字段、对内存的访问和基于系统设计的外围设备,以及MPU配置。

处理器支持两种操作模式,线程模式和处理程序模式线程模式在重置时进入,通常在从例外当处于线程模式时,代码可以作为特权或无特权。

由于出现异常,将进入处理程序模式。代码在处理程序模式总是以特权模式执行,因此核心将发生异常时自动切换到特权模式。你可以当通过修改链路寄存器(R14)。您还可以将特权线程更改为用户线程模式,方法是使用MSR指令清除CONTROL[0]。但是,您不能从直接更改为特权模式无特权模式而不经历异常,例如SVC。

主要和工艺堆栈

Cortex-M3支持两个不同的堆栈,一个主堆栈和一个过程堆栈。为了支持这一点,Cortex-M3有两个堆栈指针(R13)。根据使用中的堆栈,其中一个会堆积起来。这意味着一次只有一个堆栈指针作为R13可见。但是,可以使用MRS和MSR访问这两个堆栈指针说明书主堆栈用于重置,并且始终用于处理程序模式(当输入异常处理程序时)。流程堆栈指针仅在线程中可用作当前堆栈指针模式您可以选择在中使用哪个堆栈指针(主指针或进程指针)使用EXC_RETURN值的两种方式之一的线程模式从处理程序模式退出时,或在线程模式下写入CONTROL[1]使用MSR指令。

而且。。。

处理器发生异常时,除非异常是尾链或延迟到达的异常,处理器推送当前堆栈上的信息。此操作称为堆叠,并且八个数据字的结构被称为堆栈帧。。。

堆叠后,堆栈指针立即指示最低堆栈帧中的地址

摘自《ARM Cortex-M3的最终指南》:

MSP,在ARM文档中也称为SP_main,是默认的SP上电后;它由内核代码和异常处理程序使用。这个PSP,或ARM文档中的SP_process,通常由线程使用运行嵌入式操作系统的系统中的进程。

由于异常处理程序总是使用主堆栈指针堆栈内存应该包含足够的空间来容纳嵌套中断。

当发生异常时,寄存器R0–R3、R12、LR、PC、,以及程序状态(PSR)被推送到堆栈。如果运行时使用进程堆栈指针(PSP),进程堆栈将使用;如果正在运行的代码使用主堆栈指针(MSP),将使用主堆栈。之后,主堆栈将始终在处理程序期间使用,因此所有嵌套中断都将使用主堆栈。

更新6/2017:

我之前的答案是不正确的,我分析了皮层处理器的FreeRTOS,并将我的答案改写为:

Cortex-M3的标准FreeRTOS版本实际上同时配置和使用MSP和PSP。当第一个任务运行时,它修改MSP以指向矢量表中指定的第一个地址(0x00000000),这往往是SRAM中的最后一个字,然后它触发系统调用,在系统调用异常处理程序中,它将PSP设置到下一个任务堆栈位置,然后它修改异常LR值,使其"返回线程模式,返回时使用进程堆栈"。

这意味着中断服务例程(AKA异常处理程序)堆栈从矢量表中指定的地址开始向下扩展。

您可以配置您的链接器和启动代码,以将异常处理程序堆栈定位到任何您喜欢的位置,确保堆或其他内存区域不会与异常处理程序区域重叠,并确保该区域足够大。

其他芯片和操作系统的答案可能完全不同!

为了确保您的应用程序在ISR堆栈(MSP)上有适当的空间,这里有一些额外的代码来检查ISR堆栈的实际使用情况。除了你已经在FreeRTOS任务堆栈上进行的检查之外,还可以使用:

https://sourceforge.net/p/freertos/discussion/382005/thread/8418dd523e/

更新:我已经在github:上发布了我的port.c版本,其中包括ISR堆栈使用检查

https://github.com/DRNadler/FreeRTOS_helpers

相关内容

最新更新