有没有办法从计时器ISR操纵堆栈?所以我可以通过强制一个长时间运行的函数退出来扔掉堆栈的最高帧? (在这种情况下,我知道丢失了堆分配的内存)
目标可能是ARM CPU。
最好的问候
答案 0 :(得分:1)
看起来你想在ISR终止后调用long {setjmp/longjmp之类的东西。
有可能以这种方式改变ISR返回地址,而不是返回long-running function
longjmp将使用正确的参数调用,而long-running function
将被中止到调用setjmp的地方。
只是想到了另一个解决方案。可能更容易将所有寄存器(堆栈指针,PC,LR和其他寄存器)恢复为在ISR堆栈帧中调用long-running functions
之前的值(使用汇编)。为此,您需要在long-running functions
之前保存所有必需的值(使用程序集)。
答案 1 :(得分:1)
我建议避免长时间运行的功能。虽然它可能在短期内起作用,但随着代码的增长,它可能会成为问题。
相反,请考虑在主循环中使用状态机或状态机系统,并使用ISR作为标志。这将减少时间问题,并允许您一次管理更多任务。
答案 2 :(得分:0)
这在理论上是可行的,但可能无法可靠地完成。
您可以使用GCC内置__builtin_frame_address
和__builtin_return_address
来正确恢复堆栈并从上一个函数返回,但它会破坏程序行为。强制返回的函数可能会在堆栈中保存一些寄存器,并且需要在返回之前恢复它们。问题是,我无法找到或模仿恢复代码。它肯定位于函数返回之前(你甚至不知道它在哪里),但它可能是1,2,甚至0指令。即使您找到它或模仿它,您也无法对其进行硬编码,因为当您更改功能时它可能会发生变化。
总之,您可以使用一些内置函数和2-3个内联汇编指令,但是您需要为要返回的函数定制硬编码,并且每当更改函数时都必须更改它
答案 3 :(得分:0)
为什么你不能在你的isr中设置一个标志,你的函数会定期检查它是否需要退出?我不赞成你试图这样做的原因是因为在某个操作过程中“杀死”一个函数是非常危险的。除非你有办法彻底清理它之后的所有东西(比如杀死一个进程),否则没有别的方法可以安全地完成它。最好通过isr中的某种标志或信号量来表示函数,然后让该函数自行清理并正常退出。