apps: add linux applications for linux rpc communication

Added linux_rpc_demo and linux_rpc_demod for rpc communication
between linux master and slave configuration

Signed-off-by: ViswaHarsha C <cviswa.harsha_ext@ltts.com>
This commit is contained in:
ViswaHarsha C
2021-09-23 14:12:19 +05:30
committed by Arnaud Pouliquen
parent 413ff36118
commit bdd4aa5d14
6 changed files with 1100 additions and 0 deletions

View File

@@ -13,5 +13,6 @@ if (WITH_LOAD_FW)
endif (WITH_LOAD_FW)
if (WITH_PROXY_APPS)
add_subdirectory (rpc_demo)
add_subdirectory (linux_rpc_demo)
endif (WITH_PROXY_APPS)
endif (MACHINE MATCHES ".*microblaze.*")

View File

@@ -0,0 +1,47 @@
set (_cflags "${CMAKE_C_FLAGS} ${APP_EXTRA_C_FLAGS}")
set (_fw_dir "${APPS_SHARE_DIR}")
collector_list (_list PROJECT_INC_DIRS)
collector_list (_app_list APP_INC_DIRS)
include_directories (${_list} ${_app_list} ${CMAKE_CURRENT_SOURCE_DIR})
collector_list (_list PROJECT_LIB_DIRS)
collector_list (_app_list APP_LIB_DIRS)
link_directories (${_list} ${_app_list})
get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_LARGE_TEXT_OPT)
if (NOT _linker_opt)
get_property (_linker_opt GLOBAL PROPERTY APP_LINKER_OPT)
endif (NOT _linker_opt)
collector_list (_deps PROJECT_LIB_DEPS)
set (OPENAMP_LIB open_amp)
if (${PROJECT_SYSTEM} STREQUAL "linux")
set (app_list linux_rpc_demod linux_rpc_demo)
endif (${PROJECT_SYSTEM} STREQUAL "linux")
foreach (_app ${app_list})
collector_list (_sources APP_COMMON_SOURCES)
list (APPEND _sources "${CMAKE_CURRENT_SOURCE_DIR}/${_app}.c")
if (WITH_SHARED_LIB)
add_executable (${_app}-shared ${_sources})
target_link_libraries (${_app}-shared ${OPENAMP_LIB}-shared ${_deps})
install (TARGETS ${_app}-shared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif (WITH_SHARED_LIB)
if (WITH_STATIC_LIB)
if (${PROJECT_SYSTEM} STREQUAL "linux")
add_executable (${_app}-static ${_sources})
target_link_libraries (${_app}-static ${OPENAMP_LIB}-static ${_deps})
install (TARGETS ${_app}-static RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
else (${PROJECT_SYSTEM})
add_executable (${_app}.out ${_sources})
set_source_files_properties(${_sources} PROPERTIES COMPILE_FLAGS "${_cflags}")
target_link_libraries(${_app}.out -Wl,-Map=${_app}.map -Wl,--gc-sections ${_linker_opt} -Wl,--start-group ${OPENAMP_LIB}-static ${_deps} -Wl,--end-group)
install (TARGETS ${_app}.out RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif (${PROJECT_SYSTEM} STREQUAL "linux" )
endif (WITH_STATIC_LIB)
endforeach(_app)

View File

@@ -0,0 +1,58 @@
# linux_rpc_demo
This readme is about the OpenAMP linux_rpc_demo.
The linux_rpc_demo is about remote procedure calls between linux master and linux
slave using rpmsg to perform
1. File operations such as open, read, write and close
2. I/O operation such as printf, scanf
## Compilation
### Linux Compilation
* Install libsysfs devel and libhugetlbfs devel packages on your Linux.
* build libmetal library:
```
$ mkdir -p build-libmetal
$ cd build-libmetal
$ cmake <libmetal_source>
$ make VERBOSE=1 DESTDIR=<libmetal_install> install
```
* build OpenAMP library:
```
$ mkdir -p build-openamp
$ cd build-openamp
$ cmake <openamp_source> -DCMAKE_INCLUDE_PATH=<libmetal_built_include_dir> \
-DCMAKE_LIBRARY_PATH=<libmetal_built_lib_dir> -DWITH_APPS=ON -DWITH_PROXY=ON
$ make VERBOSE=1 DESTDIR=$(pwd) install
```
The OpenAMP library will be generated to `build/usr/local/lib` directory, headers will be
generated to `build/usr/local/include` directory, and the applications executable will be
generated to `build/usr/local/bin` directory.
* cmake option `-DWITH_APPS=ON` is to build the demonstration applications.
* cmake option `-DWITH_PROXY=ON` to build the linux rpc app.
## Run the Demo
### linux_rpc_demo:
* Start rpc demo server on one console
```
$ sudo LD_LIBRARY_PATH=<openamp_built>/usr/local/lib:<libmetal_built>/usr/local/lib \
build-openamp/usr/local/bin/linux_rpc_demod-shared
```
* Run rpc demo client on another console to perform file and I/O operations on the server
```
$ sudo LD_LIBRARY_PATH=<openamp_built>/usr/local/lib:<libmetal_built>/usr/local/lib \
build-openamp/usr/local/bin/linux_rpc_demo-shared 1
```
Enter the inputs on the master side the same gets printed on the remote side. You will see communication between the master and remote process using rpmsg calls.
## Note:
`sudo` is required to run the OpenAMP demos between Linux processes, as it doesn't work on
some systems if you are normal users.

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2021, L&T Technology Services Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RPMSG_RPC_DEMO_H
#define RPMSG_RPC_DEMO_H
#define OPEN_ID 0x1UL
#define CLOSE_ID 0x2UL
#define WRITE_ID 0x3UL
#define READ_ID 0x4UL
#define ACK_STATUS_ID 0x5UL
#define TERM_ID 0x6UL
#define INPUT_ID 0x7UL
#define MAX_STRING_LEN 300
#define MAX_FILE_NAME_LEN 10
typedef int (*rpmsg_rpc_poll)(void *arg);
struct polling {
rpmsg_rpc_poll poll;
void *poll_arg;
};
struct rpmsg_rpc_req_open {
char filename[MAX_FILE_NAME_LEN];
int flags;
int mode;
};
struct rpmsg_rpc_req_read {
int fd;
uint32_t buflen;
};
struct rpmsg_rpc_req_input {
uint32_t buflen;
};
struct rpmsg_rpc_req_write {
int fd;
uint32_t len;
char ptr[MAX_STRING_LEN];
};
struct rpmsg_rpc_req_close {
int fd;
};
struct rpmsg_rpc_req_term {
int id;
};
struct rpmsg_rpc_resp_open {
int fd;
};
struct rpmsg_rpc_resp_read {
int bytes_read;
char buf[MAX_STRING_LEN];
};
struct rpmsg_rpc_resp_input {
int bytes_read;
char buf[MAX_STRING_LEN];
};
struct rpmsg_rpc_resp_write {
int bytes_written;
};
struct rpmsg_rpc_resp_close {
int close_ret;
};
#endif /* RPMSG_RPC_DEMO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,316 @@
/*
* Copyright (c) 2021, L&T Technology Services Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*This is a sample demonstration application that showcases usage of proxy
*from the remote core.
*This application is meant to run on the remote CPU running linux.
*This application can print to the master console and perform file I/O through
*rpmsg channels.
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <openamp/open_amp.h>
#include <openamp/rpmsg_rpc_client_server.h>
#include "platform_info.h"
#include "linux-rpmsg-rpc-demo.h"
#define REDEF_O_CREAT 100
#define REDEF_O_EXCL 200
#define REDEF_O_RDONLY 0
#define REDEF_O_WRONLY 1
#define REDEF_O_RDWR 2
#define REDEF_O_APPEND 2000
#define REDEF_O_ACCMODE 3
#define raw_printf(format, ...) printf(format, ##__VA_ARGS__)
#define LPRINTF(format, ...) raw_printf("Master> " format, ##__VA_ARGS__)
#define LPERROR(format, ...) LPRINTF("ERROR: " format, ##__VA_ARGS__)
static void *platform;
static struct rpmsg_device *rpdev;
static struct rpmsg_rpc_svr rpcs;
int request_termination;
int ept_deleted;
void rpmsg_service_server_unbind(struct rpmsg_endpoint *ept)
{
(void)ept;
rpmsg_destroy_ept(&rpcs.ept);
LPRINTF("Endpoint is destroyed\r\n");
ept_deleted = 1;
}
void terminate_rpc_app(void)
{
LPRINTF("Destroying endpoint.\r\n");
if (!ept_deleted)
rpmsg_destroy_ept(&rpcs.ept);
}
void exit_action_handler(int signum)
{
(void)signum;
terminate_rpc_app();
}
void kill_action_handler(int signum)
{
(void)signum;
LPRINTF("RPC service killed !!\r\n");
terminate_rpc_app();
if (rpdev)
platform_release_rpmsg_vdev(rpdev, platform);
if (platform)
platform_cleanup(platform);
}
int rpmsg_handle_open(void *data, struct rpmsg_rpc_svr *rpcs)
{
void *req_ptr = data + MAX_FUNC_ID_LEN;
struct rpmsg_rpc_req_open *rpc_open_req = req_ptr;
char *buf;
struct rpmsg_rpc_resp_open rpc_open_resp;
int payload_size = sizeof(rpc_open_resp);
struct rpmsg_endpoint *ept = &rpcs->ept;
int fd, ret;
if (!rpc_open_req || !ept)
return -EINVAL;
buf = rpc_open_req->filename;
/* Open remote fd */
fd = open(buf, rpc_open_req->flags, rpc_open_req->mode);
/* Construct rpc response */
rpc_open_resp.fd = fd;
/* Transmit rpc response */
ret = rpmsg_rpc_server_send(rpcs, OPEN_ID, RPMSG_RPC_OK, &rpc_open_resp,
payload_size);
return ret > 0 ? 0 : ret;
}
int rpmsg_handle_close(void *data, struct rpmsg_rpc_svr *rpcs)
{
void *req_ptr = data + MAX_FUNC_ID_LEN;
struct rpmsg_rpc_req_close *rpc_close_req = req_ptr;
struct rpmsg_rpc_resp_close rpc_close_resp;
struct rpmsg_endpoint *ept = &rpcs->ept;
int payload_size = sizeof(rpc_close_resp);
int ret;
if (!rpc_close_req || !ept)
return -EINVAL;
/* Close remote fd */
ret = close(rpc_close_req->fd);
/* Construct rpc response */
rpc_close_resp.close_ret = ret;
/* Transmit rpc response */
ret = rpmsg_rpc_server_send(rpcs, CLOSE_ID, RPMSG_RPC_OK,
&rpc_close_resp, payload_size);
return ret > 0 ? 0 : ret;
}
int rpmsg_handle_read(void *data, struct rpmsg_rpc_svr *rpcs)
{
void *req_ptr = data + MAX_FUNC_ID_LEN;
struct rpmsg_rpc_req_read *rpc_read_req = req_ptr;
struct rpmsg_rpc_resp_read rpc_read_resp;
struct rpmsg_endpoint *ept = &rpcs->ept;
unsigned long int bytes_read;
int payload_size = sizeof(rpc_read_resp);
int ret;
if (!rpc_read_req || !ept)
return -EINVAL;
if (rpc_read_req->fd == 0) {
bytes_read = MAX_STRING_LEN;
/* Perform read from fd for large size since this is a
* STD/I request
*/
bytes_read = read(rpc_read_req->fd, rpc_read_resp.buf,
bytes_read);
} else {
/* Perform read from fd */
bytes_read = read(rpc_read_req->fd, rpc_read_resp.buf,
rpc_read_req->buflen);
}
/* Construct rpc response */
rpc_read_resp.bytes_read = bytes_read;
/* Transmit rpc response */
ret = rpmsg_rpc_server_send(rpcs, READ_ID, RPMSG_RPC_OK, &rpc_read_resp,
payload_size);
return ret > 0 ? 0 : ret;
}
int rpmsg_handle_write(void *data, struct rpmsg_rpc_svr *rpcs)
{
void *req_ptr = data + MAX_FUNC_ID_LEN;
struct rpmsg_rpc_req_write *rpc_write_req = req_ptr;
struct rpmsg_rpc_resp_write rpc_write_resp;
struct rpmsg_endpoint *ept = &rpcs->ept;
int payload_size = sizeof(rpc_write_resp);
int bytes_written;
int ret;
if (!rpc_write_req || !ept)
return -EINVAL;
/* Write to remote fd */
bytes_written = write(rpc_write_req->fd, rpc_write_req->ptr,
rpc_write_req->len);
/* Construct rpc response */
rpc_write_resp.bytes_written = bytes_written;
/* Transmit rpc response */
ret = rpmsg_rpc_server_send(rpcs, WRITE_ID, RPMSG_RPC_OK,
&rpc_write_resp, payload_size);
return ret > 0 ? 0 : ret;
}
int rpmsg_handle_input(void *data, struct rpmsg_rpc_svr *rpcs)
{
void *req_ptr = data + MAX_FUNC_ID_LEN;
struct rpmsg_rpc_req_input *rpc_input_req = req_ptr;
struct rpmsg_rpc_resp_input rpc_input_resp;
struct rpmsg_endpoint *ept = &rpcs->ept;
int bytes_read;
int payload_size = sizeof(rpc_input_resp);
int ret;
if (!rpc_input_req || !ept)
return -EINVAL;
/* Input from remote */
scanf("%s", rpc_input_resp.buf);
bytes_read = sizeof(rpc_input_resp.buf);
/* Construct rpc response */
rpc_input_resp.bytes_read = bytes_read;
/* Transmit rpc response */
ret = rpmsg_rpc_server_send(rpcs, INPUT_ID, RPMSG_RPC_OK,
&rpc_input_resp, payload_size);
return ret > 0 ? 0 : ret;
}
int rpmsg_handle_term(void *data, struct rpmsg_rpc_svr *rpcs)
{
void *req_ptr = data + MAX_FUNC_ID_LEN;
struct rpmsg_rpc_req_term *rpc_term_req = req_ptr;
struct rpmsg_endpoint *ept = &rpcs->ept;
printf("Received termination request at id %d from endpoint %s\r\n",
rpc_term_req->id, ept->name);
request_termination = 1;
return 0;
}
/* Service table */
static struct rpmsg_rpc_services rpc_table[] = {
{OPEN_ID, &rpmsg_handle_open },
{READ_ID, &rpmsg_handle_read },
{WRITE_ID, &rpmsg_handle_write },
{CLOSE_ID, &rpmsg_handle_close },
{INPUT_ID, &rpmsg_handle_input },
{TERM_ID, &rpmsg_handle_term }
};
/* Application entry point */
int app(struct rpmsg_device *rdev, void *priv)
{
int ret = 0;
struct sigaction exit_action;
struct sigaction kill_action;
/* Initialize signalling infrastructure */
memset(&exit_action, 0, sizeof(struct sigaction));
memset(&kill_action, 0, sizeof(struct sigaction));
exit_action.sa_handler = exit_action_handler;
kill_action.sa_handler = kill_action_handler;
sigaction(SIGTERM, &exit_action, NULL);
sigaction(SIGINT, &exit_action, NULL);
sigaction(SIGKILL, &kill_action, NULL);
sigaction(SIGHUP, &kill_action, NULL);
/* Initialize RPMSG framework */
LPRINTF("Try to create rpmsg endpoint.\r\n");
ret = rpmsg_rpc_server_init(&rpcs, rdev, rpc_table,
(int)sizeof(rpc_table) / sizeof(
struct rpmsg_rpc_services),
rpmsg_service_server_unbind);
if (ret) {
LPERROR("Failed to create endpoint.\r\n");
return -EINVAL;
}
LPRINTF("Successfully created rpmsg endpoint.\r\n");
while (1) {
platform_poll(priv);
/* we got a shutdown request, exit */
if (ept_deleted || request_termination) {
break;
}
}
LPRINTF("\nRPC service exiting !!\r\n");
terminate_rpc_app();
return ret;
}
int main(int argc, char *argv[])
{
int ret;
LPRINTF("Starting application...\r\n");
/* Initialize platform */
ret = platform_init(argc, argv, &platform);
if (ret) {
LPERROR("Failed to initialize platform.\r\n");
ret = -1;
} else {
rpdev = platform_create_rpmsg_vdev(platform, 0,
VIRTIO_DEV_MASTER,
NULL, NULL);
if (!rpdev) {
LPERROR("Failed to create rpmsg virtio device.\r\n");
ret = -1;
} else {
app(rpdev, platform);
platform_release_rpmsg_vdev(rpdev, platform);
ret = 0;
}
}
LPRINTF("Stopping application...\r\n");
platform_cleanup(platform);
return ret;
}