介绍 eRPC 本教程介绍eRPC(嵌入式远程过程调用)开源项目。
eRPC(嵌入式远程过程调用)是由恩智浦创建的远程过程调用(RPC)系统。RPC是一种机制,用于通过简易本地函数调用远程系统上的调用软件例程。远程系统可以是通过通信信道连接的任何CPU:例如,网络中的服务器、多核系统中的另一个CPU内核,等等。对客户端而言,这就像在应用中调用某个库中的函数一样。唯一的区别在于通信信道引入的任何延迟或不可靠性。
重要链接:
所有与 eRPC 开发相关的内容都位于:GitHub - eRPC base
eRPC开发数据位于GitHub - eRPC development。
eRPC 发布版本位于:GitHub - eRPC Releases
eRPC文档位于Github - eRPC wiki
eRPC已作为Python软件包发布至pypi
eRPC支持多核和多处理器类型的应用。
在哪里可以找到 eRPC 示例
在 NXP MCUXpressoSDK 软件包中可以找到大量 eRPC 多核和多处理器示例。访问 https://mcuxpresso.nxp.com 可配置、构建并下载这些软件包。 要获取支持多核(包含 eRPC)的开发板列表,请基于 “中间件 (Middleware)” 进行筛选,并搜索 “multicore” 关键词。下载包含多核中间件的选定软件包后,可参考以下路径: /boards/ /multicore_examples :eRPC 多核示例(使用 RPMsg_Lite 或消息单元传输)或者 /boards/ /multiprocessor_examples :eRPC 多处理器示例(使用 UART 或 SPI 传输)。 eRPC 示例均以 “erpc_” 为名称前缀。
获取 NXP MCUXpressoSDK 的 eRPC 多核和多处理器示例的另一种方法是使用 mcux-sdk 的 GitHub 代码库。请按照 README 概述部分中关于如何使用 West 工具克隆和更新 mcuxsdk 代码库的说明操作。完成后,armgcc 版本的 eRPC 示例可以在以下文件夹中找到: mcuxsdk/examples/ /multicore_examples or in mcuxsdk/examples/ /multiprocessor_examples folders. 例如,你可以使用 evkmimxrt1170 作为 board_name。与 MCUXpressoSDK 软件包类似,这些 eRPC 示例都使用 “erpc_” 作为名称前缀。
Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Kunal,您好!您的问题似乎已在此得到解答:需要帮助——在iMx6sx中实现eRPC的分步过程?· 问题#5 · EmbeddedRPC/erpc-imx-demos · GitHub Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
HI
[email protected], 我不知道 eRPC 在 MPC5748G 上的官方使用方式。只是提醒一下:eRPC 取决于编程语言、操作系统和传输层。它没有特定于电路板的文件。所以,如果使用的是 FreeRTOS 和 C 语言,那几乎就成功了,你只需要移植你想用的传输层(如果还没有移植的话)。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan, eRPC是否已移植到恩智浦MPC5748G?有没有可供参考的示例代码? 顺祝商祺! Alex Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi
[email protected], 我在这方面没有太多经验。最近,当从多个任务中调用多个 eRPC 调用时,我们不得不添加一些互斥锁。不过我喜欢你的想法。 我快速浏览了一下源代码。你需要说明你的用例。但我认为是 i.MX Linux 与使用 RPMsg 的 M 核之间的通信。在这种情况下,我认为你可以像我们那样添加互斥锁(这将使 eRPC 调用序列化。你需要在 performRequest 函数的某个地方添加它们)。为每个线程创建端点在我看来是个好主意,但我发现有更多问题需要解决。一个更简单的解决方案可能是:传输初始化函数将初始化更多端点(基于任务数量),客户端的 eRPC rpmsg 发送 / 接收函数改为使用未使用的端点进行发送,并使用相同的端点接收消息,服务器上的 eRPC rpmsg 接收函数需要等待所有端点上的消息。 我不知道这对你来说是简单的任务还是更复杂的任务。但恐怕如果不修改代码,你将无法进行多线程调用。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan, 我目前在Cubic与Chandini共事。我只是想了解一下从多个线程调用eRPC的额外信息。当前我们采用单一端点进行即止型调用,每次调用完成后才发起下一次调用。现在我们希望通过多个线程发起多次调用,因此想了解实现该功能的最佳方案。 其实由于我对这方面了解不足,我们尝试过并发进行其他调用,不过直到出现问题,我们才意识到正在这么做。 我们已观测到eRPC返回的通信故障错误代码。 是否可以使用单一端点来实现这一点,也就是说客户端这边是否应该是线程安全的? 如果不建议执行此操作,是否应该为每个线程配置独立的端点, 或者我们应该做别的事情吗? 此致 李 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi
[email protected], 感谢您告知我们。真有趣,我今天因为另一项目刚刚研读过相关方案:smileygrin: Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan, 感谢您的快速回复。 通过在客户端和服务器端的套接字连接中禁用Nagle算法,并使用以下API调用,我可以在TCP中实现更好的性能(响应时间以微秒为单位)。 int result = setsockopt(sock, /* 受影响的套接字 */ IPPROTO_TCP, /* 在TCP级别设置选项 */ TCP_NODELAY, /* 选项名称 */ (char *) &flag, /* 类型转换是历史遗留问题 */ sizeof(int)); /* 选项值的长度 */ 参考资料:TCP_NODELAY:2018 年 TCP 优化最佳实践 | ExtraHop 谢谢! 萨西达兰。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi
[email protected], 或许您可以询问GitHub的相关用户(在同一主题下,或创建新主题)。至少有两名用户正在执行与TCP相关的任务: github: GitHub - EmbeddedRPC/erpc: Embedded RPC 线程1:使用具备TCP传输功能的多连接处理服务器 · 问题#32 · EmbeddedRPC/erpc · GitHub 讨论帖 2:TCP Example client /server code・Issue #39・EmbeddedRPC/erpc・GitHub 就个人而言我建议这个方案,但不确定是否适用于您的情况:linux - Ubuntu上的低延迟TCP设置 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan, 我想要将eRPC移植到TCP套接字上。 我在虚拟串口(Linux 系统内)上运行了你的示例测试代码 (test_arrays),串口的响应时间不到 1 毫秒。 当我通过TCP运行同一示例代码时,TCP的响应时间约为90毫秒。 有没有办法像优化串口那样,降低 TCP 的延迟并提升其性能呢? 谢谢! 萨西达兰。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi, Dusan. 这很有帮助。顺便说一下,示例的头文件中提到了这一点。 来自A9的函数调用运行良好,M4则可返回数据。 但当前问题出现在M4调用函数时。A9中显示如下错误:“MU传输缓冲等待清空超时!imx_mu_rpmsg_send()失败,错误码:-5”。 在出现此错误之后,数据函数调用也无法在另一端正常运行:“rpmsg_multiept rpmsg0: virtqueue_add_outbuf失败,错误码:-5” 我应该检查什么? 感谢您的帮助。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Vadim, 通常情况下,您需要执行两项任务。一项针对客户端,另一项则针对服务器。问题还在于erpc_arbitrated_client_init的输出结果应作为参数传递给初始化服务器。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
嗨,Dusan、Marek、社区。 我已经使用eRPC创建多个应用,M4(客户端)-A9(服务器)或M4(服务器)-A9(客户端)均能正常运行,但我希望在各端使用客户端/服务器应用。不过它现在无法正常工作或运行,只要从一端执行一次,应用就会挂起。 我想检查一下代码的整体结构。 我哪里做错了呢? 是不是应该在 M4 上为客户端和服务器分别使用两个独立的 FreeRTOS 任务? M4 . . erpc_transport_t transport = erpc_transport_rpmsg_lite_rtos_remote_init(.....); erpc_mbf_t message_buffer_factory = erpc_mbf_rpmsg_init(transport); erpc_server_init(transport, message_buffer_factory); erpc_add_service_to_server(create_TEST_service()); erpc_arbitrated_client_init(transport, message_buffer_factory); while (true) { erpc_server_poll(); function1(....); } A9 . . erpc_transport_t transport = erpc_transport_rpmsg_linux_init(......); erpc_mbf_t message_buffer_factory = erpc_mbf_dynamic_init(); erpc_server_init(transport, message_buffer_factory); erpc_add_service_to_server(create_TEST_service()); erpc_arbitrated_client_init(transport, message_buffer_factory); while (true) { erpc_server_poll(); function2(....); } Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
vadimfilippenko,您好!如果您仍然对使用Python版本的话题感兴趣,可以查看此线程:将MPU补丁添加到内核中 - 我无法查看新模块 · 问题#2 · EmbeddedRPC/erpc-imx-demos · GitHub。来自mhanuel26 的最后两条消息值得您关注,因其已成功使用python应用。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Dusan, Marek, 我终于成功启动了修改后的 eRPC 示例。不过在 Linux 端我用的是 C 语言,且在 M4 端使用的是 eRPC 1.5.0 版本,其中 rpmsg 初始化函数带 6 个参数(这是杜尚在 GitHub 上提到的关于第 6 个参数的提示)。感谢你们的帮助。准备好迎接新的问题吧) Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您需要在运行python应用之前运行M4应用。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Vadim, 请在这里贴出:ls /sys/class/rpmsg 的结果 看起来 M4 没有发送命名服务(M4 是否运行了正确的固件?)。正因为如此,没有创建来自 M4 的动态宣告通道的文件夹,因此 Python 无法创建 rpmsg 传输... 请检查你的 M4 内核打印输出。 此致, Marek Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Vadim, 正如你在其他评论中看到的,我一直努力尽快回复。但这周(可能还有下周)我比较忙。 不过,从你遇到的错误来看,你应该对比一下 transport.py 中 RpmsgTransport 类里的初始化函数, 以及erpc-imx-demos/sysfs.py at master · EmbeddedRPC/erpc-imx-demos · GitHub - class RpmsgEndpoint 请确保 GitHub - EmbeddedRPC/erpc-imx-demos: eRPC demos for i.MX devices 是最新版本,且子仓库已根据与 erpc-imx-demos 匹配的提交进行了检出 也许mareknovak能更准确地指出问题所在。 看起来 如果self.id == -1: raise Exception() 返回 -1 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
有人能帮我解决以下问题吗? 我正在 iMX6COM 开发板上使用 erpc-imx-demos 中的 eRPC 演示示例。 在M4侧启动演示应用程序: "硬件已初始化 eRPC已初始化 MatrixMultiply服务已添加" 在 Linux 中添加驱动: "root@imx6sxea-com:~# modprobe -v rpmsg_multiept insmod /lib/modules/4.1.15-2.0.3+geb0b90b/kernel/drivers/rpmsg/rpmsg_multiept.ko" (系统并未反馈关于rpmsg通道已创建的信息,并且sys/class/rpmsg目录下的rpmsg文件夹为空) 在 Linux 上启动 appl 演示: 回溯(最近一次调用在最后): 文件"example.py",第111行,在 transport = erpc.transport.RpmsgTransport() 文件"build/bdist.linux-armv7l/egg/erpc/transport.py",第 199 行,在 __init__ 文件 "build/bdist.linux-armv7l/egg/rpmsg/sysfs.py" 中,第 116 行,在__init__ 异常 异常类型错误:'需要整数' 在 <绑定方法 RpmsgEndpoint.__del__ of > 被忽略 附言: 我已构建M4 eRPC演示应用,所用平台为cmake和eclipse。 M4 rpmsg演示应用运行良好。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Vakul, 抱歉,我错过了您的评论。目前我们不支持任何加密传输。但由于eRPC是模块化的,我认为您可以轻松地将此功能添加到您的eRPC项目中。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi eRPC 通信能否通过某种加密传输方式(例如 TLS)来保障安全? 此致 Vakul Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
嗨,Evgeny,目前我们对此还没有预估。但我认为你可以通过编写自己的 erpc_malloc/erpc_free 函数实现来编写/使用自己的分配器。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan, 是否计划在其他部分(例如erpcMatrixMultiply_shim 的生成等效实现)中增加更多静态内存分配?每个输入参数是否都需要动态分配内存(从编解码器填充数据后,在函数调用结束时释放)? 比如将预先分配的内存(由用户应用静态分配)传递给框架? 谢谢! Evgeny Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
嗨,Evgeny,这看起来像是 MCUExpresso 项目文件/ IDE 的问题。顶层文件夹名称应该是虚拟目录,未来这些目录将不会存在。你磁盘上的软件包中,eRPC 的目录结构应该与 GitHub 上的类似。GitHub 的目录结构更为推荐。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan, 我注意到ERPC在运行时使用了大量动态内存分配。是否有计划使其更适合嵌入式系统,并添加静态内存分配方案? 编辑: 很抱歉我刚才的问题,我确实在代码仓库中看到了 erpc_setup_mbf_static.cpp 文件。问题在于,我的代码是基于 MCUXpresso SDK 中提供的示例 ——frdmk66f_multiprocessor_examples_erpc_server_matrix_multiply_spi 和 frdmk66f_multiprocessor_examples_erpc_client_matrix_multiply_spi。这些示例的目录结构与代码仓库中的代码大不相同。 所以我的问题再问一次,应该使用 SDK 示例的目录结构还是代码仓库中的呢?它们为什么会有这么大的差异? 谢谢! Evgeny Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Evgeny, 首先:您是否正在使用 develop 分支中的 smac.erpc(并且应用程序是从该分支构建的)?对我来说,这个版本是可以正常工作的。 目前erpcgen应用版本和其余eRPC代码已连接。这意味着如需使用您从github构建的新版erpcgen应用,则必须将github上的github erpc_c/*文件复制至您的示例中。然后,您可以使用新版erpcgen应用重新生成代码,更新应用(erpc初始化 + 传输)功能,其他部分即可正常运行。否则,如果您不更新erpc_c文件,则必须使用提供的erpcgen应用。 查看这个页面的底部内容:入门指南・EmbeddedRPC/erpc Wiki・GitHub,对于较新的 erpcgen 版本来说,该内容应该是相当新的。 我不确定最新提交是否已修改spi,建议您暂时使用旧版实现。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hey Dusan, 当我使用自己编译的 erpcgen.exe 时,我在 smac.erpc 示例中遇到了相同的错误: error: file smac.erpc:135:5: syntax error, unexpected identifier, expecting '}' 我之前提到的目录结构是存储库中的erpc_c目录,并且: 来自SDK示例。哪个目录结构是“正确”的?结合使用我生成的文件与SDK示例代码是否安全? 谢谢! Evgeny Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hey dusancervenka-b51352, 感谢您的快速回复!我克隆了开发分支。我注意到erpc_c目录结构与Kinetis SDK提供的示例有很大不同。哪一个更合适? 谢谢! Evgeny Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi evgenyerlihman, 实际上,我们正在进行更频繁地更新。您需要切换到开发分支。GitHub - EmbeddedRPC/erpc at develop。最后一次代码更新是昨天。但您需要在该此构建erpcgen应用。有了smac IDL,就能正常运行。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi dusancervenka-b51352, 我正在考虑将 eRPC 框架用于我正在开发的一款新产品,该产品使用多个 NXP 的 Kinetis 器件。我注意到 eRPC 的 GitHub 仓库最后一次更新是在 6 个月前。我的问题是,这个框架目前还在维护、修复和开发吗?我尝试了 GitHub 上的示例: erpcgen.exe smac.erpc 并且它未能生成 cpp 源代码,出现了错误。 erpcgen可执行文件来自MCUXpresso SDK。 谢谢! Evgeny Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,Chandini, 没关系。我也刚休完长假,希望您度过了一段美好时光。 我已通过社区消息系统(私信)给你发了邮件。 我们可以通过邮件详细讨论。大致流程是,你需要在 GitHub 上创建分支,切换到开发分支,应用你的修改,创建提交记录,再发起拉取请求。我们会审核你的修改,提出修改建议,之后将其合并到开发分支。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan , 非常抱歉回复迟了,我刚结束长假回来。已与团队成员进行内部沟通,请提供您的电子邮箱地址以便我们转发资料。根据公司政策,我们无法直接将任何内容直接上传至您的github。 谢谢 Chandini Re: Introducing eRPC 嗨,杜桑 、
当然,我会与我的前辈讨论并创建拉取请求。目前我正在度假,抱歉迟复。
谢谢
Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
嗨,Chandini。很高兴你成功了。我有一个特别的提议,你能否在 eRPC 的 GitHub 开发分支上,就你新创建的传输层提交一个拉取请求(基于开发分支)?或许还需要做些工作才能让它与更新版本的 eRPC 兼容。但如果你不想更新的话,我可以来做:)通过在 GitHub 上提交拉取请求,你将成为有价值的贡献者,并且会永远出现在贡献者历史记录中。 希望 eRPC 能成为你的理想解决方案。我们会一直在这儿(或 GitHub 上)为你提供帮助:) Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi dusancervenka-b51352 , b50844 , novakma7 终于恢复正常运行,演示程序现可在Linux上配合我的c++代码运行。 非常感谢各位回答了我所有的问题。:) 特别感谢Dusan:smileyhappy 谢谢 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
HI Dusan , 由于我昨天忙于其他任务,所以未能进行任何尝试。今天我会进行尝试,并及时通知您。 我觉得我得稍微修改一下我的函数,再进行尝试。因为到目前为止,我在发送和接收函数中只传递了 char * 类型的数据。 很快会回来找您。 谢谢 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Chandini,您好!是的,没错。我当时不在公司,所以无法获知具体功能的名称。此功能是否能正常运行? Re: Introducing eRPC 你好,杜桑
感谢您的答复:
write(fd、 >getBuffer(), >getUsed()😞
我可以看到getused函数(位于erpc/message_buffer.h at 9e18d069aeae19a6e80a5e8783903bc63bd9b567 · EmbeddedRPC/erpc · GitHub中),但找不到getbuffer函数。
我想我必须用下面这个函数来获取我的缓冲区,对吗?
/*! * @brief This function returns pointer to buffer to read/write. * * @return Pointer to buffer to read/write. */ uint8_t *get() { return m_buf; }
因此函数为如下形式:
send :erpc_status_t send(MessageBuffer *message) { write(fd, message->get, message->getUsed())};
谢谢
chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,chanidi,您需要以不同的方式来做:您必须使用 transport.h。如果您不使用它,它将无法正常工作。 也许您可以使用我上面提到的 ioctl 命令: erpc_status_t receive(MessageBuffer *message) {int fd = open("/dev/rpmsg_ept1024.1", O_RDWR);} 发送:erpc_status_t send(MessageBuffer *message) { write(fd, message->getBuffer(), message->getUsed())}; 读取:erpc_status_t receive(MessageBuffer *message){size_t size = read(fd, message->getBuffer(), 500); message->setUsed(size)}; novakma7您能否确认操作步骤? Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Dusan , Marek 是的,我也参考了那些文件,但是 我正在使用trasport.h创建传输层。但面临参数不匹配的问题 transport.h中的发送和接收函数以消息缓冲区作为参数, virtual erpc_status_t receive(MessageBuffer *message) = 0; virtual erpc_status_t send(MessageBuffer *message) = 0; 根据 example.py 我已经创建了我的 RpmsgEndpoint 类,该类需要以下参数 RpmsgEndpoint::receive(int maxlen) RpmsgEndpoint::send(char *buffer,int dst) 根据我的理解,我们只需要从 Linux 中读取和写入 /dev/rpmsg_ept1024.1 设备即可。 所以我在想,与其使用 transport.h,或许我需要创建自己的 transport.h 版本? 感谢大家 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
不客气。您可以从/erpc-imx-demos/middleware/erpc/transport/文件夹汲取灵感。有多种传输方式。 Re: Introducing eRPC 非常感谢 Dusan 的快速回复 ,我将继续沿着这条路走下去,不久后再来找你。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,Chandini。您是对的。这些步骤是正确的。您需要创建继承自transport.h的类 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Marek 我还有一个问题。 目前我的工作状态: 我已在c++中实现RpmsgEndpoint类 我正在研究如何让我的客户端应用程序现在正常运行。 erpc-imx-demos/MPU/example_erpc at master · EmbeddedRPC/erpc-imx-demos · GitHub中的 Python example.py调用继承自Transport类的 RpmsgTransport。 我的问题是,我是否应该使用transport.h(位于/erpc-imx-demos/middleware/erpc/erpc_c/infra)来确保应用正常运行。 以便我创建RpmsgTransport类,并在客户端应用中调用它。 我这样想对吗? 先感谢您 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
是的,你说得对。 Python 所做的一切都只是对文件的 IO 操作(读/写)。这在任何语言中都可以实现,包括 C/C++。 选择 Python 来演示是因为它在 Linux 用户空间中很受欢迎,但你完全可以将其移植到 C 语言中。 我想我们现在的理解是一致的了。 祝您好运! 祝好, Marek Re: Introducing eRPC 你好,马雷克
感谢您的答复,它消除了我的一些疑惑。
我们不打算在两边都使用 FreeRTOS。
我们的计划是
M4 核 - 运行 FreeRTOS—— 这一点在你们的演示中已经实现了
A7 核 - 运行 Linux—— 你们的演示中有 Python 代码,用于利用内核的 RPMSG 实现
我们只需要用C或C++来代替Python。
我认为我们可以轻松地将 Python 代码移植到 C 或 C++,对吗?
谢谢
Chandini
Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,Chandini Indavara Basavaraju, RPMSg-Lite是RPMsg协议的实现,仅适用于运行 FreeRTOS或裸机的M4端。 在Linux/A7端,您可以放心使用内核中的RPMsg实现。(例如:GitHub - EmbeddedRPC/erpc-imx-demos:i.MX设备的eRPC演示) 或者你是打算在 M4 和 A7 两个内核上都运行 FreeRTOS?这种情况下它是可以工作的,但这并非标准用例。这需要你为 A 内核创建一个移植层,并让 FreeRTOS 在那里运行。 希望这能给你一些方向, Marek Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Marek 不知怎的,我漏掉了你的消息,对此我很抱歉 非常感谢 。我会尽快尝试您的最新版本。 您能否回答我关于RPMSG传输层的最后一个问题? 谢谢 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,我理解您。 您需要新建一个(此外还可根据需求,通过github上的拉取请求将其添加到我们的存储库)。 在 Linux 端,您可以使用 /dev/ttyRPMSG(如果系统中存在)。 例如,在此处创建新的传输erpc_c/transports with: 初始化可以像这样: int fd = open("/dev/ttyRPMSG", O_RDWR); 发送:write(fd, buffer, buffer_size); read:size_t size = read(fd, buffer, expected size); 如果没有这样命名的设备,你可以从 Python 代码中获取灵感。RPMSG 不是我的专长。我不知道在 Linux 上应该如何使用它。我会把你的问题转发给 Marek。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan , Marek 我计划的是: 在 M4(freertos)和 A7(Linux)上使用rpmsg-lite 我需要: RPMSG C 包装器(在 erpc_c/setup 下),可在 M4 和 A7 侧使用 RPMSG 传输层(在 erpc_c/transports 下),可在 M4 和 A7 侧使用 我有以下问题: 请问,您是否有适用于该场景的传输层? 或 我们是否需要参考 rpmsg-python 并写出类似的内容? 任何建议都会非常有帮助 感谢大家 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,我不确定是否有您需要的信息(Linux端的c传输)。但新建一个也很简单。您可以从/dev/ttyRPMSG(如果系统中存在)读取和写入。 例如: 初始化操作如下: int fd = open("/dev/ttyRPMSG", O_RDWR); 发送:write(fd, buffer, buffer_size); 读取:size_t size = read(fd, buffer, expected size); mareknovak或许能就该问题分享更多专业见解。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan , 感谢您告知我此次更新。 我想现在我对ERPC有了初步的了解。一旦我让RPMSG客户端应用程序正常运行,我就可以更新ERPC版本。 我开始研究rpmsg-lite,其中包含M4平台文件。 我想知道是否有适用于A7平台的方案?任何相关信息都将大有帮助。我的主要目标是使用C语言获取客户端应用,并使用RPMSg作为传输层 谢谢 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
我很高兴您能够独立解决问题(对我们而言,这意味着该问题对开发人员来说并不复杂)。此外,正如mareknovak在上述评论中提到的那样, 他已经在存储库中更新其imx演示应用。您在进行下一步操作可以使用该版本,因其已采用新的rpc功能 Re: Introducing eRPC 感谢您的回复
这正是我想要的信息,我已经为 TCP 创建了 C 语言包装器,在对 eRPC 做了几处修复后,它运行得很顺利。
我的下一步是将TCP层替换为rpmsg。
再次感谢
Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,Chandini Indavara Basavaraju, 我刚刚更新了 GitHub 上的 erpc-imx-demos 仓库(链接:GitHub - EmbeddedRPC/erpc-imx-demos: eRPC demos for i.MX devices),使其适配 eRPC 1.4.0 和 RPMSg-Lite 1.1.0。 你可以下载预编译的 erpcgen 应用程序,它用于代码生成,下载地址是:Release v1.4・EmbeddedRPC/erpc・GitHub,在下载部分选择适合你的架构即可。 然后你可以这样调用它:./erpcgen -gpy 接口定义语言文件名.erpc,这会为你生成 Python 的序列化和反序列化垫片代码。如果你省略 - gpy 参数或指定 - gc,将会得到 C 语言的垫片代码。 erpc-imx-demos 仓库的最新提交中也更新了序列化 / 反序列化垫片代码,你可以放心使用。 欢迎以拉取请求的形式提交你的修改, 感谢你使用 eRPC 和 RPMsg-Lite! Marek Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,目前我们在 GitHub 仓库中没有示例。但是我们在那里有 C(c++) 测试。如果您熟悉 Linux 或 Mac,您可以以此为例。其他选项如上所述: 1. 下载支持的开发板的 SDK -> 多核/多处理器 C/Python 示例。 2. 阅读这篇文章:入门指南・EmbeddedRPC/erpc Wiki・GitHub Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan 请问你们有 C 语言的客户端应用示例吗?不是 Python 的那种。或者你们有计划编写一个吗?如果已经有的话,那会非常有用,能帮上大忙。 先感谢您 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
终于成功了,非常感谢你的帮助:)Dusan 抱歉未找到附件选项以上传补丁,故将内容粘贴如下: 来自 7a5b152524a3c82b5bced4a72ed396f21860b666 2001年9月17日星期一00:00:00 日期:2017年5月8日星期一11:33:05 +0100 主题:[补丁]修复问题以运行eRPC_demo演示 --- erpc_c/infra/transport.h | 4 +- erpc_c/setup/erpc_server_setup.cpp | 36 ++++- erpc_c/setup/erpc_server_setup.h | 2 +- erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp | 54 +++++++ erpc_c/setup/erpc_transport_setup.h | 18 ++- erpc_c/transports/rpmsg_lite_rtos_transport.cpp | 158 ++++++++++++++++++ erpc_c/transports/rpmsg_lite_rtos_transport.h | 177 +++++++++++++++++++++ erpc_c/transports/rpmsg_rtos_transport.h | 147 +++++++++++++++++ erpc_python/erpc/transport.py | 21 +++ 9 files changed, 602 insertions(+), 15 deletions(-) create mode 100644 erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp create mode 100644 erpc_c/transports/rpmsg_lite_rtos_transport.cpp create mode 100644 erpc_c/transports/rpmsg_lite_rtos_transport.h create mode 100644 erpc_c/transports/rpmsg_rtos_transport.h diff --git a/erpc_c/infra/transport.h b/erpc_c/infra/transport.h index eb7ec71..fd4862a 100644 --- a/erpc_c/infra/transport.h +++ b/erpc_c/infra/transport.h @@ -48,7 +48,7 @@ //////////////////////////////////////////////////////////////////////////////// namespace erpc { - +class MessageBuffer; /*! * @brief 传输层的抽象接口。 * @@ -89,7 +89,7 @@ public: * * @return基于发送实现。 */ - virtual erpc_status_t send(MessageBuffer *message) = 0; + virtual erpc_status_t send(const MessageBuffer *message) = 0; /*! * @brief 轮询传入消息。 diff --git a/erpc_c/setup/erpc_server_setup.cpp b/erpc_c/setup/erpc_server_setup.cpp index 51fa799..5cd4346 100644 --- a/erpc_c/setup/erpc_server_setup.cpp +++ b/erpc_c/setup/erpc_server_setup.cpp @@ -33,8 +33,10 @@ #include "basic_codec.h" #include "manually_constructed.h" #include "simple_server.h" -#include +#include "message_buffer.h" +#include "erpc_config_internal.h" #include +#include #if !(__embedded_cplusplus) using namespace std; @@ -43,6 +45,29 @@ using namespace std; using namespace erpc; //////////////////////////////////////////////////////////////////////////////// +// 类 +//////////////////////////////////////////////////////////////////////////////// + +class BasicMessageBufferFactory : public MessageBufferFactory +{ +public: + virtual MessageBuffer create() + { + uint8_t *buf = new (nothrow) uint8_t[ERPC_DEFAULT_BUFFER_SIZE]; + return MessageBuffer(buf, ERPC_DEFAULT_BUFFER_SIZE); + } + + virtual void dispose(MessageBuffer *buf) + { + assert(buf); + if (*buf) + { + delete[] buf->get(); + } + } +}; + +//////////////////////////////////////////////////////////////////////////////// // 变量 //////////////////////////////////////////////////////////////////////////////// @@ -50,29 +75,32 @@ using namespace erpc; static ManuallyConstructed s_server; SimpleServer *g_server; +static ManuallyConstructed s_msgFactory; static ManuallyConstructed s_codecFactory; //////////////////////////////////////////////////////////////////////////////// // 代码 //////////////////////////////////////////////////////////////////////////////// -void erpc_server_init(erpc_transport_t transport, erpc_mbf_t message_buffer_factory) +void erpc_server_init(erpc_transport_t transport) { // 初始化工厂。 + s_msgFactory.construct(); s_codecFactory.construct(); // 使用提供的传输初始化服务器。 s_server.construct();s_server->setTransport(reinterpret_cast (transport)); + s_server->setMessageBufferFactory(s_msgFactory); s_server->setCodecFactory(s_codecFactory); - s_server->setMessageBufferFactory(reinterpret_cast (message_buffer_factory)); g_server = s_server; } - void erpc_server_deinit() { + s_msgFactory.destroy(); s_codecFactory.destroy(); s_server.destroy(); + } void erpc_add_service_to_server(void *service) diff --git a/erpc_c/setup/erpc_server_setup.h b/erpc_c/setup/erpc_server_setup.h index 8e6a6ef..e4e9eaa 100644 --- a/erpc_c/setup/erpc_server_setup.h +++ b/erpc_c/setup/erpc_server_setup.h @@ -60,7 +60,7 @@ extern "C" { * * 此函数用于初始化服务器,且包含运行服务器所需的所有组件。 */ -void erpc_server_init(erpc_transport_t transport, erpc_mbf_t message_buffer_factory); +void erpc_server_init(erpc_transport_t transport); /*! * @brief 此函数用于取消初始化服务器。 diff --git a/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp b/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp new file mode 100644 index 0000000..b480d42 --- /dev/null +++ b/erpc_c/setup/erpc_setup_rpmsg_lite_rtos_remote.cpp @@ -0,0 +1,54 @@ + /* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * + * 允许以源代码或二进制形式重新分发和使用,无论是否修改, + * 只要满足以下条件: + * + * o 重新分发的源代码必须保留上述版权声明、本 + * of 条件列表以及以下免责声明。 + * + * o 以二进制形式重新分发时,必须在随分发提供的 + * 提供的文档和/或 + * 其他材料中复制上述版权声明、此条件列表和以下免责声明。 + * + * o 未经事先书面许可,不得使用Freescale Semiconductor, Inc.的名称或其 + * 贡献者的姓名来认可或推广由此 + * 软件衍生的产品。 + * + * 本软件由版权所有者和贡献者“按原样”提供,并且 + * 不提供任何明示或暗示的担保,包括但不限于 + * 对适销性和针对特定用途的适用性的暗示担保 + * 免责声明。在任何情况下,版权所有者或贡献者均不对 + * 任何直接、间接、偶然、特殊、惩戒性或后果性的损害 + *(包括但不限于采购替代商品或服务; + * 使用、数据或利润损失;或业务中断)负责,无论其由 + * 何种原因引起,也无论其基于何种责任理论,无论是在合同、严格责任还是侵权行为 + *(包括疏忽或其他行为)中,以任何方式因使用本 + *软件而引起,即使已被告知可能发生此类损害。 + */ + +#include "manually_constructed.h" +#include "rpmsg_lite_rtos_transport.h" +#include "erpc_transport_setup.h" + +using namespace erpc; + +//////////////////////////////////////////////////////////////////////////////// +// 变量 +//////////////////////////////////////////////////////////////////////////////// + +static ManuallyConstructed s_transport; + +//////////////////////////////////////////////////////////////////////////////// +// 代码 +//////////////////////////////////////////////////////////////////////////////// + +erpc_transport_t erpc_transport_rpmsg_lite_rtos_remote_init( + unsigned long src_addr, unsigned long dst_addr, void *start_address, int rpmsg_link_id, void (*ready_cb)(void), bool send_nameservice) +{ + s_transport.construct(); + s_transport->init(src_addr, dst_addr, start_address, rpmsg_link_id, ready_cb, send_nameservice); + return reinterpret_cast (s_transport.get()); +} + + diff --git a/erpc_c/setup/erpc_transport_setup.h b/erpc_c/setup/erpc_transport_setup.h index 798d92f..6c3959e 100644 --- a/erpc_c/setup/erpc_transport_setup.h +++ b/erpc_c/setup/erpc_transport_setup.h @@ -34,6 +34,7 @@ #include "erpc_version.h" #include +#include /*! * @addtogroup transport_setup @@ -48,7 +49,7 @@ //! @brief 不透明传输对象类型。 typedef struct ErpcTransport *erpc_transport_t; //! @brief RPMsg-Lite传输就绪回调对象类型。-typedef void (*rpmsg_ready_cb)(void); +//typedef void (*rpmsg_ready_cb)(void); //////////////////////////////////////////////////////////////////////////////// // API @@ -106,21 +107,21 @@ erpc_transport_t erpc_transport_rpmsg_lite_master_init(unsigned long src_addr, /*! * @brief 创建RPMsg-Lite零拷贝传输。 */ -erpc_transport_t erpc_transport_rpmsg_lite_zc_master_init(unsigned long src_addr, - unsigned long dst_addr, - int rpmsg_link_id); +//erpc_transport_t erpc_transport_rpmsg_lite_zc_master_init(unsigned long src_addr, +// unsigned long dst_addr, +// int rpmsg_link_id); /*! * @brief 创建RPMsg-Lite传输。 */ erpc_transport_t erpc_transport_rpmsg_lite_remote_init( - unsigned long src_addr, unsigned long dst_addr, void *start_address, int rpmsg_link_id, rpmsg_ready_cb ready); + unsigned long src_addr, unsigned long dst_addr, void *start_address, int rpmsg_link_id, void (*ready_cb)(void), bool send_nameservice); /*! * @brief 创建RPMsg-Lite零拷贝传输。 */ -erpc_transport_t erpc_transport_rpmsg_lite_zc_remote_init( - unsigned long src_addr, unsigned long dst_addr, void *start_address, int rpmsg_link_id, rpmsg_ready_cb ready); +//erpc_transport_t erpc_transport_rpmsg_lite_zc_remote_init( +// unsigned long src_addr, unsigned long dst_addr, void *start_address, int rpmsg_link_id, rpmsg_ready_cb ready); /*! * @brief 创建RPMsg-Lite RTOS传输。 @@ -133,7 +134,8 @@ erpc_transport_t erpc_transport_rpmsg_lite_rtos_master_init(unsigned long src_ad * @brief 创建RPMsg-Lite RTOS传输。 */ erpc_transport_t erpc_transport_rpmsg_lite_rtos_remote_init( - unsigned long src_addr, unsigned long dst_addr, void *start_address, int rpmsg_link_id, rpmsg_ready_cb ready); + unsigned long src_addr, unsigned long dst_addr, void *start_address, int rpmsg_link_id, void (*ready_cb)(void), bool send_nameservice); + //@} diff --git a/erpc_c/transports/rpmsg_lite_rtos_transport.cpp b/erpc_c/transports/rpmsg_lite_rtos_transport.cpp new file mode 100644 index 0000000..e04ae91 --- /dev/null +++ b/erpc_c/transports/rpmsg_lite_rtos_transport.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * + * 允许以源代码或二进制形式重新分发和使用,无论是否修改, + * 只要满足以下条件: + * + * o 重新分发的源代码必须保留上述版权声明、本 + *条件列表以及以下免责声明。 + * + * o 以二进制形式重新分发时,必须在随分发提供的 + * 提供的文档和/或 + * 其他材料中复制上述版权声明、此条件列表和以下免责声明。 + * + * o 未经事先书面许可,不得使用 + * Freescale Semiconductor, Inc.的名称或其贡献者的姓名来认可或推广由此 + * 软件衍生的产品。 + * + * 本软件由版权所有者和贡献者“按原样”提供,并且 + * 不提供任何明示或暗示的担保,包括但不限于 + * 对适销性和针对特定用途的适用性的暗示担保 + * 免责声明。在任何情况下,版权所有者或贡献者均不对 + * 任何直接、间接、偶然、特殊、惩戒性或后果性的损害 + *(包括但不限于采购替代商品或服务; + * 使用、数据或利润损失;或业务中断)负责,无论其由 + * 何种原因引起,也无论其基于何种责任理论,无论是在合同、严格责任还是侵权行为 + *(包括疏忽或其他行为)中,以任何方式因使用本 + *软件而引起,即使已被告知可能发生此类损害。 + */ + +#include "rpmsg_lite_rtos_transport.h" +#include + +#if !(__embedded_cplusplus) +using namespace std; +#endif + +using namespace erpc; + +//////////////////////////////////////////////////////////////////////////////// +// 变量 +//////////////////////////////////////////////////////////////////////////////// +uint8_t RPMsgRTOSTransport::s_initialized = 0; +struct rpmsg_lite_instance *RPMsgRTOSTransport::s_rpmsg; + +//////////////////////////////////////////////////////////////////////////////// +// 代码 +//////////////////////////////////////////////////////////////////////////////// + +RPMsgRTOSTransport::RPMsgRTOSTransport() +: Transport() +, m_dst_addr(0) +{ +} + +RPMsgRTOSTransport::~RPMsgRTOSTransport() +{ + rpmsg_lite_deinit(s_rpmsg); + s_initialized = 0; +} + +erpc_status_t RPMsgRTOSTransport::init( + unsigned long src_addr, unsigned long dst_addr, void *base_address, unsigned long length, int rpmsg_link_id) +{ + if (!s_initialized) + { + s_rpmsg = rpmsg_lite_master_init(base_address, length, rpmsg_link_id, RL_NO_FLAGS); + s_initialized = 1; + } + + m_rpmsg_queue = rpmsg_queue_create(s_rpmsg); + m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue); + + m_dst_addr = dst_addr; + return m_rpmsg_ept == RL_NULL ? kErpcStatus_InitFailed : kErpcStatus_Success; +} + +erpc_status_t RPMsgRTOSTransport::init( + unsigned long src_addr, unsigned long dst_addr, void *base_address, int rpmsg_link_id, void (*ready_cb)(void), bool send_nameservice) +{ + if (!s_initialized) + { + s_rpmsg = rpmsg_lite_remote_init(base_address, rpmsg_link_id, RL_NO_FLAGS); + + /* Signal the other core we are ready */ + if (ready_cb != NULL) + { + ready_cb(); + } + + while (!rpmsg_lite_is_link_up(s_rpmsg)) + { + } + + s_initialized = 1; + } + + m_rpmsg_queue = rpmsg_queue_create(s_rpmsg); + m_rpmsg_ept = rpmsg_lite_create_ept(s_rpmsg, src_addr, rpmsg_queue_rx_cb, m_rpmsg_queue); + + if(send_nameservice) + { + rpmsg_ns_announce(s_rpmsg, m_rpmsg_ept, + "rpmsg-openamp-demo-channel", + 0); + } + + m_dst_addr = dst_addr; + return m_rpmsg_ept == RL_NULL ? kErpcStatus_InitFailed : kErpcStatus_Success; +} + +erpc_status_t RPMsgRTOSTransport::receive(MessageBuffer *message) +{ + int ret_val = rpmsg_queue_recv(s_rpmsg, m_rpmsg_queue, &m_dst_addr, (char *)message->get(), kRpmsgMessageBufferSize, + NULL, RL_BLOCK); + return ret_val != RL_SUCCESS ? kErpcStatus_ReceiveFailed : kErpcStatus_Success; +} + +erpc_status_t RPMsgRTOSTransport::send(const MessageBuffer *message) +{ + int ret_val = + rpmsg_lite_send(s_rpmsg, m_rpmsg_ept, m_dst_addr, (char *)message->get(), message->getUsed(), RL_BLOCK); + return ret_val != RL_SUCCESS ? kErpcStatus_SendFailed : kErpcStatus_Success; +} + +MessageBuffer RPMsgMessageBufferFactory::create() +{ + uint8_t idx = 0; + while (((m_freeBufferBitmap & idx) == 0) && (idx < kInitCountMessageBuffers)) + { + idx++; + } + + assert(idx < kInitCountMessageBuffers); + + m_freeBufferBitmap &= ~(1 << idx); + + uint8_t *buf; + buf = m_buffers[idx]; + + assert(NULL != buf); + return MessageBuffer(buf, kRpmsgMessageBufferSize); +} + +void RPMsgMessageBufferFactory::dispose(MessageBuffer *buf) +{ + assert(buf); + uint8_t *tmp = buf->get(); + + if (tmp) + { + uint8_t idx = 0; + while ((tmp != m_buffers[idx]) && (idx < kInitCountMessageBuffers)) + { + ++idx; + } + m_freeBufferBitmap |= 1 << idx; + } +} diff --git a/erpc_c/transports/rpmsg_lite_rtos_transport.h b/erpc_c/transports/rpmsg_lite_rtos_transport.h new file mode 100644 index 0000000..f1aec8a --- /dev/null +++ b/erpc_c/transports/rpmsg_lite_rtos_transport.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015-2016, Freescale Semiconductor, Inc. + * + * 允许以源代码或二进制形式重新分发和使用,无论是否修改, + * 只要满足以下条件: + * + * o 重新分发的源代码必须保留上述版权声明、本 + *条件列表以及以下免责声明。 + * + * o 以二进制形式重新分发时,必须在随分发提供的 + * 提供的文档和/或 + * 其他材料中复制上述版权声明、此条件列表和以下免责声明。 + * + * o 未经事先书面许可,不得使用 + * Freescale Semiconductor, Inc.的名称或其贡献者的姓名来认可或推广由此 + * 软件衍生的产品。 + * + * 本软件由版权所有者和贡献者“按原样”提供,并且 + * 不提供任何明示或暗示的担保,包括但不限于 + * 对适销性和针对特定用途的适用性的暗示担保 + * 免责声明。在任何情况下,版权所有者或贡献者均不对 + * 任何直接、间接、偶然、特殊、惩戒性或后果性的损害 + *(包括但不限于采购替代商品或服务; + * 使用、数据或利润损失;或业务中断)负责,无论其由 + * 何种原因引起,也无论其基于何种责任理论,无论是在合同、严格责任还是侵权行为 + *(包括疏忽或其他行为)中,以任何方式因使用本 + *软件而引起,即使已被告知可能发生此类损害。 + */ + +#ifndef _EMBEDDED_RPC__RPMSG_LITE_RTOS_TRANSPORT_H_ +#define _EMBEDDED_RPC__RPMSG_LITE_RTOS_TRANSPORT_H_ + +#include "transport.h" +#include "message_buffer.h" +#include "rpmsg_lite.h" +#include "rpmsg_queue.h" +#include "rpmsg_ns.h" + +/*! + * @addtogroup rpmsg_lite_rtos_transport + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// 定义 +//////////////////////////////////////////////////////////////////////////////// + +enum +{ + kRpmsgMessageBufferSize = RPMSG_BUFFER_SIZE, + kInitCountMessageBuffers = 2, +}; + +//////////////////////////////////////////////////////////////////////////////// +// 类 +//////////////////////////////////////////////////////////////////////////////// + +namespace erpc +{ +/*! + * @brief 使用RPMsg RTOS API进行进程间消息传递的传输。 + * + * @ingroup rpmsg_lite_rtos_transport + */ +class RPMsgRTOSTransport : public Transport +{ +public: + /*! + * @brief 构造函数。 + * + * 此函数用于初始化对象属性。 + */ + RPMsgRTOSTransport(); + + /*! + * @brief RPMsgRTOSTransport析构函数 + */ + virtual ~RPMsgRTOSTransport(); + + /*! + * @brief 此函数调用RPMsg rtos初始化函数 - 作为RPMsg主服务器 + * + * @Param[in] src_addr 源地址。 + * @Param[in] dst_addr 目标地址。 + * @Param[in] base_address 共享内存中的RPMsg基地址。 + * @Param[in] length RPMsg共享内存区域长度。 + * @Param[in] rpmsg_link_id 选择通信将在哪些内核之间进行。 + * + * @retval kErpcStatus_Success 当rpmsg初始化函数成功执行时。 + * @retval kErpcStatus_InitFailed 当rpmsg初始化函数未成功执行时。 + */ + virtual erpc_status_t init( + unsigned long src_addr, unsigned long dst_addr, void *base_address, unsigned long length, int rpmsg_link_id); + + /*! + * @brief 此函数调用RPMsg rtos初始化函数 - 作为RPMsg远程 + * + * @Param[in] src_addr 源地址。 + * @Param[in] dst_addr 目标地址。 + * @Param[in] base_address 共享内存中的RPMsg基地址。 + * @Param[in] rpmsg_link_id 选择通信将在哪些内核之间进行。 + * @Param[in] ready_cb 在RPMsg初始化完成且内核就绪后调用的回调函数。 + * @Param [in] send_nameservice 如果为true,RPMsg主服务器会收到域名服务通知。 + * + * @retval kErpcStatus_Success 当rpmsg初始化函数成功执行时。 + * @retval kErpcStatus_InitFailed 当rpmsg初始化函数未成功执行时。 + */ + virtual erpc_status_t init( + unsigned long src_addr, unsigned long dst_addr, void *base_address, int rpmsg_link_id, void (*ready_cb)(void), bool send_nameservice); + + /*! + * @brief 将传入消息存储于消息缓冲区。 + * + * 在无消息传入时进行循环。 + * + * @Param[in] message 消息缓冲区,用于存储传入的消息。 + * + * @retval kErpcStatus_ReceiveFailed 无法接收消息缓冲区。 + * @retval kErpcStatus_Success 成功接收所有数据。 + */ + virtual erpc_status_t receive(MessageBuffer *message); + + /*! + * @brief 函数用于发送就绪消息。 + * + * @Param[in] message 传递要发送的消息缓冲区。 + * + * @retval kErpcStatus_SendFailed 无法发送消息缓冲区。 + * @retval kErpcStatus_Success 成功发送所有数据。 + */ + virtual erpc_status_t send(const MessageBuffer *message); + +protected: + /* 远程设备 */ + struct remote_device *m_rdev; /*!< 代表第二个内核的设备。*/ + struct rpmsg_channel *m_app_rp_chnl; /*!< 代表两台设备(两个内核)间的连接。*/ + unsigned long m_dst_addr; /*!< rpmsg使用的目标地址。*/ + rpmsg_queue_handle m_rpmsg_queue; /*!< 处理RPMsg队列。*/ + struct rpmsg_lite_endpoint *m_rpmsg_ept; /*!< 指向RPMsg Lite端点结构的指针。*/ + + static struct rpmsg_lite_instance *s_rpmsg; /*!< 指向RPMSG lite实例的指针。*/ + static uint8_t s_initialized; /*!< 表示rpmsg-lite是否已初始化的信息。*/ +}; + +class RPMsgMessageBufferFactory : public MessageBufferFactory +{ + uint8_t m_freeBufferBitmap; + uint8_t m_buffers[kInitCountMessageBuffers][kRpmsgMessageBufferSize]; + +public: + /*! + * @brief 构造函数。 + */ + RPMsgMessageBufferFactory() + : m_freeBufferBitmap(0xFF) + { + } + /*! + * @brief RPMsgMessageBufferFactory destructor + */ + virtual ~RPMsgMessageBufferFactory() {} + /*! + * @brief 此函数可创建用于设备间通信的消息缓冲区。 + */ + virtual MessageBuffer create(); + /*! + * @brief 此函数可处理用于设备间通信的消息缓冲区。 + */ + virtual void dispose(MessageBuffer *buf); +}; + +} // 命名空间erpc + +/*! @} */ + +#endif // _EMBEDDED_RPC__RPMSG_LITE_RTOS_TRANSPORT_H_ diff --git a/erpc_c/transports/rpmsg_rtos_transport.h b/erpc_c/transports/rpmsg_rtos_transport.h new file mode 100644 index 0000000..ad1d229 --- /dev/null +++ b/erpc_c/transports/rpmsg_rtos_transport.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * + * 允许以源代码或二进制形式重新分发和使用,无论是否修改, + * 只要满足以下条件: + * + * o 重新分发的源代码必须保留上述版权声明、本 + *条件列表以及以下免责声明。 + * + * o 以二进制形式重新分发时,必须在随分发提供的 + * 提供的文档和/或 + * 其他材料中复制上述版权声明、此条件列表和以下免责声明。 + * + * o 未经事先书面许可,不得使用Freescale Semiconductor, Inc.的名称或其 + * 贡献者的姓名来认可或推广由此 + * 软件衍生的产品。 + * + * 本软件由版权所有者和贡献者“按原样”提供,并且 + * 不提供任何明示或暗示的担保,包括但不限于 + * 对适销性和针对特定用途的适用性的暗示担保 + * 免责声明。在任何情况下,版权所有者或贡献者均不对 + * 任何直接、间接、偶然、特殊、惩戒性或后果性的损害 + *(包括但不限于采购替代商品或服务; + * 使用、数据或利润损失;或业务中断)负责,无论其由 + * 何种原因引起,也无论其基于何种责任理论,无论是在合同、严格责任还是侵权行为 + *(包括疏忽或其他行为)中,以任何方式因使用本 + *软件而引起,即使已被告知可能发生此类损害。 + */ + +#ifndef _EMBEDDED_RPC__RPMSG_RTOS_TRANSPORT_H_ +#define _EMBEDDED_RPC__RPMSG_RTOS_TRANSPORT_H_ + +#include "transport.h" +#include "message_buffer.h" + +extern "C" { +#include "rpmsg.h" +#include "rpmsg_rtos.h" +#include "rpmsg.h" +} + +/*! + * @addtogroup rpmsg_rtos_transport + * @{ + * @file + */ + +//////////////////////////////////////////////////////////////////////////////// +// 定义 +//////////////////////////////////////////////////////////////////////////////// + +enum +{ + kRpmsgMessageBufferSize = RPMSG_BUFFER_SIZE, +}; + +//////////////////////////////////////////////////////////////////////////////// +// 类 +//////////////////////////////////////////////////////////////////////////////// + +namespace erpc +{ +/*! + * @brief 使用RPMsg RTOS API进行进程间消息传递的传输。 + * + * @ingroup rpmsg_rtos_transport + */ +class RPMsgRTOSTransport : public Transport +{ +public: + /*! + * @brief 构造函数。 + * + * 此函数用于初始化对象属性。 + */ + RPMsgRTOSTransport(); + + /*! + * @brief RPMsgRTOSTransport析构函数 + */ + virtual ~RPMsgRTOSTransport(); + + /*! + * @brief 此函数用于调用rpmsg rtos初始化函数。 + * + * @Param[in] dev_id 设备ID号。 + * @Param[in] role 设备角色编号。 + * + * @retval kErpcStatus_Success 当rpmsg初始化函数成功执行时。 + * @retval kErpcStatus_InitFailed 当rpmsg初始化函数未成功执行时。 + */ + virtual erpc_status_t init(int dev_id, int role); + + /*! + * @brief 将传入消息存储于消息缓冲区。 + * + * 在无消息传入时进行循环。 + * + * @Param[in] message 消息缓冲区,用于存储传入的消息。 + * + * @retval kErpcStatus_ReceiveFailed 无法接收消息缓冲区。 + * @retval kErpcStatus_Success 成功接收了所有数据。 + */ + virtual erpc_status_t receive(MessageBuffer *message); + + /*! + * @brief 用于发送就绪消息的函数。 + * + * @Param[in] message 传递要发送的消息缓冲区。 + * + * @retval kErpcStatus_SendFailed 无法发送消息缓冲区。 + * @retval kErpcStatus_Success 成功发送所有数据。 + */ + virtual erpc_status_t send(const MessageBuffer *message); + +protected: + /* 远程设备 */ + static struct remote_device *m_rdev; /*!< 代表第二个内核的设备。*/ + static struct rpmsg_channel *m_app_rp_chnl; /*!< 代表两台设备(两个内核)之间的连接。*/ +}; + +class RPMsgMessageBufferFactory : public MessageBufferFactory +{ +public: + /*! + * @brief 构造函数。 + */ + RPMsgMessageBufferFactory() {} + /*! + * @brief RPMsgMessageBufferFactory destructor + */ + virtual ~RPMsgMessageBufferFactory() {} + /*! + * @brief 此函数可创建用于设备间通信的消息缓冲区。 + */ + virtual MessageBuffer create(); + /*! + * @brief 此函数可处理用于设备间通信的消息缓冲区。 + */ + virtual void dispose(MessageBuffer *buf); +}; + +} // 命名空间erpc + +/*! @} */ + +#endif // _EMBEDDED_RPC__RPMSG_RTOS_TRANSPORT_H_ diff --git a/erpc_python/erpc/transport.py b/erpc_python/erpc/transport.py index 0765e9f..c335943 100644 --- a/erpc_python/erpc/transport.py +++ b/erpc_python/erpc/transport.py @@ -31,6 +31,8 @@ import struct import serial +from rpmsg.sysfs import RpmsgEndpoint +import time import socket import threading from .crc16 import crc16 @@ -107,6 +109,25 @@ class SerialTransport(FramedTransport): class ConnectionClosed(Exception): pass +class RpmsgTransport(Transport): + def __init__(self): + self.ept = RpmsgEndpoint( + RpmsgEndpoint.rpmsg_openamp_channel, + RpmsgEndpoint.LOCAL_DEFAULT_ADDRESS, + RpmsgEndpoint.Types.DATAGRAM) + + def send(self, message): + self.ept.send(message, RpmsgEndpoint.REMOTE_DEFAULT_ADDRESS) + + def receive(self): + while True: + ret = self.ept.recv(2048) + if len(ret[1]) != 0: + return ret[1] + else: + time.sleep(0.001) + return ret[1] + class TCPTransport(FramedTransport): def __init__(self, host, port, isServer): super(TCPTransport, self).__init__() -- 2.7.4 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Dusan,谢谢 。一旦演示程序正常运行,我将创建拉取请求。 再次感谢你的回复,我已经拿到了 Python 文件。我会运行演示,很快再跟你说。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
嗨,做得真棒:)如果你愿意的话,可以为 i.MX 演示代码库创建一个拉取请求来修复这个问题。mareknovak 可以审核并将其合并到代码库中。 要生成python代码:与其他应用一样,您可以在命令行中输入"erpcgen --help"(-h也应有效)。 python -gpy idl_file -> gpy 表示生成 python。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
太好了,在更新之前我可以继续使用这个稳定版本。 经过几次修复,我的 MCU 演示现在可以正常构建和运行。感谢您的信息。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan 我已修复此问题,现在MCU演示程序恢复正常运行......感谢您推荐的稳定版本...... 你能告诉我如何使用 erpcgen 工具生成 Python 代码吗? 谢谢 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
嗨,最早也要到明天。但我不能保证一定是明天。我的同事 mareknovak 今天没来上班。不过应该很快就会处理。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
请问您能告诉我,您什么时候会更新? Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,感谢您的关注。erpc似乎使用不同的erpcgen生成文件,且与Marek提交时的版本不一致(这是我们的失误)。最佳解决方案是将该演示程序更新为erpc和erpcgen的最新稳定版本。您可以从主分支GitHub - EmbeddedRPC/erpc: Embedded RPC(且已部署预构建erpcgen 1.4.0)尝试此操作。但我不知道您需要完成多少变更。或者您可以等待我们进行更新。 mareknovak Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi Dusan 我正在使用您推荐的同一个eRPC库 我遵循的步骤如下: 克隆 erpc-imx-demos(包含子模块,该子模块会克隆 eRPC 库,对应链接为 GitHub - MarekNovakNXP/erpc at 232afb209f0a0cfceb25a1be11879f7d1934e065) 1. git clone --recursive https://github.com/EmbeddedRPC/erpc-imx-demos.git 2. 进入 erpc-imx-demos/middleware/erpc 文件夹,然后像这样构建 erpcgen: 安装所需的 flex、bison 和 boost 包 make eprc 生成eprcgen sudo make install 成功获取 erpcgen 3. 尝试使用相同的 erpc_matrix_multiply.erpc 文件创建我自己的输出文件,命令如下: erpcgen -I erpc-imx-demos/MCU/example_erpc/service -o test/erpc-imx-demos/MCU/example_erpc/service erpc_matrix_multiply.erpc 成功获取以下文件: erpc_matrix_multiply.h erpc_matrix_multiply_server.cpp erpc_matrix_multiply_server.h erpc_matrix_multiply_client.cpp 4. 尝试构建 MCU/example_erpc/build/armgcc/imx7d_sdb_m4/build_all.sh。 失败并出现错误: /home/basavarajuc/test/erpc-imx-demos/MCU/example_erpc/service/erpc_matrix_multiply_server.cpp:在函数 'void* create_MatrixMultiplyService_service()' 中: /home/basavarajuc/test/erpc-imx-demos/MCU/example_erpc/service/erpc_matrix_multiply_server.cpp:168:56:错误:抽象类类型“MatrixMultiplyService_service”的 new-expression 无效 返回 new(nothrow) MatrixMultiplyService_service(); 很抱歉再次询问,只是为了澄清我的理解。 如果我使用的是 GitHub - MarekNovakNXP/erpc at 232afb209f0a0cfceb25a1be11879f7d1934e065 这个 eRPC 库,那我是否需要更新演示程序才能成功运行演示? 2. 您能否告知我erpc-imx-demos/MCU/example_erpc/service at master · EmbeddedRPC/erpc-imx-demos · GitHub中的输出文件是由哪个erpcgen版本生成的? 这样我就能暂时使用旧版本的 erpcgen 来创建我自己的文件了。 非常感谢。很抱歉打扰您 Chandini Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
您好,感谢您的评论。 您提到的示例版本早于当前erpcgen构建版本。mareknovak也因当时官方eRPC版本未包含某些细微改动,而创建了官方eRPC存储库的分支版本。如果您点击中间件文件夹下erpc-imx-demos存储库中的eRPC引用,将重定向到其eRPC存储库。您需要借助该版本构建erpcgen。我们计划在未来更新演示。 希望我的回答对你有帮助。如果你有任何疑问,欢迎随时向我们咨询。 Re: 介绍 eRPC <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
Hi 抱歉,如果我问的是基本问题。 我正在尝试理解如何使用恩智浦的erpcgen工具。 参考 https://github.com/EmbeddedRPC/erpc-imx-demos,我成功运行了示例演示。 我的下一步计划是构建 erpcgen,然后使用相同的 erpc_matrix_multiply.erpc 文件创建自己的输出文件,再次运行相同的演示,以便熟悉 erpcgen 工具的使用方法。 我得到了输出文件,但即使我使用了相同的erpc_matrix_multiply.erpc文件,我的文件与示例文件不同。 变更如下: 示例演示中的输出文件显示(erpc_matrix_multiply_server.h): erpc_status_t erpcMatrixMultiply_shim(erpc::Codec * in, erpc::Codec * out, uint32_t sequence); 我的文件 (erpc_matrix_multiply_server.h): erpc_status_t erpcMatrixMultiply_shim(erpc::Codec * codec, uint32_t sequence); 为什么文件会不同呢?我是不是漏掉了什么配置? 我是否需要手动编辑 erpc_matrix_multiply_server.h 和 erpc_matrix_multiply_server.cpp 文件? 先感谢您 Chandini