前言

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. 用户态程序调用系统态程序-快速系统调用
  2. 安卓四大组件之二广播
  3. ios文件系统架构图,图片解说
  4. not enough arguments for format string
  5. Python之进程+线程+协程(进程的本质 与 threading线程模块)
  6. MOOC推荐及三门基础学科
  7. MIT“食人花”机器人,能抓起120倍重的物体,软硬皆可,不问形状
  8. QCon思考之通过Quora和Spotify案例,直击数据处理背后的魅影
  9. metacube 链接 mysql_2019 年 5月 随笔档案 - rgqancy - 博客园
  10. 校园网设计超超超级详细的配置来了(以河北科技大学为例)
  11. java 租房系统源码,JAVA房屋出租管理系统
  12. python 离线安装paramiko_离线安装 Python 2.7, paramiko 和 tornado
  13. 如何使用IntelliJ IDEA中自带的mvn命令
  14. 如何利用 Apache APISX 提升 Nginx 的可观测性
  15. opengl自学记录_键盘控制图形平移
  16. 机器学习-吃瓜教程(西瓜书+南瓜书)-神经网络
  17. 程序员的数学基础课 二进制(自我提升第6天)
  18. crmebpro2.3多店版,赠送PC版.可包更新,官方授权
  19. 实现无损视频/GIF/图像放大(翻译)
  20. 正交法---测试用例设计方法

热门文章

  1. C#小工具 ---- 压缩图片并指定图片大小
  2. c语言 数组的抽奖小游戏
  3. 短裙高跟丝袜外拍,真的很漂亮哦!
  4. 警惕,贡献商业源码入群!专门针对程序员的一种网络诈骗!
  5. mongodb-18.聚合查询练习1
  6. 如何使用CAD编辑器来画箭头
  7. Python数据分析与可视化期末简答题复习
  8. C# 结束进程的解决方法
  9. SharePoint 2007部署过程
  10. 【调剂】大连民族大学2020年硕士研究生招生调剂公告