当使用RTOS(来自FreeRTOS)时,每个线程都有单独的堆栈空间。那么ISR(中断服务程序)呢,它们在内存中有一个单独的堆栈吗?或者这是可配置的吗?
如果他们没有堆栈,ISR中声明的局部变量会被存储?
答案 0 :(得分:4)
我有完全相同的问题,很多搜索引导我得出这个结论:答案取决于你的芯片以及你使用的操作系统如何配置芯片。
所以看看我最喜欢的芯片之一ARM Cortex-M3(中断是一种例外),各个地方的文档都是:
运作模式
Cortex-M3支持特权和用户(非特权)执行。 以特权运行的代码具有完全访问权限,而代码执行为 用户具有有限的访问权限。限制包括限制 关于指令使用,如MSR字段,访问内存和 基于系统设计的外围设备,以及由此产生的限制 MPU配置。
处理器支持两种操作模式:Thread模式和Handler 模式。线程模式在复位时进入,通常在从a返回时进入 例外。在线程模式下,代码可以执行 特权或非特权。
处理程序模式将作为异常的结果输入。代码 处理程序模式始终以特权方式执行,因此核心将执行 发生异常时自动切换到特权模式。您可以 在特权线程模式和用户线程模式之间切换时 通过修改中的EXC_RETURN值从异常返回 链接寄存器(R14)。您也可以从Privileged Thread更改为 用户线程模式通过使用MSR指令清除CONTROL [0]。 但是,您无法直接从更改为特权模式 非特权模式,不经过例外,例如 SVC。
主要和过程堆栈
Cortex-M3支持两个不同的堆栈,一个主堆栈和一个 进程堆栈。为了支持这一点,Cortex-M3有两个堆栈指针 (R13)。根据使用的堆栈,其中一个是库存的。这个 表示一次只有一个堆栈指针可见为R13。 但是,可以使用MRS和MSR访问两个堆栈指针 说明。主堆栈在复位时使用,并始终用于 处理程序模式(进入异常处理程序时)。进程堆栈 指针仅在Thread中可用作当前堆栈指针 模式。您可以选择使用哪个堆栈指针(主要或进程) 线程模式有两种方式,使用EXC_RETURN值 从处理程序模式退出或在线程模式下写入时 使用MSR指令控制[1]。
和...
当处理器发生异常时,除非异常是a 尾部链接或迟到的异常,处理器推动 信息到当前堆栈。此操作称为 堆叠和八个数据字的结构称为 堆栈框架。 ......
堆叠后,堆栈指针立即显示最低值 堆栈框架中的地址
从书" ARM Cortex-M3的权威指南":
MSP(在ARM文档中也称为SP_main)是默认SP 上电后;它由内核代码和异常处理程序使用。该 ARM文档中的PSP或SP_process通常由线程使用 嵌入式操作系统运行的系统中的进程。
因为异常处理程序总是使用主堆栈指针 堆栈内存应包含足够数量的空间 嵌套中断。
发生异常时,寄存器R0-R3,R12,LR,PC, 和程序状态(PSR)被推入堆栈。如果代码是 运行使用进程堆栈指针(PSP),进程堆栈将 使用;如果正在运行的代码使用主堆栈指针 (MSP),将使用主堆栈。之后,主堆栈将 总是在处理程序中使用,因此所有嵌套中断都将使用 主要的堆栈。
更新6月1日:
我之前的回答是不正确的,我已经分析了皮质处理器的FreeRTOS并重写了我的回答:
Cortex-M3的标准FreeRTOS版本实际上配置和使用MSP和PSP。当第一个任务运行时,它修改MSP指向向量表中指定的第一个地址(0x00000000),这往往是SRAM中的最后一个字,然后它触发系统调用,在它设置的系统调用异常处理程序中PSP到下一个任务堆栈位置,然后它修改异常LR值,使得"返回线程模式并在返回时使用进程堆栈"。
这意味着中断服务例程(AKA异常处理程序)堆栈从向量表中指定的地址开始增长。
您可以配置链接器和启动代码,以便在任何位置找到异常处理程序堆栈,确保堆或其他内存区域不与异常处理程序区域重叠,并确保该区域足够大。
其他芯片和操作系统的答案可能完全不同!
答案 1 :(得分:0)
为帮助确保您的应用程序在ISR堆栈(MSP)上具有适当的空间, 这是一些其他代码,用于检查ISR堆栈的实际使用情况。除了对FreeRTOS任务堆栈已经进行的检查以外,还可以使用:
https://sourceforge.net/p/freertos/discussion/382005/thread/8418dd523e/