您可以通过创建指向内存块的指针队列而不是复制内存本身来实现“零复制”队列。将音频数据直接写入一个块(例如通过 DMA),然后在写满时,将指向该块的指针排入队列,并切换到池中的下一个可用块。然后接收任务可以直接对内存块进行操作,而无需将数据复制到队列中或从队列中复制出来——唯一复制的是指针。
接收任务完成后,将块返回池中。池应具有与队列长度相同的块数。
要创建内存池,您将从静态数组开始:
tAudioSample block[QUEUE_LENGTH][BLOCK_SIZE] ;
然后用指向每个块元素的指针填充block_pool 队列 - 伪代码:
for( int i = 0; i < QUEUE_LENGTH; i++ )
{
queue_send( block_pool, block[i] ) ;
}
然后要获得一个“可用”块,您只需从队列中获取一个指针,填充它,然后发送到您的音频流队列,接收器在完成块后将指针发送回block_pool .
一些 RTOS 提供了一个固定的块分配器,它完全按照我在上面描述的 block_pool 队列。如果您使用的是 CMSIS RTOS API 而不是本机 FreeRTOS API,则会提供memory pool API。
但是,这听起来可能是一个 X-Y 问题 - 您已经提出了您的诊断,该诊断可能正确也可能不正确,并决定了一个解决方案,然后您正在寻求帮助。但是,如果它是错误的或不是最佳解决方案怎么办?最好包含一些代码来显示数据是如何生成和使用的,并提供具体信息,例如数据来自哪里、生成 ISR 的频率、采样率、运行平台、优先级和调度接收任务,以及正在运行的其他哪些任务可能会延迟它。
在大多数平台上 384 字节并不是很大的数据量,并且中断率必须非常高或接收任务被过度延迟(即非实时)或执行过多或不确定的工作导致这个问题。问题可能不是 ISR 频率,而是接收任务的性能和可调度性。
不清楚你是384字节导致单个中断还是384中断还是什么?
也就是说,这可能是一个更全面的设计问题,而不是简单地如何更有效地传递数据——尽管这并不是一件坏事。