1 /*
2  * Copyright (c) 2021 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr.h>
8 #include <drivers/ipm.h>
9 #include <sys/printk.h>
10 #include <device.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <ipc/ipc_service.h>
16 
17 #define APP_TASK_STACK_SIZE  1024
18 
19 K_THREAD_STACK_DEFINE(thread_stack_1, APP_TASK_STACK_SIZE);
20 K_THREAD_STACK_DEFINE(thread_stack_2, APP_TASK_STACK_SIZE);
21 
22 static struct k_thread thread_data_1;
23 static struct k_thread thread_data_2;
24 
25 static volatile uint8_t received_data_1;
26 static volatile uint8_t received_data_2;
27 
28 static K_SEM_DEFINE(bound_ept1_sem, 0, 1);
29 static K_SEM_DEFINE(bound_ept2_sem, 0, 1);
30 
31 static K_SEM_DEFINE(data_rx1_sem, 0, 1);
32 static K_SEM_DEFINE(data_rx2_sem, 0, 1);
33 
34 static struct ipc_ept *ept_1;
35 static struct ipc_ept *ept_2;
36 
ept_bound_1(void * priv)37 static void ept_bound_1(void *priv)
38 {
39 	k_sem_give(&bound_ept1_sem);
40 }
41 
ept_recv_1(const void * data,size_t len,void * priv)42 static void ept_recv_1(const void *data, size_t len, void *priv)
43 {
44 	received_data_1 = *((uint8_t *) data);
45 	k_sem_give(&data_rx1_sem);
46 }
47 
ept_error_1(const char * message,void * priv)48 static void ept_error_1(const char *message, void *priv)
49 {
50 	printk("Endpoint [1] error: %s", message);
51 }
52 
ept_bound_2(void * priv)53 static void ept_bound_2(void *priv)
54 {
55 	k_sem_give(&bound_ept2_sem);
56 }
57 
ept_recv_2(const void * data,size_t len,void * priv)58 static void ept_recv_2(const void *data, size_t len, void *priv)
59 {
60 	received_data_2 = *((uint8_t *) data);
61 	k_sem_give(&data_rx2_sem);
62 }
63 
ept_error_2(const char * message,void * priv)64 static void ept_error_2(const char *message, void *priv)
65 {
66 	printk("Endpoint [2] error: %s", message);
67 }
68 
app_task_1(void * arg1,void * arg2,void * arg3)69 void app_task_1(void *arg1, void *arg2, void *arg3)
70 {
71 	ARG_UNUSED(arg1);
72 	ARG_UNUSED(arg2);
73 	ARG_UNUSED(arg3);
74 	int status = 0;
75 	uint8_t message = 0U;
76 
77 	printk("\r\nIPC Service [remote 1] demo started\r\n");
78 
79 	static struct ipc_ept_cfg ept_cfg = {
80 		.name = "ep_1",
81 		.prio = 0,
82 		.priv = NULL,
83 		.cb = {
84 			.bound    = ept_bound_1,
85 			.received = ept_recv_1,
86 			.error    = ept_error_1,
87 		},
88 	};
89 
90 	status = ipc_service_register_endpoint(&ept_1, &ept_cfg);
91 	if (status < 0) {
92 		printk("ipc_service_register_endpoint failed %d\n", status);
93 		return;
94 	}
95 
96 	k_sem_take(&bound_ept1_sem, K_FOREVER);
97 
98 	while (message < 99) {
99 		k_sem_take(&data_rx1_sem, K_FOREVER);
100 		message = received_data_1;
101 		printk("Remote [1] received a message: %d\n", message);
102 
103 		message++;
104 		status = ipc_service_send(ept_1, &message, sizeof(message));
105 		if (status < 0) {
106 			printk("send_message(%d) failed with status %d\n",
107 			       message, status);
108 			break;
109 		}
110 	}
111 
112 	printk("IPC Service [remote 1] demo ended.\n");
113 }
114 
app_task_2(void * arg1,void * arg2,void * arg3)115 void app_task_2(void *arg1, void *arg2, void *arg3)
116 {
117 	ARG_UNUSED(arg1);
118 	ARG_UNUSED(arg2);
119 	ARG_UNUSED(arg3);
120 	int status = 0;
121 	uint8_t message = 0U;
122 
123 	printk("\r\nIPC Service [remote 2] demo started\r\n");
124 
125 	static struct ipc_ept_cfg ept_cfg = {
126 		.name = "ep_2",
127 		.prio = 0,
128 		.priv = NULL,
129 		.cb = {
130 			.bound    = ept_bound_2,
131 			.received = ept_recv_2,
132 			.error    = ept_error_2,
133 		},
134 	};
135 
136 	status = ipc_service_register_endpoint(&ept_2, &ept_cfg);
137 
138 	if (status < 0) {
139 		printk("ipc_service_register_endpoint failed %d\n", status);
140 		return;
141 	}
142 
143 	k_sem_take(&bound_ept2_sem, K_FOREVER);
144 
145 	while (message < 99) {
146 		k_sem_take(&data_rx2_sem, K_FOREVER);
147 		message = received_data_2;
148 		printk("Remote [2] received a message: %d\n", message);
149 
150 		message++;
151 		status = ipc_service_send(ept_2, &message, sizeof(message));
152 		if (status < 0) {
153 			printk("send_message(%d) failed with status %d\n",
154 			       message, status);
155 			break;
156 		}
157 	}
158 
159 	printk("IPC Service [remote 2] demo ended.\n");
160 }
161 
main(void)162 void main(void)
163 {
164 	k_thread_create(&thread_data_1, thread_stack_1, APP_TASK_STACK_SIZE,
165 			(k_thread_entry_t)app_task_1,
166 			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
167 
168 	k_thread_create(&thread_data_2, thread_stack_2, APP_TASK_STACK_SIZE,
169 			(k_thread_entry_t)app_task_2,
170 			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
171 }
172