openamp RPU-APU双核间通信 建立多个通道

news/2025/2/12 23:49:55/

前言

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的大小不能调整


http://www.ppmy.cn/news/859131.html

相关文章

APU异构计算论文总结

目录 Accelerated Processing Unit(APU) Potential N-body simulation case study摘要引言主体结论 链接&#xff1a;Accelerated Processing Unit(APU) Potential N-body simulation case study论文总结 Accelerated Processing Unit(APU) Potential N-body simulation case s…

NES APU Replayer

做了一个重播 NES APU 指令的 UI&#xff1a; 点击图片或这里体验。 使用说明&#xff1a; 将录制好的文本文件拖放到 UI 中即可开始播放录制文件格式如下&#xff1a;82946, $4015, $0f 82952, $4017, $c0 83145, $4015, $0b 83151, $4008, $00 83157, $4015, $0f 83169, $4…

什么是APU(辅助动力装置)?

原文&#xff1a;https://www.sohu.com/a/166415510_465912 让我们来聊一聊现代飞机&#xff0c;尤其是大中型客机不可或缺的系统——辅助动力装置APU。提起“APU”,老多人会一下子想起电脑的APU&#xff0c;在航空界&#xff0c;还有这个部件&#xff0c;也叫“APU”-Auxilia…

APU是什么

APU的英文全称是Accelerated Processing Unit&#xff0c;中文意思是加速处理器&#xff0c;是AMD融聚理念的产品。APU第一次将处理器和独显核心做在一个晶片上&#xff0c;同时具有高性能处理器和最新独立显卡的处理性能&#xff0c;支持DX11游戏和最新应用的“加速运算”&…

APU(美国AMD公司研发的加速处理器)

APU(Accelerated Processing Unit)中文名字叫加速处理器&#xff0c;是AMD“融聚未来”理念的产品&#xff0c;它第一次将中央处理器和独显核心做在一个晶片上&#xff0c;它同时具有高性能处理器和最新独立显卡的处理性能&#xff0c;支持DX11游戏和最新应用的“加速运算”&am…

uniapp下载和上传照片

利用uniapp开发的时候&#xff0c;需要下载和上传照片&#xff0c;在H5和微信小程序中的写法不一样。 H5环境下 浏览器中下载就是模拟超链接下载。也不需要获取什么权限&#xff0c;比较简单。 // #ifdef H5 this.isLoading true; let oA document.createElement("a&…

Web前端技术 Web学习资料 Web学习路线 Web入门宝典(不断更新中)

(此文档于2019年3月停止再更新&#xff0c;后续更新移步至&#xff1a;https://github.com/liuyuqin1991/polaris) 学习路线 第一章 技术&#xff08;核心单独列章节&#xff09; 1.Node Node.js 就是运行在服务端的 JavaScript。Node.js 是一个基于Chrome JavaScript 运行时…

3、Redis底层原理(持久化+分布式锁)

Redis底层原理 持久化 Redis虽然是个内存数据库&#xff0c;但是Redis支持RDB和AOF两种持久化机制&#xff0c;将数据写往磁盘&#xff0c;可以有效地避免因进程退出造成的数据丢失问题&#xff0c;当下次重启时利用之前持久化的文件即可实现数据恢复。 RDB RDB持久化是把当…