Introducing eRPC This tutorial is introducing the eRPC (embedded remote procedure call) open-source project.
The eRPC (Embedded Remote Procedure Call) is a Remote Procedure Call (RPC) system created by NXP. An RPC is a mechanism used to invoke a software routine on a remote system using a simple local function call. The remote system may be any CPU connected by an arbitrary communications channel: a server across a network, another CPU core in a multicore system, and so on. To the client, it is just like calling a function in a library built into the application. The only difference is any latency or unreliability introduced by the communications channel.
Important links:
Everything related to the eRPC development is placed GitHub - eRPC base.
The eRPC development is placed GitHub - eRPC development.
The eRPC releases are placed GitHub - eRPC Releases.
The eRPC documentation is placed Github - eRPC wiki
The eRPC as Python Package on pypi
The eRPC is supporting multicore and multiprocessor types of applications.
Where to find eRPC examples
Plenty of eRPC multicore and multiprocessor examples can be found in NXP MCUXpressoSDK packages. Visit https://mcuxpresso.nxp.com to configure, build and download these packages. To get the board list with multicore support (eRPC included) use filtering based on Middleware and search for 'multicore' string. Once the selected package with the multicore middleware is downloaded, see /boards/ /multicore_examples for eRPC multicore examples (RPMsg_Lite or Messaging Unit transports used) or /boards/ /multiprocessor_examples for eRPC multiprocessor examples (UART or SPI transports used). eRPC examples use the 'erpc_' name prefix.
Another way of getting NXP MCUXpressoSDK eRPC multicore and multiprocessor examples is using the mcux-sdk Github repo. Follow the description how to use the West tool to clone and update the mcuxsdk repo in readme Overview section. Once done the armgcc eRPC examples can be found in mcuxsdk/examples/ /multicore_examples or in mcuxsdk/examples/ /multiprocessor_examples folders. You can use the evkmimxrt1170 as the board_name for instance. Similar to MCUXpressoSDK packages the eRPC examples use the 'erpc_' name prefix.
Re: Introducing eRPC Hello Kunal, it seems your question is addressed here: Need Help-Step by Step procedure to implement eRPC in iMx6sx ? · Issue #5 · EmbeddedRPC/erpc-imx-demos · GitHub Re: Introducing eRPC HI
[email protected], I don't know about official usage of eRPC on MPC5748G. Just the remind: eRPC depends on program language, OS, transport layer. There are not board specific files. So if there is used Freertos and C language you almost win, you need just port transport you want to use (if it is not already). Re: Introducing eRPC Hi Dusan, Has eRPC been ported to NXP MPC5748G ? Is there any example code I can reference? Best Regards, Alex Re: Introducing eRPC Hi
[email protected], i didn't have big experience in this area. Recently we had to add some mutexes when multiple erpc calls were called from multiple taks. But i like your idea. I quickly looked into source code. You need to specify your usecase. But i think it is imx Linux vs Mcore using RPSMG. In this case i think you can add mutexes as we did (which will serialize eRPC calls. you would need add them somewhere in performRequest function). The creating endpoints for each thread sounds good to me, but i see more issues which has to be solved. The smaller solution could looks like: transport init function will initialize more endpoints (based on number of tasks), eRPC rpmsg send/receive function on client side change to use unused undepoint to send and same endpoint for receive messages, eRPC rpmsg receive function on server need wait for message on all endpoints. I don't know if it is simple task or more complicated for you. But i am affraid that without modification to code you will be not able to have multithread calls. Re: Introducing eRPC Hi Dusan, I am working with Chandini here at Cubic. I just wanted to get extra info about eRPC when called from multiple threads. At the moment we are using a single end point and using this for one off calls that complete before making the next call. Now we'd potentially like to make multiple calls from multiple threads so we're wondering the best way to do this. In fact with my lack of knowledge here we've tried making other calls concurrently, well we didn't realise we were doing this until there was an issue. Now we see comms failure error codes coming back from the eRPC. Can a single end point be used for this i.e. should this be thread safe on the client side? If not should we use a separate end point for each thread, or should we be doing something else? Regards Lee Re: Introducing eRPC Hi
[email protected], Thank you to let us know. It is funny, i read about this today because of another project :smileygrin: Re: Introducing eRPC Hi Dusan, Thanks for the quick response. I could able to achieve better performance(response in microsec) in TCP by disabling the Nagel's algorithm using the below API call on both client and server socket connection. int result = setsockopt(sock, /* socket affected */ IPPROTO_TCP, /* set option at TCP level */ TCP_NODELAY, /* name of option */ (char *) &flag, /* the cast is historical cruft */ sizeof(int)); /* length of option value */ Reference : TCP_NODELAY: 2018 Best Practices for TCP Optimization | ExtraHop Thanks, Sasidharan. Re: Introducing eRPC Hi
[email protected], Maybe you can ask guys on github (in same topic, or create new one). There are at least two guys who where doing something with TCP: github: GitHub - EmbeddedRPC/erpc: Embedded RPC thread1:Server with TCP Transport handling multiple connections · Issue #32 · EmbeddedRPC/erpc · GitHub thread2:TCP Example client / server code · Issue #39 · EmbeddedRPC/erpc · GitHub Personaly i found this, but i don't know if this is your case and if it will help: linux - Low latency TCP settings on Ubuntu Re: Introducing eRPC Hi Dusan, I want to port eRPC over TCP socket. I ran your example test code(test_arrays) over virtual serial(inside linux) and the response time taken for serial is less than 1ms. When I ran the same example code over TCP, the response time is taken for TCP is around 90ms. Is there a way to reduce the latency and increase the performance over TCP as like as serial? Thanks, Sasidharan. Re: Introducing eRPC Hi, Dusan. It helped. By the way it was mentioned in example in header file. The function call from A9 works fine and M4 returns data. But now the issue is when M4 calls function. The error is appears in A9 "Waiting MU transmit buffer empty timeout! ugh, imx_mu_rpmsg_send() failed: -5". After this error data function call doesn't work in another side too: "rpmsg_multiept rpmsg0: virtqueue_add_outbuf failed: -5" What should I check? Thank you for your help. Re: Introducing eRPC Hi Vadim, Generally yes you need two tasks. One for client and one for server. Issue is also that output from erpc_arbitrated_client_init you have to put as a parameter to init server. Re: Introducing eRPC Hi Dusan, Marek, community. I've made several applications with eRPC, M4(client)-A9(server) or M4(server)-A9(client) works fine, but I want to use client/server appl on each side. But now it doesn't work or function from one side only executes 1 time and appl hangs. I want to check the general structure of the code. What I do wrong? Should I use 2 separate FreeRTOS tasks for client and server on M4? 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: Introducing eRPC Hi vadimfilippenko, if you are stilll interested in using python version you can look into this thread adding MPU patch to my kernel - I cannot see the new module · Issue #2 · EmbeddedRPC/erpc-imx-demos · GitHub . At least last two messages from mhanuel26 should be interesting for you because he was able to use python application. Re: Introducing eRPC Dusan, Marek, finally I successfully started modified eRPC example. But I use C on Linux side and erpc 1.5.0 with 6x parameters rpmsg init function in M4 (Dusan tips at github concerning 6th parameter). Thank you for help. Be ready for new questions) Re: Introducing eRPC You need to run M4 app befor the python app. Re: Introducing eRPC Hi Vadim, Please post here: ls /sys/class/rpmsg it looks like the nameservice was not sent from the M4 (is M4 running with the right firmware?). Because of this, a folder with dynamically announced channel from M4 was not created and therefore python cannot create rpmsg transport... Please check your M4 core print-outs. Regards, Marek Re: Introducing eRPC Hi Vadim, as you see in other comments, i am trying to answer as soon as possible. But this week (and maybe next) i am busy. But from what i see in error you should compare init function in transport.py - class RpmsgTransport And here erpc-imx-demos/sysfs.py at master · EmbeddedRPC/erpc-imx-demos · GitHub - class RpmsgEndpoint Be sure that GitHub - EmbeddedRPC/erpc-imx-demos: eRPC demos for i.MX devices is up to date and and subrepos are checkout on commits as they are aligned with erpc-imx-demos. Maybe mareknovak can help better here what is wrong. Looks like if self.id == -1: raise Exception() is returning -1 Re: Introducing eRPC Could anybody help me with follow ussue?: I'm using use eRPC demo example from erpc-imx-demos on iMX6COM board. Starting demo application on M4 side: "Hardware initialized eRPC intialized MatrixMultiply service added" adding driver in linux: "root@imx6sxea-com:~# modprobe -v rpmsg_multiept insmod /lib/modules/4.1.15-2.0.3+geb0b90b/kernel/drivers/rpmsg/rpmsg_multiept.ko" (Here are not any feedback from the system that rpmsg channel was created and rpmsg folder under sys/class/rpmsg is empty) Starting appl demo on linux: Traceback (most recent call last): File "example.py", line 111, in transport = erpc.transport.RpmsgTransport() File "build/bdist.linux-armv7l/egg/erpc/transport.py", line 199, in __init__ File "build/bdist.linux-armv7l/egg/rpmsg/sysfs.py", line 116, in __init__ Exception Exception TypeError: 'an integer is required' in > ignored P.S. I've built M4 eRPC demo appl. using cmake and also eclipse. M4 rpmsg demo appl works fine. Re: Introducing eRPC Hi Vakul, sorry i miss your comment. Currently we don't have any cryptographic transport supported. But because of eRPC is modular, i think you can easily add this feature to your eRPC project. Re: Introducing eRPC Hi Can eRPC communication be protected using some cryptographic transport (e.g. TLS)? Regards Vakul Re: Introducing eRPC Hi Evgeny, currently we have no estimation for that. But i think you can write/use your own allocator by writing your own implementation of erpc_malloc/erpc_free functions. Re: Introducing eRPC Hi Dusan, Are there plans to add more static memory allocation to additional parts, such as generated equivalents of erpcMatrixMultiply_shim? Where every input argument gets dynamically allocated before filling it up with data from the codec and then freed after the function invocation? Something like passing pre-allocated memory (statically by user app) to the framework? Thanks, Evgeny Re: Introducing eRPC Hi Evgeny, this looks like MCUExpresso project files/IDE issue. Top layer of folder names should be virtual directories, which will be not presented there in future. In your package on your disk should eRPC have similar directory structure as on github. Github directory structure is preferred. Re: Introducing eRPC Hi Dusan, I see that the erpc uses a lot of dynamic memory allocation at run-time. Is there a plan to make it more embedded friendly and add a static memory allocation scheme? EDIT: I am sorry for the first question, i do see the erpc_setup_mbf_static.cpp in the repository. The thing is that i am basing my code on the examples provided in the MCUXpresso SDK - frdmk66f_multiprocessor_examples_erpc_server_matrix_multiply_spi & frdmk66f_multiprocessor_examples_erpc_client_matrix_multiply_spi. Which have a very different directories structure from the code in the repository. So my question is, again, should the SDK examples directories structure should be used or the repositories? ANd why are they so different? Thanks, Evgeny Re: Introducing eRPC Hi Evgeny, first of all: Are you using smac.erpc from develop branch (and app built from that branch)? For me is this version working. Right now version of erpcgen app and rest of eRPC code is connected. That means if you want use newer erpcgen app you built from github, you should and have to copy github erpc_c/* files from github into your example. After than you can regenerate code with newer erpcgen app, update application (erpc init + transport) functions and everything else should work. Otherwise if you will not update erpc_c files you have to use provided erpcgen app. Look at the bottom of this page: Getting Started · EmbeddedRPC/erpc Wiki · GitHub Should be pretty up to date for newer erpcgen version. I am not sure but on newest commit spi could get changed so you can use older implementation instead. Re: Introducing eRPC Hey Dusan, When i use the erpcgen.exe that i built, i get the same error on the smac.erpc example: error: file smac.erpc:135:5: syntax error, unexpected identifier, expecting '}' The directory structure that i was referring to is the erpc_c from the repository and: From the SDK example. Which directory structure is the "right" one? Would it be safe to use the newly generated files (by me) with the SDK example code? Thanks, Evgeny Re: Introducing eRPC Hi evgenyerlihman, Prefered code is always on github on develop branch. Once this code will meet our requirements for new release we will merge it into master branch and we will provide also binaries of application. These updates on develop branch are more often than releases of Kinetis SDK. If some existing eRPC transport will not met version with transport used in Kinetis SDK you can compare old eRPC transport with newer one, or look on file changes in git repository. Re: Introducing eRPC Hey dusancervenka-b51352, Thank you for the quick reply! I cloned the dev branch. I see that the erpc_c directory structure is way different than the example provided with the Kinetis SDK. Which one is preferable? Thanks, Evgeny Re: Introducing eRPC Hi evgenyerlihman, Actually we are doing updates more frequently. You need switch to develop branch. GitHub - EmbeddedRPC/erpc at develop. Last code update was yesterday. But you need build erpcgen application there. With that smac IDL should works. Re: Introducing eRPC Hi dusancervenka-b51352, I am considering using the erpc framework for a new product i am working on, that uses multiple nxp kinetis devices. I see that last updates to erpc github were made 6 months ago. My question is, is it still being maintained/fixed/developed? I tried the example from github: erpcgen.exe smac.erpc And it failed to generate the cpp source code with an error. The erpcgen executable is from the SDK for MCUXpresso. Thanks, Evgeny Re: Introducing eRPC Hi Chandini, It is ok. I was on long holiday too. I hope you enjoyed it well. I sent you email through community messaging system (private message). We can discuss details through emails. Basically you ned create fork on github, checkout to develop branch, apply your changes, create commit, create pull request. We will review your changes, suggest changes and merge to develop branch. Re: Introducing eRPC Hi Dusan , Very sorry for late response , i was on long holiday . came back now . spoke with my everyone here . could you please send me your email id so that we will forward stuff for you . according to our company we cant put anything directly to your github . Thank you Chandini Re: Introducing eRPC Hi Dusan ,
Sure , i will talk to my seniors and create pull request . currently i am on holiday .Sorry for the late reply.
Thank you
Chandini Re: Introducing eRPC Hi Chandini. We are glad you have succeeded. If i can have one special proposal for you, could you send pull request on develop branch on eRPC github with your newly created transport layer (on develop branch). Maybe there will be some work to get it working with newer eRPC. But if you not want updated it i can do that With pull request on github you will be valuable contributor always seen in contributor's history. I hope eRPC will be good solution for you. And we are always here/ or on github for you Re: Introducing eRPC Hi dusancervenka-b51352 , b50844 , novakma7 Finally got it working , now demo working fine with my c++ code in Linux . Thanks a lot guys for answering all my questions. Special thanks to Dusan Thank you Chandini Re: Introducing eRPC HI Dusan , As i was busy in some other task , Yesterday i could not try anything . today i will try and let you know . I think i have to change my functions little bit and need to try . because till now i was passing just char* to my send and receive functions. Come back to you soon. Thank you Chandini Re: Introducing eRPC Hi Chandini, yes that is correct. I was outside of company, so i didn't know exact names for functions. Is it working for you? Re: Introducing eRPC Hi Dusan
Thank you for your reply :
write(fd, message->getBuffer(), message->getUsed()😞
I can see getused function in erpc/message_buffer.h at 9e18d069aeae19a6e80a5e8783903bc63bd9b567 · EmbeddedRPC/erpc · GitHub but could not find getbuffer function.
I think i have to use below function to get my buffer ? is that right ?
/*! * @brief This function returns pointer to buffer to read/write. * * @return Pointer to buffer to read/write. */ uint8_t *get() { return m_buf; }
so my functions becomes like this:
send :erpc_status_t send(MessageBuffer *message) { write(fd, message->get, message->getUsed())};
Thank you
chandini Re: Introducing eRPC Hi chanidi, well you need do it in diferent way 😕 You have to use transport.h. It will not work if you will not use that. Maybe you can use ioctl commands as i mentioned above: erpc_status_t receive(MessageBuffer *message) {int fd = open("/dev/rpmsg_ept1024.1", O_RDWR);} send :erpc_status_t send(MessageBuffer *message) { write(fd, message->getBuffer(), message->getUsed())}; read: erpc_status_t receive(MessageBuffer *message){size_t size = read(fd, message->getBuffer(), 500); message->setUsed(size)}; novakma7 Can you confirm steps? Re: Introducing eRPC Dusan , Marek Ya i am referring those files as well , but i am using trasport.h to create my transport layer. but facing argument miss-match problem send and receive functions in transport.h , take Messagebuffer as argument, virtual erpc_status_t receive(MessageBuffer *message) = 0; virtual erpc_status_t send(MessageBuffer *message) = 0; As per example.py i have created my RpmsgEndpoint class which need below arguments RpmsgEndpoint::receive(int maxlen) RpmsgEndpoint::send(char *buffer,int dst) As per my understanding, we are just need to read and write /dev/rpmsg_ept1024.1 device from Linux . So i think instead of using transport.h , i think should i need to create my own transport.h version ,? Thank you guys Chandini Re: Introducing eRPC You are welcome. You can get inspirations in /erpc-imx-demos/middleware/erpc/transport/ folder. There is several transports. Re: Introducing eRPC Thanks a lot Dusan for quick reply , i will continue in the same path then and come back to u shortly . Re: Introducing eRPC Hi Chandini. You are right. That are correct steps. You need create your class which is inheriting class from transport.h Re: Introducing eRPC Hi Marek I have question again . Currently my working status : i got RpmsgEndpoint class in c++ I am working on how to make my client application working now. Python example.py in erpc-imx-demos/MPU/example_erpc at master · EmbeddedRPC/erpc-imx-demos · GitHub call RpmsgTransport which inherited from Transport class. Question i have is , shall i use transport.h which is inside /erpc-imx-demos/middleware/erpc/erpc_c/infra to make my application work. So that i can create my RpmsgTransport class and call it my client application . Am i thinking correctly ? Thank you in advance Chandini Re: Introducing eRPC Yes, you are right. All the Python does are just IO operations on the files (read/write). This is doable in any language, including C/C++. Python was selected to show how it can be done due to its popularity in Linux user-space, but you can certainly port it to C. I think we are on the same wavelenght now, Good luck! Regards, Marek Re: Introducing eRPC Hi Marek
Thank you for your reply , it cleared few of my doubts.
We are not planning to use freeRTOS on both side.
Our plan is
M4- FreeRTOS ----This we have it in your Demo
A7-Linux -----Your Demo got python code , to make use of kernel RPMSG implemenation
All we need is instead of python either C or C++.
I think we can port python code to C or C++ , easily right ?
Thank you
Chandini
Re: Introducing eRPC Hi Chandini Indavara Basavaraju, RPMSg-Lite is implementation of RPMsg protocol and is intended only for the M4 side running FreeRTOS or baremetal. On the Linux/A7 side, you should be fine with the RPMsg implementation in kernel. (like here: GitHub - EmbeddedRPC/erpc-imx-demos: eRPC demos for i.MX devices ) Or are you planning to run FreeRTOS on both M4 and A7 cores? In that case it would work, but this is not a standard use-case. It would require you to create a porting layer for the A core and to make FreeRTOS run there. I hope this gives you some direction, Marek Re: Introducing eRPC Hi Marek Some how i have missed your message , sorry for that thanks a lot . i will try your new version soon. Could you please answer my last question regarding RPMSG transport layer ? Thank you Chandini Re: Introducing eRPC Hi, i understand you. You need create new one (and with pull request on github you can add it to our repository if you want). On Linux side you can use /dev/ttyRPMSG (if it is present in system). for example create new transport here erpc_c/transports with: init can looks like: int fd = open("/dev/ttyRPMSG", O_RDWR); send : write(fd, buffer, buffer_size); read: size_t size = read(fd, buffer, expected size); If there is no device named like this, you can be inspired from python code. RPMSG is not my cup of tea. I don't know how it should be used on Linux. I will forward your question to Marek. Re: Introducing eRPC Hi Dusan , Marek What i am planning : use rpmsg-lite on both M4(freertos) and A7(Linux) What i need: RPMSG C warrper (under erpc_c/setup) which can be use on both M4 and A7 side RPMSG Transport Layer (under erpc_c/transports) which can be use on both M4 and A7 side Questions i have: Could please tell me , Do you have any transport layer for that ? or Do we need to refer rpmsg-python and write similar like that ? Any suggestions will be so helpful Thank you guys Chandini Re: Introducing eRPC Hi, i am not sure if we have what you need (c transport for Linux side). But it should be easy to create new one. You can read and write from/to /dev/ttyRPMSG (if it is present in system). for example: init can looks like: int fd = open("/dev/ttyRPMSG", O_RDWR); send : write(fd, buffer, buffer_size); read: size_t size = read(fd, buffer, expected size); mareknovak can brings more sun into this issue. Re: Introducing eRPC Hi Dusan , thank you for letting me know about update. I thiink now i am ok with erpc what i have shortly , once i got rpmsg Client application working then i can update erpc version as well. I was started looking rpmsg-lite , that got M4 platform files . i wonder do have anything for A7 platform ? or any information will be so helpful. my main aim is to get Client Application using C with RPMSg as Transport layer Thank you Chandini Re: Introducing eRPC I am happy that you are progressing independently with your issue (for us it means it is not too much complicated for developers). Also mareknovak already updated his imx demo application inside the repository as he mentioned in few comments above. Your next step can be used that version because it is using new rpc features Re: Introducing eRPC Thank you for reply Dusan
that was the information i was looking for, i have created C wrapper for TCP , after couple of fixes in erpc, it works fine .
My next step is to replace TCP layer with rpmsg .
Thank you again
Chandini Re: Introducing eRPC Hi Chandini Indavara Basavaraju, I have just updated the GitHub - EmbeddedRPC/erpc-imx-demos: eRPC demos for i.MX devices repository to use eRPC 1.4.0 and RPMSg-Lite 1.1.0. You can download a pre-built erpcgen application, which is used for code generation here: Release v1.4 · EmbeddedRPC/erpc · GitHub in the downloads section, just choose your architecture. Then you invoke it like this: ./erpcgen -gpy nameOfInterfaceDefinitionLanguageFile.erpc, this will generate Python serialization and deserialization shim code for you. If you omit -gpy or specify -gc, you will get C shim code. The ser/des shim code was also update in the latest commit in the erpc-imx-demos repository, so feel free to use it. Feel free to submit your changes in form of a pull-request, Regards and thank you for using eRPC & RPMsg-Lite! Marek Re: Introducing eRPC Hi, we don't have currently example on github repository. But we have C(c++) test there. If you are familiar with Linux or Mac you can use that as a example. Other options are as described above: 1. Download sdk for supported board -> multicore/multiprocessor c/python examples. 2. Read this article: Getting Started · EmbeddedRPC/erpc Wiki · GitHub Re: Introducing eRPC Hi Dusan Could you please tell me , do u have any client application c example instead of python .? or Do you guys are planning to write one ?it will be so useful and helpful, if you have one already. Thank you in advance Chandini Re: Introducing eRPC Finally i got it working , thank a lot for you help Dusan sorry i could not find attach option to attach my patch . so pasted below. From 7a5b152524a3c82b5bced4a72ed396f21860b666 Mon Sep 17 00:00:00 2001 Date: Mon, 8 May 2017 11:33:05 +0100 Subject: [PATCH] fix to run 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 Abstract interface for transport layer. * @@ -89,7 +89,7 @@ public: * * @return based on send implementation. */ - virtual erpc_status_t send(MessageBuffer *message) = 0; + virtual erpc_status_t send(const MessageBuffer *message) = 0; /*! * @brief Poll for an incoming message. 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; //////////////////////////////////////////////////////////////////////////////// +// Classes +//////////////////////////////////////////////////////////////////////////////// + +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(); + } + } +}; + +//////////////////////////////////////////////////////////////////////////////// // Variables //////////////////////////////////////////////////////////////////////////////// @@ -50,29 +75,32 @@ using namespace erpc; static ManuallyConstructed s_server; SimpleServer *g_server; +static ManuallyConstructed s_msgFactory; static ManuallyConstructed s_codecFactory; //////////////////////////////////////////////////////////////////////////////// // Code //////////////////////////////////////////////////////////////////////////////// -void erpc_server_init(erpc_transport_t transport, erpc_mbf_t message_buffer_factory) +void erpc_server_init(erpc_transport_t transport) { // Init factories. + s_msgFactory.construct(); s_codecFactory.construct(); // Init server with the provided transport. 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" { * * This function initializes server with all components necessary for running server. */ -void erpc_server_init(erpc_transport_t transport, erpc_mbf_t message_buffer_factory); +void erpc_server_init(erpc_transport_t transport); /*! * @brief This function de-initializes server. 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. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "manually_constructed.h" +#include "rpmsg_lite_rtos_transport.h" +#include "erpc_transport_setup.h" + +using namespace erpc; + +//////////////////////////////////////////////////////////////////////////////// +// Variables +//////////////////////////////////////////////////////////////////////////////// + +static ManuallyConstructed s_transport; + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +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 Opaque transport object type. typedef struct ErpcTransport *erpc_transport_t; //! @brief Ready callback object type for RPMsg-Lite transport. -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 Create an RPMsg-Lite zero copy transport. */ -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 Create an RPMsg-Lite transport. */ 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 Create an RPMsg-Lite zero copy transport. */ -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 Create an RPMsg-Lite RTOS transport. @@ -133,7 +134,8 @@ erpc_transport_t erpc_transport_rpmsg_lite_rtos_master_init(unsigned long src_ad * @brief Create an RPMsg-Lite RTOS 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, 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. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rpmsg_lite_rtos_transport.h" +#include + +#if !(__embedded_cplusplus) +using namespace std; +#endif + +using namespace erpc; + +//////////////////////////////////////////////////////////////////////////////// +// Variables +//////////////////////////////////////////////////////////////////////////////// +uint8_t RPMsgRTOSTransport::s_initialized = 0; +struct rpmsg_lite_instance *RPMsgRTOSTransport::s_rpmsg; + +//////////////////////////////////////////////////////////////////////////////// +// Code +//////////////////////////////////////////////////////////////////////////////// + +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. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#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 + */ + +//////////////////////////////////////////////////////////////////////////////// +// Definitions +//////////////////////////////////////////////////////////////////////////////// + +enum +{ + kRpmsgMessageBufferSize = RPMSG_BUFFER_SIZE, + kInitCountMessageBuffers = 2, +}; + +//////////////////////////////////////////////////////////////////////////////// +// Classes +//////////////////////////////////////////////////////////////////////////////// + +namespace erpc +{ +/*! + * @brief Transport that uses RPMsg RTOS API for interprocessor messaging. + * + * @ingroup rpmsg_lite_rtos_transport + */ +class RPMsgRTOSTransport : public Transport +{ +public: + /*! + * @brief Constructor. + * + * This function initializes object attributes. + */ + RPMsgRTOSTransport(); + + /*! + * @brief RPMsgRTOSTransport destructor + */ + virtual ~RPMsgRTOSTransport(); + + /*! + * @brief This function call RPMsg rtos init function - as RPMsg master + * + * @Param[in] src_addr Source address. + * @Param[in] dst_addr Destination address. + * @Param[in] base_address RPMsg base address in the shared memory. + * @Param[in] length RPMsg shared memory region length. + * @Param[in] rpmsg_link_id Selection between what cores the communication will occur. + * + * @retval kErpcStatus_Success When rpmsg init function was executed successfully. + * @retval kErpcStatus_InitFailed When rpmsg init function wasn't executed successfully. + */ + virtual erpc_status_t init( + unsigned long src_addr, unsigned long dst_addr, void *base_address, unsigned long length, int rpmsg_link_id); + + /*! + * @brief This function call RPMsg rtos init function - as RPMsg remote + * + * @Param[in] src_addr Source address. + * @Param[in] dst_addr Destination address. + * @Param[in] base_address RPMsg base address in the shared memory. + * @Param[in] rpmsg_link_id Selection between what cores the communication will occur. + * @Param[in] ready_cb Callback called after RPMsg init is done and the core is ready. + * @Param[in] send_nameservice If true, RPMsg master notified by nameservice. + * + * @retval kErpcStatus_Success When rpmsg init function was executed successfully. + * @retval kErpcStatus_InitFailed When rpmsg init function wasn't executed successfully. + */ + 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 Store incoming message to message buffer. + * + * In loop while no message come. + * + * @Param[in] message Message buffer, to which will be stored incoming message. + * + * @retval kErpcStatus_ReceiveFailed Failed to receive message buffer. + * @retval kErpcStatus_Success Successfully received all data. + */ + virtual erpc_status_t receive(MessageBuffer *message); + + /*! + * @brief Function to send prepared message. + * + * @Param[in] message Pass message buffer to send. + * + * @retval kErpcStatus_SendFailed Failed to send message buffer. + * @retval kErpcStatus_Success Successfully sent all data. + */ + virtual erpc_status_t send(const MessageBuffer *message); + +protected: + /* Remote device */ + struct remote_device *m_rdev; /*!< Device which represent the second core. */ + struct rpmsg_channel *m_app_rp_chnl; /*!< Represent connection between two device (two cores). */ + unsigned long m_dst_addr; /*!< Destination address used by rpmsg. */ + rpmsg_queue_handle m_rpmsg_queue; /*!< Handle of RPMsg queue. */ + struct rpmsg_lite_endpoint *m_rpmsg_ept; /*!< Pointer to RPMsg Lite Endpoint structure. */ + + static struct rpmsg_lite_instance *s_rpmsg; /*!< Pointer to instance of RPMSG lite. */ + static uint8_t s_initialized; /*!< Represent information if the rpmsg-lite was initialized. */ +}; + +class RPMsgMessageBufferFactory : public MessageBufferFactory +{ + uint8_t m_freeBufferBitmap; + uint8_t m_buffers[kInitCountMessageBuffers][kRpmsgMessageBufferSize]; + +public: + /*! + * @brief Constructor. + */ + RPMsgMessageBufferFactory() + : m_freeBufferBitmap(0xFF) + { + } + /*! + * @brief RPMsgMessageBufferFactory destructor + */ + virtual ~RPMsgMessageBufferFactory() {} + /*! + * @brief This function create message buffer used for communication between devices. + */ + virtual MessageBuffer create(); + /*! + * @brief This function dispose message buffer used for communication between devices. + */ + virtual void dispose(MessageBuffer *buf); +}; + +} // namespace 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. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#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 + */ + +//////////////////////////////////////////////////////////////////////////////// +// Definitions +//////////////////////////////////////////////////////////////////////////////// + +enum +{ + kRpmsgMessageBufferSize = RPMSG_BUFFER_SIZE, +}; + +//////////////////////////////////////////////////////////////////////////////// +// Classes +//////////////////////////////////////////////////////////////////////////////// + +namespace erpc +{ +/*! + * @brief Transport that uses RPMsg RTOS API for interprocessor messaging. + * + * @ingroup rpmsg_rtos_transport + */ +class RPMsgRTOSTransport : public Transport +{ +public: + /*! + * @brief Constructor. + * + * This function initializes object attributes. + */ + RPMsgRTOSTransport(); + + /*! + * @brief RPMsgRTOSTransport destructor + */ + virtual ~RPMsgRTOSTransport(); + + /*! + * @brief This function call rpmsg rtos init function. + * + * @Param[in] dev_id Device id number. + * @Param[in] role Device role number. + * + * @retval kErpcStatus_Success When rpmsg init function was executed successfully. + * @retval kErpcStatus_InitFailed When rpmsg init function wasn't executed successfully. + */ + virtual erpc_status_t init(int dev_id, int role); + + /*! + * @brief Store incoming message to message buffer. + * + * In loop while no message come. + * + * @Param[in] message Message buffer, to which will be stored incoming message. + * + * @retval kErpcStatus_ReceiveFailed Failed to receive message buffer. + * @retval kErpcStatus_Success Successfully received all data. + */ + virtual erpc_status_t receive(MessageBuffer *message); + + /*! + * @brief Function to send prepared message. + * + * @Param[in] message Pass message buffer to send. + * + * @retval kErpcStatus_SendFailed Failed to send message buffer. + * @retval kErpcStatus_Success Successfully sent all data. + */ + virtual erpc_status_t send(const MessageBuffer *message); + +protected: + /* Remote device */ + static struct remote_device *m_rdev; /*!< Device which represent the second core. */ + static struct rpmsg_channel *m_app_rp_chnl; /*!< Represent connection between two device (two cores). */ +}; + +class RPMsgMessageBufferFactory : public MessageBufferFactory +{ +public: + /*! + * @brief Constructor. + */ + RPMsgMessageBufferFactory() {} + /*! + * @brief RPMsgMessageBufferFactory destructor + */ + virtual ~RPMsgMessageBufferFactory() {} + /*! + * @brief This function create message buffer used for communication between devices. + */ + virtual MessageBuffer create(); + /*! + * @brief This function dispose message buffer used for communication between devices. + */ + virtual void dispose(MessageBuffer *buf); +}; + +} // namespace 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: Introducing eRPC Thank you Dusan . once i got my demo working , i will create pull request ..
Thanks again for your reply , i got python files . i will run demo and come back to u shortly . Re: Introducing eRPC Hi, great work If you want you can create pull request for imx demo repository to fix it. mareknovak can review it and merge it to the repository. To generate python code: As other application you can do in command line "erpcgen --help (-h should work too)". python -gpy idl_file -> gpy means generate python. Re: Introducing eRPC That's cool, i can continue to work in the same stable version until update . with couples of fixes my MCU demo build and run properly now ..Thanks for your information Re: Introducing eRPC Hi Dusan I did fix and now i got MCU demo working properly ... Thanks for pointing out me a stable version .. Could you please tell me How to generate python code using erpcgen tool .. ? Thank you Chandini Re: Introducing eRPC Hi, not sooner than tomorrow. But i can't promise that it will be tomorrow. My colleague mareknovak is not in work today. But it should be soon. Re: Introducing eRPC Could you please tell me , when are you going to update ? Re: Introducing eRPC Hi thanks for you interest. Then it looks like the erpc generated files were generated with different erpcgen then on commit Marek provided (our mistake). Best solution looks like we need updated that demo with latests stable erpc and erpcgen version. You can try this from master branch GitHub - EmbeddedRPC/erpc: Embedded RPC (and there is erpcgen prebuilt 1.4.0). But i don't know how much changes you need to do. Or you can wait for our update. mareknovak Re: Introducing eRPC Hi Dusan I was using same eRPC library one which u refereed Steps i followed are below: Clone erpc-imx-demos including sub module(which clone eRPC GitHub - MarekNovakNXP/erpc at 232afb209f0a0cfceb25a1be11879f7d1934e065 ) 1. git clone --recursive https://github.com/EmbeddedRPC/erpc-imx-demos.git 2. go to erpc-imx-demos/middleware/erpc folder and build erpcgen like this: installed required packages flex/bison and boost make eprc make eprcgen sudo make install successfully got erpcgen 3. Tried create my own output files using same erpc_matrix_multiply.erpc like this : erpcgen -I erpc-imx-demos/MCU/example_erpc/service -o test/erpc-imx-demos/MCU/example_erpc/service erpc_matrix_multiply.erpc successfully got below files: erpc_matrix_multiply.h erpc_matrix_multiply_server.cpp erpc_matrix_multiply_server.h erpc_matrix_multiply_client.cpp 4. Tried to build MCU/example_erpc/build/armgcc/imx7d_sdb_m4/build_all.sh failed with error : /home/basavarajuc/test/erpc-imx-demos/MCU/example_erpc/service/erpc_matrix_multiply_server.cpp: In function 'void* create_MatrixMultiplyService_service()': /home/basavarajuc/test/erpc-imx-demos/MCU/example_erpc/service/erpc_matrix_multiply_server.cpp:168:56: error: invalid new-expression of abstract class type 'MatrixMultiplyService_service' return new (nothrow) MatrixMultiplyService_service(); Sorry for asking again , just to clarify my understanding . 1.if i am using eRPC library from GitHub - MarekNovakNXP/erpc at 232afb209f0a0cfceb25a1be11879f7d1934e065 then Do i need to update demo ? to run demo successfully 2. Could you please tell me output files from erpc-imx-demos/MCU/example_erpc/service at master · EmbeddedRPC/erpc-imx-demos · GitHub are generated by which erpcgen version ? So that i can use old erpcgen shortly to create my own files Thanks a lot . and sorry for disturbance Chandini Re: Introducing eRPC Hi and thanks for your comment. Example you mentioned is an older version than your erpcgen build. mareknovak also created his fork of official eRPC repository due to some minor changes which were not present in an official release at that time. If you click on eRPC reference from erpc-imx-demos repository from middleware folder, you will be redirect to his eRPC repository. You need build erpcgen from that version. We want update demo in the future. Hope i helped you. If you have any concerns don't hesitate and ask us. Re: Introducing eRPC Hi Sorry if i am asking basic question. I am trying to understand how to use erpcgen tool from NXP. I successfully ran example demo , with reference : https://github.com/EmbeddedRPC/erpc-imx-demos My next approach was build erpcgen and create my own output files using same erpc_matrix_multiply.erpc and run same demo again so i get familiar to use erpcgen tool. i got output files but even though i am using same erpc_matrix_multiply.erpc my files different than example files the changes are : Output files in example demo says (erpc_matrix_multiply_server.h): erpc_status_t erpcMatrixMultiply_shim(erpc::Codec * in, erpc::Codec * out, uint32_t sequence); my files(erpc_matrix_multiply_server.h): erpc_status_t erpcMatrixMultiply_shim(erpc::Codec * codec, uint32_t sequence); why files are different , Am i missing any config ? Do i need to manually edit erpc_matrix_multiply_server.h & erpc_matrix_multiply_server.cpp Thank you in advance Chandini