我会尝试根据有限的信息给你一个答案,假设:
- 一个简单的自制调度程序用于根据简单的标准调用 task1 和 task2
- task1 和 task2 运行完成(即不互相抢占)
- data 是基于字节的流(如果您需要数据包,则需要稍微不同的实现)
在设计嵌入式系统时,我通常会尝试尽量减少信号量的使用,并对无锁数据流进行建模。我将在下面说明这一点:
异步(无锁)通信队列 http://www.freeimagehosting.net/uploads/477741db06.gif
ISR 可以通过使用线程安全的 FIFO 队列与任务分离。可以在http://msmvps.com/blogs/vandooren/archive/2007/01/05/creating-a-thread-safe-producer-consumer-queue-in-c-without-using-locks 中找到一个示例。 aspx
这样的实现(没有锁)没有操作系统依赖,应该很容易支持。这也提供了一个清晰的生产者-消费者设计,没有死锁。
假设任务是由自制的调度程序触发的,您可以选择在那里检查事件(非空 fifo)。即 if (TRUE == fifo_filled(my_read_queue)) { 调用任务 1 }
现在关于task1和task2的同步。如果 task1 只是产生数据,则可以使用相同的机制:如果您有一个队列 (fifo),task1 可以在其中写入数据,而任务 2 可以读取这些数据,那么这些任务就会解耦。同样,这可以在您的调度程序中检查(if (TRUE==fifo_filled(task1_to_2_queue() ) { invoke task2) }
如果您需要更多(即如果任务没有运行完成,而是被抢占),您将需要一些同步机制。选项包括: - 使用(免费)操作系统或简单的调度程序 - 自己酿造(我的经验:只有当它像 for 循环和一些 if 语句一样简单时才应该这样做) - 使用简单的调度程序(更多比完整的 RTOS 轻量级) - 重构代码以将 task1 和 task2 集成为一个。在这种情况下,您将有效地使调度程序成为应用程序代码的一部分。
注意:我在本说明中使用的示例函数 (fifo_filled() ) 不是示例代码的一部分。它应该返回 true if (read != write) 另外,示例代码使用全局变量 read 和 write;您可以搜索一个能够处理多个队列的函数,或者将读/写和缓冲区变量移动到结构中,并在参数中引用结构。
另一种方法是通过中断禁用来创建关键部分。但是,我试图限制这一点,因为它通常会产生强大的系统耦合,并且代码变得更难重用。