Skip to content

Commit fcdfce5

Browse files
committed
samples: mcuboot: Add firmware loader entrance sample
Adds a sample showing how to reboot into MCUboot's firmware loader application for being able to load firmware updates Signed-off-by: Jamie McCrae <[email protected]>
1 parent 531b27e commit fcdfce5

File tree

7 files changed

+313
-0
lines changed

7 files changed

+313
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.20.0)
8+
9+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
10+
project(firmware_loader_entrance)
11+
12+
target_sources(app PRIVATE src/main.c)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
mcuboot:
2+
address: 0x0
3+
region: flash_primary
4+
size: 0x8000
5+
app:
6+
address: 0x8200
7+
region: flash_primary
8+
size: 0x5fe00
9+
mcuboot_pad:
10+
address: 0x8000
11+
region: flash_primary
12+
size: 0x200
13+
mcuboot_primary:
14+
address: 0x8000
15+
orig_span: &id001
16+
- app
17+
- mcuboot_pad
18+
region: flash_primary
19+
size: 0x60000
20+
span: *id001
21+
mcuboot_primary_app:
22+
address: 0x8200
23+
orig_span: &id002
24+
- app
25+
region: flash_primary
26+
size: 0x5fe00
27+
span: *id002
28+
mcuboot_secondary:
29+
address: 0x68000
30+
orig_span: &id003
31+
- mcuboot_secondary_pad
32+
- firmware_loader
33+
region: flash_primary
34+
size: 0x60000
35+
span: *id003
36+
mcuboot_secondary_pad:
37+
region: flash_primary
38+
address: 0x68000
39+
size: 0x200
40+
firmware_loader:
41+
region: flash_primary
42+
address: 0x68200
43+
size: 0x5fe00
44+
settings_storage:
45+
address: 0xc8000
46+
region: flash_primary
47+
size: 0x4000
48+
unallocated:
49+
address: 0xcc000
50+
region: flash_primary
51+
size: 0x34000
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Enable MCUmgr and dependencies.
2+
CONFIG_NET_BUF=y
3+
CONFIG_ZCBOR=y
4+
CONFIG_MCUMGR=y
5+
CONFIG_BT=y
6+
CONFIG_BT_PERIPHERAL=y
7+
8+
# Allow for large Bluetooth data packets.
9+
CONFIG_BT_L2CAP_TX_MTU=498
10+
CONFIG_BT_BUF_ACL_RX_SIZE=502
11+
CONFIG_BT_BUF_ACL_TX_SIZE=502
12+
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
13+
14+
# Enable the Bluetooth mcumgr transport (unauthenticated).
15+
CONFIG_MCUMGR_TRANSPORT_BT=y
16+
CONFIG_MCUMGR_TRANSPORT_BT_CONN_PARAM_CONTROL=y
17+
18+
# Enable the mcumgr Packet Reassembly feature over Bluetooth and its configuration dependencies.
19+
# MCUmgr buffer size is optimized to fit one SMP packet divided into five Bluetooth Write Commands,
20+
# transmitted with the maximum possible MTU value: 498 bytes.
21+
CONFIG_MCUMGR_TRANSPORT_BT_REASSEMBLY=y
22+
CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE=2475
23+
CONFIG_MCUMGR_GRP_OS_MCUMGR_PARAMS=y
24+
CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_STACK_SIZE=4608
25+
26+
# Enable OS management with bootloader information and boot mode support
27+
CONFIG_MCUMGR_GRP_OS=y
28+
CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE=y
29+
CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO=y
30+
31+
# Disable Bluetooth ping support
32+
CONFIG_BT_CTLR_LE_PING=n
33+
34+
# Enable logging
35+
CONFIG_LOG=y
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
sample:
2+
name: Firmware loader entrance
3+
description: Demo application for entering the firmware loader application
4+
common:
5+
sysbuild: true
6+
build_only: true
7+
tests:
8+
sample.mcuboot.firmware_loader_entrance:
9+
harness: bluetooth
10+
tags: bluetooth
11+
platform_allow:
12+
- nrf52840dk/nrf52840
13+
integration_platforms:
14+
- nrf52840dk/nrf52840
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/settings/settings.h>
9+
#include <zephyr/bluetooth/bluetooth.h>
10+
#include <zephyr/bluetooth/hci.h>
11+
#include <zephyr/bluetooth/conn.h>
12+
#include <zephyr/bluetooth/uuid.h>
13+
#include <zephyr/bluetooth/gatt.h>
14+
#include <zephyr/mgmt/mcumgr/transport/smp_bt.h>
15+
#include <zephyr/logging/log.h>
16+
17+
LOG_MODULE_REGISTER(firmware_entrance_loader, LOG_LEVEL_DBG);
18+
19+
static struct k_work adv_work;
20+
21+
static const struct bt_data ad[] = {
22+
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
23+
BT_DATA_BYTES(BT_DATA_UUID128_ALL, SMP_BT_SVC_UUID_VAL),
24+
};
25+
26+
static const struct bt_data sd[] = {
27+
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, (sizeof(CONFIG_BT_DEVICE_NAME) - 1)),
28+
};
29+
30+
static void adv_work_handler(struct k_work *work)
31+
{
32+
int rc = bt_le_adv_start(BT_LE_ADV_CONN_FAST_2, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
33+
34+
if (rc) {
35+
LOG_ERR("Advertising failed to start: %d", rc);
36+
return;
37+
}
38+
39+
LOG_INF("Advertising successfully started, device name: %s", CONFIG_BT_DEVICE_NAME);
40+
}
41+
42+
static void advertising_start(void)
43+
{
44+
k_work_submit(&adv_work);
45+
}
46+
47+
static void connected(struct bt_conn *conn, uint8_t err)
48+
{
49+
if (err) {
50+
LOG_ERR("Connection failed: 0x%02x (%s)", err, bt_hci_err_to_str(err));
51+
return;
52+
}
53+
54+
LOG_INF("Connected");
55+
}
56+
57+
static void disconnected(struct bt_conn *conn, uint8_t reason)
58+
{
59+
LOG_INF("Disconnected, reason: 0x%02x (%s)", reason, bt_hci_err_to_str(reason));
60+
}
61+
62+
static void recycled_cb(void)
63+
{
64+
LOG_INF("Connection object available from previous conn. Disconnect is complete!");
65+
advertising_start();
66+
}
67+
68+
#ifdef CONFIG_BT_SMP
69+
static void security_changed(struct bt_conn *conn, bt_security_t level,
70+
enum bt_security_err err)
71+
{
72+
char addr[BT_ADDR_LE_STR_LEN];
73+
74+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
75+
76+
if (!err) {
77+
LOG_INF("Security changed: %s level %u", addr, level);
78+
} else {
79+
LOG_INF("Security failed: %s level %u error: %d (%s)", addr, level, err,
80+
bt_security_err_to_str(err));
81+
}
82+
}
83+
#endif
84+
85+
BT_CONN_CB_DEFINE(conn_callbacks) = {
86+
.connected = connected,
87+
.disconnected = disconnected,
88+
.recycled = recycled_cb,
89+
#ifdef CONFIG_BT_SMP
90+
.security_changed = security_changed,
91+
#endif
92+
};
93+
94+
#if defined(CONFIG_BT_SMP)
95+
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
96+
{
97+
char addr[BT_ADDR_LE_STR_LEN];
98+
99+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
100+
101+
LOG_INF("Passkey for %s: %06u", addr, passkey);
102+
}
103+
104+
static void auth_cancel(struct bt_conn *conn)
105+
{
106+
char addr[BT_ADDR_LE_STR_LEN];
107+
108+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
109+
110+
LOG_INF("Pairing cancelled: %s", addr);
111+
}
112+
113+
static void pairing_complete(struct bt_conn *conn, bool bonded)
114+
{
115+
char addr[BT_ADDR_LE_STR_LEN];
116+
117+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
118+
119+
LOG_INF("Pairing completed: %s, bonded: %d", addr, bonded);
120+
}
121+
122+
static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
123+
{
124+
char addr[BT_ADDR_LE_STR_LEN];
125+
126+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
127+
128+
LOG_INF("Pairing failed conn: %s, reason: %d (%s)", addr, reason,
129+
bt_security_err_to_str(reason));
130+
}
131+
132+
static struct bt_conn_auth_cb conn_auth_callbacks = {
133+
.passkey_display = auth_passkey_display,
134+
.cancel = auth_cancel,
135+
};
136+
137+
static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
138+
.pairing_complete = pairing_complete,
139+
.pairing_failed = pairing_failed
140+
};
141+
#else
142+
static struct bt_conn_auth_cb conn_auth_callbacks;
143+
static struct bt_conn_auth_info_cb conn_auth_info_callbacks;
144+
#endif
145+
146+
int main(void)
147+
{
148+
int rc;
149+
150+
if (IS_ENABLED(CONFIG_BT_SMP)) {
151+
rc = bt_conn_auth_cb_register(&conn_auth_callbacks);
152+
153+
if (rc) {
154+
LOG_ERR("Failed to register authorization callbacks.");
155+
return 0;
156+
}
157+
158+
rc = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
159+
160+
if (rc) {
161+
LOG_ERR("Failed to register authorization info callbacks.");
162+
return 0;
163+
}
164+
}
165+
166+
rc = bt_enable(NULL);
167+
168+
if (rc) {
169+
LOG_ERR("Bluetooth init failed: %d", rc);
170+
return 0;
171+
}
172+
173+
LOG_INF("Bluetooth initialized");
174+
175+
if (IS_ENABLED(CONFIG_SETTINGS)) {
176+
settings_load();
177+
}
178+
179+
k_work_init(&adv_work, adv_work_handler);
180+
advertising_start();
181+
182+
return 0;
183+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
SB_CONFIG_BOOTLOADER_MCUBOOT=y
8+
SB_CONFIG_MCUBOOT_MODE_FIRMWARE_UPDATER=y
9+
SB_CONFIG_MCUBOOT_MODE_FIRMWARE_UPDATER_BOOT_MODE_ENTRANCE=y
10+
SB_CONFIG_FIRMWARE_LOADER_IMAGE_SMP_SVR_MINI_BOOT=y
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#
2+
# Copyright (c) 2025 Nordic Semiconductor ASA
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO=y
8+
CONFIG_BOOT_FIRMWARE_LOADER_NO_APPLICATION=y

0 commit comments

Comments
 (0)