How to modify an app to be updated and update from it with MCUBoot.

I need to upgrade firmware with MCUBoot (buttonless). I have read these tutorials:

https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.1.0/zephyr/samples/subsys/mgmt/mcumgr/smp_svr/README.html#smp-svr-sample-build

https://devzone.nordicsemi.com/guides/nrf-connect-sdk-guides/b/software/posts/ncs-dfu#modify_hello_world

I have a nrf52840dk and working with ncs v2.2.0 and my limitation is that I have to use the J3 USB connector.

If I follow the steps provided in the first tutorial (SMP_Server), I can build the sample with the next command:

west build  -p  -b nrf52840dk_nrf52840    zephyr/samples/subsys/mgmt/mcumgr/smp_svr    --    -DOVERLAY_CONFIG=overlay-cdc.conf   -DDTC_OVERLAY_FILE=usb.overlay

I can acces to mcumgr through J3 usb connector:

mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" echo hello
hello

So now I can go to the second tutorial I provided. There I can see how to modify a sample to be uploaded to the board. I just have to add to the prj.conf:

# Enable mcumgr.
CONFIG_MCUMGR=y

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

# Ensure an MCUboot-compatible binary is generated.
CONFIG_BOOTLOADER_MCUBOOT=y

# Enable the serial mcumgr transport.
CONFIG_MCUMGR_SMP_UART=y

# Disable UART Console and enable the RTT console
CONFIG_UART_CONSOLE=n
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y

# Some command handlers require a large stack.
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096

And add in the main the next code:

#include "os_mgmt/os_mgmt.h"
#include "img_mgmt/img_mgmt.h"

#inside main
os_mgmt_register_group();
img_mgmt_register_group();

So now I can compile a blinky sample with that modification and I can upgrade my board with the blinky sample. The problem is that once the board is updated, the J3 usb connector is not available anymore.

I decided to modify the blinky sample to be FLASHED and that the J3 usb port is available. So the first step was include in the building command the same overlay-cdc.conf and usb.overlay that are included in the SMP_Server sample. 

I modified the main.c file too, because in the last post of this thread tell that the USB has to be initialized, including:

#include "os_mgmt/os_mgmt.h"
#include "img_mgmt/img_mgmt.h"
#include <zephyr/usb/usb_device.h>

//inside main
os_mgmt_register_group();
img_mgmt_register_group();
	
if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) {
	    int rc = usb_enable(NULL);
	    if (rc) {
	      LOG_ERR("Failed to enable USB");
	      return;
	    }
	}

And obviously the prj.conf is modified too:

CONFIG_GPIO=y

# Enable mcumgr.
CONFIG_MCUMGR=y

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

# Ensure an MCUboot-compatible binary is generated.
CONFIG_BOOTLOADER_MCUBOOT=y

# Enable the serial mcumgr transport.
CONFIG_MCUMGR_SMP_UART=y

# Disable UART Console and enable the RTT console
CONFIG_UART_CONSOLE=n
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y

# Some command handlers require a large stack.
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096

When I build and flash into my DK board I can see the J3 port available (ls /dev/tty*), but mcumgr is nos responding. What more should I add from the SMP_Server sample to my blinky project to enable mcumgr?

I attach the project in the case you want to check something:

3010.blinky.zip

  • Resolved!

    I have to add this to the "nrf52840dk_nrf52840.overlay":

    / {
    	chosen {
    		zephyr,uart-mcumgr = &cdc_acm_uart0;
    	};
    };
    
    zephyr_udc0: &usbd {
    	compatible = "nordic,nrf-usbd";
    	status = "okay";
    };
    
    &zephyr_udc0 {
    	cdc_acm_uart0: cdc_acm_uart0 {
    		compatible = "zephyr,cdc-acm-uart";
    	};
    };

    The main.c would be:

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/gpio.h>
    #include "os_mgmt/os_mgmt.h"
    #include "img_mgmt/img_mgmt.h"
    #include <zephyr/usb/usb_device.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   100
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    
    /*
     * A build error on this line means your board is unsupported.
     * See the sample documentation for information on how to fix this.
     */
    static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
    
    void main(void)
    {
    	int ret;
    
    	os_mgmt_register_group();
    	img_mgmt_register_group();
    	
    	if (IS_ENABLED(CONFIG_USB_DEVICE_STACK)) {
    		int rc = usb_enable(NULL);
    		if (rc) {
    			//LOG_ERR("Failed to enable USB");
    			return;
    		}
    	}
    
    	if (!device_is_ready(led.port)) {
    		return;
    	}
    
    	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
    	if (ret < 0) {
    		return;
    	}
    
    	while (1) {
    		ret = gpio_pin_toggle_dt(&led);
    		if (ret < 0) {
    			return;
    		}
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    

    And the prj.conf:

    CONFIG_GPIO=y
    
    ### overlay-cdc.conf
    # Enable USB subsystem
    CONFIG_USB_DEVICE_STACK=y
    CONFIG_SERIAL=y
    CONFIG_UART_LINE_CTRL=y
    # USB backend is serial device
    CONFIG_MCUMGR_SMP_UART=y
    ###
    
    # Enable mcumgr.
    CONFIG_MCUMGR=y
    
    # Enable most core commands.
    CONFIG_MCUMGR_CMD_IMG_MGMT=y
    CONFIG_MCUMGR_CMD_OS_MGMT=y
    
    # Ensure an MCUboot-compatible binary is generated.
    CONFIG_BOOTLOADER_MCUBOOT=y
    # Enable the serial mcumgr transport.
    CONFIG_MCUMGR_SMP_UART=y
    
    # Disable UART Console and enable the RTT console
    CONFIG_UART_CONSOLE=n
    CONFIG_RTT_CONSOLE=y
    CONFIG_USE_SEGGER_RTT=y
    
    # Some command handlers require a large stack.
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096

    Now it works!

Related