安全的“任务切换”在 ATmega 芯片上
我开始在 atmega8 上的应用程序中实现类似于任务切换的功能。主要思想是有一个指向“当前屏幕”结构的指针。 “当前屏幕”包含用于刷新屏幕、处理按钮和中断的处理程序。
不幸的是,我发现更改函数指针需要两次操作才能完成。这意味着在 current_screen
部分更改时,某些中断可能会尝试执行 current_screen->handle_signal(...);
操作。由于要处理精确的计时,我不能在该更改期间禁用并重新启用中断。设置一个关于正在更改的处理程序的标志可以解决这个问题,因为我不太关心在任务更改过程中错过一些中断(但是处理那些我不能错过的中断会变得有点困难)。
我考虑过在更改期间将 current_screen
复制到 current_screen_old
并设置一个标志,如下所示:
current_screen_old = current_screen; // safe to call current_screen->handler
during_update = 1; // safe to call current_screen_old->handler
current_screen = new_value;
during_update = 0; // safe to call current_screen->handler again
但我不能 100% 确定这不包含其他一些技巧,如果处理程序也想更改 current_screen
。
有没有更好的方法来处理它?有哪些好的成语?
I started implementing something similar to task switching in my app on atmega8. The main idea is that there's a pointer to a "current screen" structure. The "current screen" contains handlers for refreshing the screen, handling buttons and interrupts.
Unfortunately I discovered that changing a function pointer is done in done in 2 operations. That means some interrupt may try to do current_screen->handle_signal(...);
while current_screen
is partly changed. Due to handling precise timing, I cannot just disable and reenable interrupts during that change. Setting a flag about the handler being changed could do the trick, since I don't care that much about missing some interrupts in the middle of the task change (but then handling those I cannot miss becomes a bit harder).
I thought about copying current_screen
to current_screen_old
during the change and setting a flag, like this:
current_screen_old = current_screen; // safe to call current_screen->handler
during_update = 1; // safe to call current_screen_old->handler
current_screen = new_value;
during_update = 0; // safe to call current_screen->handler again
But I'm not 100% sure this doesn't contain some other tricks if the handler wants to change current_screen
too.
Is there some better way to approach it? Some good idioms?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以使用双缓冲。
也就是说,使用一个由两个函数指针和当前函数指针的索引组成的数组。将非当前指针设置为新值,然后切换索引。由于索引很小(0 或 1),因此它是原子的。
您需要确保在更改期间访问指针的任务不会被挂起足够长的时间,以免受到下一次更改的干扰。
You can use double buffering.
That is, use an array of two function pointers and an index to the current one. Set the non-current pointer to the new value, then toggle the index. Since the index is small (0 or 1) setting it is atomic.
You need to make sure that no task accessing the pointer during a change can be suspended long enough to be disturbed by the next change.