前言

RPU-APU使用openamp进行通信

源码中只有单通道,并且通道最大512字节。

两种方法:
1)使用更多的通道;2)将通道的缓冲区扩大;

本文介绍建立多个通道方法

一、创建节点函数

先看一下手册中函数的使用说明

函数有删减,分析用

int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev,const char *name, uint32_t src, uint32_t dest,rpmsg_ept_cb cb, rpmsg_ns_unbind_cb unbind_cb)
{
...//如果源地址不是RPMSG_ADDR_ANYif (src != RPMSG_ADDR_ANY) {status = rpmsg_is_address_set(rdev->bitmap,RPMSG_ADDR_BMP_SIZE, src);if (!status) {/* Mark the address as used in the address bitmap. */rpmsg_set_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE,src);} else if (status > 0) {status = RPMSG_SUCCESS;goto ret_status;} else {goto ret_status;}} else {addr = rpmsg_get_address(rdev->bitmap, RPMSG_ADDR_BMP_SIZE);}rpmsg_init_ept(ept, name, addr, dest, cb, unbind_cb);rpmsg_register_endpoint(rdev, ept);//目的地址RPMSG_ADDR_ANYif (rdev->support_ns && ept->dest_addr == RPMSG_ADDR_ANY) {/* Send NS announcement to remote processor */metal_mutex_release(&rdev->lock);status = rpmsg_send_ns_message(ept, RPMSG_NS_CREATE);metal_mutex_acquire(&rdev->lock);if (status)rpmsg_unregister_endpoint(ept);}
...
}

src源地址,可以是0,1,2…RPMSG_ADDR_ANY
dest目的地址必须是:RPMSG_ADDR_ANY

官方文档中发送函数

RPU有的函数指定源地址和目的地址,
源地址就是通道创建时的src,
目的地址:比如APU侧,建立连接的时候需要源地址和目的地址,此源地址就是RPU的dest地址

使用rpmsg_send函数 根据 endpoint可以知道建立的连接,可以不使用带src,dest参数的函数。

二、RPU侧创建多通道

创建连接16个连接endpoint
源地址:[0-15],
目的地址:RPMSG_ADDR_ANY

//函数指针
typedef int (*FUN_CALC) (struct rpmsg_endpoint *ept, void *data, size_t len,uint32_t src, void *priv);//回调函数数组,为了能方便注册函数,使代码简介
FUN_CALC pFuncList[] = {&rpmsg0_endpoint_cb, &rpmsg1_endpoint_cb, &rpmsg2_endpoint_cb, &rpmsg3_endpoint_cb,&rpmsg4_endpoint_cb, &rpmsg5_endpoint_cb, &rpmsg6_endpoint_cb, &rpmsg7_endpoint_cb,&rpmsg8_endpoint_cb, &rpmsg9_endpoint_cb,&rpmsg10_endpoint_cb, &rpmsg11_endpoint_cb,&rpmsg12_endpoint_cb, &rpmsg13_endpoint_cb, &rpmsg14_endpoint_cb,&rpmsg15_endpoint_cb
};
//官方的app函数修改,创建过个endpoint
int app(struct rpmsg_device *rdev, void *priv)
{int ret,i;LPRINTF("Try to create rpmsg endpoint.\n");char service_name[32];for(i=0;i<16;i++){sprintf(service_name,"rpmsg-openamp-demo-channel%d",i);//服务名字/* Initialize RPMSG framework */ret = rpmsg_create_ept(&lept[i], rdev, service_name,i, RPMSG_ADDR_ANY, pFuncList[i],rpmsg_service_unbind);if (ret) {LPERROR("Failed to create endpoint1.\n");return -1;}}if (ret) {LPERROR("Failed to create endpoint2.\n");return -1;}LPRINTF("Successfully created rpmsg endpoint1.\n");while(1) {vTaskDelay(100);//增加调度延时函数platform_poll(priv);//阻塞函数修改,取消_rproc_wait()}for(i=0;i<17;i++)rpmsg_destroy_ept(&lept[i]);return 0;
}//回调函数1
static int rpmsg0_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,uint32_t src, void *priv)
{(void)priv;(void)src;/* On reception of a shutdown we signal the application to terminate */if ((*(unsigned int *)data) == SHUTDOWN_MSG) {LPRINTF("shutdown message is received.\n");shutdown_req = 1;return RPMSG_SUCCESS;}/* Send data back to master */if (rpmsg_send(ept, data, len) < 0) {LPERROR("rpmsg_send failed2\n");}else{LPRINTF("rpmsg_send ok0 \n");}return RPMSG_SUCCESS;
}//回调函数2
static int rpmsg1_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,uint32_t src, void *priv)
{(void)priv;(void)src;/* On reception of a shutdown we signal the application to terminate */if ((*(unsigned int *)data) == SHUTDOWN_MSG) {LPRINTF("shutdown message is received.\n");shutdown_req = 1;return RPMSG_SUCCESS;}/* Send data back to master */if (rpmsg_send(ept, data, len) < 0) {LPERROR("rpmsg_send failed3\n");}else{LPRINTF("rpmsg_send ok1 \n");}return RPMSG_SUCCESS;
}
//回调函数3
static int rpmsg2_endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len,uint32_t src, void *priv)
{(void)priv;(void)src;/* On reception of a shutdown we signal the application to terminate */if ((*(unsigned int *)data) == SHUTDOWN_MSG) {LPRINTF("shutdown message is received.\n");shutdown_req = 1;return RPMSG_SUCCESS;}/* Send data back to master */if (rpmsg_send(ept, data, len) < 0) {LPERROR("rpmsg_send failed3\n");}else{LPRINTF("rpmsg_send ok2 \n");}return RPMSG_SUCCESS;
}
...(剩下的回调函数省略)

platform_poll 函数如下
注释内部while循环,等待函数

int platform_poll(void *priv)
{struct remoteproc *rproc = priv;struct remoteproc_priv *prproc;unsigned int flags;prproc = rproc->priv;//while(1) {flags = metal_irq_save_disable();if (!(atomic_flag_test_and_set(&prproc->ipi_nokick))) {metal_irq_restore_enable(flags);remoteproc_get_notification(rproc, RSC_NOTIFY_ID_ANY);//RSC_NOTIFY_ID_ANYreturn 0;//break;}//_rproc_wait();metal_irq_restore_enable(flags);//}return 0;
}

三、APU侧创建多通道

在RPU侧建立好16通道后,加载运行,在ls -l /sys/bus/rpmsg/devices

lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel0.-1.0 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel0.-1.0
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel1.-1.1 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel1.-1.1
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel10.-1.10 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel10.-1.10
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel11.-1.11 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel11.-1.11
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel12.-1.12 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel12.-1.12
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel13.-1.13 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel13.-1.13
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel14.-1.14 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel14.-1.14
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel15.-1.15 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel15.-1.15
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel16.-1.16 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel16.-1.16
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel2.-1.2 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel2.-1.2
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel3.-1.3 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel3.-1.3
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel4.-1.4 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel4.-1.4
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel5.-1.5 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel5.-1.5
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel6.-1.6 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel6.-1.6
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel7.-1.7 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel7.-1.7
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel8.-1.8 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel8.-1.8
lrwxrwxrwx 1 root root 0 Nov 26 01:20 virtio0.rpmsg-openamp-demo-channel9.-1.9 -> ../../../devices/platform/ff9a0000.zynqmp-rpu/r5@0/r5@0#vdev0buffer/virtio0/virtio0.rpmsg-openamp-demo-channel9.-1.9

节点规律:virtio0.rpmsg-openamp-demo-channelX.-1.X

APU 源码echo_test 在创建节点的时候,需要根据virtio0.rpmsg-openamp-demo-channelX.-1.X创建

char rpmsg_dev[][50]={"virtio0.rpmsg-openamp-demo-channel0.-1.0","virtio0.rpmsg-openamp-demo-channel1.-1.1","virtio0.rpmsg-openamp-demo-channel2.-1.2","virtio0.rpmsg-openamp-demo-channel3.-1.3","virtio0.rpmsg-openamp-demo-channel4.-1.4","virtio0.rpmsg-openamp-demo-channel5.-1.5","virtio0.rpmsg-openamp-demo-channel6.-1.6","virtio0.rpmsg-openamp-demo-channel7.-1.7","virtio0.rpmsg-openamp-demo-channel8.-1.8","virtio0.rpmsg-openamp-demo-channel9.-1.9","virtio0.rpmsg-openamp-demo-channel10.-1.10","virtio0.rpmsg-openamp-demo-channel11.-1.11","virtio0.rpmsg-openamp-demo-channel12.-1.12","virtio0.rpmsg-openamp-demo-channel13.-1.13","virtio0.rpmsg-openamp-demo-channel14.-1.14","virtio0.rpmsg-openamp-demo-channel15.-1.15","virtio0.rpmsg-openamp-demo-channel16.-1.16",
};char rpmsg_name[][40]={"rpmsg-openamp-demo-channel0","rpmsg-openamp-demo-channel1","rpmsg-openamp-demo-channel2","rpmsg-openamp-demo-channel3","rpmsg-openamp-demo-channel4","rpmsg-openamp-demo-channel5","rpmsg-openamp-demo-channel6","rpmsg-openamp-demo-channel7","rpmsg-openamp-demo-channel8","rpmsg-openamp-demo-channel9","rpmsg-openamp-demo-channel10","rpmsg-openamp-demo-channel11","rpmsg-openamp-demo-channel12","rpmsg-openamp-demo-channel13","rpmsg-openamp-demo-channel14","rpmsg-openamp-demo-channel15","rpmsg-openamp-demo-channel16",
};#define RPMSG_MAX_CHANNEL 17//主函数
int main(int argc, char *argv[])
{int ret, i, j;int size, bytes_rcvd, bytes_sent;err_cnt = 0;int opt;//char *rpmsg_dev="virtio0.rpmsg-openamp-demo-channel.-1.0";int ntimes = 1;char fpath[256];int rec[474];char rpmsg_char_name[16][16];struct rpmsg_endpoint_info eptinfo[16];char ept_dev_name[16];char ept_dev_path[32];int rmpsg_fd[16];while ((opt = getopt(argc, argv, "d:n:")) != -1) {switch (opt) {case 'd'://rpmsg_dev = optarg;break;case 'n':ntimes = atoi(optarg);break;default:printf("getopt return unsupported option: -%c\n",opt);break;}}printf("\r\n Echo test start \r\n");/* Load rpmsg_char driver */printf("\r\nMaster>probe rpmsg_char\r\n");ret = system("modprobe rpmsg_char");if (ret < 0) {perror("Failed to load rpmsg_char driver.\n");return -EINVAL;}for(i=0;i<RPMSG_MAX_CHANNEL ;i++){charfd[i]=-1;memset(rpmsg_char_name[i],0,sizeof(rpmsg_char_name[0]));}for(i=0;i<RPMSG_MAX_CHANNEL;i++){printf("\r\n Open rpmsg dev %s! \r\n", rpmsg_dev);sprintf(fpath, "%s/devices/%s", RPMSG_BUS_SYS, rpmsg_dev[i]);if (access(fpath, F_OK)) {fprintf(stderr, "Not able to access rpmsg device %s, %s\n",fpath, strerror(errno));return -EINVAL;}memset(fpath,0,sizeof(fpath));ret = bind_rpmsg_chrdev(rpmsg_dev[i]);if (ret < 0)return ret;charfd[i] = get_rpmsg_chrdev_fd(rpmsg_dev[i], rpmsg_char_name[i]);if (charfd[i] < 0)return charfd[i];/* Create endpoint from rpmsg char driver */strcpy(eptinfo[i].name, rpmsg_name[i]);eptinfo[i].src = i;eptinfo[i].dst = 0xFFFFFFFF;ret = rpmsg_create_ept(charfd[i], &eptinfo[i]);if (ret) {printf("failed to create RPMsg endpoint.\n");return -EINVAL;}if (!get_rpmsg_ept_dev_name(rpmsg_char_name[i], eptinfo[i].name,ept_dev_name))return -EINVAL;sprintf(ept_dev_path, "/dev/%s", ept_dev_name);rmpsg_fd[i] = open(ept_dev_path, O_RDWR | O_NONBLOCK);if (rmpsg_fd[i] < 0) {perror("Failed to open rpmsg device.");close(rmpsg_fd[i]);return -1;}memset(ept_dev_path,0,sizeof(ept_dev_path));memset(ept_dev_name,0,sizeof(ept_dev_name));}i_payload = (struct _payload *)malloc(2 * sizeof(unsigned long) + PAYLOAD_MAX_SIZE);r_payload = (struct _payload *)malloc(2 * sizeof(unsigned long) + PAYLOAD_MAX_SIZE);if (i_payload == 0 || r_payload == 0) {printf("ERROR: Failed to allocate memory for payload.\n");return -1;}while(1){if(i==15)i=0;//16个通道轮询收发bytes_sent = write(rmpsg_fd[i], i_payload,(2 * sizeof(unsigned long)) + size);printf("fd bytes_sent=%d\n",bytes_sent);bytes_rcvd = read(rmpsg_fd[i], RX_BUF,PAYLOAD_MAX_SIZE);while (bytes_rcvd <= 0) {bytes_sent = write(rmpsg_fd[i], i_payload,(2 * sizeof(unsigned long)) + size);printf("while fd bytes_sent=%d\n",bytes_sent);usleep(10000);bytes_rcvd = read(rmpsg_fd[i],RX_BUF,PAYLOAD_MAX_SIZE);}printf("index=%d,recv data len=%d\n",i,bytes_rcvd);i++;}free(i_payload);free(r_payload);for(i=0;i<16;i++)close(rmpsg_fd[i]);if (charfd >= 0)close(charfd);return 0;
}

串口输出,收发正常

index=1,recv data len=17
fd bytes_sent=17
index=2,recv data len=17
fd bytes_sent=17
index=3,recv data len=17
fd bytes_sent=17
index=4,recv data len=17
fd bytes_sent=17
index=5,recv data len=17
fd bytes_sent=17
index=6,recv data len=17
fd bytes_sent=17
index=7,recv data len=17
fd bytes_sent=17
index=8,recv data len=17
fd bytes_sent=17
index=9,recv data len=17
fd bytes_sent=17
index=10,recv data len=17
fd bytes_sent=17
index=11,recv data len=17
fd bytes_sent=17
index=12,recv data len=17
fd bytes_sent=17
index=13,recv data len=17
fd bytes_sent=17
index=14,recv data len=17

openamp测试发现的问题
1)RPU只有收到APU的数据后,才能调用rpmsg_send函数发送数据,这里不知道哪里有问题?

2)单通道缓冲区扩大方法?

The RPMsg buffer size is limited to 512 bytes, but 496 bytes are used for the payload.
The OpenAMP message size is limited by the buffer size defined in the rpmsg kernel module.
IMPORTANT: Do not redefine the RPMsg buffer size.

手册中提示,RPMsg buffer的大小不能调整

openamp RPU-APU双核间通信 建立多个通道相关推荐

  1. 计算机网络如何新建vlan和划分vlan,[单选] 划分VLAN后,不同VLAN的计算机之间不能实现二层通信。如果在VLAN间通信,需要建立()...

    [单选] 划分VLAN后,不同VLAN的计算机之间不能实现二层通信.如果在VLAN间通信,需要建立() 更多相关问题 图是王强同学在研究性学习活动中,为某仓库设计的一种防盗报警器.其踏板放在仓库的门口 ...

  2. 多核异构核间通信-mailbox/RPMsg 介绍及实验

    1. 多核异构核间通信 由于MP157是一款多核异构的芯片,其中既包含的高性能的A7核及实时性强的M4内核,那么这两种处理器在工作时,怎么互相协调配合呢? 这就涉及到了核间通信的概念了. IPCC ( ...

  3. 第十八节 多核异构核间通信–ipcc

    由于MP157 是一款多核异构的芯片,其中既包含的高性能的A7 核及实时性强的M4 内核,那么这两种处理器在工作时,怎么互相协调配合呢?这就涉及到了核间通信的概念了. IPCC (inter-proc ...

  4. 容器间通信_Vue组件间通信的6种方式,前端工程师人人都会,网友:太简单了...

    Vue 组件间通信只要指以下 3 类通信:父子组件通信.隔代组件通信.兄弟组件通信,下面分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信. (1)props / $emit 适用 父子组件通 ...

  5. Docker网络——实现容器间通信、容器与外网通信以及容器的跨主机访问

    前言 自定义网络 建议使用自定义的网桥来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址.Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的Bridge网络,Over ...

  6. Java基础学习——多线程(线程间通信-生产者消费者代码示例)

    JDK 1.5提供了多线程升级方案 将同步synchronized替换成了显示的Lock操作.可以实现唤醒.冻结指定的线程. Lock接口 Lock 实现提供了比使用 synchronized 方法和 ...

  7. Socket编程(C语言实现)——TCP协议(网络间通信AF_INET)的流式(SOCK_STREAM)+报式(SOCK_DGRAM)传输【多线程+循环监听】

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  8. Net线程间通信的异步机制

    线程间通信 我们看下面的图 图1 我们来看线程间通信的原理:线程(Thread B)和线程(Thread A)通信, 首先线程A 必须实现同步上下文对象(Synchronization Context ...

  9. linux线程间通信优点,进程间通信与线程间通信【转】

    一个进程写管道:写入字节数小于PIPE_BUF是原子操作,写操作在管道缓冲区没有及时读走时发生阻塞. 一个进程读管道:读操作在管道缓冲区没有数据时发生阻塞. 以前一直想找个机会总结一下进程和线程的通信 ...

最新文章

  1. EXT iconCls说明
  2. 糟心!苹果无人车裁员190人,程序员却首当其冲
  3. DDD助力平台能力复用
  4. mysql autocommit 脚本_mysql autocommit的差异
  5. OpenCV学习(7.16)
  6. php程序访问mysql数据实现查询_PHP+MySql实现后台数据的读取
  7. python半圆代码_趣味项目:用Python代码做个月饼送给你!
  8. Asp.Net MVC 体验 2 持久层的构建
  9. java使用Poi导出excel表格
  10. 乐优商城(11)--用户中心
  11. 溜客php0day挖掘,【漏洞预警】PHP7被发现三个0day漏洞,其中一个还
  12. “撤县设市”の利与弊
  13. GROMACS .mdp 选项翻译及笔记
  14. css 唤醒qq聊天,移动端唤起QQ聊天
  15. MySQL 变量和条件
  16. IMEISV码转换成IMEI码
  17. Word删除下划线上的文字
  18. 2021-06-06 SpringBoot 入门(五)组件添加(三) @Conditional条件装配
  19. 基于Vue实现电商SKU组合算法问题
  20. ORACLE 11G Data Guard 角色转换

热门文章

  1. shell 删除simatic_西门子技术--TIA Portal 软件安装时注册表的删除
  2. 期货公司最低标准的手续费和保证金
  3. 972信息检索 | 第一章 信息检索概述
  4. android 铃声设置失败,无法通过Android代码设置铃声
  5. TI 生态大宇宙 - 波卡 Polkadot
  6. JavaScript设计模式之观察者模式(学习笔记)
  7. IE8-下背景色半透明滤镜在jquery动画中失效问题记录
  8. 基于Spark的出租车信息查询系统
  9. 2021秋招面试经历----硬件工程师
  10. VGA接口复习笔记(原理,时序)VGA接口FPGA实现