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 #include "common.h"
13
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(remote, LOG_LEVEL_INF);
16
17 #if defined(CONFIG_MULTITHREADING)
18 K_SEM_DEFINE(bound_sem, 0, 1);
19 #else
20 volatile uint32_t bound_sem = 1;
21 volatile uint32_t recv_sem = 1;
22 #endif
23
24 static unsigned char expected_message = 'a';
25 static size_t expected_len = PACKET_SIZE_START;
26 static size_t received;
27
ep_bound(void * priv)28 static void ep_bound(void *priv)
29 {
30 received = 0;
31 #if defined(CONFIG_MULTITHREADING)
32 k_sem_give(&bound_sem);
33 #else
34 bound_sem = 0;
35 #endif
36 LOG_INF("Ep bounded");
37 }
38
ep_recv(const void * data,size_t len,void * priv)39 static void ep_recv(const void *data, size_t len, void *priv)
40 {
41 #if defined(CONFIG_ASSERT)
42 struct data_packet *packet = (struct data_packet *)data;
43
44 __ASSERT(packet->data[0] == expected_message, "Unexpected message. Expected %c, got %c",
45 expected_message, packet->data[0]);
46 __ASSERT(len == expected_len, "Unexpected length. Expected %zu, got %zu",
47 expected_len, len);
48 #endif
49
50 #ifndef CONFIG_MULTITHREADING
51 recv_sem = 0;
52 #endif
53
54 received += len;
55 expected_message++;
56 expected_len++;
57
58 if (expected_message > 'z') {
59 expected_message = 'a';
60 }
61
62 if (expected_len > sizeof(struct data_packet)) {
63 expected_len = PACKET_SIZE_START;
64 }
65 }
66
send_for_time(struct ipc_ept * ep,const int64_t sending_time_ms)67 static int send_for_time(struct ipc_ept *ep, const int64_t sending_time_ms)
68 {
69 struct data_packet msg = {.data[0] = 'A'};
70 size_t mlen = PACKET_SIZE_START;
71 size_t bytes_sent = 0;
72 int ret = 0;
73
74 LOG_INF("Perform sends for %lld [ms]", sending_time_ms);
75
76 int64_t start = k_uptime_get();
77
78 while ((k_uptime_get() - start) < sending_time_ms) {
79 ret = ipc_service_send(ep, &msg, mlen);
80 if (ret == -ENOMEM) {
81 /* No space in the buffer. Retry. */
82 ret = 0;
83 continue;
84 } else if (ret < 0) {
85 LOG_ERR("Failed to send (%c) failed with ret %d", msg.data[0], ret);
86 break;
87 }
88 #if !defined(CONFIG_MULTITHREADING)
89 else {
90 recv_sem = 1;
91 }
92 #endif
93
94 msg.data[0]++;
95 if (msg.data[0] > 'Z') {
96 msg.data[0] = 'A';
97 }
98
99 bytes_sent += mlen;
100 mlen++;
101
102 if (mlen > sizeof(struct data_packet)) {
103 mlen = PACKET_SIZE_START;
104 }
105
106 #if defined(CONFIG_MULTITHREADING)
107 k_usleep(1);
108 #else
109 while ((recv_sem != 0) && ((k_uptime_get() - start) < sending_time_ms)) {
110 };
111 #endif
112 }
113
114 LOG_INF("Sent %zu [Bytes] over %lld [ms]", bytes_sent, sending_time_ms);
115
116 return ret;
117 }
118
119 static struct ipc_ept_cfg ep_cfg = {
120 .cb = {
121 .bound = ep_bound,
122 .received = ep_recv,
123 },
124 };
125
main(void)126 int main(void)
127 {
128 const struct device *ipc0_instance;
129 struct ipc_ept ep;
130 int ret;
131
132 LOG_INF("IPC-service REMOTE demo started");
133
134 ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0));
135
136 ret = ipc_service_open_instance(ipc0_instance);
137 if ((ret < 0) && (ret != -EALREADY)) {
138 LOG_ERR("ipc_service_open_instance() failure");
139 return ret;
140 }
141
142 ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg);
143 if (ret < 0) {
144 LOG_ERR("ipc_service_register_endpoint() failure");
145 return ret;
146 }
147
148 #if defined(CONFIG_MULTITHREADING)
149 k_sem_take(&bound_sem, K_FOREVER);
150 #else
151 while (bound_sem != 0) {
152 };
153 #endif
154
155 ret = send_for_time(&ep, SENDING_TIME_MS);
156 if (ret < 0) {
157 LOG_ERR("send_for_time() failure");
158 return ret;
159 }
160
161 LOG_INF("Received %zu [Bytes] in total", received);
162 LOG_INF("IPC-service REMOTE demo ended");
163
164 return 0;
165 }
166