在网络上看到中断函数和中断嵌套使用栈空间,但我的认知始终认为栈中只存临时的变量,程序与函数都存于flash而不是ram才对不是吗?
是一种内存区域,用于存储程序运行时的临时变量和函数调用的信息。栈通常位于RAM中,因为它需要在程序运行时动态地分配和释放内存。
相比之下,程序代码和静态变量通常存储在Flash或ROM等非易失性存储器中,因为这些数据不需要在程序运行时进行修改,并且可以在程序重启后保持不变。
然而,并非所有的临时变量都存储在栈中。在一些编程语言和环境中,如C语言中的静态变量、全局变量等也可能存储在栈上。此外,一些特定用途的存储器区域,如堆(heap)等,也可能被用来存储临时变量。
因此,虽然栈通常被用来存储临时变量和函数调用信息,但它并不限于此,并且使用具体的编程语言和环境也会有所不同。
对于堆栈大小的调整
在程序中调用堆栈,对堆栈大小的挑战才是有意义的,例如在程序中没有申请动态内存,那么不论给堆多大的内存,在程序编译时都不会占用单片机flash。可以尝试,分别在用/不用 动态内存时调整堆给堆分配的空间,编译后观察ZI-data大小的变化。栈区方法相同,可以尝试不定义任何形参和 局部变量观察ZI-data大小的变化。
中断函数和中断嵌套会影响栈空间。在MCU中,调用子程序时会将当前程序执行位置以及相关寄存器等信息压入栈中,中断函数同样如此。当中断函数内部再次发生中断时,程序会进入到嵌套中断中,此时会将新的执行位置以及寄存器等信息压入栈中,导致栈空间的使用量增加。因此,在编写中断函数时需要注意栈空间的使用情况。
栈空间与程序、函数存储的位置有关联。在MCU中,栈空间由堆栈指针SP指定。堆栈指针SP指向的内存区域通常是存储器的高地址区域,而程序和函数通常存储在低地址区域。因此,在使用堆栈时需要注意栈的生长方向,即栈从哪个方向开始增长,以避免栈空间与程序、函数存储区域产生冲突。
代码示例:
// 中断函数示例 void interruptFunc() { // 此处会将寄存器等信息压入栈中 // 处理中断请求
// 发生中断嵌套
if(some_condition)
{
// 将新的寄存器等信息压入栈中
// 处理嵌套的中断请求
}
// 中断处理完成,执行栈弹出操作
}
// 堆栈操作示例 void someFunc() { // 压栈操作 // 保存寄存器等信息
// 执行函数体内部逻辑
// 出栈操作
// 恢复寄存器等信息
}
// SP寄存器示例 void initStack() { // 将SP指向RAM高地址区域 SP = 0xFF; }
// 示例说明:在中断函数中,处理完中断请求后需要执行栈弹出操作,将栈中压入的信息弹出并恢复现场。在函数调用过程中,需要先执行压栈操作保存寄存器等信息,执行完函数体内部逻辑后再执行出栈操作恢复现场。在初始化函数中,需要将堆栈指针SP指向RAM的高地址区域。