Synchronization 两个任务之间的同步

Synchronization 两个任务之间的同步,synchronization,embedded,firmware,Synchronization,Embedded,Firmware,这实际上是嵌入式系统中固件的设计问题 我有两个独立执行的ISR(优先级相同)。 这些ISR在h/w生成数据时触发。 我想要一个机制,它必须在task1和task2之间同步。任务2必须了解在任务1中计算的特定值,然后在计算任务2中的特定值时必须考虑这些值。 我没有可以使用的操作系统原语,即系统没有任何操作系统。 Task1在ISR1上下文中执行,task2在ISR2上下文中执行。 我们使用的处理器是STMicroelectronics 32控制器 编辑:其他信息 处理器连接到某些IP,这些IP在准

这实际上是嵌入式系统中固件的设计问题 我有两个独立执行的ISR(优先级相同)。 这些ISR在h/w生成数据时触发。 我想要一个机制,它必须在task1和task2之间同步。任务2必须了解在任务1中计算的特定值,然后在计算任务2中的特定值时必须考虑这些值。 我没有可以使用的操作系统原语,即系统没有任何操作系统。 Task1在ISR1上下文中执行,task2在ISR2上下文中执行。 我们使用的处理器是STMicroelectronics 32控制器

编辑:其他信息 处理器连接到某些IP,这些IP在准备好数据时会触发中断。这些IP充当输入流帧数据的累加器类型。

  • 在读取或写入共享值之前禁用中断
  • 读取或写入共享值后重新启用中断

我将根据有限的信息给您一个答案,假设:

  • 一个简单的自制调度程序用于根据简单的标准调用task1和task2
  • task1和task2运行至完成(即,不要相互抢占)
  • 数据是基于字节的流(如果需要数据包,则需要稍微不同的实现)
在设计嵌入式系统时,我通常会尽量减少信号量的使用,并对无锁数据流进行建模。我将在下面说明这一点:

ISR可以通过使用线程安全FIFO队列与任务解耦。可以在中找到一个例子

这样的实现(没有锁)没有操作系统依赖项,应该非常容易支持。这也提供了一个清晰的生产者-消费者设计,没有死锁

假设任务由home brewn调度程序触发,您可以选择在那里检查事件(非空fifo)。 i、 e.如果(TRUE==fifo_filled(my_read_queue)){invoke task 1}

现在是task1和task2的同步。 如果task1只是在生成数据,则可以使用相同的机制:如果您有一个队列(fifo),task1可以在其中写入数据,而Task2可以读取这些数据,则任务是解耦的。同样,这可以在调度程序中检查(如果(TRUE==fifo_filled(task1_to_2_queue()){invoke task2)}

如果您需要更多(即,如果任务没有运行到完成,但被抢占),您将需要某种机制来同步。选项包括: -无论如何都要使用(免费)操作系统或简单的调度程序 -自己酿制(我的经验:只有当它像for循环和几个if语句一样简单时,才应该进行) -使用一个简单的调度程序(比完整的RTOS轻得多) -重构代码,将task1和task2集成在一起。在这种情况下,您将有效地使调度程序成为应用程序代码的一部分

注意:我在本说明中使用的示例函数(fifo_filled())不是示例代码的一部分。如果(read!=write),则应返回true 此外,示例代码使用全局变量read和write;您可以通过谷歌搜索一个能够处理多个队列的函数,或者将read/write和buffer变量移动到structure,并在参数中引用该结构


另一种方法是通过中断禁用创建一个关键部分。但是,我尝试限制这种方法,因为它通常会创建一个强大的系统耦合,代码变得更难重用。

我不会在中断上下文中进行大量处理,只需读取数据并设置一个标志

然后,可以在主循环中的一个简单调度程序中检查这些标志,以根据需要执行任务。因此,任务不能相互中断,也不能看到其他任务的不一致输出

任务还可以设置此标志来激活另一个任务。例如,Task1可以激活Task2,因为Task2需要Task1的值


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

我的观点是,除了C和寄存器等,没有操作系统,没有真正的框架。我要做的是为每个ISR提供一个状态变量,通过t可以看到然后,当您输入ISR1时,您只需检查ISR2任务的状态并根据需要进行操作。然后,ISR2被调用并检查其自身状态和ISR1的状态,并根据需要进行操作。为了清晰起见,我会在头文件中使用枚举来枚举状态(INIT、waitonda等)然后在ISR中设置一个交换机来处理每个状态。然后,您只需确保两个ISR都能看到需要共享的数据,并且您已设置好

当然,正如其他人所说,您不想在ISR中进行大量计算。您只想设置一个标志,表明事件已发生或存在某些数据,然后在主循环中处理数据。这样,您的系统在处理ISR时不会被阻塞太长时间。您可以用相同的方式执行此操作—可以在主循环中看到的状态变量(或者至少是您从主循环调用以执行数据操作的函数)和ISR。更改其在ISR中的状态,并在主循环函数中检查该状态。根据需要执行杂务

别忘了-如果您要更新ISR中的变量,则必须将它们定义为volatile

易失性uint8状态=INIT


例如。

您在哪个平台上工作?鉴于两个ISR具有相同的优先级,它们是否可以相互中断?如果没有,您可能不需要任何额外的同步。@Matthem-通常ISR在进入时会禁用中断。但这是一个检查的好方法。您是否试图确保task1在task2 rega之前运行中断的顺序是什么?请你把插图放大一点好吗?