eRPC example
This section shows how to create an example eRPC application called “Matrix multiply”, which implements one eRPC function (matrix multiply) with two function parameters (two matrices). The client-side application calls this eRPC function, and the server side performs the multiplication of received matrices. The server side then returns the result.
For example, use the NXP MIMXRT1170-EVK board as the target dual-core platform, and the IAR Embedded Workbench for ARM (EWARM) as the target IDE for developing the eRPC example.
The primary core (CM7) runs the eRPC client.
The secondary core (CM4) runs the eRPC server.
RPMsg-Lite (Remote Processor Messaging Lite) is used as the eRPC transport layer.
The “Matrix multiply” application can be also run in the multi-processor setup. In other words, the eRPC client running on one SoC comunicates with the eRPC server that runs on anothe SoC, utilizing different transport channels. It is possible to run the board-to-PC example (PC as the eRPC server and a board as the eRPC client, and vice versa) and also the board-to-board example. These multiprocessor examples are prepared for selected boards only.
|Multicore application source and project files|<MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/erpc_matrix_multiply_rpmsg/| |Multiprocessor application source and project files|<MCUXpressoSDK_install_dir>/boards/<board_name>/multiprocessor_examples/erpc_client_matrix_multiply_<transport_layer>/
<MCUXpressoSDK_install_dir>/boards/<board_name>/multiprocessor_examples/erpc_server_matrix_multiply_<transport_layer>/
| |eRPC source files|<MCUXpressoSDK_install_dir>/middleware/multicore/erpc/| |RPMsg-Lite source files|<MCUXpressoSDK_install_dir>/middleware/multicore/rpmsg_lite/|
Designing the eRPC application
The matrix multiply application is based on calling single eRPC function that takes 2 two-dimensional arrays as input and returns matrix multiplication results as another 2 two-dimensional array. The IDL file syntax supports arrays with the dimension length set by the number only (in the current eRPC implementation). Because of this, a variable is declared in the IDL dedicated to store information about matrix dimension length, and to allow easy maintenance of the user and server code.
For a simple use of the two-dimensional array, the alias name (new type definition) for this data type has is declared in the IDL. Declaring this alias name ensures that the same data type can be used across the client and server applications.
Parent topic:eRPC example
Creating the IDL file
The created IDL file is located in the following folder:
<MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/erpc_common/erpc_matrix_multiply/service/erpc_matrix_multiply.erpc
The created IDL file contains the following code:
program erpc_matrix_multiply
/*! This const defines the matrix size. The value has to be the same as the
Matrix array dimension. Do not forget to re-generate the erpc code once the
matrix size is changed in the erpc file */
const int32 matrix_size = 5;
/*! This is the matrix array type. The dimension has to be the same as the
matrix size const. Do not forget to re-generate the erpc code once the
matrix size is changed in the erpc file */
type Matrix = int32[matrix_size][matrix_size];
interface MatrixMultiplyService {
erpcMatrixMultiply(in Matrix matrix1, in Matrix matrix2, out Matrix result_matrix) ->
void
}
Details:
The IDL file starts with the program name (erpc_matrix_multiply), and this program name is used in the naming of all generated outputs.
The declaration and definition of the constant variable named matrix_size follows next. The matrix_size variable is used for passing information about the length of matrix dimensions to the client/server user code.
The alias name for the two-dimensional array type (Matrix) is declared.
The interface group MatrixMultiplyService is located at the end of the IDL file. This interface group contains only one function declaration erpcMatrixMultiply.
As shown above, the function’s declaration contains three parameters of Matrix type: matrix1 and matrix2 are input parameters, while result_matrix is the output parameter. Additionally, the returned data type is declared as void.
When writing the IDL file, the following order of items is recommended:
Program name at the top of the IDL file.
New data types and constants declarations.
Declarations of interfaces and functions at the end of the IDL file.
Parent topic:eRPC example
Using the eRPC generator tool
|Windows OS|<MCUXpressoSDK_install_dir>/middleware/multicore/tools/erpcgen/Windows| |Linux OS|<MCUXpressoSDK_install_dir>/middleware/multicore/tools/erpcgen/Linux_x64
<MCUXpressoSDK_install_dir>/middleware/multicore/tools/erpcgen/Linux_x86
| |Mac OS|<MCUXpressoSDK_install_dir>/middleware/multicore/tools/erpcgen/Mac|
The files for the “Matrix multiply” example are pre-generated and already a part of the application projects. The following section describes how they have been created.
The easiest way to create the shim code is to copy the erpcgen application to the same folder where the IDL file (
*.erpc
) is located; then run the following command:erpcgen <IDL_file>.erpc
In the “Matrix multiply” example, the command should look like:
erpcgen erpc_matrix_multiply.erpc
Additionally, another method to create the shim code is to execute the eRPC application using input commands:
“-?”/”—help” – Shows supported commands.
“-o <filePath>”/”—output<filePath>” – Sets the output directory.
For example,
<path_to_erpcgen>/erpcgen –o <path_to_output>
<path_to_IDL>/<IDL_file_name>.erpc
For the “Matrix multiply” example, when the command is executed from the default erpcgen
location, it looks like:
erpcgen –o
../../../../../boards/evkmimxrt1170/multicore_examples/erpc_common/erpc_matrix_multiply/service ../../../../../boards/evkmimxrt1170/multicore_examples/erpc_common/erpc_matrix_multiply/service/erpc_matrix_multiply.erpc
In both cases, the following four files are generated into the <MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/erpc_common/erpc_matrix_multiply/service folder.
erpc_matrix_multiply.h
erpc_matrix_multiply_client.cpp
erpc_matrix_multiply_server.h
erpc_matrix_multiply_server.cpp
For multiprocessor examples, the eRPC file and pre-generated files can be found in the <MCUXpressoSDK_install_dir>/boards/<board_name>/multiprocessor_examples/erpc_common/erpc_matrix_multiply/service folder.
For Linux OS users:
Do not forget to set the permissions for the eRPC generator application.
Run the application as
./erpcgen
… instead of as erpcgen ….
Parent topic:eRPC example
Create an eRPC application
This section describes a generic way to create a client/server eRPC application:
Design the eRPC application: Decide which data types are sent between applications, and define functions that send/receive this data.
Create the IDL file: The IDL file contains information about data types and functions used in an eRPC application, and is written in the IDL language.
Use the eRPC generator tool: This tool takes an IDL file and generates the shim code for the client and the server-side applications.
Create an eRPC application:
Create two projects, where one project is for the client side (primary core) and the other project is for the server side (secondary core).
Add generated files for the client application to the client project, and add generated files for the server application to the server project.
Add infrastructure files.
Add user code for client and server applications.
Set the client and server project options.
Run the eRPC application: Run both the server and the client applications. Make sure that the server has been run before the client request was sent.
A specific example follows in the next section.
Multicore server application
The “Matrix multiply” eRPC server project is located in the following folder:
<MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/erpc_matrix_multiply_rpmsg/cm4/iar/
The project files for the eRPC server have the _cm4
suffix.
Server project basic source files
The startup files, board-related settings, peripheral drivers, and utilities belong to the basic project source files and form the skeleton of all MCUXpresso SDK applications. These source files are located in:
<MCUXpressoSDK_install_dir>/devices/<device>
<MCUXpressoSDK_install_dir>/boards/<board_name>/multicore_examples/<example_name>/
|
|
Parent topic:Multicore server application
Server infrastructure files
The eRPC infrastructure files are located in the following folder:
<MCUXpressoSDK_install_dir>/middleware/multicore/erpc/erpc_c
The erpc_c folder contains files for creating eRPC client and server applications in the C/C++ language. These files are distributed into subfolders.
The infra subfolder contains C++ infrastructure code used to build server and client applications.
Four files,
erpc_server.hpp
,erpc_server.cpp
,erpc_simple_server.hpp
, anderpc_simple_server.cpp
, are used for running the eRPC server on the server-side applications. The simple server is currently the only implementation of the server, and its role is to catch client requests, identify and call requested functions, and send data back when requested.Three files (
erpc_codec.hpp
,erpc_basic_codec.hpp
, anderpc_basic_codec.cpp
) are used for codecs. Currently, the basic codec is the initial and only implementation of the codecs.The
erpc_common.hpp
file is used for common eRPC definitions, typedefs, and enums.The
erpc_manually_constructed.hpp
file is used for allocating static storage for the used objects.Message buffer files are used for storing serialized data:
erpc_message_buffer.h
anderpc_message_buffer.cpp
.The
erpc_transport.h
file defines the abstract interface for transport layer.
The port subfolder contains the eRPC porting layer to adapt to different environments.
erpc_port.h
file contains definition oferpc_malloc()
anderpc_free()
functions.erpc_port_stdlib.cpp
file ensures adaptation to stdlib.erpc_config_internal.h
internal erpc configuration file.
The setup subfolder contains a set of plain C APIs that wrap the C++ infrastructure, providing client and server init and deinit routines that greatly simplify eRPC usage in C-based projects. No knowledge of C++ is required to use these APIs.
The
erpc_server_setup.h
anderpc_server_setup.cpp
files needs to be added into the “Matrix multiply” example project to demonstrate the use of C-wrapped functions in this example.The
erpc_transport_setup.h
anderpc_setup_rpmsg_lite_remote.cpp
files needs to be added into the project in order to allow the C-wrapped function for transport layer setup.The
erpc_mbf_setup.h
anderpc_setup_mbf_rpmsg.cpp
files needs to be added into the project in order to allow message buffer factory usage.
The transports subfolder contains transport classes for the different methods of communication supported by eRPC. Some transports are applicable only to host PCs, while others are applicable only to embedded or multicore systems. Most transports have corresponding client and server setup functions in the setup folder.
RPMsg-Lite is used as the transport layer for the communication between cores,
erpc_rpmsg_lite_base_transport.hpp
,erpc_rpmsg_lite_transport.hpp
, anderpc_rpmsg_lite_transport.cpp
files need to be added into the server project.
|
|
Parent topic:Multicore server application
Server multicore infrastructure files
Because of the RPMsg-Lite (transport layer), it is also necessary to include RPMsg-Lite related files, which are in the following folder:
<MCUXpressoSDK_install_dir>/middleware/multicore/rpmsg_lite/
The multicore example applications also use the Multicore Manager software library to control the secondary core startup and shutdown. These source files are located in the following folder:
<MCUXpressoSDK_install_dir>/middleware/multicore/mcmgr/
|
|
Parent topic:Multicore server application
Server user code
The server’s user code is stored in the main_core1.c
file, located in the following folder:
<MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/erpc_matrix_multiply_rpmsg/cm4
The main_core1.c
file contains two functions:
The main() function contains the code for the target board and eRPC server initialization. After the initialization, the matrix multiply service is added and the eRPC server waits for client’s requests in the while loop.
The erpcMatrixMultiply() function is the user implementation of the eRPC function defined in the IDL file.
There is the possibility to write the application-specific eRPC error handler. The eRPC error handler of the matrix multiply application is implemented in the
erpc_error_handler.h
anderpc_error_handler.cpp
files.
The eRPC-relevant code is captured in the following code snippet:
/* erpcMatrixMultiply function user implementation */
void erpcMatrixMultiply(const Matrix *matrix1, const Matrix *matrix2, Matrix *result_matrix)
{
...
}
int main()
{
...
/* RPMsg-Lite transport layer initialization */
erpc_transport_t transport;
transport = erpc_transport_rpmsg_lite_remote_init(src, dst, (void*)startupData,
ERPC_TRANSPORT_RPMSG_LITE_LINK_ID, SignalReady, NULL);
...
/* MessageBufferFactory initialization */
erpc_mbf_t message_buffer_factory;
message_buffer_factory = erpc_mbf_rpmsg_init(transport);
...
/* eRPC server side initialization */
erpc_server_t server;
server = erpc_server_init(transport, message_buffer_factory);
...
/* Adding the service to the server */
erpc_service_t service = create_MatrixMultiplyService_service();
erpc_add_service_to_server(server, service);
...
while (1)
{
/* Process eRPC requests */
erpc_status_t status = erpc_server_poll(server);
/* handle error status */
if (status != kErpcStatus_Success)
{
/* print error description */
erpc_error_handler(status, 0);
...
}
...
}
}
Except for the application main file, there are configuration files for the RPMsg-Lite (rpmsg_config.h
) and eRPC (erpc_config.h
), located in the <MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/ erpc_matrix_multiply_rpmsg folder.
|
|
Parent topic:Multicore server application
Parent topic:Create an eRPC application
Multicore client application
The “Matrix multiply” eRPC client project is located in the following folder:
<MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/erpc_matrix_multiply_rpmsg/cm7/iar/
Project files for the eRPC client have the _cm7
suffix.
Client project basic source files
The startup files, board-related settings, peripheral drivers, and utilities belong to the basic project source files and form the skeleton of all MCUXpresso SDK applications. These source files are located in the following folders:
<MCUXpressoSDK_install_dir>/devices/<device>
<MCUXpressoSDK_install_dir>/boards/<board_name>/multicore_examples/<example_name>/
|
|
Parent topic:Multicore client application
Client infrastructure files
The eRPC infrastructure files are located in the following folder:
<MCUXpressoSDK_install_dir>/middleware/multicore/erpc/erpc_c
The erpc_c folder contains files for creating eRPC client and server applications in the C/C++ language. These files are distributed into subfolders.
The infra subfolder contains C++ infrastructure code used to build server and client applications.
Two files,
erpc_client_manager.h
anderpc_client_manager.cpp
, are used for managing the client-side application. The main purpose of the client files is to create, perform, and release eRPC requests.Three files (
erpc_codec.hpp
,erpc_basic_codec.hpp
, anderpc_basic_codec.cpp
) are used for codecs. Currently, the basic codec is the initial and only implementation of the codecs.erpc_common.h
file is used for common eRPC definitions, typedefs, and enums.erpc_manually_constructed.hpp
file is used for allocating static storage for the used objects.Message buffer files are used for storing serialized data:
erpc_message_buffer.hpp
anderpc_message_buffer.cpp
.erpc_transport.hpp
file defines the abstract interface for transport layer.
The port subfolder contains the eRPC porting layer to adapt to different environments.
erpc_port.h
file contains definition of erpc_malloc() and erpc_free() functions.erpc_port_stdlib.cpp
file ensures adaptation to stdlib.erpc_config_internal.h
internal eRPC configuration file.
The setup subfolder contains a set of plain C APIs that wrap the C++ infrastructure, providing client and server init and deinit routines that greatly simplify eRPC usage in C-based projects. No knowledge of C++ is required to use these APIs.
erpc_client_setup.h
anderpc_client_setup.cpp
files needs to be added into the “Matrix multiply” example project to demonstrate the use of C-wrapped functions in this example.erpc_transport_setup.h
anderpc_setup_rpmsg_lite_master.cpp
files needs to be added into the project in order to allow C-wrapped function for transport layer setup.erpc_mbf_setup.h
anderpc_setup_mbf_rpmsg.cpp
files needs to be added into the project in order to allow message buffer factory usage.
The transports subfolder contains transport classes for the different methods of communication supported by eRPC. Some transports are applicable only to host PCs, while others are applicable only to embedded or multicore systems. Most transports have corresponding client and server setup functions, in the setup folder.
RPMsg-Lite is used as the transport layer for the communication between cores,
erpc_rpmsg_lite_base_transport.hpp
,erpc_rpmsg_lite_transport.hpp
, anderpc_rpmsg_lite_transport.cpp
files needs to be added into the client project.
|
|
Parent topic:Multicore client application
Client multicore infrastructure files
Because of the RPMsg-Lite (transport layer), it is also necessary to include RPMsg-Lite related files, which are in the following folder:
<MCUXpressoSDK_install_dir>/middleware/multicore/rpmsg_lite/
The multicore example applications also use the Multicore Manager software library to control the secondary core startup and shutdown. These source files are located in the following folder:
<MCUXpressoSDK_install_dir>/middleware/multicore/mcmgr/
|
|
Parent topic:Multicore client application
Client user code
The client’s user code is stored in the main_core0.c file, located in the following folder:
<MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_example/erpc_matrix_multiply_rpmsg/cm7
The main_core0.c
file contains the code for target board and eRPC initialization.
After initialization, the secondary core is released from reset.
When the secondary core is ready, the primary core initializes two matrix variables.
The erpcMatrixMultiply eRPC function is called to issue the eRPC request and get the result.
It is possible to write the application-specific eRPC error handler. The eRPC error handler of the matrix multiply application is implemented in erpc_error_handler.h
and erpc_error_handler.cpp
files.
The matrix multiplication can be issued repeatedly, when pressing a software board button.
The eRPC-relevant code is captured in the following code snippet:
...
extern bool g_erpc_error_occurred;
...
/* Declare matrix arrays */
Matrix matrix1 = {0}, matrix2 = {0}, result_matrix = {0};
...
/* RPMsg-Lite transport layer initialization */
erpc_transport_t transport;
transport = erpc_transport_rpmsg_lite_master_init(src, dst,
ERPC_TRANSPORT_RPMSG_LITE_LINK_ID);
...
/* MessageBufferFactory initialization */
erpc_mbf_t message_buffer_factory;
message_buffer_factory = erpc_mbf_rpmsg_init(transport);
...
/* eRPC client side initialization */
erpc_client_t client;
client = erpc_client_init(transport, message_buffer_factory);
...
/* Set default error handler */
erpc_client_set_error_handler(client, erpc_error_handler);
...
while (1)
{
/* Invoke the erpcMatrixMultiply function */
erpcMatrixMultiply(matrix1, matrix2, result_matrix);
...
/* Check if some error occured in eRPC */
if (g_erpc_error_occurred)
{
/* Exit program loop */
break;
}
...
}
Except for the application main file, there are configuration files for the RPMsg-Lite (rpmsg_config.h
) and eRPC (erpc_config.h
), located in the following folder:
<MCUXpressoSDK_install_dir>/boards/evkmimxrt1170/multicore_examples/erpc_matrix_multiply_rpmsg
|
|
Parent topic:Multicore client application
Parent topic:Create an eRPC application
Multiprocessor server application
The “Matrix multiply” eRPC server project for multiprocessor applications is located in the <MCUXpressoSDK_install_dir>>/boards/<board_name>/multiprocessor_examples/ erpc_server_matrix_multiply_<transport_layer> folder.
Most of the multiprocessor application setup is the same as for the multicore application. The multiprocessor server application requires server-related generated files (server shim code), server infrastructure files, and the server user code. There is no need for server multicore infrastructure files (MCMGR and RPMsg-Lite). The RPMsg-Lite transport layer is replaced either by SPI or UART transports. The following table shows the required transport-related files per each transport type.
|SPI|<eRPC base directory>/erpc_c/setup/erpc_setup_(d)spi_slave.cpp
<eRPC base directory>/erpc_c/transports/erpc_(d)spi_slave_transport.hpp
<eRPC base directory>/erpc_c/transports/erpc_(d)spi_slave_transport.cpp
|
|UART|<eRPC base directory>/erpc_c/setup/erpc_setup_uart_cmsis.cpp
<eRPC base directory>/erpc_c/transports/erpc_uart_cmsis_transport.hpp
<eRPC base directory>/erpc_c/transports/erpc_uart_cmsis_transport.cpp
|
Server user code
The server’s user code is stored in the main_server.c
file, located in the <MCUXpressoSDK_install_dir>/boards/ <board_name>/multiprocessor_examples/erpc_server_matrix_multiply_<transport_layer>/ folder.
The eRPC-relevant code with UART as a transport is captured in the following code snippet:
/* erpcMatrixMultiply function user implementation */
void erpcMatrixMultiply(Matrix matrix1, Matrix matrix2, Matrix result_matrix)
{
...
}
int main()
{
...
/* UART transport layer initialization, ERPC_DEMO_UART is the structure of CMSIS UART driver operations */
erpc_transport_t transport;
transport = erpc_transport_cmsis_uart_init((void *)&ERPC_DEMO_UART);
...
/* MessageBufferFactory initialization */
erpc_mbf_t message_buffer_factory;
message_buffer_factory = erpc_mbf_dynamic_init();
...
/* eRPC server side initialization */
erpc_server_t server;
server = erpc_server_init(transport, message_buffer_factory);
...
/* Adding the service to the server */
erpc_service_t service = create_MatrixMultiplyService_service();
erpc_add_service_to_server(server, service);
...
while (1)
{
/* Process eRPC requests */
erpc_status_t status = erpc_server_poll(server)
/* handle error status */
if (status != kErpcStatus_Success)
{
/* print error description */
erpc_error_handler(status, 0);
...
}
...
}
}
Parent topic:Multiprocessor server application
Multiprocessor client application
The “Matrix multiply” eRPC client project for multiprocessor applications is located in the <MCUXpressoSDK_install_dir>/ boards/<board_name>/multiprocessor_examples/erpc_client_matrix_multiply_<transport_layer>/iar/ folder.
Most of the multiprocessor application setup is the same as for the multicore application. The multiprocessor server application requires client-related generated files (server shim code), client infrastructure files, and the client user code. There is no need for client multicore infrastructure files (MCMGR and RPMsg-Lite). The RPMsg-Lite transport layer is replaced either by SPI or UART transports. The following table shows the required transport-related files per each transport type.
|SPI|<eRPC base directory>/erpc_c/setup/erpc_setup_(d)spi_master.cpp
<eRPC base directory>/erpc_c/transports/ erpc_(d)spi_master_transport.hpp
<eRPC base directory>/erpc_c/transports/ erpc_(d)spi_master_transport.cpp
|
|UART|<eRPC base directory>/erpc_c/setup/erpc_setup_uart_cmsis.cpp
<eRPC base directory>/erpc_c/transports/erpc_uart_cmsis_transport.hpp
<eRPC base directory>/erpc_c/transports/erpc_uart_cmsis_transport.cpp
|
Client user code
The client’s user code is stored in the main_client.c
file, located in the <MCUXpressoSDK_install_dir>/boards/<board_name>/multiprocessor_examples/ erpc_client_matrix_multiply_<transport_layer>/ folder.
The eRPC-relevant code with UART as a transport is captured in the following code snippet:
...
extern bool g_erpc_error_occurred;
...
/* Declare matrix arrays */
Matrix matrix1 = {0}, matrix2 = {0}, result_matrix = {0};
...
/* UART transport layer initialization, ERPC_DEMO_UART is the structure of CMSIS UART driver operations */
erpc_transport_t transport;
transport = erpc_transport_cmsis_uart_init((void *)&ERPC_DEMO_UART);
...
/* MessageBufferFactory initialization */
erpc_mbf_t message_buffer_factory;
message_buffer_factory = erpc_mbf_dynamic_init();
...
/* eRPC client side initialization */
erpc_client_t client;
client = erpc_client_init(transport,message_buffer_factory);
...
/* Set default error handler */
erpc_client_set_error_handler(client, erpc_error_handler);
...
while (1)
{
/* Invoke the erpcMatrixMultiply function */
erpcMatrixMultiply(matrix1, matrix2, result_matrix);
...
/* Check if some error occured in eRPC */
if (g_erpc_error_occurred)
{
/* Exit program loop */
break;
}
...
}
Parent topic:Multiprocessor client application
Parent topic:Multiprocessor server application
Parent topic:Create an eRPC application
Running the eRPC application
Follow the instructions in Getting Started with MCUXpresso SDK (document MCUXSDKGSUG) (located in the <MCUXpressoSDK_install_dir>/docs folder), to load both the primary and the secondary core images into the on-chip memory, and then effectively debug the dual-core application. After the application is running, the serial console should look like:
|
|
For multiprocessor applications that are running between PC and the target evaluation board or between two boards, follow the instructions in the accompanied example readme files that provide details about the proper board setup and the PC side setup (Python).
Parent topic:Create an eRPC application
Parent topic:eRPC example