From 3db3e1bdbae96d1eaa05af18b4898ae1cc7f150e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bobo=20B=C3=A4ck=20Engstr=C3=B6m?= Date: Wed, 25 Mar 2026 13:28:20 +0100 Subject: [PATCH] feat: integrate mender-mcu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bobo Bäck Engström --- app/CMakeLists.txt | 2 +- app/boards/mikroe_clicker_2.overlay | 30 ++++- app/boards/mikroe_clicker_2_mcuboot.conf | 6 + app/boards/mikroe_clicker_2_mcuboot.overlay | 39 +++++++ app/prj.conf | 16 +++ app/src/main.c | 6 + app/src/mender.c | 118 ++++++++++++++++++++ app/src/mender.h | 12 ++ west.yml | 7 ++ 9 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 app/boards/mikroe_clicker_2_mcuboot.conf create mode 100644 app/boards/mikroe_clicker_2_mcuboot.overlay create mode 100644 app/src/mender.c create mode 100644 app/src/mender.h diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 45b552f..2e18890 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -22,6 +22,6 @@ else() set(creds "src/creds/ca.c" "src/creds/key.c" "src/creds/cert.c") endif() -set(helpers "src/sensor.c" "src/modem.c" "src/aws.c") +set(helpers "src/sensor.c" "src/modem.c" "src/aws.c" "src/mender.c") target_sources(app PRIVATE src/main.c ${helpers} ${creds}) diff --git a/app/boards/mikroe_clicker_2.overlay b/app/boards/mikroe_clicker_2.overlay index 082c20e..7b24117 100644 --- a/app/boards/mikroe_clicker_2.overlay +++ b/app/boards/mikroe_clicker_2.overlay @@ -22,7 +22,35 @@ chosen { zephyr,modem-uart = &mikrobus_uart; - zephyr,code-partition = &flash0; + zephyr,code-partition = &slot0_partition; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00020000>; + }; + + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x00020000 0x00060000>; + }; + + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x00060000>; + }; + + mender_partition: partition@e0000 { + label = "mender"; + reg = <0x000e0000 0x00020000>; + }; }; }; diff --git a/app/boards/mikroe_clicker_2_mcuboot.conf b/app/boards/mikroe_clicker_2_mcuboot.conf new file mode 100644 index 0000000..6d3dbb8 --- /dev/null +++ b/app/boards/mikroe_clicker_2_mcuboot.conf @@ -0,0 +1,6 @@ +CONFIG_BOOT_UPGRADE_ONLY=y +CONFIG_BOOT_SWAP_USING_OFFSET=n +CONFIG_BOOT_SWAP_USING_SCRATCH=n +CONFIG_MCUBOOT_LOG_LEVEL_DBG=y +CONFIG_MCUBOOT_LOG_LEVEL_INF=n +CONFIG_MCUBOOT_UTIL_LOG_LEVEL_DBG=y diff --git a/app/boards/mikroe_clicker_2_mcuboot.overlay b/app/boards/mikroe_clicker_2_mcuboot.overlay new file mode 100644 index 0000000..845157a --- /dev/null +++ b/app/boards/mikroe_clicker_2_mcuboot.overlay @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2026 ID8 Engineering AB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,code-partition = &boot_partition; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x00020000>; + }; + + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x00020000 0x00060000>; + }; + + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x00060000>; + }; + + mender_partition: partition@e0000 { + label = "mender"; + reg = <0x000e0000 0x00020000>; + }; + }; +}; diff --git a/app/prj.conf b/app/prj.conf index 8f6d95f..24135a8 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -22,7 +22,11 @@ CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=32768 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=4096 CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PK_WRITE_C=y CONFIG_MBEDTLS_SSL_SERVER_NAME_INDICATION=y CONFIG_MBEDTLS_HAVE_TIME_DATE=y CONFIG_MBEDTLS_SSL_ALPN=y @@ -79,8 +83,20 @@ CONFIG_JSON_LIBRARY=y # Logging CONFIG_LOG=y CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_OUTPUT_FORMAT_ISO8601_TIMESTAMP=y CONFIG_MODEM_MODULES_LOG_LEVEL_INF=y +# Mender +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_MCUBOOT_IMGTOOL_OVERWRITE_ONLY=y +CONFIG_MENDER_MCU_CLIENT=y +CONFIG_MENDER_SERVER_HOST_EU=y +CONFIG_MENDER_SERVER_TENANT_TOKEN="..." +CONFIG_MENDER_DEVICE_TYPE="mikroe-clicker-2" +CONFIG_MENDER_ZEPHYR_IMAGE_UPDATE_MODULE=y +CONFIG_MENDER_DEPLOYMENT_LOGS=n +CONFIG_MENDER_ARTIFACT_GENERATE=n + # App CONFIG_SENSOR=y CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/app/src/main.c b/app/src/main.c index b6011c3..b2ee8d8 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -10,6 +10,7 @@ #include #include "aws.h" +#include "mender.h" #include "modem.h" #include "sensor.h" @@ -71,6 +72,11 @@ int main(void) LOG_ERR("sensor: device not ready"); return -ENODEV; } + ret = mender_start(); + if (ret < 0) { + LOG_ERR("Mender start failed: %d", ret); + return ret; + } ret = aws_init(); if (ret < 0) { LOG_ERR("AWS init failed: %d", ret); diff --git a/app/src/mender.c b/app/src/mender.c new file mode 100644 index 0000000..6d2db39 --- /dev/null +++ b/app/src/mender.c @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2026 ID8 Engineering AB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(mender_app, LOG_LEVEL_INF); + +static char mender_identity_value[32]; +static mender_identity_t mender_identity = { + .name = "imei", + .value = mender_identity_value, +}; + +static mender_err_t mender_network_connect_cb(void) +{ + /* The application keeps the PPP link up continuously. */ + return MENDER_OK; +} + +static mender_err_t mender_network_release_cb(void) +{ + /* The PPP link is shared with AWS and should remain connected. */ + return MENDER_OK; +} + +static mender_err_t mender_restart_cb(void) +{ + LOG_INF("Mender requested restart"); + sys_reboot(SYS_REBOOT_COLD); + return MENDER_OK; +} + +static mender_err_t mender_deployment_status_cb(mender_deployment_status_t status, + const char *status_name) +{ + ARG_UNUSED(status); + LOG_INF("Mender deployment status: %s", status_name); + return MENDER_OK; +} + +static mender_err_t mender_get_identity_cb(const mender_identity_t **identity) +{ + const struct device *modem = DEVICE_DT_GET(DT_ALIAS(modem)); + int ret; + + if (identity == NULL) { + return MENDER_FAIL; + } + + if (mender_identity.value[0] == '\0') { + ret = cellular_get_modem_info(modem, CELLULAR_MODEM_INFO_IMEI, mender_identity_value, + sizeof(mender_identity_value)); + if (ret < 0 || mender_identity_value[0] == '\0') { + LOG_ERR("Unable to read modem IMEI for Mender identity: %d", ret); + return MENDER_FAIL; + } + } + + *identity = &mender_identity; + return MENDER_OK; +} + +int mender_start(void) +{ + mender_err_t ret; + mender_client_config_t config = { + .device_type = CONFIG_MENDER_DEVICE_TYPE, + .host = NULL, + .tenant_token = NULL, + .device_tier = CONFIG_MENDER_DEVICE_TIER, + .update_poll_interval = 0, +#ifndef CONFIG_MENDER_CLIENT_INVENTORY_DISABLE + .inventory_update_interval = 0, +#endif + .backoff_interval = 0, + .max_backoff_interval = 0, + .recommissioning = false, + }; + mender_client_callbacks_t callbacks = { + .network_connect = mender_network_connect_cb, + .network_release = mender_network_release_cb, + .deployment_status = mender_deployment_status_cb, + .restart = mender_restart_cb, + .get_identity = mender_get_identity_cb, + .get_user_provided_keys = NULL, + }; + + ret = mender_client_init(&config, &callbacks); + if (ret != MENDER_OK) { + LOG_ERR("Mender init failed: %d", ret); + return -EINVAL; + } + + ret = mender_zephyr_image_register_update_module(); + if (ret != MENDER_OK) { + LOG_ERR("Mender update module registration failed: %d", ret); + return -EINVAL; + } + + ret = mender_client_activate(); + if (ret != MENDER_OK) { + LOG_ERR("Mender activation failed: %d", ret); + return -EINVAL; + } + + LOG_INF("Mender activated"); + return 0; +} diff --git a/app/src/mender.h b/app/src/mender.h new file mode 100644 index 0000000..3cbc2ef --- /dev/null +++ b/app/src/mender.h @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: 2026 ID8 Engineering AB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef MENDER_H_ +#define MENDER_H_ + +int mender_start(void); + +#endif /* MENDER_H_ */ diff --git a/west.yml b/west.yml index e0fd9f9..ffdb399 100644 --- a/west.yml +++ b/west.yml @@ -17,6 +17,13 @@ manifest: - hal_st - hal_stm32 - mbedtls + - mcuboot + + - name: mender-mcu + url: https://github.com/mendersoftware/mender-mcu + revision: main + path: modules/mender-mcu + import: true self: path: seven-clicker-sample