1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/device.h>
9
10 #include <zephyr/ipc/ipc_service.h>
11
12 #define STACKSIZE (1024)
13 #define PRIORITY K_PRIO_PREEMPT(2)
14
15 K_THREAD_STACK_DEFINE(ipc0A_stack, STACKSIZE);
16 K_THREAD_STACK_DEFINE(ipc0B_stack, STACKSIZE);
17 K_THREAD_STACK_DEFINE(ipc1_stack, STACKSIZE);
18
19 static volatile uint8_t ipc0A_received_data;
20 static volatile uint8_t ipc0B_received_data;
21 static volatile uint8_t ipc1_received_data;
22
23 static K_SEM_DEFINE(ipc0A_bound_sem, 0, 1);
24 static K_SEM_DEFINE(ipc0B_bound_sem, 0, 1);
25 static K_SEM_DEFINE(ipc1_bound_sem, 0, 1);
26
27 static K_SEM_DEFINE(ipc0A_data_sem, 0, 1);
28 static K_SEM_DEFINE(ipc0B_data_sem, 0, 1);
29 static K_SEM_DEFINE(ipc1_data_sem, 0, 1);
30
31 /*
32 * ==> THREAD 0A (IPC instance 0 - endpoint A) <==
33 */
34
ipc0A_ept_bound(void * priv)35 static void ipc0A_ept_bound(void *priv)
36 {
37 k_sem_give(&ipc0A_bound_sem);
38 }
39
ipc0A_ept_recv(const void * data,size_t len,void * priv)40 static void ipc0A_ept_recv(const void *data, size_t len, void *priv)
41 {
42 ipc0A_received_data = *((uint8_t *) data);
43
44 k_sem_give(&ipc0A_data_sem);
45 }
46
47 static struct ipc_ept_cfg ipc0A_ept_cfg = {
48 .name = "ipc0A",
49 .cb = {
50 .bound = ipc0A_ept_bound,
51 .received = ipc0A_ept_recv,
52 },
53 };
54
ipc0A_entry(void * dummy0,void * dummy1,void * dummy2)55 static void ipc0A_entry(void *dummy0, void *dummy1, void *dummy2)
56 {
57 ARG_UNUSED(dummy0);
58 ARG_UNUSED(dummy1);
59 ARG_UNUSED(dummy2);
60
61 const struct device *ipc0_instance;
62 unsigned char message = 0;
63 struct ipc_ept ipc0A_ept;
64 int ret;
65
66 printk("IPC-service REMOTE [INST 0 - ENDP A] demo started\n");
67
68 ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0));
69
70 ret = ipc_service_open_instance(ipc0_instance);
71 if (ret < 0 && ret != -EALREADY) {
72 printk("ipc_service_open_instance() failure\n");
73 return;
74 }
75
76 ret = ipc_service_register_endpoint(ipc0_instance, &ipc0A_ept, &ipc0A_ept_cfg);
77 if (ret < 0) {
78 printf("ipc_service_register_endpoint() failure\n");
79 return;
80 }
81
82 k_sem_take(&ipc0A_bound_sem, K_FOREVER);
83
84 while (message < 99) {
85 k_sem_take(&ipc0A_data_sem, K_FOREVER);
86 message = ipc0A_received_data;
87
88 printk("REMOTE [0A]: %d\n", message);
89
90 message++;
91
92 ret = ipc_service_send(&ipc0A_ept, &message, sizeof(message));
93 if (ret < 0) {
94 printk("send_message(%d) failed with ret %d\n", message, ret);
95 break;
96 }
97 }
98
99 printk("IPC-service REMOTE [INST 0 - ENDP A] demo ended.\n");
100 }
101 K_THREAD_DEFINE(ipc0A_thread_id, STACKSIZE, ipc0A_entry, NULL, NULL, NULL, PRIORITY, 0, 0);
102
103 /*
104 * ==> THREAD 0B (IPC instance 0 - endpoint B) <==
105 */
106
ipc0B_ept_bound(void * priv)107 static void ipc0B_ept_bound(void *priv)
108 {
109 k_sem_give(&ipc0B_bound_sem);
110 }
111
ipc0B_ept_recv(const void * data,size_t len,void * priv)112 static void ipc0B_ept_recv(const void *data, size_t len, void *priv)
113 {
114 ipc0B_received_data = *((uint8_t *) data);
115
116 k_sem_give(&ipc0B_data_sem);
117 }
118
119 static struct ipc_ept_cfg ipc0B_ept_cfg = {
120 .name = "ipc0B",
121 .cb = {
122 .bound = ipc0B_ept_bound,
123 .received = ipc0B_ept_recv,
124 },
125 };
126
ipc0B_entry(void * dummy0,void * dummy1,void * dummy2)127 static void ipc0B_entry(void *dummy0, void *dummy1, void *dummy2)
128 {
129 ARG_UNUSED(dummy0);
130 ARG_UNUSED(dummy1);
131 ARG_UNUSED(dummy2);
132
133 const struct device *ipc0_instance;
134 unsigned char message = 0;
135 struct ipc_ept ipc0B_ept;
136 int ret;
137
138 printk("IPC-service REMOTE [INST 0 - ENDP B] demo started\n");
139
140 ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0));
141
142 ret = ipc_service_open_instance(ipc0_instance);
143 if (ret < 0 && ret != -EALREADY) {
144 printk("ipc_service_open_instance() failure\n");
145 return;
146 }
147
148 /*
149 * Wait 1 sec to give the opportunity to the PRIMARY core to register
150 * the endpoint first
151 */
152
153 k_sleep(K_MSEC(1000));
154
155 ret = ipc_service_register_endpoint(ipc0_instance, &ipc0B_ept, &ipc0B_ept_cfg);
156 if (ret < 0) {
157 printf("ipc_service_register_endpoint() failure\n");
158 return;
159 }
160
161 k_sem_take(&ipc0B_bound_sem, K_FOREVER);
162
163 while (message < 99) {
164 k_sem_take(&ipc0B_data_sem, K_FOREVER);
165 message = ipc0B_received_data;
166
167 printk("REMOTE [0B]: %d\n", message);
168
169 message++;
170
171 ret = ipc_service_send(&ipc0B_ept, &message, sizeof(message));
172 if (ret < 0) {
173 printk("send_message(%d) failed with ret %d\n", message, ret);
174 break;
175 }
176 }
177
178 printk("IPC-service REMOTE [INST 0 - ENDP B] demo ended.\n");
179 }
180 K_THREAD_DEFINE(ipc0B_thread_id, STACKSIZE, ipc0B_entry, NULL, NULL, NULL, PRIORITY, 0, 0);
181
182 /*
183 * ==> THREAD 1 (IPC instance 1) <==
184 *
185 */
186
ipc1_ept_bound(void * priv)187 static void ipc1_ept_bound(void *priv)
188 {
189 k_sem_give(&ipc1_bound_sem);
190 }
191
ipc1_ept_recv(const void * data,size_t len,void * priv)192 static void ipc1_ept_recv(const void *data, size_t len, void *priv)
193 {
194 ipc1_received_data = *((uint8_t *) data);
195
196 k_sem_give(&ipc1_data_sem);
197 }
198
199 static struct ipc_ept_cfg ipc1_ept_cfg = {
200 .name = "ipc1",
201 .cb = {
202 .bound = ipc1_ept_bound,
203 .received = ipc1_ept_recv,
204 },
205 };
206
ipc1_entry(void * dummy0,void * dummy1,void * dummy2)207 static void ipc1_entry(void *dummy0, void *dummy1, void *dummy2)
208 {
209 ARG_UNUSED(dummy0);
210 ARG_UNUSED(dummy1);
211 ARG_UNUSED(dummy2);
212
213 const struct device *ipc1_instance;
214 unsigned char message = 0;
215 struct ipc_ept ipc1_ept;
216 int ret;
217
218 printk("IPC-service REMOTE [INST 1] demo started\n");
219
220 ipc1_instance = DEVICE_DT_GET(DT_NODELABEL(ipc1));
221
222 ret = ipc_service_open_instance(ipc1_instance);
223 if (ret < 0 && ret != -EALREADY) {
224 printk("ipc_service_open_instance() failure\n");
225 return;
226 }
227
228 ret = ipc_service_register_endpoint(ipc1_instance, &ipc1_ept, &ipc1_ept_cfg);
229 if (ret < 0) {
230 printf("ipc_service_register_endpoint() failure\n");
231 return;
232 }
233
234 k_sem_take(&ipc1_bound_sem, K_FOREVER);
235
236 while (message < 99) {
237 k_sem_take(&ipc1_data_sem, K_FOREVER);
238 message = ipc1_received_data;
239
240 printk("REMOTE [1]: %d\n", message);
241
242 message++;
243
244 ret = ipc_service_send(&ipc1_ept, &message, sizeof(message));
245 if (ret < 0) {
246 printk("send_message(%d) failed with ret %d\n", message, ret);
247 break;
248 }
249 }
250
251 printk("IPC-service REMOTE [INST 1] demo ended.\n");
252 }
253 K_THREAD_DEFINE(ipc1_thread_id, STACKSIZE, ipc1_entry, NULL, NULL, NULL, PRIORITY, 0, 0);
254