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