Shell configuration interaction with MCUMGR dependency (Base64)

nRF Connect SDK v3.2.1, nRF9160dk


Hi,

I'm working on an application which connects to a MQTT broker over cellular network, and have MCUMGR enabled for firmware updates. I'm trying to integrate some sample shell code, which works fine in isolation, but is resulting in issues when I bring it over to my application.

When this option is present, it results in the board not showing any output when I monitor VCOM0.

# Configure dependencies for CONFIG_MCUMGR_TRANSPORT_UART
CONFIG_BASE64=y


Here's the main.c and prj.conf I used to test this.

# C++ standard
CONFIG_CPP=y
CONFIG_STD_CPP17=y
CONFIG_NEWLIB_LIBC=y
CONFIG_REQUIRES_FULL_LIBCPP=y


# Assert
CONFIG_POWEROFF=y
CONFIG_REBOOT=y
CONFIG_ASSERT=y
CONFIG_ASSERT_VERBOSE=y
CONFIG_RESET_ON_FATAL_ERROR=n


CONFIG_LOG=y
CONFIG_LOG_BUFFER_SIZE=32768
CONFIG_CBPRINTF_FP_SUPPORT=y


# Stack Analyzer
CONFIG_THREAD_ANALYZER=y
CONFIG_THREAD_STACK_INFO=y
CONFIG_THREAD_NAME=y
CONFIG_THREAD_ANALYZER_USE_PRINTK=y
# Stack initialization for watermarking
CONFIG_INIT_STACKS=y


# Stack protection
CONFIG_STACK_SENTINEL=y
CONFIG_HW_STACK_PROTECTION=y


# WDT
CONFIG_WATCHDOG=y
CONFIG_WDT_DISABLE_AT_BOOT=n
CONFIG_WDT_NRFX=y


# Input event handler
CONFIG_INPUT=y
CONFIG_INPUT_THREAD_STACK_SIZE=1536
# Input event logs
# CONFIG_INPUT_EVENT_DUMP=y


# Enable MCUMGR
CONFIG_MCUMGR=y

# Enable MCUMGR management for both OS and Images
CONFIG_MCUMGR_GRP_OS=y
CONFIG_MCUMGR_GRP_IMG=y

# Configure MCUMGR transport to UART
CONFIG_MCUMGR_TRANSPORT_UART=y

# Configure dependencies for CONFIG_MCUMGR
CONFIG_NET_BUF=y
CONFIG_ZCBOR=y
CONFIG_CRC=y

# Configure dependencies for CONFIG_MCUMGR_GRP_IMG
CONFIG_FLASH=y
CONFIG_IMG_MANAGER=y

# Configure dependencies for CONFIG_IMG_MANAGER
CONFIG_STREAM_FLASH=y
CONFIG_FLASH_MAP=y



# Configure dependencies for CONFIG_MCUMGR_TRANSPORT_UART
# NOTE: application works working if this is enabled
# CONFIG_BASE64=y 



CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y

# Shell features
CONFIG_SHELL_HISTORY=y
CONFIG_SHELL_HISTORY_BUFFER=512
CONFIG_SHELL_TAB=y
CONFIG_SHELL_TAB_AUTOCOMPLETION=y

# Shell configurations
CONFIG_SHELL=y
CONFIG_SHELL_WILDCARD=n
CONFIG_SHELL_PROMPT_UART="test > "
CONFIG_SHELL_ARGC_MAX=40
# -h and --help options are handled in Modem Shell
CONFIG_SHELL_HELP_OPT_PARSE=n
# Command line buffer is set this large to enable writing of certificates and injecting A-GNSS data on command line.
CONFIG_SHELL_CMD_BUFF_SIZE=3584
# Shell stack has impact for modem shell application, not CONFIG_MAIN_STACK_SIZE
CONFIG_SHELL_STACK_SIZE=9216
# Shell RX buffer needs to be increased to avoid problems with test automation
CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE=512
# Use interrupt driven shell UART, otherwise we won't be able to suspend the UART
CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN=y
#CONFIG_SERIAL_SUPPORT_INTERRUPT=y

# Shell support
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_SHELL_HISTORY=y
CONFIG_SHELL_HISTORY_BUFFER=512
CONFIG_SHELL_TAB=y
CONFIG_SHELL_TAB_AUTOCOMPLETION=y

# Console and logging
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_LOG=y
CONFIG_PRINTK=y

#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);

#define GPIO_NODE DT_NODELABEL(gpio0)
static const struct device* gpio = DEVICE_DT_GET(GPIO_NODE);

#define GREEN_PIN 9
#define RED_PIN   8

int main(void)
{
    gpio_pin_configure(gpio, GREEN_PIN, GPIO_OUTPUT_ACTIVE);
    gpio_pin_configure(gpio, RED_PIN, GPIO_OUTPUT_INACTIVE);

    LOG_INF("init");
    while (1) {
        gpio_pin_toggle(gpio, GREEN_PIN);
        gpio_pin_toggle(gpio, RED_PIN);
        k_sleep(K_MSEC(500));
    }
}

#include <zephyr/kernel.h>
#include <zephyr/shell/shell.h>

static int reboot_shell(const struct shell* sh, size_t argc, char** argv)
{
    shell_print(sh, "Rebooting device...");
    return 0;
}


SHELL_CMD_ARG_REGISTER(reboot, NULL, "Reboot the device.", reboot_shell, 1, 0);

Why does enabling CONFIG_BASE64 cause the application to not function as expected? Will disabling the option prevent remote firmware updates from being possible?

Thanks



Edit:

Just realized this was specifically what depended on Base64, "CONFIG_MCUMGR_TRANSPORT_UART".

Is the issue simply that UART shell and UART MCUMGR cannot coexist?

Parents Reply Children
  • No luck. The only option I did not already have was CONFIG_UART_CONSOLE_MCUMGR=y.

    When I add that to the prj.conf, I see a couple of print log output in a application pre-init function, but nothing from main. My initial description was wrong, as this appears to be the case with my original config prior to adding the option above. 

    I tried to make a sample project based on smp_srv, with some minor changes to enable the shell, but I get a similar issue.

    main.c

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     * Copyright (c) 2020 Prevas A/S
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/stats/stats.h>
    #include <zephyr/usb/usb_device.h>
    
    #ifdef CONFIG_MCUMGR_GRP_FS
    #include <zephyr/device.h>
    #include <zephyr/fs/fs.h>
    #include <zephyr/fs/littlefs.h>
    #endif
    #ifdef CONFIG_MCUMGR_GRP_STAT
    #include <zephyr/mgmt/mcumgr/grp/stat_mgmt/stat_mgmt.h>
    #endif
    
    #define LOG_LEVEL LOG_LEVEL_DBG
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(smp_sample);
    
    #include "common.h"
    
    #define STORAGE_PARTITION_LABEL	storage_partition
    #define STORAGE_PARTITION_ID	FIXED_PARTITION_ID(STORAGE_PARTITION_LABEL)
    
    /* Define an example stats group; approximates seconds since boot. */
    STATS_SECT_START(smp_svr_stats)
    STATS_SECT_ENTRY(ticks)
    STATS_SECT_END;
    
    /* Assign a name to the `ticks` stat. */
    STATS_NAME_START(smp_svr_stats)
    STATS_NAME(smp_svr_stats, ticks)
    STATS_NAME_END(smp_svr_stats);
    
    /* Define an instance of the stats group. */
    STATS_SECT_DECL(smp_svr_stats) smp_svr_stats;
    
    #ifdef CONFIG_MCUMGR_GRP_FS
    FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(cstorage);
    static struct fs_mount_t littlefs_mnt = {
    	.type = FS_LITTLEFS,
    	.fs_data = &cstorage,
    	.storage_dev = (void *)STORAGE_PARTITION_ID,
    	.mnt_point = "/lfs1"
    };
    #endif
    
    int main(void)
    {
    	int rc = STATS_INIT_AND_REG(smp_svr_stats, STATS_SIZE_32,
    				    "smp_svr_stats");
    
    	if (rc < 0) {
    		LOG_ERR("Error initializing stats system [%d]", rc);
    	}
    
    	/* Register the built-in mcumgr command handlers. */
    #ifdef CONFIG_MCUMGR_GRP_FS
    	rc = fs_mount(&littlefs_mnt);
    	if (rc < 0) {
    		LOG_ERR("Error mounting littlefs [%d]", rc);
    	}
    #endif
    
    #ifdef CONFIG_MCUMGR_TRANSPORT_BT
    	start_smp_bluetooth_adverts();
    #endif
    
    	/* using __TIME__ ensure that a new binary will be built on every
    	 * compile which is convenient when testing firmware upgrade.
    	 */
    	LOG_INF("build time: " __DATE__ " " __TIME__);
    
    	/* The system work queue handles all incoming mcumgr requests.  Let the
    	 * main thread idle while the mcumgr server runs.
    	 */
    	while (1) {
    		k_sleep(K_MSEC(1000));
    		STATS_INC(smp_svr_stats, ticks);
    	}
    	return 0;
    }
    
    #include <zephyr/kernel.h>
    #include <zephyr/shell/shell.h>
    int test_shell(const struct shell* sh, size_t argc, char** argv)
    {
        shell_print(sh, "test_shell");
        return 0;
    }
    SHELL_CMD_ARG_REGISTER(test, NULL, "Test", test_shell, 1, 0);
    

    prj.conf

    # Enable MCUmgr and dependencies.
    CONFIG_NET_BUF=y
    CONFIG_ZCBOR=y
    CONFIG_CRC=y
    CONFIG_MCUMGR=y
    CONFIG_STREAM_FLASH=y
    CONFIG_FLASH_MAP=y
    
    # Some command handlers require a large stack.
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304
    CONFIG_MAIN_STACK_SIZE=2176
    
    # Ensure an MCUboot-compatible binary is generated.
    CONFIG_BOOTLOADER_MCUBOOT=y
    
    # Enable flash operations.
    CONFIG_FLASH=y
    
    # Required by the `taskstat` command.
    CONFIG_THREAD_MONITOR=y
    
    # Support for taskstat command
    CONFIG_MCUMGR_GRP_OS_TASKSTAT=y
    
    # Enable statistics and statistic names.
    CONFIG_STATS=y
    CONFIG_STATS_NAMES=y
    
    # Enable most core commands.
    CONFIG_FLASH=y
    CONFIG_IMG_MANAGER=y
    CONFIG_MCUMGR_GRP_IMG=y
    CONFIG_MCUMGR_GRP_OS=y
    CONFIG_MCUMGR_GRP_STAT=y
    
    # Enable logging
    CONFIG_LOG=y
    CONFIG_MCUBOOT_UTIL_LOG_LEVEL_WRN=y
    
    # Disable debug logging
    CONFIG_LOG_MAX_LEVEL=3
    
    # Enable console with MCUmgr pass through
    CONFIG_MCUMGR_TRANSPORT_UART=y
    CONFIG_BASE64=y
    CONFIG_CRC=y
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y
    CONFIG_UART_CONSOLE_MCUMGR=y
    
    
    CONFIG_SHELL=y
    CONFIG_SHELL_BACKEND_SERIAL=y
    
    # Shell features
    CONFIG_SHELL_HISTORY=y
    CONFIG_SHELL_HISTORY_BUFFER=512
    CONFIG_SHELL_TAB=y
    CONFIG_SHELL_TAB_AUTOCOMPLETION=y
    
    # Shell configurations
    CONFIG_SHELL=y
    CONFIG_SHELL_WILDCARD=n
    CONFIG_SHELL_PROMPT_UART="test > "
    CONFIG_SHELL_ARGC_MAX=40
    # -h and --help options are handled in Modem Shell
    CONFIG_SHELL_HELP_OPT_PARSE=n
    # Command line buffer is set this large to enable writing of certificates and injecting A-GNSS data on command line.
    CONFIG_SHELL_CMD_BUFF_SIZE=3584
    # Shell stack has impact for modem shell application, not CONFIG_MAIN_STACK_SIZE
    CONFIG_SHELL_STACK_SIZE=9216
    # Shell RX buffer needs to be increased to avoid problems with test automation
    CONFIG_SHELL_BACKEND_SERIAL_RX_RING_BUFFER_SIZE=512
    # Use interrupt driven shell UART, otherwise we won't be able to suspend the UART
    CONFIG_SHELL_BACKEND_SERIAL_API_INTERRUPT_DRIVEN=y
    #CONFIG_SERIAL_SUPPORT_INTERRUPT=y
    
    # Shell support
    CONFIG_SHELL=y
    CONFIG_SHELL_BACKEND_SERIAL=y
    CONFIG_SHELL_HISTORY=y
    CONFIG_SHELL_HISTORY_BUFFER=512
    CONFIG_SHELL_TAB=y
    CONFIG_SHELL_TAB_AUTOCOMPLETION=y
    
    # Console and logging
    CONFIG_CONSOLE=y
    CONFIG_UART_CONSOLE=y
    CONFIG_LOG=y
    CONFIG_PRINTK=y

    Here's the output from the sample originally, compared to after my changes.

    before

    *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 ***
    *** Using nRF Connect SDK v3.2.1-d8887f6f32df ***
    *** Using Zephyr OS v4.2.99-ec78104f1569 ***
    I: Starting bootloader
    I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Image index: 0, Swap type: none
    I: Bootloader chainload address offset: 0x10000
    I: Image version: v0.0.0
    �*** Booting nRF Connect SDK v3.2.1-d8887f6f32df ***
    *** Using Zephyr OS v4.2.99-ec78104f1569 ***
    [00:00:00.251,586] <inf> smp_sample: build time: Mar 10 2026 13:23:10

    after

    *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 ***
    *** Using nRF Connect SDK v3.2.1-d8887f6f32df ***
    *** Using Zephyr OS v4.2.99-ec78104f1569 ***
    I: Starting bootloader
    I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Image index: 0, Swap type: none
    I: Bootloader chainload address offset: 0x10000
    I: Image version: v0.0.0
    <<<I pressed the reset button here>>>
    �*** Booting MCUboot v2.3.0-dev-0d9411f5dda3 ***
    *** Using nRF Connect SDK v3.2.1-d8887f6f32df ***
    *** Using Zephyr OS v4.2.99-ec78104f1569 ***
    I: Starting bootloader
    I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Image index: 0, Swap type: none
    I: Bootloader chainload address offset: 0x10000
    I: Image version: v0.0.0
    �: Jumping to the first image slot

  • Hi,

     

    Is the issue that your application does not boot after a dfu upgrade, or that the shell in general does not work?

    Have you tried entering debug mode to see if there is any specific place that you're stuck?

     

    If you have replicated this with smp_srv, could you please share the .diff or .zip of the project?

     

    Kind regards,

    Håkon

  • It appears that the shell just doesn't work when flashing in the sample directly. I haven't tested DFU while shell is enabled.

    I went into debug mode and was able to step through main and reach the while-loop at the end, doesn't appear to be stuck.

    I've attached the project zip. 

     1106.smp_svr.zip

  • Hi,

     

    This sample seems to be directed towards nRF5340dk, given the gpio_fwd entry in sysbuild/mcuboot folder?

    However, I removed these and the same with the nrf5340-specific configs in prj.conf, and built the project (CONFIG_BASE64 is set by the extra config file):

    west build -b nrf9160dk/nrf9160/ns -- -DEXTRA_CONF_FILE="overlay-shell-mgmt.conf;overlay-serial-console.conf"

     

    And this enables both uart console + shell:

    *** Booting MCUboot v2.3.0-dev-0d9411f5dda3 ***
    *** Using nRF Connect SDK v3.2.1-d8887f6f32df ***
    *** Using Zephyr OS v4.2.99-ec78104f1569 ***
    I: Starting bootloader
    I: Primary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Secondary image: magic=unset, swap_type=0x1, copy_done=0x3, image_ok=0x3
    I: Boot source: none
    I: Image index: 0, Swap type: none
    I: Bootloader chainload address offset: 0x10000
    I: Image version: v0.0.0
    ?: Jumping to the first image slot
    *** Booting nRF Connect SDK v3.2.1-d8887f6f32df ***
    *** Using Zephyr OS v4.2.99-ec78104f1569 ***
    [00:00:00.002,899] <inf> smp_sample: build time: Mar 12 2026 13:19:31
    uart:~$ 
      clear    date     device   devmem   help     history  kernel   rem
      resize   retval   shell
    uart:~$ help
    Please press the <Tab> button to see all available commands.
    You can also use the <Tab> button to prompt or auto-complete all commands or its subcommands.
    You can try to call commands with <-h> or <--help> parameter for more information.
    
    Shell supports following meta-keys:
      Ctrl + (a key from: abcdefklnpuw)
      Alt  + (a key from: bf)
    Please refer to shell documentation for more details.
    
    Available commands:
      clear    : Clear screen.
      date     : Date commands
      device   : Device commands
      devmem   : Read/write physical memory
                 Usage:
                 Read memory at address with optional width:
                 devmem <address> [<width>]
                 Write memory at address with mandatory width and value:
                 devmem <address> <width> <value>
      help     : Prints the help message.
      history  : Command history.
      kernel   : Kernel commands
      rem      : Ignore lines beginning with 'rem '
      resize   : Console gets terminal screen size or assumes default in case the
                 readout fails. It must be executed after each terminal width change
                 to ensure correct text display.
      retval   : Print return value of most recent command
      shell    : Useful, not Unix-like shell commands.
    uart:~$ 

    Did you use a different build setup? Could you please share how you configured the sample?

     

    Kind regards,

    Håkon

  • Toolchain/SDK 3.2.1, nrf9160dk_9160_ns, prj.conf only (with copy/paste from the other over confs).

    Thanks, I'll try to reproduce your results.

Related