blob: aca4c779780664f6d7edeadcb4b61f603fabd2c9 [file] [log] [blame]
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/zephyr.h>
#include <zephyr/device.h>
#include <zephyr/ipc/ipc_service.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(host, LOG_LEVEL_INF);
#define MLEN_0 40
struct data_packet {
unsigned char message;
unsigned char data[100];
};
K_SEM_DEFINE(bound_sem, 0, 1);
static void ep_bound(void *priv)
{
k_sem_give(&bound_sem);
LOG_INF("Ep bounded");
}
static void ep_recv(const void *data, size_t len, void *priv)
{
char received_data = *((char *)data);
static char expected_message = 'A';
static uint16_t expected_len = MLEN_0;
static unsigned long long cnt;
static unsigned int stats_every;
static uint32_t start;
static unsigned int err;
if (start == 0) {
start = k_uptime_get_32();
}
if (received_data != expected_message) {
err++;
}
if (len != expected_len) {
err++;
}
expected_message++;
expected_len++;
cnt += len;
if (expected_message > 'Z') {
if (stats_every++ > 50) {
/* Print throuhput [Bytes/s]. Use printk not to overload CPU with logger.
* Sample never reaches lower priority thread because of high throughput
* (100% cpu load) so logging would not be able to handle messages in
* deferred mode (immediate mode would be heavier than printk).
*/
printk("%llu\n", (1000*cnt)/(k_uptime_get_32() - start));
stats_every = 0;
}
if (err) {
printk("Unexpected message\n");
}
expected_message = 'A';
}
if (expected_len > sizeof(struct data_packet)) {
expected_len = MLEN_0;
}
}
static struct ipc_ept_cfg ep_cfg = {
.cb = {
.bound = ep_bound,
.received = ep_recv,
},
};
int main(void)
{
const struct device *ipc0_instance;
struct data_packet msg = {.message = 'a'};
struct ipc_ept ep;
int ret;
LOG_INF("IPC-service HOST demo started");
ipc0_instance = DEVICE_DT_GET(DT_NODELABEL(ipc0));
ret = ipc_service_open_instance(ipc0_instance);
if ((ret < 0) && (ret != -EALREADY)) {
LOG_INF("ipc_service_open_instance() failure");
return ret;
}
ret = ipc_service_register_endpoint(ipc0_instance, &ep, &ep_cfg);
if (ret < 0) {
printf("ipc_service_register_endpoint() failure");
return ret;
}
k_sem_take(&bound_sem, K_FOREVER);
uint16_t mlen = MLEN_0;
while (true) {
ret = ipc_service_send(&ep, &msg, mlen);
if (ret == -ENOMEM) {
/* No space in the buffer. Retry. */
continue;
} else if (ret < 0) {
LOG_ERR("send_message(%d) failed with ret %d", msg.message, ret);
break;
}
msg.message++;
if (msg.message > 'z') {
msg.message = 'a';
}
mlen++;
if (mlen > sizeof(struct data_packet)) {
mlen = MLEN_0;
}
/* Quasi minimal busy wait time which allows to continuosly send
* data without -ENOMEM error code. The purpose is to test max
* throughput. Determined experimentally.
*/
k_busy_wait(100);
}
LOG_INF("IPC-service HOST demo ended.");
return 0;
}