From e3adf905a37e60014033221cee011d9e8ac4b8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20J=C3=A4ger?= Date: Sat, 10 Jun 2023 06:46:51 +0200 Subject: [PATCH] Add implementation for DFU via ThingSet --- .github/workflows/build.yml | 1 + Kconfig | 1 + include/thingset/sdk.h | 6 ++- samples/counter/dfu.conf | 23 ++++++++ src/CMakeLists.txt | 1 + src/Kconfig.dfu | 18 +++++++ src/dfu.c | 105 ++++++++++++++++++++++++++++++++++++ west.yml | 4 +- 8 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 samples/counter/dfu.conf create mode 100644 src/Kconfig.dfu create mode 100644 src/dfu.c diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4651bb2..a907597 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,6 +43,7 @@ jobs: west build -p -b esp32c3_devkitm samples/counter -- -DEXTRA_CONF_FILE=ble.conf -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y west build -p -b esp32c3_devkitm samples/counter -- -DEXTRA_CONF_FILE=wifi_websocket.conf -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y west build -p -b native_posix samples/counter -- -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y + west build -p -b nrf52840dk_nrf52840 samples/counter -- -DOVERLAY_CONFIG=dfu.conf west build -p -b nucleo_l073rz samples/counter -- -DEXTRA_CONF_FILE=serial.conf -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y west build -p -b nucleo_l073rz samples/counter -- -DEXTRA_CONF_FILE=storage_eeprom.conf -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y west build -p -b native_posix samples/counter -- -DEXTRA_CONF_FILE=auth.conf -DCONFIG_COMPILER_WARNINGS_AS_ERRORS=y diff --git a/Kconfig b/Kconfig index 63ce8f9..3743092 100644 --- a/Kconfig +++ b/Kconfig @@ -9,6 +9,7 @@ if THINGSET_SDK rsource "src/Kconfig.auth" rsource "src/Kconfig.ble" rsource "src/Kconfig.can" +rsource "src/Kconfig.dfu" rsource "src/Kconfig.log_backend" rsource "src/Kconfig.lorawan" rsource "src/Kconfig.serial" diff --git a/include/thingset/sdk.h b/include/thingset/sdk.h index b661805..7caafee 100644 --- a/include/thingset/sdk.h +++ b/include/thingset/sdk.h @@ -65,7 +65,11 @@ extern "C" { #define TS_ID_NET_CAN_NODE_ADDR 0x28C /* Device Firmware Upgrade group items */ -#define TS_ID_DFU 0x2D +#define TS_ID_DFU 0x2D +#define TS_ID_DFU_INIT 0x2D0 +#define TS_ID_DFU_WRITE 0x2D1 +#define TS_ID_DFU_DATA 0x2D2 +#define TS_ID_DFU_BOOT 0x2D3 /* Log group items */ #define TS_ID_LOG 0x2E diff --git a/samples/counter/dfu.conf b/samples/counter/dfu.conf new file mode 100644 index 0000000..9ac776b --- /dev/null +++ b/samples/counter/dfu.conf @@ -0,0 +1,23 @@ +# Copyright (c) The ThingSet Project Contributors +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_THINGSET_DFU=y + +# Flash driver to store firmware image +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_FLASH_PAGE_LAYOUT=y +#CONFIG_FLASH_LOG_LEVEL_WRN=y +CONFIG_IMG_MANAGER=y +#CONFIG_IMG_BLOCK_BUF_SIZE=512 +#CONFIG_IMG_ERASE_PROGRESSIVELY=y + +#CONFIG_MPU_ALLOW_FLASH_WRITE=y + +CONFIG_STREAM_FLASH=y + +# Application-side MCUboot configuration +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_MCUBOOT_IMG_MANAGER=y +CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="bootloader/mcuboot/root-ec-p256.pem" +CONFIG_MCUBOOT_GENERATE_CONFIRMED_IMAGE=y diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 122b40c..70c2edd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ zephyr_library_sources_ifdef(CONFIG_THINGSET_SDK packetizer.c) zephyr_library_sources_ifdef(CONFIG_THINGSET_AUTH auth.c) zephyr_library_sources_ifdef(CONFIG_THINGSET_BLE ble.c) zephyr_library_sources_ifdef(CONFIG_THINGSET_CAN can.c) +zephyr_library_sources_ifdef(CONFIG_THINGSET_DFU dfu.c) zephyr_library_sources_ifdef(CONFIG_THINGSET_LOG_BACKEND log_backend.c) zephyr_library_sources_ifdef(CONFIG_THINGSET_LORAWAN lorawan.c) zephyr_library_sources_ifdef(CONFIG_THINGSET_SERIAL serial.c) diff --git a/src/Kconfig.dfu b/src/Kconfig.dfu new file mode 100644 index 0000000..a02530a --- /dev/null +++ b/src/Kconfig.dfu @@ -0,0 +1,18 @@ +# Copyright (c) The ThingSet Project Contributors +# SPDX-License-Identifier: Apache-2.0 + +menuconfig THINGSET_DFU + bool "ThingSet device firmware upgrade" + depends on FLASH + select REBOOT + +if THINGSET_DFU + +config THINGSET_DFU_CHUNK_SIZE + int "Firmware chunk size" + range 64 4096 + default 256 + help + Maximum chunk size that can be transmitted in one ThingSet message. + +endif # THINGSET_DFU diff --git a/src/dfu.c b/src/dfu.c new file mode 100644 index 0000000..6489e4c --- /dev/null +++ b/src/dfu.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) The ThingSet Project Contributors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(thingset_dfu, CONFIG_LOG_DEFAULT_LEVEL); + +#define TARGET_IMAGE_AREA FIXED_PARTITION_ID(slot1_partition) + +static uint8_t bytes_buf[CONFIG_THINGSET_DFU_CHUNK_SIZE]; +static THINGSET_DEFINE_BYTES(bytes_item, bytes_buf, 0); + +static int32_t thingset_dfu_init(); +static int32_t thingset_dfu_write(); +static int32_t thingset_dfu_boot(); + +THINGSET_ADD_GROUP(TS_ID_ROOT, TS_ID_DFU, "DFU", THINGSET_NO_CALLBACK); +THINGSET_ADD_FN_INT32(TS_ID_DFU, TS_ID_DFU_INIT, "xInit", &thingset_dfu_init, THINGSET_ANY_RW); +THINGSET_ADD_FN_INT32(TS_ID_DFU, TS_ID_DFU_WRITE, "xWrite", &thingset_dfu_write, THINGSET_ANY_RW); +THINGSET_ADD_ITEM_BYTES(TS_ID_DFU_WRITE, TS_ID_DFU_DATA, "bData", &bytes_item, THINGSET_ANY_RW, 0); +THINGSET_ADD_FN_INT32(TS_ID_DFU, TS_ID_DFU_BOOT, "xBoot", &thingset_dfu_boot, THINGSET_ANY_RW); + +static bool dfu_initialized = false; + +static struct flash_img_context flash_img_ctx; + +static int32_t thingset_dfu_init() +{ + int err; + + if (!IS_ENABLED(CONFIG_IMG_ERASE_PROGRESSIVELY)) { + LOG_DBG("Erasing flash area"); + + err = boot_erase_img_bank(TARGET_IMAGE_AREA); + if (err) { + LOG_ERR("Failed to erase image bank (err %d)", err); + return err; + } + } + + err = flash_img_init_id(&flash_img_ctx, TARGET_IMAGE_AREA); + if (err) { + LOG_ERR("Failed to initialize flash img (err %d)", err); + return err; + } + + dfu_initialized = true; + + return 0; +} + +static int32_t thingset_dfu_write() +{ + int err; + + if (!dfu_initialized) { + LOG_ERR("DFU not initialized"); + return -EBUSY; + } + + err = flash_img_buffered_write(&flash_img_ctx, bytes_item.bytes, bytes_item.num_bytes, false); + if (err) { + LOG_ERR("Failed to write data (err %d)", err); + return err; + } + else { + size_t total_bytes = flash_img_bytes_written(&flash_img_ctx); + LOG_INF("Total bytes downloaded: 0x%.6X (%d)", total_bytes, total_bytes); + } + + return 0; +} + +static int32_t thingset_dfu_boot() +{ + int err; + uint8_t dummy = 0; + + /* make sure that flash_img buffer is flushed */ + flash_img_buffered_write(&flash_img_ctx, &dummy, 0, true); + + err = boot_request_upgrade(BOOT_UPGRADE_TEST); + if (err) { + LOG_ERR("Failed to request upgrade (err %d)", err); + return err; + } + + LOG_INF("Program downloaded, rebooting..."); + + sys_reboot(SYS_REBOOT_COLD); + + return 0; +} diff --git a/west.yml b/west.yml index 04f4211..ffc7771 100644 --- a/west.yml +++ b/west.yml @@ -23,8 +23,10 @@ manifest: - hal_st - loramac-node - mbedtls - - tinycrypt + - mcuboot - picolibc + - segger + - tinycrypt - name: thingset-node-c remote: thingset revision: d2a610db9a650067ce9fc3381c0b350c9246c88c