erpc
erpc copied to clipboard
Multirole device
Hi,
I'd like to use eRPC for my current project, since I have a good experience of using it in past. I have an embedded system (Cortex M4 MCU) and use C API. 2 devices can be daisy chained and eRPC used to communicate between them. In this case one device configured as master and another one - as slave. So, depending on configuration I need to switch device between client and server roles.
This is good example of what I need (I can run it as server or as client): https://github.com/EmbeddedRPC/erpc/blob/master/examples/matrix_multiply_tcp_python/matrix_multiply.py
But when using C API, there is an issue. Let's say we have erpcMatrixMultiply function to call on a client side. When I code server I have to define erpcMatrixMultiply in my code. But function with this name is already defined in erpc_matrix_multiply_client.cpp
Thanks, Eugene
Hi @eugene345, yes this sounds like a limitation of C language. Simple solution could be have two IDL files where functions inside have different postfix. (for first pair it can be _f, for second _s).
Hi @Hadatko,
Thanks for the idea. @group name also should have a different postfix? otherwise after erpcgen running files will be rewritten. And then call erpcMatrixMultiply_f from master (client) and implement erpcMatrixMultiply_s in slave (server), right?
Best regards, Eugene
Hi @eugene345 , sorry i am not enterly clear with your idea. If the device can be client or server but it is not changing during runtime, then you need two projects. One for server and one for client and use one which is needed. If you need both client and server implementation during runtime on each side, you can use transport arbitrator (limited to transport type)/ or you can use two different transports. In IDL.erpc you can define several Interfaces inside two @groups One group will define functions from one core to second and one from second to first. Group names have to be different and also function names. If there is some third device with which you are communicating the middle device can receive message and send further without client/server implementation. Only wating for messages and sending them further.
Hi @Hadatko,
I'm still trying to find the best and most elegant option. Let me remind about my case. There are 2 (but can be more) exactly same devices with same firmware. I use UART for communication between them. At run-time devices must be configured as master or slaves. For sure, there is a proper cable used for communication and only one device configured as master. Master is client and slave is server. I use arbitrator, because both, client and server, resides in the same device.
Here is my erpc file:
@output_dir("output") // output directory
program erpc; // specify name of output files
@group("daisy_chain")
// Calls from master to slave
interface DaisyChain
{
oneway slave_start()
}
Out of box this doesn't work, because slave_start() is defined already in erpc_daisy_chain_client.cpp (see attached erpc.zip). And I can't define slave_start() for the server. So, if client and server are different projects - no problem. But in my case client and server are in the same project.
At this moment to fix the issue I manually renamed slave_start() to slave_start_implemenation() in erpc_daisy_chain_server.cpp.
before:
// Server shim for slave_start of DaisyChain interface.
erpc_status_t DaisyChain_service::slave_start_shim(Codec * codec, MessageBufferFactory *messageFactory, uint32_t sequence)
{
// startReadMessage() was already called before this shim was invoked.
// Invoke the actual served function.
#if ERPC_NESTED_CALLS_DETECTION
nestingDetection = true;
#endif
slave_start();
#if ERPC_NESTED_CALLS_DETECTION
nestingDetection = false;
#endif
return codec->getStatus();
}
after:
// Server shim for slave_start of DaisyChain interface.
erpc_status_t DaisyChain_service::slave_start_shim(Codec * codec, MessageBufferFactory *messageFactory, uint32_t sequence)
{
// startReadMessage() was already called before this shim was invoked.
// Invoke the actual served function.
#if ERPC_NESTED_CALLS_DETECTION
nestingDetection = true;
#endif
slave_start_implementation();
#if ERPC_NESTED_CALLS_DETECTION
nestingDetection = false;
#endif
return codec->getStatus();
}
and added slave_start_implementation() prototype to erpc_daisy_chain.h:
//! @name DaisyChain
//@{
void slave_start(void);
void slave_start_implementation(void);
//@}
But I don't think, that this is the most elegant solution.
I think, that remote_function() can't have the same name in client and server (e.g. in server it should be remote_function_implementation())
What do you think about it? Does it make sense? Do you know any better solution?
Thanks, Eugene
Hi @eugene345, well in principle remote function name should be same on client and server side. I understand that this is bringing some restrictions based on programming language. Maybe good idea would be overwrite remote function name for server side with some annotation like
@server_prototype_name("remote_function_implementation") oneway remote_function()