我想定期执行“内务”事件,由定时器中断定期触发。中断频繁发生(kHz +),而该功能可能需要很长时间才能完成,因此我不能简单地将其执行。
过去,我在ATMEGA上完成了这项工作,其中ISR可以通过sei()简单地允许其他中断触发(包括自身)。通过将事件包装在“仍在执行”的标志中,它不会堆积在堆栈上并导致......你知道:
if (!inFunction) { inFunction = true; doFunction(); inFunction = false; }
由于PMIC中断控制器,我不认为这可以在XMEGA上完成 - 至少同样容易。看来中断标志只能通过执行RETI来重置。
所以,我在想,如果我可以说服GCC从中断产生尾调用将会很方便。这将立即执行事件,同时清除中断。
这在汇编程序中很容易做到,只需按下地址和IRET即可。 (好吧,有些堆栈错误,因为ISR,但是,是的。)但我猜它会成为GCC中的黑客攻击,可能是围绕“裸”功能的自定义ASM包装器?
或者,我很乐意设置一个低优先级的软件中断,但我没有看到有意做到这一点。
我可以使用软件从其他未使用的外设触发中断。这是一个特殊情况,但是,如果我需要使用该设备,我必须找到另一个。这对代码重用也很不利。
真的,这是一个X-Y问题,我知道。我想我想做X,但我真的需要我不知道的方法Y.
一个更好的方法是设置一个标志,然后让main()在它到达时处理它。不幸的是,我在main()中有阻塞函数(通过串行处理用户输入),这样就可以工作,并且变得一团糟。
我所知道的唯一“正确”方法是完成一个完整的任务切换 - 但是如果我要有效地实现一个RTOS,或者为了这个而拉入一个RTOS,该死的。必须有更好的方法。
我是否真的涵盖了所有可能性,并将自己画成一个角落?我是否必须妥协并选择其中一种?我错过了什么更好的吗?
答案 0 :(得分:0)
有更多解决方案。
1。。将定时器中断设为低优先级。这样,中优先级和高优先级中断将能够中断此低优先级中断,并且不会受到影响。
这类似于在较旧的处理器(无PMIC)中的中断处理程序中使用sei();
。
2.a 在中断中设置一个标志(变量)。轮询主循环中的标志。如果设置了标志,请清除它并做您的工作。
2.b 设置计时器,但不启用其中断。 Poll 主循环中计时器的OVF中断标志。如果设置了标志,请清除它并做您的工作。
根据主循环的其他功能,它们的计时精度较低,因此取决于您对准确性的期望。在没有操作系统的情况下在主循环中处理更多任务:Cooperative multitasking,State machine。