diff --git a/mcs/openamp_demo/Makefile b/mcs/openamp_demo/Makefile index c293881e76a5ef2fe60478b5a0bbb091f8594671..2e7a8f5c4029dce6c81e571d4faf8618759ab907 100644 --- a/mcs/openamp_demo/Makefile +++ b/mcs/openamp_demo/Makefile @@ -1,11 +1,14 @@ -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: rpmsg_main.o rpmsg_ping.o rpmsg_pty.o + $(CC) -g rpmsg_main.o rpmsg_ping.o rpmsg_pty.o $(SDKTARGETSYSROOT)/usr/lib64/libmetal.so $(SDKTARGETSYSROOT)/usr/lib64/libopen_amp.so $(SDKTARGETSYSROOT)/lib64/libsysfs.so $(SDKTARGETSYSROOT)/lib64/libpthread.so.0 -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 + $(CC) -g -I$(SDKTARGETSYSROOT)/usr/include -c rpmsg_main.c -o rpmsg_main.o rpmsg_ping.o: rpmsg_ping.c rpmsg-internal.h - $(CC) -I$(SDKTARGETSYSROOT)/usr/include -c rpmsg_ping.c -o rpmsg_ping.o + $(CC) -g -I$(SDKTARGETSYSROOT)/usr/include -c rpmsg_ping.c -o rpmsg_ping.o + +rpmsg_pty.o: rpmsg_pty.c + $(CC) -g -I$(SDKTARGETSYSROOT)/usr/include -c rpmsg_pty.c -o rpmsg_pty.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..42c2a4a92a6ca9e530acee33118c4c09027233dd 100644 --- a/mcs/openamp_demo/rpmsg-internal.h +++ b/mcs/openamp_demo/rpmsg-internal.h @@ -24,6 +24,22 @@ #define DEV_CLIENT_OS_AGENT "/dev/cpu_handler" extern char *cpu_id; +extern struct metal_io_region *io; + +struct thread_args { + int fd; + int *pipefd; +}; + +struct remoteproc *platform_create_proc(unsigned int id); +int load_bin(void); +void rpmsg_endpoint_init(void); +int rpmsg_endpoint_app(int fds, int ns_setup); + +void open_pty(int *pfdm, int *pfds); +//void master(int fdm, int pipefd[2]); +void *master(void *arg_list); +//int slave(int fds, int pipefd[2]); +void *slave(void *arg_list); -void rpmsg_app_master(void); #endif diff --git a/mcs/openamp_demo/rpmsg_main.c b/mcs/openamp_demo/rpmsg_main.c index 037ec8e9fbc96a4237ef26e12dd72f865777efef..d67ae703cbe79a7a007f127d19bc33151c640712 100644 --- a/mcs/openamp_demo/rpmsg_main.c +++ b/mcs/openamp_demo/rpmsg_main.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "rpmsg-internal.h" @@ -24,7 +25,20 @@ struct rproc_priv { unsigned int id; }; -static int load_bin(void) +static void cleanup(void) +{ + printf("\nOpenAMP demo ended.\n"); + remoteproc_remove(&rproc_inst); + if (io) + free(io); +} + +static void handler(int sig) +{ + exit(0); +} + +int load_bin(void) { int memfd = open("/dev/mem", O_RDWR); int bin_fd = open(target_binfile, O_RDONLY); @@ -108,7 +122,7 @@ struct remoteproc_ops rproc_ops = { .start = rproc_start, }; -static struct remoteproc *platform_create_proc(unsigned int id) +struct remoteproc *platform_create_proc(unsigned int id) { struct remoteproc *rproc; @@ -122,10 +136,13 @@ static struct remoteproc *platform_create_proc(unsigned int id) int main(int argc, char **argv) { - struct remoteproc *rproc = NULL; - unsigned int id = 1; - int ret; int opt; + int fdm = -1, fds = -1; + pid_t pid; + int pipefd[2]; + pthread_t tidm, tids; + struct thread_args args; + void *retval; while ((opt = getopt(argc, argv, "c:b:t:a:")) != -1) { switch (opt) { @@ -146,28 +163,48 @@ int main(int argc, char **argv) } } - rproc = platform_create_proc(id); - if (!rproc) { - printf("create rproc failed\n"); - return -1; - } + /* Open the master side and the slave side of the PTY */ + open_pty(&fdm, &fds); - ret = load_bin(); - if (ret) { - printf("failed to load client os\n"); - return ret; + /* Create unamed pipe */ + if (pipe(pipefd) < 0) { + perror("pipe"); + return -1; } - ret = remoteproc_start(rproc); - if (ret) { - printf("start processor failed\n"); - return ret; + /* Create the child process */ + if ((pid = fork()) < 0) { + perror("fork"); + return -1; + } else if (pid > 0) { + close(fds); /* Close the slave side of the PTY */ + + args.fd = fdm; + args.pipefd = pipefd; + if (pthread_create(&tidm, NULL, master, (void*)&args) < 0) { //T3 + perror("parent pthread_create"); + exit(1); + } + //printf("This is thread1: %ld, pid:%d\n", pthread_self(), getpid()); //T1 + pthread_join(tidm, NULL); + } else { + /* ctrl+c signal, exit program and do cleanup */ + atexit(cleanup); + signal(SIGINT, handler); + + close(fdm); /* Close the master side of the PTY */ + + args.fd = fds; + args.pipefd = pipefd; + if (pthread_create(&tids, NULL, slave, (void*)&args) < 0) { //T4 + perror("child pthread_create"); + exit(1); + } + //printf("This is thread2: %ld, pid:%d\n", pthread_self(), getpid()); //T2 + pthread_join(tids, &retval); + if (*(int*)retval) + exit(1); } - sleep(5); - printf("start processing OpenAMP demo...\n"); - rpmsg_app_master(); - - 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..722b0853c79d399dddf5a9ca2ffdb0dd2b1ff95a 100644 --- a/mcs/openamp_demo/rpmsg_ping.c +++ b/mcs/openamp_demo/rpmsg_ping.c @@ -18,11 +18,13 @@ static struct virtio_vring_info rvrings[2] = { }; static int g_memfd; -static volatile unsigned int received_data; +volatile unsigned int received_data; static struct virtio_device vdev; static struct rpmsg_virtio_device rvdev; -static struct metal_io_region *io; -static struct virtqueue *vq[2]; +struct metal_io_region *io; +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) { @@ -94,61 +96,11 @@ void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest) rpmsg_service_unbind); } -static unsigned int receive_message(void) -{ - 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); - return cpu_handler_fd; - } - - fds.fd = cpu_handler_fd; - fds.events = POLLIN; - - printf("Master core waiting for messages.... \n"); - while (1) { - ret = poll(&fds, 1, -1); - if (ret < 0) { - printf("poll error.\n"); - close(cpu_handler_fd); - return ret; - } - - if (ret == 0) { - printf("poll time out.\n"); - close(cpu_handler_fd); - return ret; - } - - if (fds.revents & POLLIN) { - printf("Master core receiving messages....\n"); - virtqueue_notification(vq[0]); - break; - } - } - close(cpu_handler_fd); - return received_data; -} - -static int send_message(unsigned int message) -{ - return rpmsg_send(ep, &message, sizeof(message)); -} - 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"); 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); @@ -201,29 +153,68 @@ void rpmsg_app_master(void) free(io); return; } +} + +int rpmsg_endpoint_app(int fds, int ns_setup) +{ + int cpu_handler_fd; + struct pollfd poll_fd[2] = {0}; + + cpu_handler_fd = open(DEV_CLIENT_OS_AGENT, O_RDWR); + if (cpu_handler_fd < 0) { + printf("open %s failed.\n", DEV_CLIENT_OS_AGENT); + return -1; + } + + poll_fd[0].fd = fds; + poll_fd[0].events = POLLIN; + poll_fd[1].fd = cpu_handler_fd; + poll_fd[1].events = POLLIN; + + /* Wait for data from slave side of PTY, and data from endpoint of openamp, blocked */ + if (poll(poll_fd, 2, -1) == -1) { + printf("Error %d on poll()\n", errno); + goto err; + } + + close(cpu_handler_fd); + + /* If data on slave side of PTY */ + if (poll_fd[0].revents & POLLIN) { + char recv_buf[200] = {0}; + unsigned int number; + + poll_fd[0].revents = 0; + if (read(fds, recv_buf, sizeof(recv_buf)) > 0) { + number = atoi(recv_buf); + //printf("Master core sending messages: %d\n", number); + rpmsg_send(ep, &number, sizeof(number)); + } + } - /* 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); + /* If data on endpoint of openamp */ + if (poll_fd[1].revents & POLLIN) { + char send_buf[200] = {0}; + int wc; + + poll_fd[1].revents = 0; + virtqueue_notification(vq[0]); + //printf("Master core receiving messages: %d\n", received_data); + + /* Check whether poll event is ns setup */ + if (ns_setup == 1) + return 0; + + received_data++; + wc = snprintf(send_buf, sizeof(send_buf), "Output number: %d\n", received_data); + if (write(fds, send_buf, wc) == -1) { + printf("Error %d on rpmsg_endpoint_app write()\n", errno); + goto err; + } } -_cleanup: - free(io); - printf("OpenAMP demo ended.\n"); + return 0; +err: + close(cpu_handler_fd); + return -1; } diff --git a/mcs/openamp_demo/rpmsg_pty.c b/mcs/openamp_demo/rpmsg_pty.c new file mode 100644 index 0000000000000000000000000000000000000000..465bb7008b0bef90a1649111ab5412fd51af0f73 --- /dev/null +++ b/mcs/openamp_demo/rpmsg_pty.c @@ -0,0 +1,155 @@ +#define _XOPEN_SOURCE 600 +#define _DEFAULT_SOURCE +#include +#include +#include +#include +#include +#include + +#include + +#include "rpmsg-internal.h" + +void open_pty(int *pfdm, int *pfds) +{ + int rc, 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); + + rc = grantpt(fdm); + if (rc != 0) + printf("Error %d on grantpt()\n", errno); + + rc = unlockpt(fdm); + if (rc != 0) + printf("Error %d on unlockpt()\n", errno); + + /* Open the slave side of the PTY */ + fds = open(ptsname(fdm), O_RDWR | O_NOCTTY); + + *pfdm = fdm; + *pfds = fds; +} + +static void ptmx_read_write(const char *name, int in, int out) +{ + char input[200]; + int rc, ret; + + rc = read(in, input, sizeof(input)); + if (rc == -1) + printf("Error %d on ptmx_read %s\n", errno, name); + + ret = write(out, input, rc); + if (ret == -1) + printf("Error %d on ptmx_write %s\n", errno, name); +} + +//void master(int fdm, int pipefd[2]) +void *master(void *arg_list) +{ + fd_set fd_in; + char buf[50] = {0}; + int nullfd; + struct thread_args *args = (struct thread_args*)arg_list; + + /* Wait for child */ + close(args->pipefd[1]); + while (read(args->pipefd[0], buf, sizeof(buf)) > 0) { + if (strcmp(buf, "init done\n") == 0) + break; + } + + //printf("This is thread3: %ld, pid:%d\n", pthread_self(), getpid()); //T3 + //printf("thread3 fd:%d, pipefd[0]:%d, pipefd[1]:%d\n", args->fd, args->pipefd[0], args->pipefd[1]); + + printf("----------PTY Terminal----------\n"); + printf("Input number: "); + fflush(stdout); + + for (;;) { + /* Wait for data from standard input and master side of PTY */ + FD_ZERO(&fd_in); + FD_SET(0, &fd_in); + FD_SET(args->fd, &fd_in); + + if (select(args->fd + 1, &fd_in, NULL, NULL, NULL) == -1) + printf("Error %d on select()\n", errno); + + /* If data on standard input */ + if (FD_ISSET(0, &fd_in)) { + ptmx_read_write("standard input", 0, args->fd); + + /* flush data to /dev/null on ptmx, avoid printing repeatedly */ + nullfd = open("/dev/null", O_RDWR); + ptmx_read_write("standard input", args->fd, nullfd); + } + + /* If data on master side of PTY */ + if (FD_ISSET(args->fd, &fd_in)) { + ptmx_read_write("master pty", args->fd, 1); + printf("Input number: "); + fflush(stdout); + } + } +} + +//int slave(int fds, int pipefd[2]) +void *slave(void *arg_list) +{ + struct remoteproc *rproc = NULL; + unsigned int id = 1; + int ret; + struct thread_args *args = (struct thread_args*)arg_list; + + //printf("This is thread4: %ld, pid:%d\n", pthread_self(), getpid()); //T4 + //printf("thread4 fd:%d, pipefd[0]:%d, pipefd[1]:%d\n", args->fd, args->pipefd[0], args->pipefd[1]); + + rproc = platform_create_proc(id); + if (!rproc) { + printf("create rproc failed\n"); + return (void*)1; + } + + ret = load_bin(); + if (ret) { + printf("failed to load client os\n"); + return (void*)1; + } + + ret = remoteproc_start(rproc); + if (ret) { + printf("start processor failed\n"); + return (void*)1; + } + + sleep(5); /* wait for clientos booting */ + rpmsg_endpoint_init(); + + /* Since we are using name service, we need to wait for a response + * from NS setup and then we need to process it + */ + rpmsg_endpoint_app(args->fd, 1); + + /* now wake up parent using unamed pipe, init console */ + close(args->pipefd[0]); + ret = write(args->pipefd[1], "init done\n", strlen("init done\n")); + if (ret == -1) { + printf("failed to wake up parent\n"); + return (void*)1; + } + + for (;;) { + ret = rpmsg_endpoint_app(args->fd, 0); + if (ret) { + printf("rpmsg_endpoint_app failed\n"); + return (void*)1; + } + } + + return (void*)0; +}