其他
FreeRTOS消息缓冲区实现M4和M7双核之间通信的原理
关注+星标公众号,不错过精彩内容
作者 | strongerHuang
微信公众号 | 嵌入式专栏
嵌入式专栏
1
嵌入式专栏
2
嵌入式专栏
3
这里官方提供了实现该方案的基础代码(仅供参考)。
xMessageBufferSend()
{
/* If a time out is specified and there isn't enough
space in the message buffer to send the data, then
enter the blocked state to wait for more space. */
if( time out != 0 )
{
while( there is insufficient space in the buffer &&
not timed out waiting )
{
Enter the blocked state to wait for space in the buffer
}
}
if( there is enough space in the buffer )
{
write data to buffer
sbSEND_COMPLETED()
}
}
xMessageBufferReceive()
{
/* If a time out is specified and the buffer doesn't
contain any data that can be read, then enter the
blocked state to wait for the buffer to contain data. */
if( time out != 0 )
{
while( there is no data in the buffer &&
not timed out waiting )
{
Enter the blocked state to wait for data
}
}
if( there is data in the buffer )
{
read data from buffer
sbRECEIVE_COMPLETED()
}
}
如果任务在xMessageBufferReceive()中进入阻塞状态以等待缓冲区包含数据,则将数据发送到缓冲区必须取消阻塞该任务,以便它可以完成其操作。
当xMessageBufferSend()调用sbSEND_COMPLETED()时,任务将不受阻碍。
ISR通过将消息缓冲区的句柄作为参数传递给xMessageBufferSendCompletedFromISR()函数来解除对任务的阻塞。
如图箭头所示,其中发送和接收任务位于不同的MCU内核上:
嵌入式专栏
4
当只有一个消息缓冲区时,很容易将消息缓冲区的句柄传递到xMessageBufferSendCompletedFromISR()中。
如果硬件允许,则每个消息缓冲区可以使用不同的中断线,从而使中断服务程序和消息缓冲区之间保持一对一的映射。
中断服务例程可以简单地查询每个消息缓冲区以查看其是否包含数据。
可以通过传递元数据(消息是什么,消息的预期接收者是什么等等)以及实际数据的单个消息缓冲区来代替多个消息缓冲区。
/* Added to FreeRTOSConfig.h to override the default implementation. */
#define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateCoreToCoreInterrupt( pxStreamBuffer )
/* Implemented in a C file. */
void vGenerateCoreToCoreInterrupt( MessageBufferHandle_t xUpdatedBuffer )
{
size_t BytesWritten.
/* Called by the implementation of sbSEND_COMPLETED() in FreeRTOSConfig.h.
If this function was called because data was written to any message buffer
other than the control message buffer then write the handle of the message
buffer that contains data to the control message buffer, then raise an
interrupt in the other core. If this function was called because data was
written to the control message buffer then do nothing. */
if( xUpdatedBuffer != xControlMessageBuffer )
{
BytesWritten = xMessageBufferSend( xControlMessageBuffer,
&xUpdatedBuffer,
sizeof( xUpdatedBuffer ),
0 );
/* If the bytes could not be written then the control message buffer
is too small! */
configASSERT( BytesWritten == sizeof( xUpdatedBuffer );
/* Generate interrupt in the other core (pseudocode). */
GenerateInterrupt();
}
}
然后,ISR读取控制消息缓冲区以获得句柄,将句柄作为参数传递到xMessageBufferSendCompletedFromISR()中:
void InterruptServiceRoutine( void )
{
MessageBufferHandle_t xUpdatedMessageBuffer;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Receive the handle of the message buffer that contains data from the
control message buffer. Ensure to drain the buffer before returning. */
while( xMessageBufferReceiveFromISR( xControlMessageBuffer,
&xUpdatedMessageBuffer,
sizeof( xUpdatedMessageBuffer ),
&xHigherPriorityTaskWoken )
== sizeof( xUpdatedMessageBuffer ) )
{
/* Call the API function that sends a notification to any task that is
blocked on the xUpdatedMessageBuffer message buffer waiting for data to
arrive. */
xMessageBufferSendCompletedFromISR( xUpdatedMessageBuffer,
&xHigherPriorityTaskWoken );
}
/* Normal FreeRTOS "yield from interrupt" semantics, where
xHigherPriorityTaskWoken is initialised to pdFALSE and will then get set to
pdTRUE if the interrupt unblocks a task that has a priority above that of
the currently executing task. */
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
当然,以上仅提供基础原理和方法,具体实现需结合项目实际情况。更多相关内容,请参看官方相关资料。
------------ END ------------
点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。