加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    •  简介
    •   双核通信
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

【产品应用】AWorksLP 样例详解(MR6750)——双核通信

2023/09/27
2921
阅读需 12 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

AWorksLP 对外设进行了高度抽象化,为同一类外设提供了相同的接口,应用程序可以轻松跨平台。本文以MR6750 平台为例,介绍AWorksLP  双核通信的基本用法。

 简介

通信信箱MBX 有2 套寄存器访问接口,接口A 和接口B。A 和B 接口都具有一套TX FIFO 寄存器、RX FIFO

寄存器、控制寄存器和状态寄存器。用户从A 接口的发送端TX 发送的数据,可以在B 接口的接收端RX 接收 到。同理,A 接口的接收端RX 可以接收到B 接口发送端TX 发送的数据。

双核烧录的用法请参考《AWorksLP样例详解(MR6750)——双核烧录》

双核调试的用法请参考《AWorksLP样例详解(MR6750)——双核调试》

  双核通信

1. MBX信箱

{SDK}demosmulti-coreopenamp路径下为openamp的例程。双核通信需要使用信箱在gui上勾选对应的信箱接口,hart0和hart1需勾选同一个信箱的两个不同接口。例如hart0勾选了mbx0a、则hart1需勾选mbx0b。

图1 mbx设备

2. OpenAMP

OpenMP是由OpenMP Architecture Review Board牵头提出的,并已被广泛接受,用于共享内存并行系统的多处理器程序设计的一套指导性编译处理方案。

3. 例程

#if CONFIG_AW_OPENAMP_MASTERaw_local int rx_callback (struct rpmsg_endpoint *ept, void *data,                size_t len, uint32_t src, void *priv){    aw_kprintf("[Master receive]: %sn", data);    return 0;}#elseaw_local int rx_callback (struct rpmsg_endpoint *ept, void *data,                size_t len, uint32_t src, void *priv){    char sendbuf[512];
    aw_kprintf("[Slave receive]: %sn", data);    aw_snprintf(sendbuf, sizeof(sendbuf), "%s ACK", data);    if (rpmsg_send(&__resmgr_ept, sendbuf, strlen(sendbuf) + 1) < 0) {        aw_kprintf("[Slave send]: error!n");    }    return 0;}#endif

aw_local int __mail_box_notify(void *priv, uint32_t id){    uint32_t tmp;
#if CONFIG_AW_OPENAMP_MASTER    /* master to remote */    if (id == VRING1_ID) {        /* send msg */        tmp = EPT_SEND_MSG_FLAG;    } else { /* remote to master */        /* send ack */        tmp = EPT_SEND_ACK_FLAG;    }#else    if (id == VRING1_ID) {        /* send ack */        tmp = EPT_SEND_ACK_FLAG;    } else {        /* send msg */        tmp = EPT_SEND_MSG_FLAG;    }#endif
    aw_write(__g_mbx_fd, &tmp, 4);    return 0;}

/* 处理其它设备发送过来的MBX */aw_local void __openamp_task(void *p_arg){
    struct rpmsg_virtio_device *p_dev = (struct rpmsg_virtio_device *)p_arg;
    aw_kprintf("Entry OpenAMP task!n");
    while(1) {        uint32_t tmp;
        aw_read(__g_mbx_fd, &tmp, 4);
        /*         * 默认Master VRING0是接收, VRING1是发送, 从机反之         */#if CONFIG_AW_OPENAMP_MASTER        if (tmp == EPT_SEND_MSG_FLAG) {
            /* 接收到来自从机的消息 */            rproc_virtio_notified(p_dev->vdev, VRING0_ID);        } else {
            /* 接收到来自从机的ACK */            rproc_virtio_notified(p_dev->vdev, VRING1_ID);        }#else
        if (tmp == EPT_SEND_MSG_FLAG) {            rproc_virtio_notified(p_dev->vdev, VRING1_ID);        } else {            rproc_virtio_notified(p_dev->vdev, VRING0_ID);        }#endif    }}
void rpmsg_demo(){    int ret = 0;#if CONFIG_AW_OPENAMP_MASTER    int i = 0;    int RPMsgRole = 0;#else    int RPMsgRole = 1;#endif
    __g_mbx_fd = aw_open(CONFIG_MBX_CHOOSE, AW_O_RDWR, 0);
    ret = aw_openamp_init(&rpmsg_dev, RPMsgRole, NULL, __mail_box_notify);
#if CONFIG_AW_OPENAMP_MASTER    /* 启动固件 */    ret = aw_openamp_remoteproc_init(&__aworks_rproc_ops);    if (ret) {        aw_kprintf("Start processor fail!n");    }#endif
    if (ret) {        aw_kprintf("OpenAMP init error!n");        while(1);    }
    aw_openamp_create_ept(&rpmsg_dev,                          &__resmgr_ept,                           "rpmsg-client-sample",                           0xFFFFFFFF,                           rx_callback, NULL);
    aw_openamp_ep_poll_task_start(&rpmsg_dev);    aw_openamp_wait_ept_ready(&__resmgr_ept);
    while(1) {
#if CONFIG_AW_OPENAMP_MASTER        char sendbuf[512];        aw_snprintf(sendbuf, sizeof(sendbuf), "AWorks %d", i);        aw_kprintf("[Master send]: %sn", sendbuf);        if (aw_openamp_send(&__resmgr_ept, sendbuf, strlen(sendbuf) + 1) < 0) {            aw_kprintf("[Master send]: error!n");        }        i++;#else        aw_kprintf("Salve is alive!n");#endif        aw_mdelay(100);    }}

由于篇幅原因本文仅截取部分关键代码。

    • 在rpmsg_demo中使用aw_open打开信箱、使用aw_openamp_init并注册__mail_box_notify函数;在__mail_box_notify函数中发送相应的标记、使用aw_openamp_remoteproc_init函数注册__aworks_rproc_ops,参数中是各运行阶段的函数接口;使用aw_openamp_create_ept函数注册rx_callback接收回调函数,当作为主核时打印从核发送的数据,当作为从核时将收到的数据发送回去;使用aw_openamp_ep_poll_task_start函数创建一个任务,任务的函数入口为__openamp_task,在__openamp_task函数中根据读到的标记做相应的处理。

使用aw_openamp_wait_ept_ready函数等待从机准备好。

在while循环中主核使用aw_openamp_send函数循环的发送数据、从核在rx_callback回调函数中将主核发送的数据发送回去、串口打印如下图。

图2 串口打印

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
TJA1051T/3/1J 1 NXP Semiconductors TJA1051 - High-speed CAN transceiver SOIC 8-Pin

ECAD模型

下载ECAD模型
$1.11 查看
TJA1043T,118 1 NXP Semiconductors TJA1043 - High-speed CAN transceiver SOIC 14-Pin

ECAD模型

下载ECAD模型
$2.43 查看
RTL8211F-CG 1 Realtek Semiconductor Ethernet Transceiver, QCC40, QFN-40
暂无数据 查看
致远电子

致远电子

广州致远电子股份有限公司成立于2001年,注册资金5000万元,国家级高新技术认证企业,广州市高端工控测量仪器工程技术研究开发中心,Intel ECA全球合作伙伴和微软嵌入式系统金牌合作伙伴。

广州致远电子股份有限公司成立于2001年,注册资金5000万元,国家级高新技术认证企业,广州市高端工控测量仪器工程技术研究开发中心,Intel ECA全球合作伙伴和微软嵌入式系统金牌合作伙伴。收起

查看更多

相关推荐

电子产业图谱