| /* |
| * Copyright (c) 2022 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/kernel.h> |
| #include <zephyr/device.h> |
| |
| #include <zephyr/ipc/ipc_service.h> |
| |
| #define STACKSIZE (4096) |
| #define PRIORITY K_PRIO_PREEMPT(2) |
| |
| K_THREAD_STACK_DEFINE(ipc0A_stack, STACKSIZE); |
| K_THREAD_STACK_DEFINE(ipc0B_stack, STACKSIZE); |
| K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE); |
| |
| static volatile uint8_t ipc0A_received_data; |
| static volatile uint8_t ipc0B_received_data; |
| static volatile uint8_t ipc1_received_data; |
| |
| static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1); |
| static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1); |
| static K_SEM_DEFINE(ipc1_bound_sem, 0, 1); |
| |
| static K_SEM_DEFINE(ipc0A_data_sem, 0, 1); |
| static K_SEM_DEFINE(ipc0B_data_sem, 0, 1); |
| static K_SEM_DEFINE(ipc1_data_sem, 0, 1); |
| |
| /* |
| * ==> THREAD 0A (IPC instance 0 - endpoint A) <== |
| */ |
| |
| static void ipc0A_ept_bound(void *priv) |
| { |
| k_sem_give(&ipc0A_bound_sem); |
| } |
| |
| static void ipc0A_ept_recv(const void *data, size_t len, void *priv) |
| { |
| ipc0A_received_data = *((uint8_t *) data); |
| |
| k_sem_give(&ipc0A_data_sem); |
| } |
| |
| static struct ipc_ept_cfg ipc0A_ept_cfg = { |
| .name = "ipc0A", |
| .cb = { |
| .bound = ipc0A_ept_bound, |
| .received = ipc0A_ept_recv, |
| }, |
| }; |
| |
| static void ipc0A_entry(void *dummy0, void *dummy1, void *dummy2) |
| { |
| ARG_UNUSED(dummy0); |
| ARG_UNUSED(dummy1); |
| ARG_UNUSED(dummy2); |
| |
| const struct device *ipc0_instance; |
| unsigned char message = 0; |
| struct ipc_ept ipc0A_ept; |
| int ret; |
| |
| printk("IPC-service HOST [INST 0 - ENDP A] demo started\n"); |
| |
| ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); |
| |
| ret = ipc_service_open_instance(ipc0_instance); |
| if (ret < 0 && ret != -EALREADY) { |
| printk("ipc_service_open_instance() failure\n"); |
| return; |
| } |
| |
| /* |
| * Wait 1 sec to give the opportunity to the SECONDARY core to register |
| * the endpoint first |
| */ |
| |
| k_sleep(K_MSEC(1000)); |
| |
| ret = ipc_service_register_endpoint(ipc0_instance, &ipc0A_ept, &ipc0A_ept_cfg); |
| if (ret < 0) { |
| printf("ipc_service_register_endpoint() failure\n"); |
| return; |
| } |
| |
| k_sem_take(&ipc0A_bound_sem, K_FOREVER); |
| |
| while (message < 100) { |
| ret = ipc_service_send(&ipc0A_ept, &message, sizeof(message)); |
| if (ret < 0) { |
| printk("send_message(%d) failed with ret %d\n", message, ret); |
| break; |
| } |
| |
| k_sem_take(&ipc0A_data_sem, K_FOREVER); |
| message = ipc0A_received_data; |
| |
| printk("HOST [0A]: %d\n", message); |
| message++; |
| } |
| |
| printk("IPC-service HOST [INST 0 - ENDP A] demo ended.\n"); |
| } |
| K_THREAD_DEFINE(ipc0A_thread_id, STACKSIZE, ipc0A_entry, NULL, NULL, NULL, PRIORITY, 0, 0); |
| |
| /* |
| * ==> THREAD 0B (IPC instance 0 - endpoint B) <== |
| */ |
| |
| static void ipc0B_ept_bound(void *priv) |
| { |
| k_sem_give(&ipc0B_bound_sem); |
| } |
| |
| static void ipc0B_ept_recv(const void *data, size_t len, void *priv) |
| { |
| ipc0B_received_data = *((uint8_t *) data); |
| |
| k_sem_give(&ipc0B_data_sem); |
| } |
| |
| static struct ipc_ept_cfg ipc0B_ept_cfg = { |
| .name = "ipc0B", |
| .cb = { |
| .bound = ipc0B_ept_bound, |
| .received = ipc0B_ept_recv, |
| }, |
| }; |
| |
| static void ipc0B_entry(void *dummy0, void *dummy1, void *dummy2) |
| { |
| ARG_UNUSED(dummy0); |
| ARG_UNUSED(dummy1); |
| ARG_UNUSED(dummy2); |
| |
| const struct device *ipc0_instance; |
| unsigned char message = 0; |
| struct ipc_ept ipc0B_ept; |
| int ret; |
| |
| printk("IPC-service HOST [INST 0 - ENDP B] demo started\n"); |
| |
| ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0)); |
| |
| ret = ipc_service_open_instance(ipc0_instance); |
| if (ret < 0 && ret != -EALREADY) { |
| printk("ipc_service_open_instance() failure\n"); |
| return; |
| } |
| |
| ret = ipc_service_register_endpoint(ipc0_instance, &ipc0B_ept, &ipc0B_ept_cfg); |
| if (ret < 0) { |
| printf("ipc_service_register_endpoint() failure\n"); |
| return; |
| } |
| |
| k_sem_take(&ipc0B_bound_sem, K_FOREVER); |
| |
| while (message < 100) { |
| ret = ipc_service_send(&ipc0B_ept, &message, sizeof(message)); |
| if (ret < 0) { |
| printk("send_message(%d) failed with ret %d\n", message, ret); |
| break; |
| } |
| |
| k_sem_take(&ipc0B_data_sem, K_FOREVER); |
| message = ipc0B_received_data; |
| |
| printk("HOST [0B]: %d\n", message); |
| message++; |
| } |
| |
| printk("IPC-service HOST [INST 0 - ENDP B] demo ended.\n"); |
| } |
| K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIORITY, 0, 0); |
| |
| /* |
| * ==> THREAD 1 (IPC instance 1) <== |
| * |
| * NOTE: This instance is using the NOCOPY copability of the backend. |
| */ |
| |
| static struct ipc_ept ipc1_ept; |
| |
| static void ipc1_ept_bound(void *priv) |
| { |
| k_sem_give(&ipc1_bound_sem); |
| } |
| |
| static void ipc1_ept_recv(const void *data, size_t len, void *priv) |
| { |
| ipc1_received_data = *((uint8_t *) data); |
| |
| k_sem_give(&ipc1_data_sem); |
| } |
| |
| static struct ipc_ept_cfg ipc1_ept_cfg = { |
| .name = "ipc1", |
| .cb = { |
| .bound = ipc1_ept_bound, |
| .received = ipc1_ept_recv, |
| }, |
| }; |
| |
| static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2) |
| { |
| ARG_UNUSED(dummy0); |
| ARG_UNUSED(dummy1); |
| ARG_UNUSED(dummy2); |
| |
| const struct device *ipc1_instance; |
| unsigned char message = 0; |
| int ret; |
| |
| printk("IPC-service HOST [INST 1] demo started\n"); |
| |
| ipc1_instance = DEVICE_DT_GET(DT_NODELABEL(ipc1)); |
| |
| ret = ipc_service_open_instance(ipc1_instance); |
| if (ret < 0 && ret != -EALREADY) { |
| printk("ipc_service_open_instance() failure\n"); |
| return; |
| } |
| |
| ret = ipc_service_register_endpoint(ipc1_instance, &ipc1_ept, &ipc1_ept_cfg); |
| if (ret < 0) { |
| printf("ipc_service_register_endpoint() failure\n"); |
| return; |
| } |
| |
| k_sem_take(&ipc1_bound_sem, K_FOREVER); |
| |
| /* |
| * Wait 1 sec to start sending simultaneously with other threads |
| * the endpoint first |
| */ |
| |
| k_sleep(K_MSEC(1000)); |
| |
| while (message < 100) { |
| ret = ipc_service_send(&ipc1_ept, &message, sizeof(message)); |
| if (ret < 0) { |
| printk("send_message(%d) failed with ret %d\n", message, ret); |
| break; |
| } |
| |
| k_sem_take(&ipc1_data_sem, K_FOREVER); |
| message = ipc1_received_data; |
| |
| printk("HOST [1]: %d\n", message); |
| message++; |
| } |
| |
| printk("IPC-service HOST [INST 1] demo ended.\n"); |
| } |
| K_THREAD_DEFINE(ipc1_thread_id, STACKSIZE, ipc1_entry, NULL, NULL, NULL, PRIORITY, 0, 0); |