Skip to content

Commit

Permalink
samples: Add mctp host and client samples
Browse files Browse the repository at this point in the history
Samples work by sending MCTP encoded messages over a uart between two
boards.

Signed-off-by: Tom Burdick <thomas.burdick@intel.com>
  • Loading branch information
teburd authored and henrikbrixandersen committed Jan 14, 2025
1 parent 4148512 commit be4a3d9
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 0 deletions.
5 changes: 5 additions & 0 deletions samples/modules/mctp/mctp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.. zephyr:code-sample-category:: mctp
:name: MCTP
:show-listing:

These samples demonstrate how to build communicating firmwares using MCTP in Zephyr.
7 changes: 7 additions & 0 deletions samples/modules/mctp/mctp_endpoint/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})

project(mctp_endpoint)

target_sources(app PRIVATE src/main.c)
41 changes: 41 additions & 0 deletions samples/modules/mctp/mctp_endpoint/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.. zephyr:code-sample:: mctp_endpoint_sample
:name: MCTP Endpoint Sample

Create an MCTP endpoint over UART.

Overview
********
Sets up an MCTP node that listens on a UART for messages targeting a particular
MCTP endpoint id with the message "hello". Responds to this "hello" message with
"world".

Requirements
************
A board and SoC that provide access to a UART and a driver that implements the
UART async API.

Wiring
******
The listening UART pins should be wired to a board which will run the MCTP host
sample such that this board's UART tx pin connects to the host board's rx pin,
and this board's UART rx pin connects to the host board's tx pin. The boards'
grounds should also be wired together.

Optionally a logic analyzer can be wired up and listening to the UART to inspect
the data flowing.

Building and Running
********************


.. zephyr-app-commands::
:zephyr-app: samples/modules/mctp/mctp_endpoint
:host-os: unix
:board: nrf52840_nrf52840dk
:goals: run
:compact:

References
**********

`MCTP Base Specification 2019 <https://www.dmtf.org/sites/default/files/standards/documents/DSP0236_1.3.1.pdf>`_
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
&arduino_serial{
status = "okay";
};
8 changes: 8 additions & 0 deletions samples/modules/mctp/mctp_endpoint/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_MCTP=y
CONFIG_MCTP_UART=y
CONFIG_LOG=y
CONFIG_LOG_BUFFER_SIZE=4096
CONFIG_MCTP_LOG_LEVEL_DBG=y
CONFIG_ISR_STACK_SIZE=4096
68 changes: 68 additions & 0 deletions samples/modules/mctp/mctp_endpoint/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <zephyr/kernel.h>
#include <zephyr/types.h>
#include <zephyr/mctp/mctp_uart.h>
#include <libmctp.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mctp_endpoint);

#include <zephyr/drivers/uart.h>

static struct mctp *mctp_ctx;

#define LOCAL_HELLO_EID 10

#define REMOTE_HELLO_EID 20

K_SEM_DEFINE(mctp_rx, 0, 1);

static void rx_message(uint8_t eid, bool tag_owner, uint8_t msg_tag, void *data, void *msg,
size_t len)
{
switch (eid) {
case REMOTE_HELLO_EID:
LOG_INF("got mctp message %s for eid %d, replying to 5 with \"world\"", (char *)msg,
eid);
mctp_message_tx(mctp_ctx, LOCAL_HELLO_EID, false, 0, "world", sizeof("world"));
break;
default:
LOG_INF("Unknown endpoint %d", eid);
break;
}

k_sem_give(&mctp_rx);
}

MCTP_UART_DT_DEFINE(mctp_endpoint, DEVICE_DT_GET(DT_NODELABEL(arduino_serial)));

#define RX_BUF_SZ 128

int main(void)
{
LOG_INF("MCTP Endpoint EID:%d on %s\n", LOCAL_HELLO_EID, CONFIG_BOARD_TARGET);

mctp_set_alloc_ops(malloc, free, realloc);
mctp_ctx = mctp_init();
__ASSERT_NO_MSG(mctp_ctx != NULL);
mctp_register_bus(mctp_ctx, &mctp_endpoint.binding, LOCAL_HELLO_EID);
mctp_set_rx_all(mctp_ctx, rx_message, NULL);

/* MCTP poll loop */
while (true) {
mctp_uart_start_rx(&mctp_endpoint);
k_sem_take(&mctp_rx, K_FOREVER);
}

LOG_INF("exiting");
return 0;
}
6 changes: 6 additions & 0 deletions samples/modules/mctp/mctp_host/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(mctp_host)

target_sources(app PRIVATE src/main.c)
40 changes: 40 additions & 0 deletions samples/modules/mctp/mctp_host/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.. zephyr:code-sample:: mctp_host_sample
:name: MCTP Host Sample

Create an MCTP host over UART.

Overview
********
Sets up an MCTP node that sends a request on a UART targeting a particular MCTP
endpoint id with the message "hello". Expects and waits for a response to this
"hello" message containing "world".

Requirements
************
A board and SoC that provide access to a UART and a driver that implements the
UART async API.

Wiring
******
The UART pins should be wired to a board which will run the MCTP endpoint
sample such that this board's UART tx pin connects to the endpoint board's rx
pin, and this board's UART rx pin connects to the endpoint board's tx pin. The
boards' grounds should also be wired together.

Optionally a logic analyzer can be wired up and listening to the UART to inspect
the data flowing.

Building and Running
********************

.. zephyr-app-commands::
:zephyr-app: samples/modules/mctp/mctp_host
:host-os: unix
:board: nrf52840_nrf52840dk
:goals: run
:compact:

References
**********

`MCTP Base Specification 2019 <https://www.dmtf.org/sites/default/files/standards/documents/DSP0236_1.3.1.pdf>`_
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
&arduino_serial{
status = "okay";
};
8 changes: 8 additions & 0 deletions samples/modules/mctp/mctp_host/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# nothing here
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_MCTP=y
CONFIG_MCTP_UART=y
CONFIG_MCTP_LOG_LEVEL_DBG=y
CONFIG_LOG=y
CONFIG_LOG_BUFFER_SIZE=4096
63 changes: 63 additions & 0 deletions samples/modules/mctp/mctp_host/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <libmctp.h>
#include <zephyr/mctp/mctp_uart.h>

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mctp_host);

#define LOCAL_HELLO_EID 20

#define REMOTE_HELLO_EID 10

K_SEM_DEFINE(mctp_rx, 0, 1);

static void rx_message(uint8_t eid, bool tag_owner, uint8_t msg_tag, void *data, void *msg,
size_t len)
{
LOG_INF("received message %s for endpoint %d, msg_tag %d, len %zu", (char *)msg, eid,
msg_tag, len);
k_sem_give(&mctp_rx);
}

MCTP_UART_DT_DEFINE(mctp_host, DEVICE_DT_GET(DT_NODELABEL(arduino_serial)));

int main(void)
{
int rc;
struct mctp *mctp_ctx;

LOG_INF("MCTP Host EID:%d on %s\n", LOCAL_HELLO_EID, CONFIG_BOARD_TARGET);

mctp_set_alloc_ops(malloc, free, realloc);
mctp_ctx = mctp_init();
__ASSERT_NO_MSG(mctp_ctx != NULL);
mctp_register_bus(mctp_ctx, &mctp_host.binding, LOCAL_HELLO_EID);
mctp_set_rx_all(mctp_ctx, rx_message, NULL);
mctp_uart_start_rx(&mctp_host);

/* MCTP poll loop, send "hello" and get "world" back */
while (true) {
rc = mctp_message_tx(mctp_ctx, REMOTE_HELLO_EID, false, 0, "hello",
sizeof("hello"));
if (rc != 0) {
LOG_WRN("Failed to send message, errno %d\n", rc);
k_msleep(1000);
} else {
k_sem_take(&mctp_rx, K_MSEC(10));
}
rc = 0;
}

return 0;
}

0 comments on commit be4a3d9

Please sign in to comment.