DFU in Zephyr + nsc 2.3.0

Hello guys, I've been looking for an example of using DFU (Device Firmware Update) with Zephyr for quite some time now. Previously, I used to do it quite easily with the classic SDK in Keil uVision. However, I'm struggling to find a step-by-step example with the new operating system.

1. Project Configuration
2. Using DFU with BLE (Bluetooth Low Energy) via smartphone
3. How to create a signed file and add it to nrfToolBox
4. How to verify everything

"In practice, a Buttonless DFU (Device Firmware Update) in Zephyr."

Thanks in advance

Babos

Parents
  • Hi Silvio, 

    DFU protocol in Zephyr is quite different from the nRF SDK DFU protocol. 

    Among other things here are the main difference: 


    - On air protocols are different. They are not compatible. So the sign process is now different. The bootloader is now MCUBoot. 

    - The DFU update is now background DFU update. Meaning the application doesn't switch to bootloader mode to do DFU (except for serial recovery mode)

    - Only dual bank update supported. 

    My suggestion is to have a look at the documentation here. We have a guide here that can help you to getting started with the DFU update. 

Reply
  • Hi Silvio, 

    DFU protocol in Zephyr is quite different from the nRF SDK DFU protocol. 

    Among other things here are the main difference: 


    - On air protocols are different. They are not compatible. So the sign process is now different. The bootloader is now MCUBoot. 

    - The DFU update is now background DFU update. Meaning the application doesn't switch to bootloader mode to do DFU (except for serial recovery mode)

    - Only dual bank update supported. 

    My suggestion is to have a look at the documentation here. We have a guide here that can help you to getting started with the DFU update. 

Children
  • Hi Hung,

    these samples of which you gave me the links, refer to a version SDK 1.7 of nordic. Isn't there something newer? In ncs 2.3.0 I can't find the names of the samples unless they have changed.
    Thank you

  • Attached are the changes I managed to make in Simon's example regarding updating a smartphone app. I compile but I can't insert, because it doesn't recognize them, the configurations:
    - # Enable mcumgr.
    CONFIG_MCUMGR=y

    # Enable most core commands.
    CONFIG_MCUMGR_CMD_IMG_MGMT=y
    CONFIG_MCUMGR_CMD_OS_MGMT=y

    And

    # Enable the Bluetooth (unauthenticated) and shell mcumgr transports.
    CONFIG_MCUMGR_SMP_BT=y
    CONFIG_MCUMGR_SMP_BT_AUTHEN=n

    because it doesn't seem to recognize them in my ncs 2.3.0 system so I export the file but I get an error from my smartphone: "SMP service not found"

    any idea ?

    Silvio

    #
    # Copyright (c) 2018 Nordic Semiconductor
    #
    # SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
    #
    CONFIG_NCS_SAMPLES_DEFAULTS=y
    
    CONFIG_BT=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DEVICE_NAME="NORDIC_LBS"
    
    # Enable the LBS service
    CONFIG_BT_LBS=y
    CONFIG_BT_LBS_POLL_BUTTON=y
    CONFIG_DK_LIBRARY=y
    
    # Ensure an MCUboot-compatible binary is generated.
    CONFIG_BOOTLOADER_MCUBOOT=y
    
    # Allow for large Bluetooth data packets.
    CONFIG_BT_L2CAP_TX_MTU=252
    CONFIG_BT_BUF_ACL_RX_SIZE=256
    
    # Enable the Bluetooth (unauthenticated) and shell mcumgr transports.
    
    # Some command handlers require a large stack.
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096

    Code:

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/byteorder.h>
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include <soc.h>
    
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    #include <zephyr/bluetooth/conn.h>
    #include <zephyr/bluetooth/uuid.h>
    #include <zephyr/bluetooth/gatt.h>
    
    #include <bluetooth/services/lbs.h>
    
    #include <zephyr/settings/settings.h>
    
    #include <dk_buttons_and_leds.h>
    
    #include <zephyr/mgmt/mcumgr/transport/smp_bt.h>
    
    #define DEVICE_NAME             CONFIG_BT_DEVICE_NAME
    #define DEVICE_NAME_LEN         (sizeof(DEVICE_NAME) - 1)
    
    
    #define RUN_STATUS_LED          DK_LED1
    #define CON_STATUS_LED          DK_LED2
    #define RUN_LED_BLINK_INTERVAL  1000
    
    #define USER_LED                DK_LED3
    
    #define USER_BUTTON             DK_BTN1_MSK
    
    static bool app_button_state;
    
    static const struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
    };
    
    static const struct bt_data sd[] = {
    BT_DATA_BYTES(BT_DATA_UUID128_ALL,
    		      0x84, 0xaa, 0x60, 0x74, 0x52, 0x8a, 0x8b, 0x86,
    		      0xd3, 0x4c, 0xb7, 0x1d, 0x1d, 0xdc, 0x53, 0x8d),
    };
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err) {
    		printk("Connection failed (err %u)\n", err);
    		return;
    	}
    
    	printk("Connected\n");
    
    	dk_set_led_on(CON_STATUS_LED);
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason %u)\n", reason);
    
    	dk_set_led_off(CON_STATUS_LED);
    }
    
    #ifdef CONFIG_BT_LBS_SECURITY_ENABLED
    static void security_changed(struct bt_conn *conn, bt_security_t level,
    			     enum bt_security_err err)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (!err) {
    		printk("Security changed: %s level %u\n", addr, level);
    	} else {
    		printk("Security failed: %s level %u err %d\n", addr, level,
    			err);
    	}
    }
    #endif
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected        = connected,
    	.disconnected     = disconnected,
    #ifdef CONFIG_BT_LBS_SECURITY_ENABLED
    	.security_changed = security_changed,
    #endif
    };
    
    #if defined(CONFIG_BT_LBS_SECURITY_ENABLED)
    static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Passkey for %s: %06u\n", addr, passkey);
    }
    
    static void auth_cancel(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing cancelled: %s\n", addr);
    }
    
    static void pairing_complete(struct bt_conn *conn, bool bonded)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing completed: %s, bonded: %d\n", addr, bonded);
    }
    
    static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing failed conn: %s, reason %d\n", addr, reason);
    }
    
    static struct bt_conn_auth_cb conn_auth_callbacks = {
    	.passkey_display = auth_passkey_display,
    	.cancel = auth_cancel,
    };
    
    static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
    	.pairing_complete = pairing_complete,
    	.pairing_failed = pairing_failed
    };
    #else
    static struct bt_conn_auth_cb conn_auth_callbacks;
    static struct bt_conn_auth_info_cb conn_auth_info_callbacks;
    #endif
    
    static void app_led_cb(bool led_state)
    {
    	dk_set_led(USER_LED, led_state);
    }
    
    static bool app_button_cb(void)
    {
    	return app_button_state;
    }
    
    static struct bt_lbs_cb lbs_callbacs = {
    	.led_cb    = app_led_cb,
    	.button_cb = app_button_cb,
    };
    
    static void button_changed(uint32_t button_state, uint32_t has_changed)
    {
    	if (has_changed & USER_BUTTON) {
    		uint32_t user_button_state = button_state & USER_BUTTON;
    
    		bt_lbs_send_button_state(user_button_state);
    		app_button_state = user_button_state ? true : false;
    	}
    }
    
    static int init_button(void)
    {
    	int err;
    
    	err = dk_buttons_init(button_changed);
    	if (err) {
    		printk("Cannot init buttons (err: %d)\n", err);
    	}
    
    	return err;
    }
    
    int main(void)
    {
    	int blink_status = 0;
    	int err;
    
    	printk("Starting Bluetooth Peripheral LBS example\n");
    
    	err = dk_leds_init();
    	if (err) {
    		printk("LEDs init failed (err %d)\n", err);
    		return 0;
    	}
    
    	err = init_button();
    	if (err) {
    		printk("Button init failed (err %d)\n", err);
    		return 0;
    	}
    
    	if (IS_ENABLED(CONFIG_BT_LBS_SECURITY_ENABLED)) {
    		err = bt_conn_auth_cb_register(&conn_auth_callbacks);
    		if (err) {
    			printk("Failed to register authorization callbacks.\n");
    			return 0;
    		}
    
    		err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
    		if (err) {
    			printk("Failed to register authorization info callbacks.\n");
    			return 0;
    		}
    	}
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return 0;
    	}
    
    	printk("Bluetooth initialized\n");
    	
    
    	if (IS_ENABLED(CONFIG_SETTINGS)) {
    		settings_load();
    	}
    
    	err = bt_lbs_init(&lbs_callbacs);
    	if (err) {
    		printk("Failed to init LBS (err:%d)\n", err);
    		return 0;
    	}
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    			      sd, ARRAY_SIZE(sd));
    	if (err) {
    		printk("Advertising failed to start (err %d)\n", err);
    		return 0;
    	}
        printk("\n\nbuild time: " __DATE__ " " __TIME__ "\n");
    	printk("Advertising successfully started\n");
    
    	for (;;) {
    		dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
    		k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
    	}
    }
    

  • CONFIG_MCUMGR was assigned the value y, but got the value n. Missing dependencies:
    ZCBOR

  • Hi Silvio, 
    The sample is peripheral_lbs and it's located in \nrf\samples\bluetooth\peripheral_lbs.

    Have you followed the last step to add: smp_bt_register() into the code ? 

Related