diff --git a/mcs/openamp_demo/Makefile b/mcs/openamp_demo/Makefile index c293881e76a5ef2fe60478b5a0bbb091f8594671..daccc80d5591eab2a3dc8b9a513e8555ce073c39 100644 --- a/mcs/openamp_demo/Makefile +++ b/mcs/openamp_demo/Makefile @@ -1,5 +1,5 @@ -rpmsg_main: rpmsg_main.o rpmsg_ping.o - $(CC) rpmsg_main.o rpmsg_ping.o $(SDKTARGETSYSROOT)/usr/lib64/libmetal.so $(SDKTARGETSYSROOT)/usr/lib64/libopen_amp.so $(SDKTARGETSYSROOT)/lib64/libsysfs.so -o rpmsg_main +rpmsg_main: clean rpmsg_main.o rpmsg_ping.o rpmsg_app.o + $(CC) rpmsg_main.o rpmsg_ping.o rpmsg_app.o $(SDKTARGETSYSROOT)/usr/lib64/libmetal.so $(SDKTARGETSYSROOT)/usr/lib64/libopen_amp.so $(SDKTARGETSYSROOT)/lib64/libsysfs.so -o rpmsg_main rpmsg_main.o: rpmsg_main.c rpmsg-internal.h $(CC) -I$(SDKTARGETSYSROOT)/usr/include -c rpmsg_main.c -o rpmsg_main.o @@ -7,5 +7,8 @@ rpmsg_main.o: rpmsg_main.c rpmsg-internal.h rpmsg_ping.o: rpmsg_ping.c rpmsg-internal.h $(CC) -I$(SDKTARGETSYSROOT)/usr/include -c rpmsg_ping.c -o rpmsg_ping.o +rpmsg_app.o: rpmsg_ping.c rpmsg-internal.h + $(CC) -I$(SDKTARGETSYSROOT)/usr/include -c rpmsg_app.c -o rpmsg_app.o + clean: rm -rf *.o rpmsg_main diff --git a/mcs/openamp_demo/rpmsg-internal.h b/mcs/openamp_demo/rpmsg-internal.h index ebfde5fbf7248ab013d243ee8b1551b75ea990d4..6e07328ff856366d8586cc257617617eb3ba32d7 100644 --- a/mcs/openamp_demo/rpmsg-internal.h +++ b/mcs/openamp_demo/rpmsg-internal.h @@ -24,6 +24,13 @@ #define DEV_CLIENT_OS_AGENT "/dev/cpu_handler" extern char *cpu_id; +extern struct metal_io_region *io; + +void rpmsg_endpoint_init(void); +int receive_message(unsigned char *message, int message_len, int *real_len); +int send_message(unsigned char *message, int len); + +void *shell_user(void *arg); +void *log_user(void *arg); -void rpmsg_app_master(void); #endif diff --git a/mcs/openamp_demo/rpmsg_app.c b/mcs/openamp_demo/rpmsg_app.c new file mode 100644 index 0000000000000000000000000000000000000000..749603ff4a6ba1a9cfbc4062d60c479525613a0c --- /dev/null +++ b/mcs/openamp_demo/rpmsg_app.c @@ -0,0 +1,170 @@ +#define _XOPEN_SOURCE 600 +#include +#include +#include +#include +#include +#include + +#include "rpmsg-internal.h" + +/* define the keys according to your terminfo */ +#define KEY_CTRL_C 3 +#define KEY_BACKSPACE 127 +#define KEY_ENTER '\r' + +void open_pty(int *pfdm, int *pfds) +{ + int ret; + int fdm, fds; + + /* Open the master side of the PTY */ + fdm = posix_openpt(O_RDWR | O_NOCTTY); + if (fdm < 0) + printf("Error %d on posix_openpt()\n", errno); + + ret = grantpt(fdm); + if (ret != 0) + printf("Error %d on grantpt()\n", errno); + + ret = unlockpt(fdm); + if (ret != 0) + printf("Error %d on unlockpt()\n", errno); + + /* Open the slave side of the PTY */ + fds = open(ptsname(fdm), O_RDWR | O_NOCTTY); + printf("open a new terminal, exec zephyr shell: screen %s\n", ptsname(fdm)); + + *pfdm = fdm; + *pfds = fds; +} + +int simple_shell(int fdm, unsigned char *cmd, int cmd_len, int *real_len) +{ + int i; + int ret; + char display[64] = "\ruart:~$ "; + const int title_len = strlen(display); + int dislen = strlen(display); + int dislen_echo; + + memset(cmd, 0, cmd_len); + for (i = 0; i < cmd_len; i++) { + ret = read(fdm, &cmd[i], 1); + + display[dislen] = cmd[i]; + dislen++; + dislen_echo = dislen; + + if (cmd[i] == KEY_CTRL_C) { /* special key: ctrl+c */ + pthread_exit(NULL); + } + + if ((cmd[i] == KEY_BACKSPACE) && (dislen > title_len)) { /* special key: backspace */ + dislen -= 2; + display[dislen] = ' '; + dislen_echo = dislen + 1; + } + + if (cmd[i] == KEY_ENTER) { /* special key: enter */ + cmd[i] = '\n'; + break; + } + + ret = write(fdm, display, dislen_echo); /* the command echo */ + } + + ret = write(fdm, "\ruart:~$ ", title_len); /* override the command return from rtos */ + *real_len = i + 1; + return ret; +} + +void *shell_user(void *arg) +{ + int ret; + int fdm, fds; + unsigned char cmd[64] = {0}; + int cmd_len; + unsigned char reply[2048] = {0}; + int reply_len; + + /* open PTY, pts binds to terminal, using screen to open pts */ + open_pty(&fdm, &fds); + + while (1) { + ret = simple_shell(fdm, cmd, sizeof(cmd), &cmd_len); /* get command from ptmx */ + if (ret < 0) { + printf("shell_user: simple_shell(%s) failed: %d\n", cmd, ret); + return (void*)-1; + } + + ret = send_message(cmd, cmd_len); /* send command to rtos */ + if (ret < 0) { + printf("shell_user: send_message(%s) failed: %d\n", cmd, ret); + return (void*)-1; + } + + ret = receive_message(reply, sizeof(reply), &reply_len); /* receive reply from rtos */ + if (ret < 0) { + printf("shell_user: receive_message(%s) failed: %d\n", reply, ret); + return (void*)-1; + } + + ret = write(fdm, reply, reply_len); /* send reply to ptmx */ + if (ret < 0) { + printf("shell_user: write to ptmx(%s) failed: %d\n", reply, ret); + return (void*)-1; + } + } + + return (void*)0; +} + +void *log_user(void *arg) +{ + int ret; + int cmd_fd, log_fd; + unsigned char cmd[64] = {0}; + int cmd_len; + unsigned char log[2048] = {0}; + int log_len; + const char *cmd_file = "/tmp/zephyr_cmd.txt"; + const char *log_file = "/tmp/zephyr_log.txt"; + + /* read command from file */ + cmd_fd = open(cmd_file, O_RDONLY); + if (cmd_fd < 0) { + printf("log_user: open (%s) failed: %d\n", cmd_file, cmd_fd); + return (void*)-1; + } + cmd_len = read(cmd_fd, cmd, sizeof(cmd)); + cmd[cmd_len] = '\n'; + close(cmd_fd); + + ret = send_message(cmd, cmd_len + 1); /* send command to rtos */ + if (ret < 0) { + printf("shell_user: send_message(%s) failed: %d\n", cmd, ret); + return (void*)-1; + } + + ret = receive_message(log, sizeof(log), &log_len); /* receive log from rtos */ + if (ret < 0) { + printf("log_user: receive_message(%s) failed: %d\n", log, ret); + return (void*)-1; + } + + /* write log into file */ + log_fd = open(log_file, O_RDWR | O_CREAT | O_APPEND, 0644); + if (log_fd < 0) { + printf("log_user: open (%s) failed: %d\n", log_file, log_fd); + return (void*)-1; + } + ret = write(log_fd, log, log_len); + if (ret < 0) { + printf("log_user: write to file(%s) failed: %d\n", log_file, ret); + return (void*)-1; + } + close(log_fd); + + return (void*)0; +} diff --git a/mcs/openamp_demo/rpmsg_main.c b/mcs/openamp_demo/rpmsg_main.c index 037ec8e9fbc96a4237ef26e12dd72f865777efef..a95d031121b4f1ba6cde1293369bf416e109c30b 100644 --- a/mcs/openamp_demo/rpmsg_main.c +++ b/mcs/openamp_demo/rpmsg_main.c @@ -8,7 +8,6 @@ #include "rpmsg-internal.h" -#define MAX_BIN_BUFLEN (10 * 1024 * 1024) #define BOOTCMD_MAXSIZE 100 static struct remoteproc rproc_inst; @@ -16,48 +15,28 @@ static struct remoteproc_ops ops; char *cpu_id; static char *boot_address; -static char *target_binfile; -static char *target_binaddr; struct rproc_priv { struct remoteproc *rproc; unsigned int id; }; -static int load_bin(void) +static void cleanup(void) { - int memfd = open("/dev/mem", O_RDWR); - int bin_fd = open(target_binfile, O_RDONLY); - void *access_address = NULL, *bin_buffer = NULL; - long bin_size; - long long int bin_addr = strtoll(target_binaddr, NULL, 0); - - if (bin_fd < 0 || memfd < 0) { - printf("invalid bin file fd\n"); - exit(-1); - } - - bin_buffer = (void *)malloc(MAX_BIN_BUFLEN); - if (!bin_buffer) { - printf("malloc bin_buffer failed\n"); - exit(-1); - } - - bin_size = read(bin_fd, bin_buffer, MAX_BIN_BUFLEN); - if (bin_size == 0) { - printf("read bin file failed\n"); - exit(-1); - } + printf("\nOpenAMP demo ended.\n"); + remoteproc_stop(&rproc_inst); + remoteproc_remove(&rproc_inst); + if (io) + free(io); +} - access_address = mmap((void *)bin_addr, MAX_BIN_BUFLEN, PROT_READ | PROT_WRITE, - MAP_SHARED, memfd, bin_addr); - memcpy(access_address, bin_buffer, bin_size); - free(bin_buffer); - return 0; +static void handler(int sig) +{ + exit(0); } static struct remoteproc *rproc_init(struct remoteproc *rproc, - struct remoteproc_ops *ops, void *arg) + const struct remoteproc_ops *ops, void *arg) { struct rproc_priv *priv; unsigned int id = *((unsigned int *)arg); @@ -94,6 +73,16 @@ static int rproc_start(struct remoteproc *rproc) return 0; } +static int rproc_stop(struct remoteproc *rproc) +{ +#if 0 + /* send message to zephyr, zephyr shut itself down by PSCI */ + int ret = send_message("shutdown\r\n", 10); + sleep(3); +#endif + return 0; +} + static void rproc_remove(struct remoteproc *rproc) { struct rproc_priv *priv; @@ -106,6 +95,7 @@ struct remoteproc_ops rproc_ops = { .init = rproc_init, .remove = rproc_remove, .start = rproc_start, + .stop = rproc_stop, }; static struct remoteproc *platform_create_proc(unsigned int id) @@ -126,8 +116,15 @@ int main(int argc, char **argv) unsigned int id = 1; int ret; int opt; + pthread_t tida, tidb, tidc; + void *reta, *retb, *retc; - while ((opt = getopt(argc, argv, "c:b:t:a:")) != -1) { + /* ctrl+c signal, exit program and do cleanup */ + atexit(cleanup); + signal(SIGINT, handler); + + /* using qemu arg: -device loader,file=zephyr.elf,cpu-num=1 */ + while ((opt = getopt(argc, argv, "c:b:")) != -1) { switch (opt) { case 'c': cpu_id = optarg; @@ -135,12 +132,6 @@ int main(int argc, char **argv) case 'b': boot_address = optarg; break; - case 't': - target_binfile = optarg; - break; - case 'a': - target_binaddr = optarg; - break; default: break; } @@ -152,12 +143,6 @@ int main(int argc, char **argv) return -1; } - ret = load_bin(); - if (ret) { - printf("failed to load client os\n"); - return ret; - } - ret = remoteproc_start(rproc); if (ret) { printf("start processor failed\n"); @@ -166,8 +151,43 @@ int main(int argc, char **argv) sleep(5); printf("start processing OpenAMP demo...\n"); - rpmsg_app_master(); + rpmsg_endpoint_init(); + + /* Multi-thread processing user requests */ + printf("Multi-thread processing user requests...\n"); + + /* userA: user shell, open with screen */ + if (pthread_create(&tida, NULL, shell_user, NULL) < 0) { + perror("userA pthread_create"); + return -1; + } +#if 0 + /* userB: dual user shell, open with screen */ + if (pthread_create(&tidb, NULL, shell_user, NULL) < 0) { + perror("userB pthread_create"); + return -1; + } +#endif + /* userC: zephyr log */ + if (pthread_create(&tidc, NULL, log_user, NULL) < 0) { + perror("userC pthread_create"); + return -1; + } + + pthread_join(tida, &reta); + if ((long)reta) { + printf("userA return failed: %ld", (long)reta); + } +#if 0 + pthread_join(tidb, &retb); + if ((long)retb) { + printf("userB return failed: %ld", (long)retb); + } +#endif + pthread_join(tidc, &retc); + if ((long)retc) { + printf("userC return failed: %ld", (long)retc); + } - remoteproc_remove(rproc); - return ret; + return 0; } diff --git a/mcs/openamp_demo/rpmsg_ping.c b/mcs/openamp_demo/rpmsg_ping.c index 6cea999abbefa3aa2b4ad203511ade24a4f75792..ff9b1135cbc0469f93df9e9c9b490b4cb7f14de6 100644 --- a/mcs/openamp_demo/rpmsg_ping.c +++ b/mcs/openamp_demo/rpmsg_ping.c @@ -18,11 +18,14 @@ static struct virtio_vring_info rvrings[2] = { }; static int g_memfd; -static volatile unsigned int received_data; +static unsigned char received_data[2048] = {0}; +static unsigned int received_len = 0; static struct virtio_device vdev; static struct rpmsg_virtio_device rvdev; -static struct metal_io_region *io; +struct metal_io_region *io; static struct virtqueue *vq[2]; +static void *tx_addr, *rx_addr, *shm_start_addr; +static metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR }; static unsigned char virtio_get_status(struct virtio_device *vdev) { @@ -73,7 +76,9 @@ struct virtio_dispatch dispatch = { int endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) { - received_data = *((unsigned int *) data); + memcpy(received_data + received_len, data, len); + received_len += len; + return RPMSG_SUCCESS; } @@ -94,61 +99,71 @@ void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest) rpmsg_service_unbind); } -static unsigned int receive_message(void) +/* message standard receive interface */ +int receive_message(unsigned char *message, int message_len, int *real_len) { + int ret = -1; int cpu_handler_fd; struct pollfd fds; - int ret; - + cpu_handler_fd = open(DEV_CLIENT_OS_AGENT, O_RDWR); if (cpu_handler_fd < 0) { - printf("open %s failed.\n", DEV_CLIENT_OS_AGENT); + printf("receive_message: open %s failed.\n", DEV_CLIENT_OS_AGENT); return cpu_handler_fd; } - + fds.fd = cpu_handler_fd; fds.events = POLLIN; - - printf("Master core waiting for messages.... \n"); + + /* clear the receive buffer */ + memset(received_data, 0, sizeof(received_data)); + received_len = 0; + while (1) { - ret = poll(&fds, 1, -1); + ret = poll(&fds, 1, 100); /* 100ms timeout */ if (ret < 0) { - printf("poll error.\n"); - close(cpu_handler_fd); - return ret; + printf("receive_message: poll failed.\n"); + *real_len = 0; + goto _cleanup; } - + if (ret == 0) { - printf("poll time out.\n"); - close(cpu_handler_fd); - return ret; + break; } - + if (fds.revents & POLLIN) { - printf("Master core receiving messages....\n"); - virtqueue_notification(vq[0]); - break; + virtqueue_notification(vq[0]); /* will call endpoint_cb */ } } + + if (received_len >= message_len) { + printf("receive_message: buffer is too small.\n"); + *real_len = 0; + goto _cleanup; + } + + memset(message, 0, message_len); + memcpy(message, received_data, received_len); + *real_len = received_len; + +_cleanup: close(cpu_handler_fd); - return received_data; + return ret; } -static int send_message(unsigned int message) +/* message standard send interface */ +int send_message(unsigned char *message, int len) { - return rpmsg_send(ep, &message, sizeof(message)); + return rpmsg_send(ep, message, len); } static struct rpmsg_virtio_shm_pool shpool; -void rpmsg_app_master(void) +void rpmsg_endpoint_init(void) { int status = 0; - unsigned int message = 0U; - void *tx_addr, *rx_addr, *shm_start_addr; - metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR }; - - printf("\r\nOpenAMP[master] demo started\r\n"); + char message[100] = {0}; + int len; g_memfd = open("/dev/mem", O_RDWR); tx_addr = mmap((void *)VRING_TX_ADDRESS, VDEV_STATUS_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, g_memfd, VRING_TX_ADDRESS); @@ -176,7 +191,7 @@ void rpmsg_app_master(void) return; } - vdev.role = RPMSG_MASTER; + vdev.role = RPMSG_HOST; vdev.vrings_num = VRING_COUNT; vdev.func = &dispatch; rvrings[0].io = io; @@ -205,25 +220,5 @@ void rpmsg_app_master(void) /* Since we are using name service, we need to wait for a response * from NS setup and than we need to process it */ - receive_message(); - - while (message < 99) { - status = send_message(message); - if (status < 0) { - printf("send_message(%u) failed with status %d\n", - message, status); - goto _cleanup; - } - - sleep(1); - message = receive_message(); - printf("Master core received a message: %u\n", message); - - message++; - sleep(1); - } - -_cleanup: - free(io); - printf("OpenAMP demo ended.\n"); + (void)receive_message(message, sizeof(message), &len); } diff --git a/mcs/zephyr/zephyr.bin b/mcs/zephyr/zephyr.bin deleted file mode 100644 index 585dd2d37f30ff057677080ce98ed06fb1b0c2ae..0000000000000000000000000000000000000000 Binary files a/mcs/zephyr/zephyr.bin and /dev/null differ diff --git a/mcs/zephyr/zephyr.elf b/mcs/zephyr/zephyr.elf new file mode 100755 index 0000000000000000000000000000000000000000..c7145bc26b204e3f2a0193a7a37ee02490b76c85 Binary files /dev/null and b/mcs/zephyr/zephyr.elf differ