External flash with LittleFS & FOTA

Hi support team,

I'm currently developing a project for a custom board with a nRF9160 chip and with nRF Connect SDK 2.9.0 and Zephyr 3.7.99 using VS code with nRF connect extension as IDE.
My board collects samples from a sensor and then uploads it to the cloud. However, since I cannot lose any data I need to save it somewhere while there's no connection to the cloud, so I've added an external flash (MX25R6435F). To test the connection to my flash I used the jesd216 sample, building it to my custom board. I also included it in my device tree like this:

&spi3 {
	compatible = "nordic,nrf-spim";
	status = "okay";
	cs-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
	pinctrl-0 = <&spi3_default>;
	pinctrl-1 = <&spi3_sleep>;
	pinctrl-names = "default", "sleep";
	mx25r64: mx25r6435f@0  {
		compatible = "jedec,spi-nor";
		reg = <0>;
		spi-max-frequency = <8000000>;
		jedec-id = [c2 28 17];
		size = <67108864>;
		wp-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>;
		hold-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
	};
};

This seems to work fine, the sample output:

*** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
mx25r6435f@0: SFDP v 1.6 AP ff with 3 PH
PH0: ff00 rev 1.6: 16 DW @ 30
Summary of BFP content:
DTR Clocking not supported
Addressing: 3-Byte only
4-KiBy erase: uniform
Support QSPI XIP
Support 1-1-1
Support 1-1-2: instr 3Bh, 0 mode clocks, 8 waits
Support 1-1-4: instr 6Bh, 0 mode clocks, 8 waits
Support 1-2-2: instr BBh, 0 mode clocks, 4 waits
Support 1-4-4: instr EBh, 2 mode clocks, 4 waits
Flash density: 8388608 bytes
ET1: instr 20h for 4096 By; typ 48 ms, max 384 ms
ET2: instr 52h for 32768 By; typ 240 ms, max 1920 ms
ET3: instr D8h for 65536 By; typ 480 ms, max 3840 ms
Chip erase: typ 52000 ms, max 312000 ms
Byte program: type 32 + 1 * B us, max 192 + 6 * B us
Page program: typ 896 us, max 5376 us
Page program size: 256 By
Suspend: B0h ; Resume: 30h
DPD: Enter B9h, exit ABh ; delay 40000 ns ; poll 0x3d
HOLD or RESET Disable: unsupported
QER: 2
0-4-4 Mode methods: entry 0x9 ; exit 0x2f
4-4-4 Mode sequences: en

Now I want to include LittleFS to the project so I have a file system where I can store the sensor data.

I updated my prj.conf to include the following:

# Enable SPI NOR flash support
CONFIG_SPI=y
CONFIG_SPI_NOR=y
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096

# Enable flash operations
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_FLASH_PAGE_LAYOUT=y

# Enable file system
CONFIG_FILE_SYSTEM=y
CONFIG_FILE_SYSTEM_LITTLEFS=y

# Cpp
CONFIG_CPP=y
CONFIG_STD_CPP20=y
CONFIG_MINIMAL_LIBCPP=y
CONFIG_GLIBCXX_LIBCPP=y

CONFIG_SETTINGS=y
CONFIG_SETTINGS_FILE=y
CONFIG_SETTINGS_FILE_PATH="/lfs/settings"

I also added this to the device tree, to tell the partition manager to include my external flash.

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

Finally, I added a pm_static.yml file to define my external flash partitions:

littlefs_storage:
  address: 0x00000000  # Start of the combined storage area in external flash
  region: external_flash
  size: 0x00800000  # Total size covering all three partitions
  placement:
    before: end

sensordata_partition:
  address: 0x00000000
  region: external_flash
  size: 0x00400000
  placement:
    within: littlefs_storage  # Explicitly part of littlefs_storage

log_partition:
  address: 0x00400000
  region: external_flash
  size: 0x00400000
  placement:
    after: sensordata_partition
    within: littlefs_storage

When building the project I can see that my external flash partition is indeed being included, but addresses seems wrong?

app:
  address: 0x8000
  end_address: 0x0
  region: flash_primary
  size: -0x8000
external_flash:
  address: 0x1000000
  end_address: 0x800000
  region: external_flash
  size: -0x800000
littlefs_storage:
  address: 0x0
  end_address: 0x800000
  placement:
    before: end
  region: external_flash
  size: 0x800000
log_partition:
  address: 0x400000
  end_address: 0x800000
  placement:
    after: sensordata_partition
    within: littlefs_storage
  region: external_flash
  size: 0x400000
nrf_modem_lib_ctrl:
  address: 0x20008000
  end_address: 0x200084e8
  inside:
  - sram_nonsecure
  placement:
    after:
    - tfm_sram
    - start
  region: sram_primary
  size: 0x4e8
nrf_modem_lib_rx:
  address: 0x2000a568
  end_address: 0x2000c568
  inside:
  - sram_nonsecure
  placement:
    after:
    - nrf_modem_lib_tx
  region: sram_primary
  size: 0x2000
nrf_modem_lib_sram:
  address: 0x20008000
  end_address: 0x2000c568
  orig_span: &id001
  - nrf_modem_lib_ctrl
  - nrf_modem_lib_tx
  - nrf_modem_lib_rx
  region: sram_primary
  size: 0x4568
  span: *id001
nrf_modem_lib_tx:
  address: 0x200084e8
  end_address: 0x2000a568
  inside:
  - sram_nonsecure
  placement:
    after:
    - nrf_modem_lib_ctrl
  region: sram_primary
  size: 0x2080
otp:
  address: 0xff8108
  end_address: 0xff83fc
  region: otp
  size: 0x2f4
sensordata_partition:
  address: 0x0
  end_address: 0x400000
  placement:
    within: littlefs_storage
  region: external_flash
  size: 0x400000
sram_nonsecure:
  address: 0x20008000
  end_address: 0x20040000
  orig_span: &id002
  - sram_primary
  - nrf_modem_lib_ctrl
  - nrf_modem_lib_tx
  - nrf_modem_lib_rx
  region: sram_primary
  size: 0x38000
  span: *id002
sram_primary:
  address: 0x2000c568
  end_address: 0x20040000
  region: sram_primary
  size: 0x33a98
sram_secure:
  address: 0x20000000
  end_address: 0x20008000
  orig_span: &id003
  - tfm_sram
  region: sram_primary
  size: 0x8000
  span: *id003
tfm:
  address: 0x0
  end_address: 0x8000
  placement:
    before:
    - app
  region: flash_primary
  size: 0x8000
tfm_nonsecure:
  address: 0x8000
  end_address: 0x0
  orig_span: &id004
  - app
  region: flash_primary
  size: -0x8000
  span: *id004
tfm_secure:
  address: 0x0
  end_address: 0x8000
  orig_span: &id005
  - tfm
  region: flash_primary
  size: 0x8000
  span: *id005
tfm_sram:
  address: 0x20000000
  end_address: 0x20008000
  inside:
  - sram_secure
  placement:
    after:
    - start
  region: sram_primary
  size: 0x8000

Also when running the code I instantly get a hardfault.

I just upgraded my SDK from version 2.4.0 to 2.9.0 and I can see that something called sysbuild have been introduced, maybe I'm missing a link there?

Also when this is working, I would like to configure the external flash to also have a partition for the FOTA image to free up some space on the internal flash, is this possible?

Parents
  • Hi

    At what step here did the application stop working exactly? You say you've both added the file system with partitions and moved from NCS 2.4.0 to 2.9.0. I think we should go step by step here to figure out what caused this hardfault in the first place.

    For moving from an older NCS version to the latest (2.4.0 to 2.9.0 for example). Please check out the migration guides for 2.5.0, 2.6.0, 2.7.0, 2.8.0 and 2.9.0 here. We also have a migration guide from multi-image builds to sysbuild here that should walk you through moving from multi-image to sysbuild.

    Best regards,

    Simon

  • Hi Simon,

    Apologies for any confusion in my previous message. I recently updated my main project from 2.4.0 to 2.9.0, but before integrating the external flash and FOTA, I wanted to test them separately. For this, I used the jesd216 example from the 2.9.0 toolchain.

    The issue appeared when I added the pm_static.yml file—after that, the application stopped working. As I mentioned in my post, I suspect this might be related to the flash addresses. Some seem to have negative sizes, and I also noticed that the external flash doesn’t start at 0x0000000 but instead at 0x1000000.

    Do you have any insights on this?

    Thanks,
    Nils

Reply
  • Hi Simon,

    Apologies for any confusion in my previous message. I recently updated my main project from 2.4.0 to 2.9.0, but before integrating the external flash and FOTA, I wanted to test them separately. For this, I used the jesd216 example from the 2.9.0 toolchain.

    The issue appeared when I added the pm_static.yml file—after that, the application stopped working. As I mentioned in my post, I suspect this might be related to the flash addresses. Some seem to have negative sizes, and I also noticed that the external flash doesn’t start at 0x0000000 but instead at 0x1000000.

    Do you have any insights on this?

    Thanks,
    Nils

Children
No Data
Related