Skip to content

Commit bab3aa0

Browse files
[Telink] Add DFU over BLE SMP feature (project-chip#41742)
* [Telink] Add device firmware update over BLE * [Telink] Make DFU over BLE SMP independent from Matter OTA build * [Telink] Add dfu-usb target build for CI usage * [Telink] Remove redundant code for DFU over BLE SMP * [Telink] Fix lock with dfu build and add draft implementation of header processing with DFU over BLE SMP * [Telink] Add footer validation for DFU over SMP * [Telink] Fix DFU over SMP for zephyr v3.3 * [Telink] Add image version verification for DFU over SMP * [Telink] Add image generation for DFU over BLE SMP * [Telink] Fix build target --------- Co-authored-by: Nazarii Bodnar <[email protected]>
1 parent 290cf00 commit bab3aa0

File tree

15 files changed

+453
-16
lines changed

15 files changed

+453
-16
lines changed

.github/workflows/examples-telink.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -245,15 +245,15 @@ jobs:
245245
- name: clean out build output (keep tools)
246246
run: rm -rf ./out/telink*
247247

248-
- name: Build example Telink (B92) Lock App with DFU
248+
- name: Build example Telink (B92) Lock App with DFU over BLE SMP
249249
# Run test for master and s07641069 PRs
250250
if: github.event.pull_request.number == null || github.event.pull_request.head.repo.full_name == 's07641069/connectedhomeip'
251251
run: |
252252
./scripts/run_in_build_env.sh \
253-
"./scripts/build/build_examples.py --target 'telink-tlsr9528a-lock-dfu' build"
253+
"./scripts/build/build_examples.py --target 'telink-tlsr9528a-lock-dfu-smp' build"
254254
.environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \
255-
telink tlsr9528a lock-app-dfu \
256-
out/telink-tlsr9528a-lock-dfu/zephyr/zephyr.elf \
255+
telink tlsr9528a lock-app-dfu-smp \
256+
out/telink-tlsr9528a-lock-dfu-smp/zephyr/zephyr.elf \
257257
/tmp/bloat_reports/
258258
259259
- name: clean out build output (keep tools)
@@ -540,12 +540,12 @@ jobs:
540540
- name: clean out build output (keep tools)
541541
run: rm -rf ./out/telink*
542542

543-
- name: Build example Telink (B92) Lock App with DFU
543+
- name: Build example Telink (B92) Lock App with DFU over BLE SMP
544544
# Run test for master and s07641069 PRs
545545
if: github.event.pull_request.number == null || github.event.pull_request.head.repo.full_name == 's07641069/connectedhomeip'
546546
run: |
547547
./scripts/run_in_build_env.sh \
548-
"./scripts/build/build_examples.py --target 'telink-tlsr9528a-lock-dfu' build"
548+
"./scripts/build/build_examples.py --target 'telink-tlsr9528a-lock-dfu-smp' build"
549549
550550
- name: clean out build output (keep tools)
551551
run: rm -rf ./out/telink*

config/telink/chip-module/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,19 @@ if (CONFIG_CHIP_OTA_IMAGE_BUILD)
211211
add_dependencies(chip-ota-image process_binaries)
212212
endif()
213213

214+
# ==============================================================================
215+
# Define 'dfu-smp-image' target for building DFU over BT SMP image
216+
# ==============================================================================
217+
218+
if (CONFIG_CHIP_DFU_OVER_BT_SMP_BUILD)
219+
file(WRITE "${PROJECT_BINARY_DIR}/empty.txt" "")
220+
chip_ota_image(dfu-smp-image
221+
INPUT_FILES ${PROJECT_BINARY_DIR}/empty.txt
222+
OUTPUT_FILE ${PROJECT_BINARY_DIR}/dfu.data
223+
)
224+
add_dependencies(process_binaries dfu-smp-image)
225+
endif()
226+
214227
# ==============================================================================
215228
# Define 'factory_data' target for generating a factory data partition
216229
# ==============================================================================

config/telink/chip-module/Kconfig

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ config SIGNED_OTA_IMAGE_FILE_NAME
8383
string "Zephyr signed image file name"
8484
default "zephyr.signed.lzma.signed.bin" if COMPRESS_LZMA
8585
default "zephyr.signed.bin"
86-
depends on CHIP_OTA_REQUESTOR
86+
depends on BOOTLOADER_MCUBOOT
8787
help
8888
Provides the file name of the generated Zephyr signed image.
8989

@@ -95,6 +95,28 @@ config TELINK_OTA_BUTTON_TEST
9595
Merge the signed binary with the same version as the main into slot-1 of merged.hex.
9696
Pressing the button initiates a forced image update.
9797

98+
config CHIP_DFU_OVER_BT_SMP
99+
bool "Enable DFU over Bluetooth LE SMP feature set"
100+
select BOOTLOADER_MCUBOOT
101+
select MCUMGR
102+
select MCUMGR_TRANSPORT_BT
103+
select ZCBOR
104+
select MCUMGR_GRP_IMG
105+
select MCUMGR_GRP_OS
106+
select MCUMGR_GRP_ZBASIC
107+
select MCUMGR_GRP_ZBASIC_STORAGE_ERASE
108+
select MCUMGR_TRANSPORT_BT_REASSEMBLY
109+
select MCUMGR_MGMT_NOTIFICATION_HOOKS
110+
select MCUMGR_GRP_IMG_UPLOAD_CHECK_HOOK
111+
select MCUMGR_GRP_IMG_STATUS_HOOKS
112+
help
113+
Enables Device Firmware Upgrade over Bluetooth LE with SMP and configures
114+
the set of options related to that feature.
115+
116+
config CHIP_DFU_OVER_BT_SMP_BUILD
117+
bool "Enable DFU over BT SMP image building"
118+
default n
119+
98120
config TELINK_OTA_PARTITION_ADDR
99121
hex "image-1 partition address"
100122
default $(dt_node_reg_addr_hex,$(dt_nodelabel_path,slot1_partition),0)

examples/light-switch-app/telink/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2022-2024 Project CHIP Authors
2+
# Copyright (c) 2022-2025 Project CHIP Authors
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.
@@ -59,6 +59,11 @@ if(CONFIG_BOOTLOADER_MCUBOOT)
5959
target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
6060
endif()
6161

62+
if(CONFIG_MCUMGR_TRANSPORT_BT)
63+
zephyr_library_link_libraries(MCUBOOT_BOOTUTIL)
64+
target_sources(app PRIVATE ${TELINK_COMMON}/util/src/DFUOverSMP.cpp)
65+
endif()
66+
6267
if (CONFIG_CHIP_PW_RPC)
6368
include(${TELINK_COMMON}/Rpc.cmake)
6469
endif(CONFIG_CHIP_PW_RPC)

examples/light-switch-app/telink/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ CONFIG_BT_DEVICE_NAME="TelinkSwitch"
3030

3131
# Disable Matter OTA DFU
3232
CONFIG_CHIP_OTA_REQUESTOR=n
33+
CONFIG_CHIP_DFU_OVER_BT_SMP=n
3334
CONFIG_CHIP_DEVICE_SOFTWARE_VERSION=1
3435

3536
# Disable CHIP shell support

examples/lighting-app/telink/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2022-2024 Project CHIP Authors
2+
# Copyright (c) 2022-2025 Project CHIP Authors
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.
@@ -91,6 +91,11 @@ if(CONFIG_BOOTLOADER_MCUBOOT)
9191
target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
9292
endif()
9393

94+
if(CONFIG_MCUMGR_TRANSPORT_BT)
95+
zephyr_library_link_libraries(MCUBOOT_BOOTUTIL)
96+
target_sources(app PRIVATE ${TELINK_COMMON}/util/src/DFUOverSMP.cpp)
97+
endif()
98+
9499
if (CONFIG_CHIP_PW_RPC)
95100
include(${TELINK_COMMON}/Rpc.cmake)
96101
endif(CONFIG_CHIP_PW_RPC)

examples/lighting-app/telink/prj.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ CONFIG_BT_DEVICE_NAME="TelinkLight"
3030

3131
# Disable Matter OTA DFU
3232
CONFIG_CHIP_OTA_REQUESTOR=n
33+
CONFIG_CHIP_DFU_OVER_BT_SMP=n
3334
CONFIG_CHIP_DEVICE_SOFTWARE_VERSION=1
3435
CONFIG_TELINK_OTA_BUTTON_TEST=n
3536

examples/lock-app/telink/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,8 @@ chip_configure_data_model(app
5959
if(CONFIG_BOOTLOADER_MCUBOOT)
6060
target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
6161
endif()
62+
63+
if(CONFIG_MCUMGR_TRANSPORT_BT)
64+
zephyr_library_link_libraries(MCUBOOT_BOOTUTIL)
65+
target_sources(app PRIVATE ${TELINK_COMMON}/util/src/DFUOverSMP.cpp)
66+
endif()

examples/platform/telink/common/src/AppTaskCommon.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
#include <OTAUtil.h>
4545
#endif
4646

47+
#ifdef CONFIG_MCUMGR_TRANSPORT_BT
48+
#include <DFUOverSMP.h>
49+
#endif
50+
4751
#if CONFIG_CHIP_OTA_REQUESTOR
4852
#include <app/clusters/ota-requestor/OTARequestorInterface.h>
4953
#endif
@@ -243,6 +247,13 @@ CHIP_ERROR AppTaskCommon::StartApp(void)
243247
DispatchEvent(&event);
244248
}
245249
}
250+
#ifdef CONFIG_MCUMGR_TRANSPORT_BT
251+
/* Demonstration of the fail handling */
252+
void HandleDFUFail(VerificationFailReason reason)
253+
{
254+
LOG_INF("DFU image verification failed with reason: %d", reason);
255+
}
256+
#endif
246257
void AppTaskCommon::PrintFirmwareInfo(void)
247258
{
248259
LOG_INF("SW Version: %u, %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION, CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
@@ -327,6 +338,10 @@ CHIP_ERROR AppTaskCommon::InitCommonParts(void)
327338
// src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp
328339
emberAfEndpointEnableDisable(kNetworkCommissioningEndpointSecondary, false);
329340
#endif
341+
#ifdef CONFIG_MCUMGR_TRANSPORT_BT
342+
GetDFUOverSMP().Init();
343+
GetDFUOverSMP().SetFailCallback(HandleDFUFail);
344+
#endif
330345

331346
// We need to disable OpenThread to prevent writing to the NVS storage when factory reset occurs
332347
// The OpenThread thread is running during factory reset. The nvs_clear function is called during
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
*
3+
* Copyright (c) 2025 Project CHIP Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* @file
20+
* Provides an implementation of Device Firmware Upgrade using SMP protocol
21+
* over Bluetooth LE functionality for Telink platform.
22+
*/
23+
24+
#pragma once
25+
26+
#include <lib/core/OTAImageHeader.h>
27+
#include <zephyr/drivers/flash.h>
28+
#include <zephyr/storage/flash_map.h>
29+
30+
enum VerificationFailReason : unsigned char
31+
{
32+
NO_FAIL = 0,
33+
WRONG_PRODUCT_ID = 1 << 1,
34+
WRONG_VENDOR_ID = 1 << 2,
35+
WRONG_VERSION = 1 << 3,
36+
};
37+
38+
using verificationFailCallback = void (*)(VerificationFailReason);
39+
40+
/**
41+
* @brief DFU over SMP helper class
42+
*
43+
* The purpose of this class is to enable Device Firmware Upgrade mechanism
44+
* using Simple Management Protocol (SMP) over Bluetooth LE. Besides
45+
* facilitating initialization of the SMP server, it is capable of requesting
46+
* BLE advertising in a way that is compatible with other application components
47+
* that use BLE, such as Matter BLE layer.
48+
*/
49+
class DFUOverSMP
50+
{
51+
public:
52+
/**
53+
* @brief Initialize DFU over SMP utility
54+
*
55+
* Initialize internal structures and register necessary commands in the SMP
56+
* server.
57+
*/
58+
void Init();
59+
60+
/**
61+
* @brief Set callback function for verification failing event
62+
*
63+
* Set a callback function that will be called if the image footer verification fails.
64+
* Callback function have to receive argument that will describe
65+
* what was the reason of the failure.
66+
*/
67+
void SetFailCallback(verificationFailCallback cb);
68+
69+
/**
70+
* @brief Start processing the footer of the image in slot 1.
71+
*
72+
* Starts footer check of the newly received image in the slot 1.
73+
*/
74+
CHIP_ERROR ProcessImageFooter();
75+
76+
private:
77+
static constexpr uint16_t VERSION_STRING_MAX_LENGTH = 64;
78+
79+
verificationFailCallback failCallback;
80+
81+
friend DFUOverSMP & GetDFUOverSMP();
82+
static DFUOverSMP sDFUOverSMP;
83+
84+
CHIP_ERROR GetDFUImageFooter(chip::OTAImageHeader & footer, const struct flash_area * fa);
85+
CHIP_ERROR GetDFUImageFooterOffset(unsigned int & footer_offset, const struct flash_area * fa);
86+
CHIP_ERROR CheckDFUImageFooter(chip::OTAImageHeader * imageHeader);
87+
};
88+
89+
inline DFUOverSMP & GetDFUOverSMP()
90+
{
91+
return DFUOverSMP::sDFUOverSMP;
92+
}

0 commit comments

Comments
 (0)