From be4a3d91e1b80124c999be5b291e36a524f80afb Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 14 Aug 2024 09:03:11 -0500 Subject: [PATCH] samples: Add mctp host and client samples Samples work by sending MCTP encoded messages over a uart between two boards. Signed-off-by: Tom Burdick --- samples/modules/mctp/mctp.rst | 5 ++ .../modules/mctp/mctp_endpoint/CMakeLists.txt | 7 ++ samples/modules/mctp/mctp_endpoint/README.rst | 41 +++++++++++ .../boards/nrf52840dk_nrf52840.overlay | 3 + samples/modules/mctp/mctp_endpoint/prj.conf | 8 +++ samples/modules/mctp/mctp_endpoint/src/main.c | 68 +++++++++++++++++++ samples/modules/mctp/mctp_host/CMakeLists.txt | 6 ++ samples/modules/mctp/mctp_host/README.rst | 40 +++++++++++ .../boards/nrf52840dk_nrf52840.overlay | 3 + samples/modules/mctp/mctp_host/prj.conf | 8 +++ samples/modules/mctp/mctp_host/src/main.c | 63 +++++++++++++++++ 11 files changed, 252 insertions(+) create mode 100644 samples/modules/mctp/mctp.rst create mode 100644 samples/modules/mctp/mctp_endpoint/CMakeLists.txt create mode 100644 samples/modules/mctp/mctp_endpoint/README.rst create mode 100644 samples/modules/mctp/mctp_endpoint/boards/nrf52840dk_nrf52840.overlay create mode 100644 samples/modules/mctp/mctp_endpoint/prj.conf create mode 100644 samples/modules/mctp/mctp_endpoint/src/main.c create mode 100644 samples/modules/mctp/mctp_host/CMakeLists.txt create mode 100644 samples/modules/mctp/mctp_host/README.rst create mode 100644 samples/modules/mctp/mctp_host/boards/nrf52840dk_nrf52840.overlay create mode 100644 samples/modules/mctp/mctp_host/prj.conf create mode 100644 samples/modules/mctp/mctp_host/src/main.c diff --git a/samples/modules/mctp/mctp.rst b/samples/modules/mctp/mctp.rst new file mode 100644 index 00000000000..6bfebf7c474 --- /dev/null +++ b/samples/modules/mctp/mctp.rst @@ -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. diff --git a/samples/modules/mctp/mctp_endpoint/CMakeLists.txt b/samples/modules/mctp/mctp_endpoint/CMakeLists.txt new file mode 100644 index 00000000000..e3f4e04676a --- /dev/null +++ b/samples/modules/mctp/mctp_endpoint/CMakeLists.txt @@ -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) diff --git a/samples/modules/mctp/mctp_endpoint/README.rst b/samples/modules/mctp/mctp_endpoint/README.rst new file mode 100644 index 00000000000..6f7d7b98a5f --- /dev/null +++ b/samples/modules/mctp/mctp_endpoint/README.rst @@ -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 `_ diff --git a/samples/modules/mctp/mctp_endpoint/boards/nrf52840dk_nrf52840.overlay b/samples/modules/mctp/mctp_endpoint/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..48c7f840dca --- /dev/null +++ b/samples/modules/mctp/mctp_endpoint/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,3 @@ +&arduino_serial{ + status = "okay"; +}; diff --git a/samples/modules/mctp/mctp_endpoint/prj.conf b/samples/modules/mctp/mctp_endpoint/prj.conf new file mode 100644 index 00000000000..495c9ca12fa --- /dev/null +++ b/samples/modules/mctp/mctp_endpoint/prj.conf @@ -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 diff --git a/samples/modules/mctp/mctp_endpoint/src/main.c b/samples/modules/mctp/mctp_endpoint/src/main.c new file mode 100644 index 00000000000..430447ad2fe --- /dev/null +++ b/samples/modules/mctp/mctp_endpoint/src/main.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(mctp_endpoint); + +#include + +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; +} diff --git a/samples/modules/mctp/mctp_host/CMakeLists.txt b/samples/modules/mctp/mctp_host/CMakeLists.txt new file mode 100644 index 00000000000..4b19d992eb2 --- /dev/null +++ b/samples/modules/mctp/mctp_host/CMakeLists.txt @@ -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) diff --git a/samples/modules/mctp/mctp_host/README.rst b/samples/modules/mctp/mctp_host/README.rst new file mode 100644 index 00000000000..d80d02d2137 --- /dev/null +++ b/samples/modules/mctp/mctp_host/README.rst @@ -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 `_ diff --git a/samples/modules/mctp/mctp_host/boards/nrf52840dk_nrf52840.overlay b/samples/modules/mctp/mctp_host/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..48c7f840dca --- /dev/null +++ b/samples/modules/mctp/mctp_host/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,3 @@ +&arduino_serial{ + status = "okay"; +}; diff --git a/samples/modules/mctp/mctp_host/prj.conf b/samples/modules/mctp/mctp_host/prj.conf new file mode 100644 index 00000000000..341787ecbd3 --- /dev/null +++ b/samples/modules/mctp/mctp_host/prj.conf @@ -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 diff --git a/samples/modules/mctp/mctp_host/src/main.c b/samples/modules/mctp/mctp_host/src/main.c new file mode 100644 index 00000000000..7fa9423c24c --- /dev/null +++ b/samples/modules/mctp/mctp_host/src/main.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +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; +}