nRF5340 Getting FOTA to work with both app core and net core simultaneously

Hello,

I've been working on getting FOTA to work for multi-image DFUs, but have not been able to get it. I've read through countless forums, and something I heard was that we need external flash to DFU both the app and net core. However, a coworker told me he was able to partition the internal flash on our DK boards to support FOTAing without external flashing. He's not sure how to do it on v2.4.2, though. If you have any information on how we could do this in 2.4.2, that would be great!

I've followed a few samples to get simultaneous FOTA working, such as this one https://github.com/hellesvik-nordic/samples_for_nrf_connect_sdk/tree/main/bootloader_samples/nrf5340/mcuboot_smp_ble_simultaneous . My DK board had weird functionality with this project. When I would first start the DFU, after I clicked "Confirm and Test" in the nRF Device Manager iOS mobile app, I would get an error saying "Unable to find secondary slot for image 0 in Test Response" for the "State". After, I would click "Start" and "Confirm and Test" a second time, and then it would very quickly finish and say "UPLOAD COMPLETE." This seems to mean that it worked, but I'm not certain.

For my own project, currently I'm able to build and flash my board, but I can't see it being listed as a Bluetooth device to connect to.

Here is my prj.conf file:

# Enable Bootloader
CONFIG_BOOTLOADER_MCUBOOT=y

# Enable SMP Server
CONFIG_MCUMGR=y
CONFIG_BASE64=y
CONFIG_MCUMGR_TRANSPORT_UART=y
CONFIG_MCUMGR_GRP_IMG=y

# Enable BLE transfer
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Test SMP Server"
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y

CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_MCUBOOT_USE_ALL_AVAILABLE_RAM=y
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y
CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP=y
CONFIG_MCUBOOT_IMAGE_VERSION="2.3.0+0"
CONFIG_NRF53_UPGRADE_NETWORK_CORE=y
CONFIG_UPDATEABLE_IMAGE_NUMBER=2
CONFIG_ADD_MCUBOOT_MEDIATE_SIM_FLASH_DTS=y


CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096

# configure peripherals
CONFIG_NRFX_TWIM0=y
CONFIG_NRFX_TWIM1=y
CONFIG_I2C=y
CONFIG_NRFX_QSPI=n
CONFIG_SPI=y
CONFIG_SPI_EXTENDED_MODES=y
CONFIG_NRFX_SPIM2=y
CONFIG_NRFX_SPIM3=y
CONFIG_NRFX_SPIM4=y
CONFIG_NRFX_TIMER0=y
CONFIG_NRFX_TIMER1=y
CONFIG_NRFX_TIMER2=y
CONFIG_NRFX_PWM0=y

CONFIG_SCHED_DUMB=y
CONFIG_SCHED_DEADLINE=y

#DFU Stuff
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_ZCBOR=y
CONFIG_MCUMGR=y
# CONFIG_BT_SMP=y


# add DSP libraries
CONFIG_CMSIS_DSP=y
CONFIG_CMSIS_DSP_STATISTICS=y
CONFIG_FORCE_NO_ASSERT=y
#CONFIG_BT=y
#CONFIG_BT_PERIPHERAL=y
CONFIG_ADD_MCUBOOT_MEDIATE_SIM_FLASH_DTS=y

#TDCS Stuff
CONFIG_ADC=y
CONFIG_NRFX_SAADC=y

# watchdog
CONFIG_WATCHDOG=y
CONFIG_WDT_DISABLE_AT_BOOT=y

Here is my mcuboot.conf file:

CONFIG_BOOT_SIGNATURE_KEY_FILE="C:/Users/NolanGeer/Documents/GitHub/nrf5340_firmware/keys/nirskey.pem"
# Enable flash simulator
CONFIG_FLASH_SIMULATOR=y
CONFIG_FLASH_SIMULATOR_DOUBLE_WRITES=y
CONFIG_FLASH_SIMULATOR_STATS=n
CONFIG_NORDIC_QSPI_NOR=y
CONFIG_NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE=16

CONFIG_MAIN_STACK_SIZE=10240
CONFIG_BOOT_MAX_IMG_SECTORS=256


CONFIG_NRF53_MULTI_IMAGE_UPDATE=y
CONFIG_UPDATEABLE_IMAGE_NUMBER=2

CONFIG_BOOT_UPGRADE_ONLY=y
CONFIG_BOOT_IMAGE_ACCESS_HOOK_NRF5340=y
CONFIG_BOOT_IMAGE_ACCESS_HOOKS=y

Here is my overlay file:

// To get started, press Ctrl+Space to bring up the completion menu and view the available nodes.

// You can also use the buttons in the sidebar to perform actions on nodes.
// Actions currently available include:

// * Enabling / disabling the node
// * Adding the bus to a bus
// * Removing the node
// * Connecting ADC channels

// For more help, browse the DeviceTree documentation at https://docs.zephyrproject.org/latest/guides/dts/index.html
// You can also visit the nRF DeviceTree extension documentation at https://nrfconnect.github.io/vscode-nrf-connect/devicetree/nrfdevicetree.html
/ {
	chosen {
		nordic,pm-ext-flash = &mx25r64;
	};
};


/ {
	zephyr,user {
		io-channels = <&adc 0>, <&adc 1>;
	};
};

&pinctrl {
    spi2_default: spi2_default {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
                <NRF_PSEL(SPIM_MOSI, 0, 30)>,
                <NRF_PSEL(SPIM_MISO, 1, 0)>;
        };
    };

    spi2_sleep: spi2_sleep {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK, 1, 15)>,
                <NRF_PSEL(SPIM_MOSI, 0, 30)>,
                <NRF_PSEL(SPIM_MISO, 1, 0)>;
            low-power-enable;
        };
    };
};

&spi2 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    cs-gpios = <&gpio1 14 1>;
    pinctrl-0 = <&spi2_default>;
    pinctrl-1 = <&spi2_sleep>;
    pinctrl-names = "default", "sleep";
};

&adc {
    #address-cells = <1>;
    #size-cells = <0>;
 
    channel@0 {
        reg = <0>;
        zephyr,gain = "ADC_GAIN_1_6";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,input-positive = <NRF_SAADC_AIN4>;
    };

    channel@1 {
        reg = <1>;
        zephyr,gain = "ADC_GAIN_1_6";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
        zephyr,input-positive = <NRF_SAADC_AIN5>;
    };
 };

I also have a .conf file for the NSIB first-stage bootloader (hci_rpmsg.conf)

CONFIG_SECURE_BOOT=y
CONFIG_SB_SIGNING_KEY_FILE="C:/Users/NolanGeer/Documents/GitHub/nrf5340_firmware/keys/nirskey_ecdsa.pem"

Finally, I also have an overlay file for my mcuboot, named mcuboot.overlay, but I don't think it's doing anything. I'm not sure about this, but I saw it in the example I linked above.

/ {
	chosen {
		nordic,pm-ext-flash = &mx25r64;
	};
};

I have another version of my project where I could connect to the Bluetooth and start the FOTA, but I would get the error: Invalid value(3). I wasn't sure what this meant, so I moved onto trying to copy the sample.

Let me know if you need any other information. I've read through quite a bit of forum posts to no avail, so hopefully we can figure this out.

Thanks in advance!

  • Hi Nolan,

    Let's see if we can make this work.

    First, I will comment on your ticket, and ask some questions.

    However, a coworker told me he was able to partition the internal flash on our DK boards to support FOTAing without external flashing.

    You can do it with internal flash, but thing is, the "nordic,pm-ext-flash = &mx25r64;" configuration enables a lot of stuff automatically in the background, so this is easier to start with.

    We are working on adding it more easily in these PRs:

    https://github.com/nrfconnect/sdk-nrf/pull/10060

    https://github.com/nrfconnect/sdk-mcuboot/pull/235

    If you want to use internal flash for now, I think you can have a look this sample:

    peripheral_lbs_dfu(2).zip

    When I would first start the DFU, after I clicked "Confirm and Test" i

    From  my repo:

    Does it behave as expected if you only "Confirm" and reset manually?

    That being said, it should be possible to automate this more, but you may have to enable more functionality for the project in that case. Let me know what you would expect and I can try to guide you to how to fix that.

    For my own project, currently I'm able to build and flash my board, but I can't see it being listed as a Bluetooth device to connect to.

    Can you see Bluetooth on your own device with simple Bluetooth firmware, not any bootloader or anything fancy?

    Do you get any error logs from your app or bootloader?

    Regards,
    Sigurd Hellesvik

  • Hi Sigurd, thanks for the reply!

    For your first question,

    Does it behave as expected if you only "Confirm" and reset manually?

    it does, actually! I'm not sure why I hadn't tried this before. It seems my debugging skills are failing me. I've been tunnel-visioning on changing Kconfig values for a little over a week now, so my head is stuck in the weeds!

    Let me know what you would expect and I can try to guide you to how to fix that.

    Honestly, my goal is to just get FOTAing both cores to work as easily as possible. My coworker told me we didn't have an external flash and we disabled our QSPI as you can see in our prj.conf file. The sample seemed to work with it enabled though, which was a bit confusing.

    Can you see Bluetooth on your own device with simple Bluetooth firmware, not any bootloader or anything fancy?

    Yes, the Bluetooth works for the sample project I'm using for FOTAing as well as a sample project for Bluetooth mesh. These are a bit fancier than plain Bluetooth firmware but they show that the Bluetooth works regardless.

    Do you get any error logs from your app or bootloader?

    I do not believe so. The build completes in VSCode, and that's the only logging we have. I've enabled debugging logs in prj.conf before, but I'm not sure where those are output to. I've not seen them before.

    It seems like I'm very close to getting my project to work on FOTA, and I'm hesitant to change any Kconfig values since I know that I can break the build easily. I have every property to display on Bluetooth, because I copied the sample's prj.conf and added them to the end of my own prj.conf, so if the sample project can display on Bluetooth then I'm not sure why mine can't. It was displaying before, so something may have changed it.

    Thanks for helping me with this!

    All the best,

    Nolan Geer

  • Also, what exactly is happening when I select "Confirm and Test" instead of "Confirm Only"? How is it "confirming" the images? What is being tested?

  • Nolan_G said:

    The sample seemed to work with it enabled though, which was a bit confusing.

    That is because the external flash enabling in the Partition manager sets up some stuff automatically, which are also needed for internal flash. So in current versions of the SDK, you kindof need it either way.

    Nolan_G said:
    Yes, the Bluetooth works for the sample project I'm using for FOTAing as well as a sample project for Bluetooth mesh. These are a bit fancier than plain Bluetooth firmware but they show that the Bluetooth works regardless.

    Nice nice! Just wanted to make sure the antenna on the custom board actually worked. Have had tickets before where we debugged software only for the issue to be hardware.

    Nolan_G said:
    I do not believe so. The build completes in VSCode, and that's the only logging we have. I've enabled debugging logs in prj.conf before, but I'm not sure where those are output to. I've not seen them before.

    Not only for bootloaders, I advise you to have logging output from your nRF chip. It will make it a lot easier to debug issues, for example the current issue. See Logging in nRF Connect SDK for docs on this. UART and RTT are the most used alternatives. For custom board, you have not always routed out an UART for logging, so then you may have to use RTT, whcih can be used via a debugger.
    Making RTT work with the bootloader is a bit tricky, so if you need that, I suggest you first try it from the DK. I can help doing that if needed.

    Nolan_G said:
    and I'm hesitant to change any Kconfig values since I know that I can break the build easily.

    Hold on, do you not use git?
    If you do use git, can you commit your current progress to something (testing branch or whatever), and it will be saved.
    If you do not use git, I highly recommend that you use any kind of version control.

    Nolan_G said:
    o if the sample project can display on Bluetooth then I'm not sure why mine can't.

    Maybe your project crashes before it gets to the application?
    The DK has external flash, so if the bootloader can not find external flash and therefore crashes, it will not run the application. Or something similar like that.
    So what I want to know is this: Is it only BLE from the app that does not work, or does no part of the app work? If only some parts of the app work, which? Logging would be a nice tool to figure this out.

    Nolan_G said:
    Also, what exactly is happening when I select "Confirm and Test" instead of "Confirm Only"? How is it "confirming" the images? What is being tested?

    See my repo explaining test or confirm. "Test & Confirm" mode will first tag the image as Test, then reboot the device to swap, and then tag the image as confirm. This is so that if the new image crashes, the bootloader will revert to the old one, which we know works. It is a feature to not break the device with a broker update.

  • Thanks again for the response, Sigurd!

    Hold on, do you not use git?

    Haha, I do use git. I have about 6 branches of different commits in different stages right now. I'm hesitant to change Kconfig values because I don't understand all of them, and my pristine build takes about 3min 30sec, so it's painful to change one by one without knowing what I'm actually changing. I should definitely sit and patiently read through what every option does so that I can have a better idea about what I'm doing, though.

    So what I want to know is this: Is it only BLE from the app that does not work, or does no part of the app work? If only some parts of the app work, which? Logging would be a nice tool to figure this out.

    I'm actually not sure if the rest of the app is working since connecting to Bluetooth is typically what I do before trying any of the other modules.

    In its current state, before adding any changes to make multicore FOTAing work, my application can be detected on BLE and connected to without the configuration changes from the sample application I linked as well as the sample application you linked. So, basically, my application without any changes can be seen on BLE, but when I try my app + either of the samples' Kconfig settings, it's no longer detectable. I actually, literally, append the prj.conf from the sample to the end of my prj.conf, as well as the mcuboot.conf to the end of my own mcuboot.conf. In the sample, the mcuboot.conf isn't called mcuboot.conf but rather it's a .conf within a board name folder within a mcuboot folder. These seem to have functioned the same. Duplicate values won't be set twice and/or will have a squiggly line to indicate removing them, so I'm assuming this is okay to do.

    Also, some important information, multi-image FOTAing used to work with my application in SDK 2.2.0, and I enabled dfu with these lines.

    void dfu_init(void)
    {
        os_mgmt_register_group();
        img_mgmt_register_group();
    
        smp_bt_register();
    }

    I'll try enabling and viewing Logging, and I'll let you know what I find!

Related