两个CPU之间使用棘手的队列

时间:2017-03-21 19:21:20

标签: c queue embedded message-queue

悬崖笔记版 TI F28377S有两个CPU,一个主CPU和一个辅助CPU(CLA,它一次只能执行一项任务,具有不间断的任务) - 它们共享RAM的消息区域。当快速向队列发送大约15个字节(最多32个队列长度)的队列时,CLA将发送出去,有时几个字节永远不会被传输。我认为CPU中断存在一些问题,导致单个字节在将它们交给缓冲区时偶尔会“丢失”。

完整版 (这是使用TI F28377S,它具有主时钟频率为200 MHz的主CPU,以及以相同速度运行的辅助独立CLA,但一次只能执行一个任务。它们可以共享单向可写变量)。 / p>

我对如何执行更复杂的任务感到有点困惑,涉及CLA和队列。

一些快速背景:我有两个主要的CLA任务,第一个(Task1)由ADC转换结束触发(它本身由Timer0以100 kHz触发),第二个(Task2)由Timer0本身触发(这是经过大量实验和调整后得出的,因为每当我让Task2比ADC任务更频繁地运行时,ADC任务永远不会启动 - 所以我将它们设置为使用相同的间隔,只是交错)。 Task1工作正常,将ADC结果存储在一个简单的环形缓冲区中,并在Task1完成后的ISR中执行简单的计算。第二个主要是有效的。

Task2用于切换某些GPIO引脚以与外部设备通信。因为代码的总长度大约是100微秒,而不是延迟,我在每个触发器上使用一个简单的盒子结构来确定它是否应该:什么也不做,打开代码引脚,打开选通引脚,关闭选通引脚,关闭代码引脚。这样,每次调用任务时,它几乎立即完成,输出代码是外部设备的适当长度。该任务每次只能处理一个代码,一旦完成,就会尝试从队列中获取另一个代码。如果没有,它只是继续通过。

现在,棘手的部分。我有两个要求:1)我可以比任务消耗它们更快地在队列末尾添加字节(在理论和实践中非常简单)和2)我可以在队列的前面添加一个字节(不是替换当前正在发送的字节,只是队列的前面)。第一种能力是发送中短消息(2-20个字符)。第二种能力对于发送任何外部中断的单个字节是必要的 - 尽可能快,甚至在发送消息的过程中。我已经设置好,以便Task每500微秒发送一个字节(~300“on”和~200“off)。这样,如果有中断消息,它将保证收到少于1发生后的ms。

当前工作的是:CPU上的一个函数,它接收传入的字节(一次一个)并将它们添加到CPU2CLA缓冲区并递增CPU2CLA长度计数器。每次运行Task2时,它都会检查此队列并从CLAonly缓冲区的前面抓取一个字节,增加其自己的缓冲区长度,并标记消耗了一个字节。运行Task2后任务ISR时,它将检查是否消耗了一个字节,并从CPU2CLA缓冲区中删除第一个字节。目前这个双缓冲系统没有用于添加到前面的标志,因此它不会处理中断情况。

我之前尝试过的是一个Task3,它接受了一个传递CPU2CLA的字节并使用Task3andWait从CPU运行它。虽然理论上这个方法应该同时满足这两个要求,但是大约一半的时间内一个字节或两个消息永远不会被传输(总是发送一个字节)。

CLA任务永远不会被中断,但CPU任务可以。这就是为什么我试图让队列的所有修改只发生在CLA中,因此从来没有一个不确定状态可以中断队列修改。

1 个答案:

答案 0 :(得分:0)

听起来像将高优先级和普通优先级项目拆分为单独的缓冲区将是一个接近最优的解决方案。

如果在消费任何东西之前产生高优先级项目,普通优先级项目和另一个高优先级项目,则还将确保在正常优先级项目之前消耗高优先级项目。 / p>

(使用单个缓冲区,这种情况会导致在第二个高优先级项目之前消耗正常优先级项目。我怀疑这是非常不受欢迎的。)

如果高优先级缓冲区中有项目,则接下来将使用该项目。否则,将消耗普通优先级缓冲区中的项目。

两个缓冲区都有一个生产者和一个消费者(因此, SPSC 类型),并以简单的先进先出方式处理;因此,无锁循环缓冲区实现(对于每个缓冲区)应该在这里正常工作。

(如果两个缓冲区只有32个字节可用,请考虑先尝试8:24分割。)