From 2ed0710445b2496dcca365dee2cbdc339656535e Mon Sep 17 00:00:00 2001 From: Luoject <13113951796@163.com> Date: Tue, 7 Jun 2022 20:25:56 +0800 Subject: [PATCH 1/2] add resource table parsing for openamp_demo --- mcs/openamp_demo/Makefile | 13 +- mcs/openamp_demo/rpmsg-internal.h | 12 +- mcs/openamp_demo/rpmsg_main.c | 93 ++-------- mcs/openamp_demo/rpmsg_ping.c | 47 +++-- mcs/openamp_demo/rproc_rsc.c | 274 ++++++++++++++++++++++++++++++ 5 files changed, 332 insertions(+), 107 deletions(-) create mode 100644 mcs/openamp_demo/rproc_rsc.c diff --git a/mcs/openamp_demo/Makefile b/mcs/openamp_demo/Makefile index c293881e..67c52b23 100644 --- a/mcs/openamp_demo/Makefile +++ b/mcs/openamp_demo/Makefile @@ -1,11 +1,16 @@ -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 rproc_rsc.o + $(CC) -g rpmsg_main.o rpmsg_ping.o rproc_rsc.o $(SDKTARGETSYSROOT)/usr/lib64/libmetal.so $(SDKTARGETSYSROOT)/usr/lib64/libopen_amp.so $(SDKTARGETSYSROOT)/lib64/libsysfs.so -o rpmsg_main + #$(LD) --verbose > rproc_rsc.ld + #-T rproc_rsc.ld 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 + +rproc_rsc.o: rproc_rsc.c rpmsg-internal.h + $(CC) -g -I$(SDKTARGETSYSROOT)/usr/include -c rproc_rsc.c -o rproc_rsc.o clean: rm -rf *.o rpmsg_main diff --git a/mcs/openamp_demo/rpmsg-internal.h b/mcs/openamp_demo/rpmsg-internal.h index ebfde5fb..41d71b5b 100644 --- a/mcs/openamp_demo/rpmsg-internal.h +++ b/mcs/openamp_demo/rpmsg-internal.h @@ -20,10 +20,20 @@ #define VRING_ALIGNMENT 4 #define VRING_SIZE 16 +#define RSC_TABLE_ADDR 0x71000000 + #define IRQ_SENDTO_CLIENTOS _IOW('A', 0, int) #define DEV_CLIENT_OS_AGENT "/dev/cpu_handler" extern char *cpu_id; +extern char *boot_address; +extern volatile unsigned int received_data; +extern struct rpmsg_endpoint *ep; + +struct remoteproc *platform_create_proc(unsigned int id); +struct rpmsg_device *platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, + unsigned int role, void (*rst_cb)(struct virtio_device *vdev), rpmsg_ns_bind_cb ns_bind_cb); -void rpmsg_app_master(void); +void rpmsg_app_master(struct remoteproc *rproc); #endif + diff --git a/mcs/openamp_demo/rpmsg_main.c b/mcs/openamp_demo/rpmsg_main.c index 037ec8e9..1c7e004c 100644 --- a/mcs/openamp_demo/rpmsg_main.c +++ b/mcs/openamp_demo/rpmsg_main.c @@ -9,21 +9,12 @@ #include "rpmsg-internal.h" #define MAX_BIN_BUFLEN (10 * 1024 * 1024) -#define BOOTCMD_MAXSIZE 100 - -static struct remoteproc rproc_inst; -static struct remoteproc_ops ops; char *cpu_id; -static char *boot_address; +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) { int memfd = open("/dev/mem", O_RDWR); @@ -56,77 +47,14 @@ static int load_bin(void) return 0; } -static struct remoteproc *rproc_init(struct remoteproc *rproc, - struct remoteproc_ops *ops, void *arg) -{ - struct rproc_priv *priv; - unsigned int id = *((unsigned int *)arg); - - priv = metal_allocate_memory(sizeof(*priv)); - if (!priv) - return NULL; - - memset(priv, 0, sizeof(*priv)); - priv->rproc = rproc; - priv->id = id; - priv->rproc->ops = ops; - metal_list_init(&priv->rproc->mems); - priv->rproc->priv = priv; - rproc->state = RPROC_READY; - return priv->rproc; -} - -static int rproc_start(struct remoteproc *rproc) -{ - int cpu_handler_fd; - int ret; - char on[BOOTCMD_MAXSIZE]; - - (void)snprintf(on, sizeof(on), "%s%s%s", cpu_id, "@", boot_address); - - cpu_handler_fd = open(DEV_CLIENT_OS_AGENT, O_RDWR); - if (cpu_handler_fd < 0) { - printf("failed to open %s\n", DEV_CLIENT_OS_AGENT); - return cpu_handler_fd; - } - - ret = write(cpu_handler_fd, on, sizeof(on)); - return 0; -} - -static void rproc_remove(struct remoteproc *rproc) -{ - struct rproc_priv *priv; - - priv = (struct rproc_priv *)rproc->priv; - metal_free_memory(priv); -} - -struct remoteproc_ops rproc_ops = { - .init = rproc_init, - .remove = rproc_remove, - .start = rproc_start, -}; - -static struct remoteproc *platform_create_proc(unsigned int id) -{ - struct remoteproc *rproc; - - ops = rproc_ops; - rproc = remoteproc_init(&rproc_inst, &ops, &id); - if (!rproc) - return NULL; - - return &rproc_inst; -} - int main(int argc, char **argv) { struct remoteproc *rproc = NULL; + struct rpmsg_device *rdev = NULL; unsigned int id = 1; int ret; int opt; - +#if 0 while ((opt = getopt(argc, argv, "c:b:t:a:")) != -1) { switch (opt) { case 'c': @@ -145,6 +73,11 @@ int main(int argc, char **argv) break; } } +#endif + cpu_id = "3"; + boot_address = "0x7a000ffc"; + target_binfile = "zephyr.bin"; + target_binaddr = "0x7a000000"; rproc = platform_create_proc(id); if (!rproc) { @@ -163,10 +96,16 @@ int main(int argc, char **argv) printf("start processor failed\n"); return ret; } - sleep(5); printf("start processing OpenAMP demo...\n"); - rpmsg_app_master(); +#if 0 + rdev = platform_create_rpmsg_vdev(rproc, 0, VIRTIO_DEV_MASTER, NULL, ns_bind_cb); + if (ret) { + printf("create rpmsg vdev failed\n"); + return ret; + } +#endif + rpmsg_app_master(rproc); remoteproc_remove(rproc); return ret; diff --git a/mcs/openamp_demo/rpmsg_ping.c b/mcs/openamp_demo/rpmsg_ping.c index 6cea999a..ba3b07af 100644 --- a/mcs/openamp_demo/rpmsg_ping.c +++ b/mcs/openamp_demo/rpmsg_ping.c @@ -18,10 +18,9 @@ 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]; static unsigned char virtio_get_status(struct virtio_device *vdev) @@ -70,6 +69,10 @@ struct virtio_dispatch dispatch = { .notify = virtio_notify, }; +/* NAME SERVICE CALLBACK */ +struct rpmsg_endpoint my_ept; +struct rpmsg_endpoint *ep = &my_ept; + int endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) { @@ -77,9 +80,6 @@ int endpoint_cb(struct rpmsg_endpoint *ept, void *data, return RPMSG_SUCCESS; } -struct rpmsg_endpoint my_ept; -struct rpmsg_endpoint *ep = &my_ept; - static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) { (void)ept; @@ -94,7 +94,7 @@ void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest) rpmsg_service_unbind); } -static unsigned int receive_message(void) +static unsigned int receive_message(struct remoteproc *rproc) { int cpu_handler_fd; struct pollfd fds; @@ -141,11 +141,11 @@ static int send_message(unsigned int message) static struct rpmsg_virtio_shm_pool shpool; -void rpmsg_app_master(void) +void rpmsg_app_master(struct remoteproc *rproc) { int status = 0; unsigned int message = 0U; - void *tx_addr, *rx_addr, *shm_start_addr; + void *tx_addr, *rx_addr; metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR }; printf("\r\nOpenAMP[master] demo started\r\n"); @@ -153,39 +153,36 @@ void rpmsg_app_master(void) 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); rx_addr = mmap((void *)VRING_RX_ADDRESS, VDEV_STATUS_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, g_memfd, VRING_RX_ADDRESS); - shm_start_addr = mmap((void *)SHM_START_ADDR, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, g_memfd, SHM_START_ADDR); - io = malloc(sizeof(struct metal_io_region)); - if (!io) { - printf("malloc io failed\n"); + void *shbuf; + struct metal_io_region *shbuf_io; + shbuf_io = remoteproc_get_io_with_pa(rproc, SHM_START_ADDR); + if (!shbuf_io) return; - } - metal_io_init(io, shm_start_addr, shm_physmap, SHM_SIZE, -1, 0, NULL); + shbuf = metal_io_phys_to_virt(shbuf_io, SHM_START_ADDR); /* setup vdev */ vq[0] = virtqueue_allocate(VRING_SIZE); if (vq[0] == NULL) { printf("virtqueue_allocate failed to alloc vq[0]\n"); - free(io); return; } vq[1] = virtqueue_allocate(VRING_SIZE); if (vq[1] == NULL) { printf("virtqueue_allocate failed to alloc vq[1]\n"); - free(io); return; } vdev.role = RPMSG_MASTER; vdev.vrings_num = VRING_COUNT; vdev.func = &dispatch; - rvrings[0].io = io; + rvrings[0].io = shbuf_io; rvrings[0].info.vaddr = tx_addr; rvrings[0].info.num_descs = VRING_SIZE; rvrings[0].info.align = VRING_ALIGNMENT; rvrings[0].vq = vq[0]; - rvrings[1].io = io; + rvrings[1].io = shbuf_io; rvrings[1].info.vaddr = rx_addr; rvrings[1].info.num_descs = VRING_SIZE; rvrings[1].info.align = VRING_ALIGNMENT; @@ -193,19 +190,20 @@ void rpmsg_app_master(void) vdev.vrings_info = &rvrings[0]; - /* setup rvdev */ - rpmsg_virtio_init_shm_pool(&shpool, shm_start_addr, SHM_SIZE); - status = rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, io, &shpool); + printf("initializing rpmsg shared buffer pool\r\n"); + /* Only RPMsg virtio master needs to initialize the shared buffers pool */ + rpmsg_virtio_init_shm_pool(&shpool, shbuf, SHM_SIZE); + + status = rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, shbuf_io, &shpool); if (status != 0) { printf("rpmsg_init_vdev failed %d\n", status); - free(io); return; } /* 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(); + receive_message(rproc); while (message < 99) { status = send_message(message); @@ -216,7 +214,7 @@ void rpmsg_app_master(void) } sleep(1); - message = receive_message(); + message = receive_message(rproc); printf("Master core received a message: %u\n", message); message++; @@ -224,6 +222,5 @@ void rpmsg_app_master(void) } _cleanup: - free(io); printf("OpenAMP demo ended.\n"); } diff --git a/mcs/openamp_demo/rproc_rsc.c b/mcs/openamp_demo/rproc_rsc.c new file mode 100644 index 00000000..fde06b54 --- /dev/null +++ b/mcs/openamp_demo/rproc_rsc.c @@ -0,0 +1,274 @@ +#include +#include +#include +#include + +#include "rpmsg-internal.h" + +#define BOOTCMD_MAXSIZE 100 + +struct rproc_priv { + struct remoteproc *rproc; + unsigned int id; +}; + +static struct remoteproc *rproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *arg) +{ + struct rproc_priv *priv; + unsigned int id = *((unsigned int *)arg); + + priv = metal_allocate_memory(sizeof(*priv)); + if (!priv) + return NULL; + + memset(priv, 0, sizeof(*priv)); + priv->rproc = rproc; + priv->id = id; + priv->rproc->ops = ops; + metal_list_init(&priv->rproc->mems); + priv->rproc->priv = priv; + rproc->state = RPROC_READY; + return priv->rproc; +} + +static int rproc_start(struct remoteproc *rproc) +{ + int cpu_handler_fd; + int ret; + char on[BOOTCMD_MAXSIZE]; + + (void)snprintf(on, sizeof(on), "%s%s%s", cpu_id, "@", boot_address); + + cpu_handler_fd = open(DEV_CLIENT_OS_AGENT, O_RDWR); + if (cpu_handler_fd < 0) { + printf("failed to open %s\n", DEV_CLIENT_OS_AGENT); + return cpu_handler_fd; + } + + ret = write(cpu_handler_fd, on, sizeof(on)); + return 0; +} + +static void rproc_remove(struct remoteproc *rproc) +{ + struct rproc_priv *priv; + + priv = (struct rproc_priv *)rproc->priv; + metal_free_memory(priv); +} + +void *rproc_mmap(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io) +{ + struct remoteproc_mem *mem; + struct metal_io_region *tmpio; + + if (*pa == METAL_BAD_PHYS && *da == METAL_BAD_PHYS) + return NULL; + if (*pa == METAL_BAD_PHYS) + *pa = *da; + if (*da == METAL_BAD_PHYS) + *da = *pa; + + mem = metal_allocate_memory(sizeof(*mem)); + if (!mem) + return NULL; + tmpio = metal_allocate_memory(sizeof(*tmpio)); + if (!tmpio) { + metal_free_memory(mem); + return NULL; + } + + /* mmap pa to va */ + int memfd; + void *va; + memfd = open("/dev/mem", O_RDWR); + va = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, *pa); + if (va == NULL) + return NULL; + perror("mmap"); + + remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio); + metal_io_init(tmpio, va, &mem->pa, size, -1, attribute, NULL); /* metal io manage va and pa */ + remoteproc_add_mem(rproc, mem); + if (io) + *io = tmpio; + + printf("%s: pa=0x%lx, da=0x%lx, size=0x%lx, attribute=0x%x, va=%p, io=%p, rproc=%p.\r\n", + __func__, *pa, *da, size, attribute, va, tmpio, rproc); + + return metal_io_phys_to_virt(tmpio, mem->pa); +} + +int rproc_notify(struct remoteproc *rproc, uint32_t id) +{ +#if 0 + int cpu_handler_fd; + int ret; + int cpu_num = strtol(cpu_id, NULL, 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; + } + + ret = ioctl(cpu_handler_fd, IRQ_SENDTO_CLIENTOS, cpu_num); + if (ret) { + printf("send ipi tp second os failed\n"); + } + + close(cpu_handler_fd); +#endif + return 0; +} + +struct remoteproc_ops rproc_ops = { + .init = rproc_init, + .remove = rproc_remove, + .start = rproc_start, + .mmap = rproc_mmap, + .notify = rproc_notify, +}; + +static struct remoteproc rproc_inst; + +struct mem_file { + char* base; /* store image base address */ +}; + +#define IMAGE_MAX_LEN (1024 * 1024) +char img_buffer[IMAGE_MAX_LEN] = { 0 }; + +int mem_image_open(void *store, const char *path, const void **image_data) +{ + int fd; + long img_size; + struct mem_file *image = store; + + fd = open(path, O_RDONLY); + if (fd < 0) { + printf("open %s failed.\r\n", path); + perror("open error"); + return -1; + } + + img_size = read(fd, img_buffer, IMAGE_MAX_LEN); + if (img_size <= 0) { + printf("read %s failed.\r\n", path); + perror("read error"); + return -1; + } + + *image_data = img_buffer; + image->base = img_buffer; + + printf("open image %s successfully.\r\n", path); + return img_size; +} + +void mem_image_close(void *store) +{ + return; +} + +int mem_image_load(void *store, size_t offset, size_t size, const void **data, metal_phys_addr_t pa, struct metal_io_region *io, char is_blcoking) +{ + struct mem_file *image = store; + void *va; + + if (pa == METAL_BAD_PHYS) { + if (data == NULL) + return -1; + *data = (const void*)((const char*)(image->base) + offset); + } else { + if (io == NULL) + return -1; + va = metal_io_phys_to_virt(io, pa); + if (va == NULL) + return -1; + memcpy(va, (const void*)((const char*)(image->base) + offset), size); + } + + printf("mem_image_load exec successfully. base:%p, offset:0x%x, size:0x%x, data:%p, pa:0x%x, io:%p, va:%p.\r\n", + image->base, (int)offset, (int)size, *data, (unsigned int)pa, io, va); + return (int)size; +} + +struct image_store_ops mem_image_store_ops = { + .open = mem_image_open, + .close = mem_image_close, + .load = mem_image_load, + .features = SUPPORT_SEEK, +}; + +struct remoteproc *platform_create_proc(unsigned int id) +{ + int ret; + struct mem_file image; + + /* Initialize remoteproc instance */ + if (!remoteproc_init(&rproc_inst, &rproc_ops, &id)) + return NULL; + + /* load elf firmware: resource table */ + remoteproc_config(&rproc_inst, NULL); + ret = remoteproc_load(&rproc_inst, "rsc_elf.elf", &image, &mem_image_store_ops, NULL); + if (ret) { + printf("failed to load firmware.\r\n"); + return NULL; + } + + printf("Initialize remoteproc successfully.\r\n"); + + return &rproc_inst; +} + +struct rpmsg_device *platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, + unsigned int role, void (*rst_cb)(struct virtio_device *vdev), rpmsg_ns_bind_cb ns_bind_cb) +{ + struct remoteproc *rproc = platform; + struct rpmsg_virtio_device *rpmsg_vdev; + struct virtio_device *vdev; + void *shbuf; + struct metal_io_region *shbuf_io; + int ret; + struct rpmsg_virtio_shm_pool shpool; + + rpmsg_vdev = metal_allocate_memory(sizeof(*rpmsg_vdev)); + if (!rpmsg_vdev) + return NULL; + shbuf_io = remoteproc_get_io_with_pa(rproc, SHM_START_ADDR); + if (!shbuf_io) + goto err1; + shbuf = metal_io_phys_to_virt(shbuf_io, SHM_START_ADDR); + + printf("creating remoteproc virtio\r\n"); + vdev = remoteproc_create_virtio(rproc, vdev_index, role, rst_cb); + if (!vdev) { + printf("failed remoteproc_create_virtio\r\n"); + goto err1; + } + + printf("initializing rpmsg shared buffer pool\r\n"); + /* Only RPMsg virtio master needs to initialize the shared buffers pool */ + rpmsg_virtio_init_shm_pool(&shpool, shbuf, SHM_SIZE); + + printf("initializing rpmsg vdev\r\n"); + /* RPMsg virtio slave can set shared buffers pool argument to NULL */ + ret = rpmsg_init_vdev(rpmsg_vdev, vdev, ns_bind_cb, shbuf_io, &shpool); + if (ret) { + printf("failed rpmsg_init_vdev\r\n"); + goto err2; + } + + return rpmsg_virtio_get_rpmsg_device(rpmsg_vdev); +err2: + remoteproc_remove_virtio(rproc, vdev); +err1: + metal_free_memory(rpmsg_vdev); + return NULL; +} -- Gitee From af4c34bf9d6cc92a00429dd90fd6ace289631fbf Mon Sep 17 00:00:00 2001 From: Luoject <13113951796@163.com> Date: Tue, 7 Jun 2022 20:25:56 +0800 Subject: [PATCH 2/2] add resource table parsing for openamp_demo --- mcs/openamp_demo/Makefile | 13 +- mcs/openamp_demo/elf_file/Makefile | 8 + mcs/openamp_demo/elf_file/elf_file.c | 89 +++++++++ mcs/openamp_demo/rpmsg-internal.h | 12 +- mcs/openamp_demo/rpmsg_main.c | 93 ++------- mcs/openamp_demo/rpmsg_ping.c | 47 +++-- mcs/openamp_demo/rproc_rsc.c | 274 +++++++++++++++++++++++++++ 7 files changed, 429 insertions(+), 107 deletions(-) create mode 100644 mcs/openamp_demo/elf_file/Makefile create mode 100644 mcs/openamp_demo/elf_file/elf_file.c create mode 100644 mcs/openamp_demo/rproc_rsc.c diff --git a/mcs/openamp_demo/Makefile b/mcs/openamp_demo/Makefile index c293881e..67c52b23 100644 --- a/mcs/openamp_demo/Makefile +++ b/mcs/openamp_demo/Makefile @@ -1,11 +1,16 @@ -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 rproc_rsc.o + $(CC) -g rpmsg_main.o rpmsg_ping.o rproc_rsc.o $(SDKTARGETSYSROOT)/usr/lib64/libmetal.so $(SDKTARGETSYSROOT)/usr/lib64/libopen_amp.so $(SDKTARGETSYSROOT)/lib64/libsysfs.so -o rpmsg_main + #$(LD) --verbose > rproc_rsc.ld + #-T rproc_rsc.ld 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 + +rproc_rsc.o: rproc_rsc.c rpmsg-internal.h + $(CC) -g -I$(SDKTARGETSYSROOT)/usr/include -c rproc_rsc.c -o rproc_rsc.o clean: rm -rf *.o rpmsg_main diff --git a/mcs/openamp_demo/elf_file/Makefile b/mcs/openamp_demo/elf_file/Makefile new file mode 100644 index 00000000..831a7370 --- /dev/null +++ b/mcs/openamp_demo/elf_file/Makefile @@ -0,0 +1,8 @@ +elf_file.elf: elf_file.o + $(CC) -g -Wl,-Map=elf_file.map elf_file.o $(SDKTARGETSYSROOT)/usr/lib64/libmetal.so $(SDKTARGETSYSROOT)/usr/lib64/libopen_amp.so $(SDKTARGETSYSROOT)/lib64/libsysfs.so -o elf_file.elf + +elf_file.o: elf_file.c + $(CC) -g -I$(SDKTARGETSYSROOT)/usr/include -c elf_file.c -o elf_file.o + +clean: + rm -rf *.o elf_file.elf diff --git a/mcs/openamp_demo/elf_file/elf_file.c b/mcs/openamp_demo/elf_file/elf_file.c new file mode 100644 index 00000000..1f18b181 --- /dev/null +++ b/mcs/openamp_demo/elf_file/elf_file.c @@ -0,0 +1,89 @@ +#include +#include + +#define NO_RESOURCE_ENTRIES 8 + +/* Resource table for the given remote */ +struct remote_resource_table { + unsigned int version; + unsigned int num; + unsigned int reserved[2]; + unsigned int offset[NO_RESOURCE_ENTRIES]; + + /* 1. resource table mem entry */ + struct fw_rsc_carveout rsc_mem; + /* 2. rpmsg buffer mem entry */ + struct fw_rsc_carveout rpmsg_mem; + /* 3. vdev status mem entry */ + struct fw_rsc_carveout vdev_sta_mem; + + /* 4. rpmsg vdev entry */ + struct fw_rsc_vdev rpmsg_vdev; + struct fw_rsc_vdev_vring rpmsg_vring0; + struct fw_rsc_vdev_vring rpmsg_vring1; +} __attribute__((__packed__)); + +/* Place resource table in special ELF section */ +#define __section_t(S) __attribute__((__section__(#S))) +#define __resource __section_t(.resource_table) + +#define NUM_TABLE_ENTRIES 4 + +/* Address */ +#define VDEV_START_ADDR 0x70000000 +#define VDEV_SIZE 0x30000 + +#define VDEV_STATUS_ADDR VDEV_START_ADDR +#define VDEV_STATUS_SIZE 0x4000 + +#define SHM_START_ADDR (VDEV_START_ADDR + VDEV_STATUS_SIZE) +#define SHM_SIZE (VDEV_SIZE - VDEV_STATUS_SIZE) + +#define VRING_RX_ADDRESS (VDEV_START_ADDR + SHM_SIZE - VDEV_STATUS_SIZE) +#define VRING_TX_ADDRESS (VDEV_START_ADDR + SHM_SIZE) + +#define RSC_TABLE_ADDR 0x71000000 + +/* Vdev properties */ +#define VRING_COUNT 2 +#define VRING_SIZE 16 +#define VRING_ALIGNMENT 4 + +#define DFEATURE_SUPPORT_NS 1 +#define VDEV_NOTIFY_ID 0 +#define VRING_RX_NOTIFY_ID 1 +#define VRING_TX_NOTIFY_ID 2 + +struct remote_resource_table __resource resources = { + /* Version */ + RSC_TAB_SUPPORTED_VERSION, + /* NUmber of table entries */ + NUM_TABLE_ENTRIES, + /* reserved fields */ + { 0, 0 }, + /* Offsets of rsc entries */ + { + offsetof(struct remote_resource_table, rsc_mem), + offsetof(struct remote_resource_table, rpmsg_mem), + offsetof(struct remote_resource_table, vdev_sta_mem), + offsetof(struct remote_resource_table, rpmsg_vdev), + }, + + /* 1. Resource table memory entry */ + { RSC_CARVEOUT, RSC_TABLE_ADDR, RSC_TABLE_ADDR, sizeof(resources), 0 }, + /* 2. Rpmsg buffer memory entry including vring TX/RX memory */ + { RSC_CARVEOUT, SHM_START_ADDR, SHM_START_ADDR, SHM_SIZE, 0 }, + /* 3. Vdev status memory entry */ + { RSC_CARVEOUT, VDEV_STATUS_ADDR, VDEV_STATUS_ADDR, VDEV_STATUS_SIZE, 0 }, + + /* 4. Virtio device entry */ + { RSC_VDEV, VIRTIO_ID_RPMSG, VDEV_NOTIFY_ID, DFEATURE_SUPPORT_NS, 0, 0, 0, VRING_COUNT, { 0, 0 } }, + /* Vring rsc entry - part of vdev rsc entry */ + { VRING_RX_ADDRESS, VRING_ALIGNMENT, VRING_SIZE, VRING_RX_NOTIFY_ID, 0 }, /* VRING_RX */ + { VRING_TX_ADDRESS, VRING_ALIGNMENT, VRING_SIZE, VRING_TX_NOTIFY_ID, 0 }, /* VRING_TX */ +}; + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/mcs/openamp_demo/rpmsg-internal.h b/mcs/openamp_demo/rpmsg-internal.h index ebfde5fb..41d71b5b 100644 --- a/mcs/openamp_demo/rpmsg-internal.h +++ b/mcs/openamp_demo/rpmsg-internal.h @@ -20,10 +20,20 @@ #define VRING_ALIGNMENT 4 #define VRING_SIZE 16 +#define RSC_TABLE_ADDR 0x71000000 + #define IRQ_SENDTO_CLIENTOS _IOW('A', 0, int) #define DEV_CLIENT_OS_AGENT "/dev/cpu_handler" extern char *cpu_id; +extern char *boot_address; +extern volatile unsigned int received_data; +extern struct rpmsg_endpoint *ep; + +struct remoteproc *platform_create_proc(unsigned int id); +struct rpmsg_device *platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, + unsigned int role, void (*rst_cb)(struct virtio_device *vdev), rpmsg_ns_bind_cb ns_bind_cb); -void rpmsg_app_master(void); +void rpmsg_app_master(struct remoteproc *rproc); #endif + diff --git a/mcs/openamp_demo/rpmsg_main.c b/mcs/openamp_demo/rpmsg_main.c index 037ec8e9..1c7e004c 100644 --- a/mcs/openamp_demo/rpmsg_main.c +++ b/mcs/openamp_demo/rpmsg_main.c @@ -9,21 +9,12 @@ #include "rpmsg-internal.h" #define MAX_BIN_BUFLEN (10 * 1024 * 1024) -#define BOOTCMD_MAXSIZE 100 - -static struct remoteproc rproc_inst; -static struct remoteproc_ops ops; char *cpu_id; -static char *boot_address; +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) { int memfd = open("/dev/mem", O_RDWR); @@ -56,77 +47,14 @@ static int load_bin(void) return 0; } -static struct remoteproc *rproc_init(struct remoteproc *rproc, - struct remoteproc_ops *ops, void *arg) -{ - struct rproc_priv *priv; - unsigned int id = *((unsigned int *)arg); - - priv = metal_allocate_memory(sizeof(*priv)); - if (!priv) - return NULL; - - memset(priv, 0, sizeof(*priv)); - priv->rproc = rproc; - priv->id = id; - priv->rproc->ops = ops; - metal_list_init(&priv->rproc->mems); - priv->rproc->priv = priv; - rproc->state = RPROC_READY; - return priv->rproc; -} - -static int rproc_start(struct remoteproc *rproc) -{ - int cpu_handler_fd; - int ret; - char on[BOOTCMD_MAXSIZE]; - - (void)snprintf(on, sizeof(on), "%s%s%s", cpu_id, "@", boot_address); - - cpu_handler_fd = open(DEV_CLIENT_OS_AGENT, O_RDWR); - if (cpu_handler_fd < 0) { - printf("failed to open %s\n", DEV_CLIENT_OS_AGENT); - return cpu_handler_fd; - } - - ret = write(cpu_handler_fd, on, sizeof(on)); - return 0; -} - -static void rproc_remove(struct remoteproc *rproc) -{ - struct rproc_priv *priv; - - priv = (struct rproc_priv *)rproc->priv; - metal_free_memory(priv); -} - -struct remoteproc_ops rproc_ops = { - .init = rproc_init, - .remove = rproc_remove, - .start = rproc_start, -}; - -static struct remoteproc *platform_create_proc(unsigned int id) -{ - struct remoteproc *rproc; - - ops = rproc_ops; - rproc = remoteproc_init(&rproc_inst, &ops, &id); - if (!rproc) - return NULL; - - return &rproc_inst; -} - int main(int argc, char **argv) { struct remoteproc *rproc = NULL; + struct rpmsg_device *rdev = NULL; unsigned int id = 1; int ret; int opt; - +#if 0 while ((opt = getopt(argc, argv, "c:b:t:a:")) != -1) { switch (opt) { case 'c': @@ -145,6 +73,11 @@ int main(int argc, char **argv) break; } } +#endif + cpu_id = "3"; + boot_address = "0x7a000ffc"; + target_binfile = "zephyr.bin"; + target_binaddr = "0x7a000000"; rproc = platform_create_proc(id); if (!rproc) { @@ -163,10 +96,16 @@ int main(int argc, char **argv) printf("start processor failed\n"); return ret; } - sleep(5); printf("start processing OpenAMP demo...\n"); - rpmsg_app_master(); +#if 0 + rdev = platform_create_rpmsg_vdev(rproc, 0, VIRTIO_DEV_MASTER, NULL, ns_bind_cb); + if (ret) { + printf("create rpmsg vdev failed\n"); + return ret; + } +#endif + rpmsg_app_master(rproc); remoteproc_remove(rproc); return ret; diff --git a/mcs/openamp_demo/rpmsg_ping.c b/mcs/openamp_demo/rpmsg_ping.c index 6cea999a..ba3b07af 100644 --- a/mcs/openamp_demo/rpmsg_ping.c +++ b/mcs/openamp_demo/rpmsg_ping.c @@ -18,10 +18,9 @@ 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]; static unsigned char virtio_get_status(struct virtio_device *vdev) @@ -70,6 +69,10 @@ struct virtio_dispatch dispatch = { .notify = virtio_notify, }; +/* NAME SERVICE CALLBACK */ +struct rpmsg_endpoint my_ept; +struct rpmsg_endpoint *ep = &my_ept; + int endpoint_cb(struct rpmsg_endpoint *ept, void *data, size_t len, uint32_t src, void *priv) { @@ -77,9 +80,6 @@ int endpoint_cb(struct rpmsg_endpoint *ept, void *data, return RPMSG_SUCCESS; } -struct rpmsg_endpoint my_ept; -struct rpmsg_endpoint *ep = &my_ept; - static void rpmsg_service_unbind(struct rpmsg_endpoint *ept) { (void)ept; @@ -94,7 +94,7 @@ void ns_bind_cb(struct rpmsg_device *rdev, const char *name, uint32_t dest) rpmsg_service_unbind); } -static unsigned int receive_message(void) +static unsigned int receive_message(struct remoteproc *rproc) { int cpu_handler_fd; struct pollfd fds; @@ -141,11 +141,11 @@ static int send_message(unsigned int message) static struct rpmsg_virtio_shm_pool shpool; -void rpmsg_app_master(void) +void rpmsg_app_master(struct remoteproc *rproc) { int status = 0; unsigned int message = 0U; - void *tx_addr, *rx_addr, *shm_start_addr; + void *tx_addr, *rx_addr; metal_phys_addr_t shm_physmap[] = { SHM_START_ADDR }; printf("\r\nOpenAMP[master] demo started\r\n"); @@ -153,39 +153,36 @@ void rpmsg_app_master(void) 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); rx_addr = mmap((void *)VRING_RX_ADDRESS, VDEV_STATUS_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, g_memfd, VRING_RX_ADDRESS); - shm_start_addr = mmap((void *)SHM_START_ADDR, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, g_memfd, SHM_START_ADDR); - io = malloc(sizeof(struct metal_io_region)); - if (!io) { - printf("malloc io failed\n"); + void *shbuf; + struct metal_io_region *shbuf_io; + shbuf_io = remoteproc_get_io_with_pa(rproc, SHM_START_ADDR); + if (!shbuf_io) return; - } - metal_io_init(io, shm_start_addr, shm_physmap, SHM_SIZE, -1, 0, NULL); + shbuf = metal_io_phys_to_virt(shbuf_io, SHM_START_ADDR); /* setup vdev */ vq[0] = virtqueue_allocate(VRING_SIZE); if (vq[0] == NULL) { printf("virtqueue_allocate failed to alloc vq[0]\n"); - free(io); return; } vq[1] = virtqueue_allocate(VRING_SIZE); if (vq[1] == NULL) { printf("virtqueue_allocate failed to alloc vq[1]\n"); - free(io); return; } vdev.role = RPMSG_MASTER; vdev.vrings_num = VRING_COUNT; vdev.func = &dispatch; - rvrings[0].io = io; + rvrings[0].io = shbuf_io; rvrings[0].info.vaddr = tx_addr; rvrings[0].info.num_descs = VRING_SIZE; rvrings[0].info.align = VRING_ALIGNMENT; rvrings[0].vq = vq[0]; - rvrings[1].io = io; + rvrings[1].io = shbuf_io; rvrings[1].info.vaddr = rx_addr; rvrings[1].info.num_descs = VRING_SIZE; rvrings[1].info.align = VRING_ALIGNMENT; @@ -193,19 +190,20 @@ void rpmsg_app_master(void) vdev.vrings_info = &rvrings[0]; - /* setup rvdev */ - rpmsg_virtio_init_shm_pool(&shpool, shm_start_addr, SHM_SIZE); - status = rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, io, &shpool); + printf("initializing rpmsg shared buffer pool\r\n"); + /* Only RPMsg virtio master needs to initialize the shared buffers pool */ + rpmsg_virtio_init_shm_pool(&shpool, shbuf, SHM_SIZE); + + status = rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, shbuf_io, &shpool); if (status != 0) { printf("rpmsg_init_vdev failed %d\n", status); - free(io); return; } /* 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(); + receive_message(rproc); while (message < 99) { status = send_message(message); @@ -216,7 +214,7 @@ void rpmsg_app_master(void) } sleep(1); - message = receive_message(); + message = receive_message(rproc); printf("Master core received a message: %u\n", message); message++; @@ -224,6 +222,5 @@ void rpmsg_app_master(void) } _cleanup: - free(io); printf("OpenAMP demo ended.\n"); } diff --git a/mcs/openamp_demo/rproc_rsc.c b/mcs/openamp_demo/rproc_rsc.c new file mode 100644 index 00000000..fde06b54 --- /dev/null +++ b/mcs/openamp_demo/rproc_rsc.c @@ -0,0 +1,274 @@ +#include +#include +#include +#include + +#include "rpmsg-internal.h" + +#define BOOTCMD_MAXSIZE 100 + +struct rproc_priv { + struct remoteproc *rproc; + unsigned int id; +}; + +static struct remoteproc *rproc_init(struct remoteproc *rproc, + struct remoteproc_ops *ops, void *arg) +{ + struct rproc_priv *priv; + unsigned int id = *((unsigned int *)arg); + + priv = metal_allocate_memory(sizeof(*priv)); + if (!priv) + return NULL; + + memset(priv, 0, sizeof(*priv)); + priv->rproc = rproc; + priv->id = id; + priv->rproc->ops = ops; + metal_list_init(&priv->rproc->mems); + priv->rproc->priv = priv; + rproc->state = RPROC_READY; + return priv->rproc; +} + +static int rproc_start(struct remoteproc *rproc) +{ + int cpu_handler_fd; + int ret; + char on[BOOTCMD_MAXSIZE]; + + (void)snprintf(on, sizeof(on), "%s%s%s", cpu_id, "@", boot_address); + + cpu_handler_fd = open(DEV_CLIENT_OS_AGENT, O_RDWR); + if (cpu_handler_fd < 0) { + printf("failed to open %s\n", DEV_CLIENT_OS_AGENT); + return cpu_handler_fd; + } + + ret = write(cpu_handler_fd, on, sizeof(on)); + return 0; +} + +static void rproc_remove(struct remoteproc *rproc) +{ + struct rproc_priv *priv; + + priv = (struct rproc_priv *)rproc->priv; + metal_free_memory(priv); +} + +void *rproc_mmap(struct remoteproc *rproc, + metal_phys_addr_t *pa, metal_phys_addr_t *da, + size_t size, unsigned int attribute, + struct metal_io_region **io) +{ + struct remoteproc_mem *mem; + struct metal_io_region *tmpio; + + if (*pa == METAL_BAD_PHYS && *da == METAL_BAD_PHYS) + return NULL; + if (*pa == METAL_BAD_PHYS) + *pa = *da; + if (*da == METAL_BAD_PHYS) + *da = *pa; + + mem = metal_allocate_memory(sizeof(*mem)); + if (!mem) + return NULL; + tmpio = metal_allocate_memory(sizeof(*tmpio)); + if (!tmpio) { + metal_free_memory(mem); + return NULL; + } + + /* mmap pa to va */ + int memfd; + void *va; + memfd = open("/dev/mem", O_RDWR); + va = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, *pa); + if (va == NULL) + return NULL; + perror("mmap"); + + remoteproc_init_mem(mem, NULL, *pa, *da, size, tmpio); + metal_io_init(tmpio, va, &mem->pa, size, -1, attribute, NULL); /* metal io manage va and pa */ + remoteproc_add_mem(rproc, mem); + if (io) + *io = tmpio; + + printf("%s: pa=0x%lx, da=0x%lx, size=0x%lx, attribute=0x%x, va=%p, io=%p, rproc=%p.\r\n", + __func__, *pa, *da, size, attribute, va, tmpio, rproc); + + return metal_io_phys_to_virt(tmpio, mem->pa); +} + +int rproc_notify(struct remoteproc *rproc, uint32_t id) +{ +#if 0 + int cpu_handler_fd; + int ret; + int cpu_num = strtol(cpu_id, NULL, 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; + } + + ret = ioctl(cpu_handler_fd, IRQ_SENDTO_CLIENTOS, cpu_num); + if (ret) { + printf("send ipi tp second os failed\n"); + } + + close(cpu_handler_fd); +#endif + return 0; +} + +struct remoteproc_ops rproc_ops = { + .init = rproc_init, + .remove = rproc_remove, + .start = rproc_start, + .mmap = rproc_mmap, + .notify = rproc_notify, +}; + +static struct remoteproc rproc_inst; + +struct mem_file { + char* base; /* store image base address */ +}; + +#define IMAGE_MAX_LEN (1024 * 1024) +char img_buffer[IMAGE_MAX_LEN] = { 0 }; + +int mem_image_open(void *store, const char *path, const void **image_data) +{ + int fd; + long img_size; + struct mem_file *image = store; + + fd = open(path, O_RDONLY); + if (fd < 0) { + printf("open %s failed.\r\n", path); + perror("open error"); + return -1; + } + + img_size = read(fd, img_buffer, IMAGE_MAX_LEN); + if (img_size <= 0) { + printf("read %s failed.\r\n", path); + perror("read error"); + return -1; + } + + *image_data = img_buffer; + image->base = img_buffer; + + printf("open image %s successfully.\r\n", path); + return img_size; +} + +void mem_image_close(void *store) +{ + return; +} + +int mem_image_load(void *store, size_t offset, size_t size, const void **data, metal_phys_addr_t pa, struct metal_io_region *io, char is_blcoking) +{ + struct mem_file *image = store; + void *va; + + if (pa == METAL_BAD_PHYS) { + if (data == NULL) + return -1; + *data = (const void*)((const char*)(image->base) + offset); + } else { + if (io == NULL) + return -1; + va = metal_io_phys_to_virt(io, pa); + if (va == NULL) + return -1; + memcpy(va, (const void*)((const char*)(image->base) + offset), size); + } + + printf("mem_image_load exec successfully. base:%p, offset:0x%x, size:0x%x, data:%p, pa:0x%x, io:%p, va:%p.\r\n", + image->base, (int)offset, (int)size, *data, (unsigned int)pa, io, va); + return (int)size; +} + +struct image_store_ops mem_image_store_ops = { + .open = mem_image_open, + .close = mem_image_close, + .load = mem_image_load, + .features = SUPPORT_SEEK, +}; + +struct remoteproc *platform_create_proc(unsigned int id) +{ + int ret; + struct mem_file image; + + /* Initialize remoteproc instance */ + if (!remoteproc_init(&rproc_inst, &rproc_ops, &id)) + return NULL; + + /* load elf firmware: resource table */ + remoteproc_config(&rproc_inst, NULL); + ret = remoteproc_load(&rproc_inst, "rsc_elf.elf", &image, &mem_image_store_ops, NULL); + if (ret) { + printf("failed to load firmware.\r\n"); + return NULL; + } + + printf("Initialize remoteproc successfully.\r\n"); + + return &rproc_inst; +} + +struct rpmsg_device *platform_create_rpmsg_vdev(void *platform, unsigned int vdev_index, + unsigned int role, void (*rst_cb)(struct virtio_device *vdev), rpmsg_ns_bind_cb ns_bind_cb) +{ + struct remoteproc *rproc = platform; + struct rpmsg_virtio_device *rpmsg_vdev; + struct virtio_device *vdev; + void *shbuf; + struct metal_io_region *shbuf_io; + int ret; + struct rpmsg_virtio_shm_pool shpool; + + rpmsg_vdev = metal_allocate_memory(sizeof(*rpmsg_vdev)); + if (!rpmsg_vdev) + return NULL; + shbuf_io = remoteproc_get_io_with_pa(rproc, SHM_START_ADDR); + if (!shbuf_io) + goto err1; + shbuf = metal_io_phys_to_virt(shbuf_io, SHM_START_ADDR); + + printf("creating remoteproc virtio\r\n"); + vdev = remoteproc_create_virtio(rproc, vdev_index, role, rst_cb); + if (!vdev) { + printf("failed remoteproc_create_virtio\r\n"); + goto err1; + } + + printf("initializing rpmsg shared buffer pool\r\n"); + /* Only RPMsg virtio master needs to initialize the shared buffers pool */ + rpmsg_virtio_init_shm_pool(&shpool, shbuf, SHM_SIZE); + + printf("initializing rpmsg vdev\r\n"); + /* RPMsg virtio slave can set shared buffers pool argument to NULL */ + ret = rpmsg_init_vdev(rpmsg_vdev, vdev, ns_bind_cb, shbuf_io, &shpool); + if (ret) { + printf("failed rpmsg_init_vdev\r\n"); + goto err2; + } + + return rpmsg_virtio_get_rpmsg_device(rpmsg_vdev); +err2: + remoteproc_remove_virtio(rproc, vdev); +err1: + metal_free_memory(rpmsg_vdev); + return NULL; +} -- Gitee