0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RTOS实现双核MCU消息通信

strongerHuang 来源:strongerHuang 2023-06-07 14:48 次阅读

手机电脑多核的CPU你可能经常看见,但多核的单片机相对来说就不那么常见了。随着需求的增加、技术的进步,单片机已不再局限于单核了,因此,近几年陆续出现了双核的单片机了。 你可能会好奇,双核单片机之间怎么通信?其实,通信的方式和方法有很多种。本文就给大家描述一下:使用FreeRTOS消息缓冲区,实现简单的非对称多处理(AMP)核心到核心通信,结合STM32H7(M4和M7) 双核处理器为例。

分享正文之前推荐一个嵌入式招聘信息的平台:

概述

实现STM32H7双核之间通信是FreeRTOS官方提供的一个方案,是基于FreeRTOS消息缓冲区,该消息缓冲区是无锁循环缓冲区,可以将大小不同的数据包从单个发送方传递到单个接收方。 说明,该消息缓冲区仅提供数据的传输,不提供通信相关协议处理。

基本原理

实现双核之间通信基本原理:发送和接收任务位于非对称多处理器(AMP)配置中的多核微控制器MCU)的不同内核上,这意味着每个内核都运行自己的FreeRTOS程序。 同时,一个内核在另一个内核中具有生成中断的能力,以及两个内核都有访问的内存区域(共享内存)。消息缓冲区以每个内核上运行在应用程序已知的地址置在共享内存中,如下图:cb6c46fc-04fe-11ee-90ce-dac502259ad0.png  理想情况下,还将有一个内存保护单元(MPU),以确保只能通过内核的消息缓冲区API来访问消息缓冲区,并最好将共享内存标记为不可被其他程序占用。

单消息代码描述

这里官方提供了实现该方案的基础代码(仅供参考)。 将数据发送到流缓冲区的代码:
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()时,任务将不受阻碍。cb8bba1e-04fe-11ee-90ce-dac502259ad0.png  ISR通过将消息缓冲区的句柄作为参数传递给xMessageBufferSendCompletedFromISR()函数来解除对任务的阻塞。 如图箭头所示,其中发送和接收任务位于不同的MCU内核上:1.接收任务尝试从空的消息缓冲区中读取数据,并进入阻止状态以等待数据到达。2.发送任务将数据写入消息缓冲区。3.sbSEND_COMPLETED()在正在执行接收任务的内核中触发一个中断。4.中断服务例程调用xMessageBufferSendCompletedFromISR()来解除阻止接收任务,该任务现在可以从缓冲区读取,因为缓冲区不再为空。

多消息代码描述

当只有一个消息缓冲区时,很容易将消息缓冲区的句柄传递到xMessageBufferSendCompletedFromISR()中。 但是要考虑有两个或更多消息缓冲区的情况,ISR必须首先确定哪个消息缓冲区包含数据。如果消息缓冲区的数量很少,则有几种方法可以实现:
  • 如果硬件允许,则每个消息缓冲区可以使用不同的中断线,从而使中断服务程序和消息缓冲区之间保持一对一的映射。
  • 中断服务例程可以简单地查询每个消息缓冲区以查看其是否包含数据。
  • 可以通过传递元数据(消息是什么,消息的预期接收者是什么等等)以及实际数据的单个消息缓冲区来代替多个消息缓冲区。
但是,如果存在大量或未知的消息缓冲区,则这些技术效率不高。 在这种情况下,可伸缩的解决方案是引入单独的控制消息缓冲区。如下面的代码所示,sbSEND_COMPLETED()使用控制消息缓冲区将包含数据的消息缓冲区的句柄传递到中断服务例程中。 使用sbSEND_COMPLETED()的实现:
/* 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 );
}
cb941420-04fe-11ee-90ce-dac502259ad0.png如图,使用控制消息缓冲区时的顺序:1.接收任务尝试从空的消息缓冲区中读取数据,并进入阻止状态以等待数据到达。2.发送任务将数据写入消息缓冲区。3.sbSEND_COMPLETED()将现在包含数据的消息缓冲区的句柄发送到控制消息缓冲区。4.sbSEND_COMPLETED()在正在执行接收任务的内核中触发一个中断。5.中断服务例程从控制消息缓冲区中读取包含数据的消息缓冲区的句柄,然后将该句柄传递给xMessageBufferSendCompletedFromISR()API函数以取消阻止接收任务,该任务现在可以从缓冲区读取,因为缓冲区不再存在空的。 当然,以上仅提供基础原理和方法,具体实现需结合项目实际情况。更多相关内容,请参看官方相关资料

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • mcu
    mcu
    +关注

    关注

    146

    文章

    16017

    浏览量

    343632
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10442

    浏览量

    206564
  • RTOS
    +关注

    关注

    20

    文章

    776

    浏览量

    118796

原文标题:RTOS实现双核MCU消息通信

文章出处:【微信号:strongerHuang,微信公众号:strongerHuang】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    RTOS实现双核MCU消息通信

    之间怎么通信?其实,通信的方式和方法有很多种。本文就给大家描述一下:使用FreeRTOS消息缓冲区,实现简单的非对称多处理(AMP)核心到核心通信,结合STM32H7(M4和M7) 双
    发表于 06-07 14:45 749次阅读
    <b class='flag-5'>RTOS</b><b class='flag-5'>实现</b>双核<b class='flag-5'>MCU</b>消息<b class='flag-5'>通信</b>

    nios ii例子

    的PIOpio_cpu_1(输入)相连,在cpu_1的程序中,如果检测到pio_cpu_1为高电平,则使得输出pio_cpu_1_out1每隔0.5s翻转一次,可以接led 灯观看效果。此例子虽然简单,但是实现
    发表于 08-12 15:18

    怎么在CCS上设计dsplink通信

    目前正在使用OMAPL138芯片,需要进行DSP与ARM通信,使用的是dsplink。请问如何在CCS5上开发dsplink呢?谢谢!
    发表于 12-02 16:29

    非对称MCU基础知识及通信

    来源 网络本文从对比两颗分立MCU与单芯片MCU开始(以LPC4350为例),展开介绍了非对称
    发表于 05-15 14:26

    WINCE6.0 如何实现OMAPL138通信呢?

    ARM端运行wince6.0 如何实现OMAPL138中的ARM与DSP的通信?可以使用 syslink 吗?有哪位大神知道呀?
    发表于 06-21 11:28

    OMAPL138的通信组件DSPLINK开发和通信演示教程

    共享一个OMAPL138的通信组件DSPLINK开发和通信演示教程,希望大家顶顶!!
    发表于 06-21 17:09

    搞定单CPU内间的通信CPU间的通信

    [table][tr][td] 终于搞定了单CPU内间的通信CPU间的通信 +-----+ + ARM ++ DDR + + DS
    发表于 08-19 01:37

    基于MCU提高系统性能

    MCU 内核的资源和不同任务所需要的运行时间,需要更多的测试时间,因此不利于扩展和产品维护。面对种种不足,异构架构应运而生,可以很好解决上述问题。事实上,非对称
    发表于 07-04 07:49

    如何采用非对称MCU提高系统性能?

    本文系统地介绍了 C2000 Concerto 系列非对称 MCU 的基础知识和重要特点。
    发表于 04-02 06:02

    怎么实现ARM/DSP系统的通信接口的设计?

    本文介绍了使用ARM和DSPCPU构成的嵌入式系统的硬件平台,以及源代码开放的Linux作为嵌入式系统中操作系统的方法,给出了系统设计的总体框图,详细介绍了ARM和DSP通信接口
    发表于 05-26 06:21

    非对称MCU的基础知识与重要特点

    本文从对比两颗分立MCU与单芯片MCU开始(以LPC4350为例),展开介绍了非对称
    发表于 11-01 06:29

    MCU Pico的相关资料分享

    树莓派不讲武德,自研MCU Pico,STM32哭晕在厕所!重磅,树莓派再出Pico自研MCU
    发表于 11-04 08:51

    如何用一个比较简单SMP的example来体现的处理能力比单核强呢?

    qemu-vexpress-a9 这个平台上实现一下。或者换个问题:在MCU的大部分应用场景下(排除MPU),大家都是如何看待,什么情况下必须上
    发表于 03-13 15:17

    Arm+RISC-V异构前景如何?

    2021航顺HK32MCU新品发布会上,航顺介绍了自主研发的异构MCU-HK32U1xx9系列产品。Arm Cortex-M3大负责主
    发表于 04-14 10:06

    请问之间如何通信

    请问之间如何通信? 怎么处理核对外设资源出现竞争的问题?
    发表于 05-26 06:37