-->

两个任务之间的同步(synchronization between two tasks)

2019-07-31 07:16发布

这实际上是独立执行一个设计问题在嵌入式系统固件我有两个中断服务例程(优先级相同)。 当H / W生成这些数据的ISR被触发。 我想必须到位TASK1和Task2之间进行同步的机制。 任务2必须了解在任务1中计算出的特定的值,而在计算TASK2某些值然后必须加以考虑。 我没有OS原语使用即系统没有任何操作系统。 任务1被ISR1的ISR2的上下文中的上下文和Task2内执行。 我们使用的处理器是一种意法半导体32控制器

编辑:附加信息处理器连接到某些IP地址,其触发,当他们准备与数据中断。 这些IP作为输入流的帧数据蓄电池的类型。

Answer 1:

我不会做繁重的处理在中断上下文,只是读取数据,并设置一个标志。

这些标志然后可以在一个简单的调度主循环执行任务必要的检查。 因此,任务不能打断对方,不能看到其他任务的输出不一致。

任务还可以设置这样的标志来激活另一个任务。 因为任务2从任务1需要值如任务1可以激活任务2。

对于在ISR中读取数据,需要一定的缓冲。 根据这可能是一个环形缓冲区或双缓冲区传入数据的时序。



Answer 2:

  • 读取或写入到共享值之前禁止中断
  • 重新允许中断读或写共享值之后


Answer 3:

我在这个从无OS,比C和寄存器及其他没有真正的框架的角度来看未来。 我会做它的方式是对可以由其他ISR中可以看出每个ISR状态变量。 然后,当你进入ISR1你只是检查ISR2的任务的状态,并在必要时进行操作。 然后ISR2被调用,并检查自己的状态和ISR1的状态和操作,因为它认为合适的。 我最好使用一个ENUM在头文件枚举状态,为了清楚起见(INIT,WAITONDATA等),然后一个开关在ISR处理每个状态。 然后,你就必须确保需要被共享的数据可以通过中断服务程序都可以看到和你设置。

当然,正如其他人说你不想做很多计算ISR中。 你只是想设置已发生事件的标志或一些数据存在,然后处理在主回路中的数据。 那么你的系统不堵的时间太长处理的ISR。 你以同样的方式做到这一点 - 一个状态变量,可以在主回路中可以看到(或至少函数调用进行从主回路数据操作)和ISR。 改变其状态在ISR并检查主循环功能状态。 根据需要做家务。

不要忘记- 如果你是在ISR中更新变量必须被定义为挥发性!

挥发性UINT8状态= INIT;

例如。



Answer 4:

我会尽力给你基于有限的信息的应答,假设:

  • 一个简单的,自制调度使用基于简单criterea调用任务1和任务2
  • TASK1和完成TASK2运行(即不抢占对方)
  • 数据是(如果你需要数据包稍有不同的实现需要)基于字节流

什么设计嵌入式系统时,我通常会尝试是尽量减少使用信号量和模型无锁的数据流。 下面我将说明这一点:

异步(锁定免费)通信队列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

这样的(无锁)的实现没有OS的依赖,应该很轻松支持。 这也给出了明确的生产者 - 消费者设计是免费的死锁。

假设该任务由一个家庭brewn调度触发,你可以选择检查事件(非空FIFO)那里。 即,如果(TRUE == fifo_filled(my_read_queue)){调用任务1}

现在TASK1和Task2的同步。 如果TASK1只是生产数据,可以使用同样的机制:如果你有一个队列(FIFO),其中TASK1可以写数据,这可以通过任务2,则任务是分离的读取。 同样,这可以在调度检查(如果(TRUE == fifo_filled(task1_to_2_queue()){调用TASK2)}

如果您需要更多(即,如果任务没有完成运行,但抢占)你需要一些机制来同步。 选项包括: - 使用(免费)操作系统或简单的调度反正 - 酿造自己(我的经验:只应做,如果它是作为一个for循环简单if语句数) - 使用简单的调度程序(更lightweigth不是一个完整的RTOS) - 重构代码TASK1和Task2集成于一体。 在这种情况下,你会有效地使你的应用程序代码调度的一部分。

注:我在这个解释中使用的示例功能(fifo_filled())是不是示例代码的一部分。 它应该返回true,如果(!读=写)此外,示例代码中使用全局变量读写; 你可以或者Google上升能够处理多个队列的函数,或者移动的读/写和缓冲变量的结构,并且是指结构中的参数。

的另一种方法是创建由中断禁止的装置一个临界增长部分。 不过,我试图限制这个,因为它往往会造成一个强大的系统耦合,代码变得难以再利用。



文章来源: synchronization between two tasks